Hi, so I did the massaging to split out the GIMPLE parsing routines out to a separate file (quite tricky to get the gengtype issues correctly so I thought to help out here and get things started).
Tested on x86_64-unknown-linux-gnu, bootstrap is still in progress. Will push to gimplefe soon. I think it shows that the GIMPLE FE should maybe not use c_parser_cast_expression or c_token_starts_typename or c_parser_next_token_starts_declspecs. But maybe it's not 100% avoidable as we want to re-use C parsing for local declarations (of types and decls) as well (eventually even local statics with initializers which remain GENERIC). Richard. commit f2dc45b7d1cbd3122944a26f449d7fd233994f50 Author: Richard Guenther <rguent...@suse.de> Date: Tue Oct 25 15:20:42 2016 +0200 2016-10-25 Richard Biener <rguent...@suse.de> c/ * Make-lang.in (C_AND_OBJC_OBJS): Add gimple-parser.o. * config-lang.in (gtfiles): Add c/c-parser.h. * c-lang.c: Include c-pragma.h and c-parser.h. * c-parser.c (enum c_id_kind, struct c_token, struct c_parser, c_parser_next_token_is, c_parser_next_token_is_not, c_parser_next_token_is_keyword, enum c_lookahead_kind, enum c_dtr_syn, enum c_parser_prec): Split out to ... * c-parser.h: ... new header. * c-parser.c (c_parser_peek_token, c_parser_peek_2nd_token, c_token_starts_typename, c_parser_next_token_starts_declspecs, c_parser_next_tokens_start_declaration, c_parser_consume_token, c_parser_error, c_parser_require, c_parser_skip_until_found, c_parser_declspecs, c_parser_declarator, c_parser_cast_expression): Export. * c-parser.h (c_parser_peek_token, c_parser_peek_2nd_token, c_token_starts_typename, c_parser_next_token_starts_declspecs, c_parser_next_tokens_start_declaration, c_parser_consume_token, c_parser_error, c_parser_require, c_parser_skip_until_found, c_parser_declspecs, c_parser_declarator, c_parser_cast_expression): Declare. * gimple-parser.c: Moved from c-parser.c. * gimple-parser.h (c_parser_parse_gimple_body): Declare. (c_parser_gimple_pass_list): Likewise. obj-c/ * config-lang.in (gtfiles): Add c/c-parser.h. diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in index 72c9ae7..cd7108b 100644 --- a/gcc/c/Make-lang.in +++ b/gcc/c/Make-lang.in @@ -51,7 +51,8 @@ CFLAGS-c/gccspec.o += $(DRIVER_DEFINES) # Language-specific object files for C and Objective C. C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \ c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \ - c/c-array-notation.o c/c-fold.o $(C_COMMON_OBJS) $(C_TARGET_OBJS) + c/c-array-notation.o c/c-fold.o c/gimple-parser.o \ + $(C_COMMON_OBJS) $(C_TARGET_OBJS) # Language-specific object files for C. C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS) diff --git a/gcc/c/c-lang.c b/gcc/c/c-lang.c index b4096d0..a2dd768 100644 --- a/gcc/c/c-lang.c +++ b/gcc/c/c-lang.c @@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "langhooks-def.h" #include "c-objc-common.h" +#include "c-family/c-pragma.h" +#include "c-parser.h" enum c_language_kind c_language = clk_c; diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 639d94f..9b51c48 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -59,18 +59,8 @@ along with GCC; see the file COPYING3. If not see #include "gimple-expr.h" #include "context.h" #include "gcc-rich-location.h" -#include "tree-vrp.h" -#include "tree-pass.h" -#include "tree-pretty-print.h" -#include "tree.h" -#include "basic-block.h" -#include "gimple.h" -#include "gimple-pretty-print.h" -#include "tree-ssa.h" -#include "pass_manager.h" -#include "tree-ssanames.h" -#include "gimple-ssa.h" -#include "tree-dfa.h" +#include "c-parser.h" +#include "gimple-parser.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -162,116 +152,6 @@ c_parse_init (void) } } -/* The C lexer intermediates between the lexer in cpplib and c-lex.c - and the C parser. Unlike the C++ lexer, the parser structure - stores the lexer information instead of using a separate structure. - Identifiers are separated into ordinary identifiers, type names, - keywords and some other Objective-C types of identifiers, and some - look-ahead is maintained. - - ??? It might be a good idea to lex the whole file up front (as for - C++). It would then be possible to share more of the C and C++ - lexer code, if desired. */ - -/* More information about the type of a CPP_NAME token. */ -enum c_id_kind { - /* An ordinary identifier. */ - C_ID_ID, - /* An identifier declared as a typedef name. */ - C_ID_TYPENAME, - /* An identifier declared as an Objective-C class name. */ - C_ID_CLASSNAME, - /* An address space identifier. */ - C_ID_ADDRSPACE, - /* Not an identifier. */ - C_ID_NONE -}; - -/* A single C token after string literal concatenation and conversion - of preprocessing tokens to tokens. */ -struct GTY (()) c_token { - /* The kind of token. */ - ENUM_BITFIELD (cpp_ttype) type : 8; - /* If this token is a CPP_NAME, this value indicates whether also - declared as some kind of type. Otherwise, it is C_ID_NONE. */ - ENUM_BITFIELD (c_id_kind) id_kind : 8; - /* If this token is a keyword, this value indicates which keyword. - Otherwise, this value is RID_MAX. */ - ENUM_BITFIELD (rid) keyword : 8; - /* If this token is a CPP_PRAGMA, this indicates the pragma that - was seen. Otherwise it is PRAGMA_NONE. */ - ENUM_BITFIELD (pragma_kind) pragma_kind : 8; - /* The location at which this token was found. */ - location_t location; - /* The value associated with this token, if any. */ - tree value; - /* Token flags. */ - unsigned char flags; - - source_range get_range () const - { - return get_range_from_loc (line_table, location); - } - - location_t get_finish () const - { - return get_range ().m_finish; - } -}; - -/* A parser structure recording information about the state and - context of parsing. Includes lexer information with up to two - tokens of look-ahead; more are not needed for C. */ -struct GTY(()) c_parser { - /* The look-ahead tokens. */ - c_token * GTY((skip)) tokens; - /* Buffer for look-ahead tokens. */ - c_token tokens_buf[4]; - /* How many look-ahead tokens are available (0 - 4, or - more if parsing from pre-lexed tokens). */ - unsigned int tokens_avail; - /* True if a syntax error is being recovered from; false otherwise. - c_parser_error sets this flag. It should clear this flag when - enough tokens have been consumed to recover from the error. */ - BOOL_BITFIELD error : 1; - /* True if we're processing a pragma, and shouldn't automatically - consume CPP_PRAGMA_EOL. */ - BOOL_BITFIELD in_pragma : 1; - /* True if we're parsing the outermost block of an if statement. */ - BOOL_BITFIELD in_if_block : 1; - /* True if we want to lex an untranslated string. */ - BOOL_BITFIELD lex_untranslated_string : 1; - - /* Objective-C specific parser/lexer information. */ - - /* True if we are in a context where the Objective-C "PQ" keywords - are considered keywords. */ - BOOL_BITFIELD objc_pq_context : 1; - /* True if we are parsing a (potential) Objective-C foreach - statement. This is set to true after we parsed 'for (' and while - we wait for 'in' or ';' to decide if it's a standard C for loop or an - Objective-C foreach loop. */ - BOOL_BITFIELD objc_could_be_foreach_context : 1; - /* The following flag is needed to contextualize Objective-C lexical - analysis. In some cases (e.g., 'int NSObject;'), it is - undesirable to bind an identifier to an Objective-C class, even - if a class with that name exists. */ - BOOL_BITFIELD objc_need_raw_identifier : 1; - /* Nonzero if we're processing a __transaction statement. The value - is 1 | TM_STMT_ATTR_*. */ - unsigned int in_transaction : 4; - /* True if we are in a context where the Objective-C "Property attribute" - keywords are valid. */ - BOOL_BITFIELD objc_property_attr_context : 1; - - /* Cilk Plus specific parser/lexer information. */ - - /* Buffer to hold all the tokens from parsing the vector attribute for the - SIMD-enabled functions (formerly known as elemental functions). */ - vec <c_token, va_gc> *cilk_simd_fn_tokens; -}; - - /* The actual parser and external interface. ??? Does this need to be garbage-collected? */ @@ -466,7 +346,7 @@ c_lex_one_token (c_parser *parser, c_token *token) /* Return a pointer to the next token from PARSER, reading it in if necessary. */ -static inline c_token * +c_token * c_parser_peek_token (c_parser *parser) { if (parser->tokens_avail == 0) @@ -477,37 +357,10 @@ c_parser_peek_token (c_parser *parser) return &parser->tokens[0]; } -/* Return true if the next token from PARSER has the indicated - TYPE. */ - -static inline bool -c_parser_next_token_is (c_parser *parser, enum cpp_ttype type) -{ - return c_parser_peek_token (parser)->type == type; -} - -/* Return true if the next token from PARSER does not have the - indicated TYPE. */ - -static inline bool -c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type) -{ - return !c_parser_next_token_is (parser, type); -} - -/* Return true if the next token from PARSER is the indicated - KEYWORD. */ - -static inline bool -c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword) -{ - return c_parser_peek_token (parser)->keyword == keyword; -} - /* Return a pointer to the next-but-one token from PARSER, reading it in if necessary. The next token is already read in. */ -static c_token * +c_token * c_parser_peek_2nd_token (c_parser *parser) { if (parser->tokens_avail >= 2) @@ -582,7 +435,7 @@ c_keyword_starts_typename (enum rid keyword) /* Return true if TOKEN can start a type name, false otherwise. */ -static bool +bool c_token_starts_typename (c_token *token) { switch (token->type) @@ -613,18 +466,6 @@ c_token_starts_typename (c_token *token) } } -enum c_lookahead_kind { - /* Always treat unknown identifiers as typenames. */ - cla_prefer_type, - - /* Could be parsing a nonabstract declarator. Only treat an identifier - as a typename if followed by another identifier or a star. */ - cla_nonabstract_decl, - - /* Never treat identifiers as typenames. */ - cla_prefer_id -}; - /* Return true if the next token from PARSER can start a type name, false otherwise. LA specifies how to do lookahead in order to detect unknown type names. If unsure, pick CLA_PREFER_ID. */ @@ -791,7 +632,7 @@ c_token_starts_declaration (c_token *token) /* Return true if the next token from PARSER can start declaration specifiers, false otherwise. */ -static inline bool +bool c_parser_next_token_starts_declspecs (c_parser *parser) { c_token *token = c_parser_peek_token (parser); @@ -813,7 +654,7 @@ c_parser_next_token_starts_declspecs (c_parser *parser) /* Return true if the next tokens from PARSER can start declaration specifiers or a static assertion, false otherwise. */ -static inline bool +bool c_parser_next_tokens_start_declaration (c_parser *parser) { c_token *token = c_parser_peek_token (parser); @@ -841,7 +682,7 @@ c_parser_next_tokens_start_declaration (c_parser *parser) /* Consume the next token from PARSER. */ -static void +void c_parser_consume_token (c_parser *parser) { gcc_assert (parser->tokens_avail >= 1); @@ -934,7 +775,7 @@ c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind, this way is not i18n-friendly and some other approach should be used. */ -static void +void c_parser_error (c_parser *parser, const char *gmsgid) { c_token *token = c_parser_peek_token (parser); @@ -977,7 +818,7 @@ c_parser_error (c_parser *parser, const char *gmsgid) been produced and no message will be produced this time. Returns true if found, false otherwise. */ -static bool +bool c_parser_require (c_parser *parser, enum cpp_ttype type, const char *msgid) @@ -1020,7 +861,7 @@ c_parser_require_keyword (c_parser *parser, already been produced and no message will be produced this time. */ -static void +void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type, const char *msgid) @@ -1255,42 +1096,6 @@ restore_extension_diagnostics (int flags) warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0); } -/* Possibly kinds of declarator to parse. */ -enum c_dtr_syn { - /* A normal declarator with an identifier. */ - C_DTR_NORMAL, - /* An abstract declarator (maybe empty). */ - C_DTR_ABSTRACT, - /* A parameter declarator: may be either, but after a type name does - not redeclare a typedef name as an identifier if it can - alternatively be interpreted as a typedef name; see DR#009, - applied in C90 TC1, omitted from C99 and reapplied in C99 TC2 - following DR#249. For example, given a typedef T, "int T" and - "int *T" are valid parameter declarations redeclaring T, while - "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are - abstract declarators rather than involving redundant parentheses; - the same applies with attributes inside the parentheses before - "T". */ - C_DTR_PARM -}; - -/* The binary operation precedence levels, where 0 is a dummy lowest level - used for the bottom of the stack. */ -enum c_parser_prec { - PREC_NONE, - PREC_LOGOR, - PREC_LOGAND, - PREC_BITOR, - PREC_BITXOR, - PREC_BITAND, - PREC_EQ, - PREC_REL, - PREC_SHIFT, - PREC_ADD, - PREC_MULT, - NUM_PRECS -}; - /* Helper data structure for parsing #pragma acc routine. */ struct oacc_routine_data { bool error_seen; /* Set if error has been reported. */ @@ -1307,15 +1112,11 @@ static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool * = NULL); static void c_parser_static_assert_declaration_no_semi (c_parser *); static void c_parser_static_assert_declaration (c_parser *); -static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool, - bool, bool, bool, enum c_lookahead_kind); static struct c_typespec c_parser_enum_specifier (c_parser *); static struct c_typespec c_parser_struct_or_union_specifier (c_parser *); static tree c_parser_struct_declaration (c_parser *); static struct c_typespec c_parser_typeof_specifier (c_parser *); static tree c_parser_alignas_specifier (c_parser *); -static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn, - bool *); static struct c_declarator *c_parser_direct_declarator (c_parser *, bool, c_dtr_syn, bool *); static struct c_declarator *c_parser_direct_declarator_inner (c_parser *, @@ -1355,7 +1156,6 @@ static struct c_expr c_parser_conditional_expression (c_parser *, struct c_expr *, tree); static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *, tree); -static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *); static struct c_expr c_parser_unary_expression (c_parser *); static struct c_expr c_parser_sizeof_expression (c_parser *); static struct c_expr c_parser_alignof_expression (c_parser *); @@ -1433,30 +1233,6 @@ static tree c_parser_array_notation (location_t, c_parser *, tree, tree); static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool); static void c_parser_cilk_grainsize (c_parser *, bool *); -/* Gimple parsing functions. */ -static void c_parser_parse_gimple_body (c_parser *); -static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *); -static void c_parser_gimple_label (c_parser *, gimple_seq *); -static void c_parser_gimple_expression (c_parser *, gimple_seq *); -static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *); -static struct c_expr c_parser_gimple_unary_expression (c_parser *); -static struct c_expr c_parser_gimple_postfix_expression (c_parser *); -static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *, - location_t, - struct c_expr); -static void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *); -static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **); -static void c_parser_gimple_declaration (c_parser *); -static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *); -static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *); -static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *); -static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *); -static void c_finish_gimple_return (location_t, tree); -static c_expr c_parser_parse_ssa_names (c_parser *); -static tree c_parser_gimple_paren_condition (c_parser *); -static vec<tree, va_gc> *c_parser_gimple_expr_list (c_parser *, - vec<tree, va_gc> **, vec<location_t> *); - /* Parse a translation unit (C90 6.7, C99 6.9). translation-unit: @@ -2496,7 +2272,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser) objc-protocol-refs */ -static void +void c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, bool scspec_ok, bool typespec_ok, bool start_attr_ok, bool alignspec_ok, bool auto_type_ok, @@ -3495,7 +3271,7 @@ c_parser_alignas_specifier (c_parser * parser) This function also accepts an omitted abstract declarator as being an abstract declarator, although not part of the formal syntax. */ -static struct c_declarator * +struct c_declarator * c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, bool *seen_id) { @@ -6946,7 +6722,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after, ( type-name ) unary-expression */ -static struct c_expr +struct c_expr c_parser_cast_expression (c_parser *parser, struct c_expr *after) { location_t cast_loc = c_parser_peek_token (parser)->location; @@ -18393,1309 +18169,4 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index, return value_tree; } -/* Parse the body of a function declaration marked with "__GIMPLE". */ - -void -c_parser_parse_gimple_body (c_parser *parser) -{ - gimple_seq seq = NULL; - gimple_seq body = NULL; - tree stmt = push_stmt_list (); - push_scope (); - location_t loc1 = c_parser_peek_token (parser)->location; - - init_tree_ssa (cfun); - - if (! c_parser_gimple_compound_statement (parser, &seq)) - { - gimple *ret = gimple_build_return (NULL); - gimple_seq_add_stmt (&seq, ret); - } - - tree block = pop_scope (); - stmt = pop_stmt_list (stmt); - stmt = c_build_bind_expr (loc1, block, stmt); - - block = DECL_INITIAL (current_function_decl); - BLOCK_SUBBLOCKS (block) = NULL_TREE; - BLOCK_CHAIN (block) = NULL_TREE; - TREE_ASM_WRITTEN (block) = 1; - - gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL, - BIND_EXPR_BLOCK (stmt)); - gimple_bind_set_body (bind_stmt, seq); - gimple_seq_add_stmt (&body, bind_stmt); - gimple_set_body (current_function_decl, body); - cfun->curr_properties = PROP_gimple_any; - - return; -} - -/* Parse a compound statement in gimple function body. - - gimple-statement: - gimple-statement - gimple-declaration-statement - gimple-if-statement - gimple-switch-statement - gimple-labeled-statement - gimple-expression-statement - gimple-goto-statement - gimple-phi-statement - gimple-return-statement -*/ - -static bool -c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq) -{ - bool return_p = false; - - if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) - return false; - - if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - { - c_parser_consume_token (parser); - return false; - } - - if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - { - c_parser_error (parser, "expected declaration or statement"); - c_parser_consume_token (parser); - return false; - } - - while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) - { - if (parser->error) - { - c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); - return return_p; - } - - if (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON) - c_parser_gimple_label (parser, seq); - - else if (c_parser_next_tokens_start_declaration (parser)) - c_parser_gimple_declaration (parser); - - else if (c_parser_next_token_is (parser, CPP_EOF)) - { - c_parser_error (parser, "expected declaration or statement"); - return return_p; - } - - else - { - switch (c_parser_peek_token (parser)->type) - { - case CPP_KEYWORD: - switch (c_parser_peek_token (parser)->keyword) - { - case RID_IF: - c_parser_gimple_if_stmt (parser, seq); - break; - case RID_SWITCH: - c_parser_gimple_switch_stmt (parser, seq); - break; - case RID_GOTO: - { - location_t loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_NAME)) - { - c_parser_gimple_goto_stmt (loc, - c_parser_peek_token - (parser)->value, - seq); - c_parser_consume_token (parser); - if (! c_parser_require (parser, CPP_SEMICOLON, - "expected %<;%>")) - return return_p; - } - } - break; - case RID_RETURN: - return_p = true; - c_parser_gimple_return_stmt (parser, seq); - if (! c_parser_require (parser, CPP_SEMICOLON, - "expected %<;%>")) - return return_p; - break; - default: - goto expr_stmt; - } - break; - case CPP_SEMICOLON: - c_parser_consume_token (parser); - break; - default: - expr_stmt: - c_parser_gimple_expression (parser, seq); - if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) - return return_p; - } - } - } - c_parser_consume_token (parser); - return return_p; -} - -/* Parse a gimple expression. - - gimple-expression: - gimple-unary-expression - gimple-call-statement - gimple-binary-expression - gimple-assign-expression - gimple-cast-expression - -*/ - -static void -c_parser_gimple_expression (c_parser *parser, gimple_seq *seq) -{ - struct c_expr lhs, rhs; - gimple *assign = NULL; - enum tree_code subcode = NOP_EXPR; - location_t loc; - tree arg = NULL_TREE; - auto_vec<tree> vargs; - - lhs = c_parser_gimple_unary_expression (parser); - rhs.value = error_mark_node; - - if (c_parser_next_token_is (parser, CPP_EQ)) - c_parser_consume_token (parser); - - loc = EXPR_LOCATION (lhs.value); - - /* GIMPLE call expression. */ - if (c_parser_next_token_is (parser, CPP_SEMICOLON) - && TREE_CODE (lhs.value) == CALL_EXPR) - { - gimple *call; - call = gimple_build_call_from_tree (lhs.value); - gimple_seq_add_stmt (seq, call); - gimple_set_location (call, loc); - return; - } - - /* Cast expression. */ - if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) - && c_token_starts_typename (c_parser_peek_2nd_token (parser))) - { - /* TODO: have a gimple_cast_expr function. */ - rhs = c_parser_cast_expression (parser, NULL); - if (lhs.value != error_mark_node && - rhs.value != error_mark_node) - { - assign = gimple_build_assign (lhs.value, rhs.value); - gimple_seq_add_stmt (seq, assign); - gimple_set_location (assign, loc); - return; - } - } - - if (POINTER_TYPE_P (TREE_TYPE (lhs.value))) - { - STRIP_USELESS_TYPE_CONVERSION (rhs.value); - if (! useless_type_conversion_p (TREE_TYPE (lhs.value), - TREE_TYPE (rhs.value))) - rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value); - } - - /* Pointer expression. */ - if (TREE_CODE (lhs.value) == INDIRECT_REF) - { - tree save_expr = lhs.value; - bool volatilep = TREE_THIS_VOLATILE (lhs.value); - bool notrap = TREE_THIS_NOTRAP (lhs.value); - tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0)); - - lhs.value = fold_indirect_ref_loc (loc, lhs.value); - if (lhs.value == save_expr) - { - lhs.value = fold_build2_loc (input_location, MEM_REF, - TREE_TYPE (lhs.value), - TREE_OPERAND (lhs.value, 0), - build_int_cst (saved_ptr_type, 0)); - TREE_THIS_VOLATILE (lhs.value) = volatilep; - TREE_THIS_NOTRAP (lhs.value) = notrap; - } - } - - if (c_parser_next_token_is (parser, CPP_AND) - || c_parser_next_token_is (parser, CPP_MULT) - || c_parser_next_token_is (parser, CPP_PLUS) - || c_parser_next_token_is (parser, CPP_MINUS) - || c_parser_next_token_is (parser, CPP_COMPL) - || c_parser_next_token_is (parser, CPP_NOT)) - { - rhs = c_parser_gimple_unary_expression (parser); - assign = gimple_build_assign (lhs.value, rhs.value); - gimple_set_location (assign, loc); - gimple_seq_add_stmt (seq, assign); - return; - } - - /* GIMPLE PHI expression. */ - if (c_parser_next_token_is_keyword (parser, RID_PHI)) - { - c_parser_consume_token (parser); - - if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - return; - - if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) - c_parser_consume_token (parser); - - while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) - { - if (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON) - { - arg = lookup_label_for_goto (loc, - c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - - if (c_parser_next_token_is (parser, CPP_COLON)) - c_parser_consume_token (parser); - vargs.safe_push (arg); - } - else if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); - else - { - arg = c_parser_parse_ssa_names (parser).value; - vargs.safe_push (arg); - } - } - - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - - /* Build internal function for PHI. */ - gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs); - gimple_call_set_lhs (call_stmt, lhs.value); - gimple_set_location (call_stmt, UNKNOWN_LOCATION); - gimple_seq_add_stmt (seq, call_stmt); - return; - } - - /* GIMPLE call with lhs. */ - if (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN - && lookup_name (c_parser_peek_token (parser)->value)) - { - rhs = c_parser_gimple_unary_expression (parser); - gimple *call = gimple_build_call_from_tree (rhs.value); - gimple_call_set_lhs (call, lhs.value); - gimple_seq_add_stmt (seq, call); - gimple_set_location (call, loc); - return; - } - - rhs = c_parser_gimple_binary_expression (parser, &subcode); - - if (lhs.value != error_mark_node - && rhs.value != error_mark_node) - { - if (subcode == NOP_EXPR) - assign = gimple_build_assign (lhs.value, rhs.value); - else - assign = gimple_build_assign (lhs.value, subcode, - TREE_OPERAND (rhs.value, 0), - TREE_OPERAND (rhs.value, 1)); - gimple_seq_add_stmt (seq, assign); - gimple_set_location (assign, loc); - } - return; -} - -/* Parse gimple binary expr. - - gimple-multiplicative-expression: - gimple-unary-expression * gimple-unary-expression - gimple-unary-expression / gimple-unary-expression - gimple-unary-expression % gimple-unary-expression - - gimple-additive-expression: - gimple-unary-expression + gimple-unary-expression - gimple-unary-expression - gimple-unary-expression - - gimple-shift-expression: - gimple-unary-expression << gimple-unary-expression - gimple-unary-expression >> gimple-unary-expression - - gimple-relational-expression: - gimple-unary-expression < gimple-unary-expression - gimple-unary-expression > gimple-unary-expression - gimple-unary-expression <= gimple-unary-expression - gimple-unary-expression >= gimple-unary-expression - - gimple-equality-expression: - gimple-unary-expression == gimple-unary-expression - gimple-unary-expression != gimple-unary-expression - - gimple-AND-expression: - gimple-unary-expression & gimple-unary-expression - - gimple-exclusive-OR-expression: - gimple-unary-expression ^ gimple-unary-expression - - gimple-inclusive-OR-expression: - gimple-unary-expression | gimple-unary-expression - - gimple-logical-AND-expression: - gimple-unary-expression && gimple-unary-expression - - gimple-logical-OR-expression: - gimple-unary-expression || gimple-unary-expression - -*/ - -static c_expr -c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode) -{ - struct { - /* The expression at this stack level. */ - struct c_expr expr; - /* The operation on its left. */ - enum tree_code op; - /* The source location of this operation. */ - location_t loc; - } stack[2]; - int sp; - /* Location of the binary operator. */ - location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */ -#define POP \ - do { \ - if (sp == 1 \ - && c_parser_peek_token (parser)->type == CPP_SEMICOLON \ - && (((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \ - | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \ - && stack[sp].op != TRUNC_MOD_EXPR \ - && stack[0].expr.value != error_mark_node \ - && stack[1].expr.value != error_mark_node) \ - stack[0].expr.value \ - = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \ - stack[0].expr.value, stack[1].expr.value); \ - else \ - stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ - stack[sp].op, \ - stack[sp - 1].expr, \ - stack[sp].expr); \ - sp--; \ - } while (0) - stack[0].loc = c_parser_peek_token (parser)->location; - stack[0].expr = c_parser_gimple_unary_expression (parser); - sp = 0; - source_range src_range; - if (parser->error) - goto out; - switch (c_parser_peek_token (parser)->type) - { - case CPP_MULT: - *subcode = MULT_EXPR; - break; - case CPP_DIV: - *subcode = TRUNC_DIV_EXPR; - break; - case CPP_MOD: - *subcode = TRUNC_MOD_EXPR; - break; - case CPP_PLUS: - *subcode = PLUS_EXPR; - break; - case CPP_MINUS: - *subcode = MINUS_EXPR; - break; - case CPP_LSHIFT: - *subcode = LSHIFT_EXPR; - break; - case CPP_RSHIFT: - *subcode = RSHIFT_EXPR; - break; - case CPP_LESS: - *subcode = LT_EXPR; - break; - case CPP_GREATER: - *subcode = GT_EXPR; - break; - case CPP_LESS_EQ: - *subcode = LE_EXPR; - break; - case CPP_GREATER_EQ: - *subcode = GE_EXPR; - break; - case CPP_EQ_EQ: - *subcode = EQ_EXPR; - break; - case CPP_NOT_EQ: - *subcode = NE_EXPR; - break; - case CPP_AND: - *subcode = BIT_AND_EXPR; - break; - case CPP_XOR: - *subcode = BIT_XOR_EXPR; - break; - case CPP_OR: - *subcode = BIT_IOR_EXPR; - break; - case CPP_AND_AND: - *subcode = TRUTH_ANDIF_EXPR; - break; - case CPP_OR_OR: - *subcode = TRUTH_ORIF_EXPR; - break; - default: - /* Not a binary operator, so end of the binary expression. */ - *subcode = NOP_EXPR; - goto out; - } - binary_loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - switch (*subcode) - { - case TRUTH_ANDIF_EXPR: - src_range = stack[sp].expr.src_range; - stack[sp].expr.value = c_objc_common_truthvalue_conversion - (stack[sp].loc, default_conversion (stack[sp].expr.value)); - set_c_expr_source_range (&stack[sp].expr, src_range); - break; - case TRUTH_ORIF_EXPR: - src_range = stack[sp].expr.src_range; - stack[sp].expr.value = c_objc_common_truthvalue_conversion - (stack[sp].loc, default_conversion (stack[sp].expr.value)); - set_c_expr_source_range (&stack[sp].expr, src_range); - break; - default: - break; - } - sp++; - stack[sp].loc = binary_loc; - stack[sp].expr = c_parser_gimple_unary_expression (parser); - stack[sp].op = *subcode; -out: - while (sp > 0) - POP; - return stack[0].expr; -#undef POP -} - -/* Parse gimple unary expression. - - gimple-unary-expression: - gimple-postfix-expression - unary-operator cast-expression - - unary-operator: one of - & * + - ~ ! -*/ - -static c_expr -c_parser_gimple_unary_expression (c_parser *parser) -{ - struct c_expr ret, op; - if (c_parser_peek_token (parser)->value - && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE - && ! lookup_name (c_parser_peek_token (parser)->value)) - return c_parser_parse_ssa_names (parser); - - location_t op_loc = c_parser_peek_token (parser)->location; - location_t finish; - ret.original_code = ERROR_MARK; - ret.original_type = NULL; - switch (c_parser_peek_token (parser)->type) - { - case CPP_AND: - c_parser_consume_token (parser); - op = c_parser_cast_expression (parser, NULL); - mark_exp_read (op.value); - return parser_build_unary_op (op_loc, ADDR_EXPR, op); - case CPP_MULT: - { - c_parser_consume_token (parser); - op = c_parser_cast_expression (parser, NULL); - finish = op.get_finish (); - location_t combined_loc = make_location (op_loc, op_loc, finish); - ret.value = build_indirect_ref (combined_loc, op.value, - RO_UNARY_STAR); - ret.src_range.m_start = op_loc; - ret.src_range.m_finish = finish; - return ret; - } - case CPP_PLUS: - c_parser_consume_token (parser); - op = c_parser_cast_expression (parser, NULL); - return parser_build_unary_op (op_loc, CONVERT_EXPR, op); - case CPP_MINUS: - c_parser_consume_token (parser); - op = c_parser_cast_expression (parser, NULL); - return parser_build_unary_op (op_loc, NEGATE_EXPR, op); - case CPP_COMPL: - c_parser_consume_token (parser); - op = c_parser_cast_expression (parser, NULL); - return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op); - case CPP_NOT: - c_parser_consume_token (parser); - op = c_parser_cast_expression (parser, NULL); - return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op); - default: - return c_parser_gimple_postfix_expression (parser); - } -} - -/* Parse gimple ssa names. */ - -static c_expr -c_parser_parse_ssa_names (c_parser *parser) -{ - tree id = NULL_TREE; - c_expr ret; - char *var_name = NULL, *var_version = NULL, *token = NULL; - ret.original_code = ERROR_MARK; - ret.original_type = NULL; - - /* SSA token string. */ - const char *ssa_token - = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); - token = new char [strlen (ssa_token) + 1]; - strcpy (token, ssa_token); - - /* Separate var name and version. */ - var_version = strrchr (token, '_'); - if (var_version) - { - var_name = new char[var_version - token + 1]; - memcpy (var_name, token, var_version - token); - var_name[var_version - token] = '\0'; - id = get_identifier (var_name); - - /* lookup for parent decl. */ - if (lookup_name (id)) - { - var_version++; - unsigned int version; - version = atoi (var_version); - if (var_version && version) - { - ret.value = NULL_TREE; - if (version < num_ssa_names) - ret.value = ssa_name (version); - if (! ret.value) - ret.value = make_ssa_name_fn (cfun, lookup_name (id), - gimple_build_nop (), version); - c_parser_consume_token (parser); - } - } - } - - /* For default definition SSA names. */ - if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) - { - c_parser_consume_token (parser); - ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); - if (! strcmp ("D", ssa_token)) - { - set_ssa_default_def (cfun, lookup_name (id), ret.value); - c_parser_consume_token (parser); - } - if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) - goto out; - } - - out: - free (var_name); - free (token); - return ret; -} - -/* Parse gimple postfix expression. - - gimple-postfix-expression: - gimple-primary-expression - gimple-primary-xpression [ gimple-primary-expression ] - gimple-primary-expression ( gimple-argument-expression-list[opt] ) - - gimple-argument-expression-list: - gimple-unary-expression - gimple-argument-expression-list , gimple-unary-expression - - gimple-primary-expression: - identifier - constant - string-literal - -*/ - -static struct c_expr -c_parser_gimple_postfix_expression (c_parser *parser) -{ - struct c_expr expr; - location_t loc = c_parser_peek_token (parser)->location; - source_range tok_range = c_parser_peek_token (parser)->get_range (); - expr.original_code = ERROR_MARK; - expr.original_type = NULL; - switch (c_parser_peek_token (parser)->type) - { - case CPP_NUMBER: - expr.value = c_parser_peek_token (parser)->value; - set_c_expr_source_range (&expr, tok_range); - loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - break; - case CPP_CHAR: - case CPP_CHAR16: - case CPP_CHAR32: - case CPP_WCHAR: - expr.value = c_parser_peek_token (parser)->value; - set_c_expr_source_range (&expr, tok_range); - c_parser_consume_token (parser); - break; - case CPP_STRING: - case CPP_STRING16: - case CPP_STRING32: - case CPP_WSTRING: - case CPP_UTF8STRING: - expr.value = c_parser_peek_token (parser)->value; - set_c_expr_source_range (&expr, tok_range); - expr.original_code = STRING_CST; - c_parser_consume_token (parser); - break; - case CPP_NAME: - if (c_parser_peek_token (parser)->id_kind == C_ID_ID) - { - tree id = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - expr.value = build_external_ref (loc, id, - (c_parser_peek_token (parser)->type - == CPP_OPEN_PAREN), - &expr.original_type); - set_c_expr_source_range (&expr, tok_range); - break; - } - else - { - c_parser_error (parser, "expected expression"); - expr.set_error (); - break; - } - break; - default: - c_parser_error (parser, "expected expression"); - expr.set_error (); - break; - } - return c_parser_gimple_postfix_expression_after_primary - (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr); -} - -/* Parse a gimple postfix expression after the initial primary or compound - literal. */ - -static struct c_expr -c_parser_gimple_postfix_expression_after_primary (c_parser *parser, - location_t expr_loc, - struct c_expr expr) -{ - struct c_expr orig_expr; - vec<tree, va_gc> *exprlist; - vec<tree, va_gc> *origtypes = NULL; - vec<location_t> arg_loc = vNULL; - location_t start; - location_t finish; - - location_t op_loc = c_parser_peek_token (parser)->location; - - switch (c_parser_peek_token (parser)->type) - { - case CPP_OPEN_SQUARE: - { - c_parser_consume_token (parser); - tree idx = c_parser_gimple_unary_expression (parser).value; - - if (! c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>")) - break; - - start = expr.get_start (); - finish = parser->tokens_buf[0].location; - expr.value = build_array_ref (op_loc, expr.value, idx); - set_c_expr_source_range (&expr, start, finish); - - expr.original_code = ERROR_MARK; - expr.original_type = NULL; - break; - } - case CPP_OPEN_PAREN: - { - /* Function call. */ - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - exprlist = NULL; - else - exprlist = c_parser_gimple_expr_list (parser, &origtypes, - &arg_loc); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - orig_expr = expr; - start = expr.get_start (); - finish = parser->tokens_buf[0].get_finish (); - expr.value = c_build_function_call_vec (expr_loc, arg_loc, expr.value, - exprlist, origtypes); - set_c_expr_source_range (&expr, start, finish); - - expr.original_code = ERROR_MARK; - if (TREE_CODE (expr.value) == INTEGER_CST - && TREE_CODE (orig_expr.value) == FUNCTION_DECL - && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL - && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P) - expr.original_code = C_MAYBE_CONST_EXPR; - expr.original_type = NULL; - if (exprlist) - { - release_tree_vector (exprlist); - release_tree_vector (origtypes); - } - arg_loc.release (); - break; - default: - return expr; - } - } - return expr; -} - -/* Parse expression list. - - gimple-expr-list: - gimple-unary-expression - gimple-expr-list , gimple-unary-expression - - */ - -static vec<tree, va_gc> * -c_parser_gimple_expr_list (c_parser *parser, vec<tree, va_gc> **p_orig_types, - vec<location_t> *locations) -{ - vec<tree, va_gc> *ret; - vec<tree, va_gc> *orig_types; - struct c_expr expr; - location_t loc = c_parser_peek_token (parser)->location; - - ret = make_tree_vector (); - if (p_orig_types == NULL) - orig_types = NULL; - else - orig_types = make_tree_vector (); - - expr = c_parser_gimple_unary_expression (parser); - vec_safe_push (ret, expr.value); - if (orig_types) - vec_safe_push (orig_types, expr.original_type); - if (locations) - locations->safe_push (loc); - while (c_parser_next_token_is (parser, CPP_COMMA)) - { - c_parser_consume_token (parser); - loc = c_parser_peek_token (parser)->location; - expr = c_parser_gimple_unary_expression (parser); - vec_safe_push (ret, expr.value); - if (orig_types) - vec_safe_push (orig_types, expr.original_type); - if (locations) - locations->safe_push (loc); - } - if (orig_types) - *p_orig_types = orig_types; - return ret; -} - -/* Parse gimple label. - - gimple-label: - identifier : - case constant-expression : - default : - -*/ - -static void -c_parser_gimple_label (c_parser *parser, gimple_seq *seq) -{ - tree name = c_parser_peek_token (parser)->value; - location_t loc1 = c_parser_peek_token (parser)->location; - gcc_assert (c_parser_next_token_is (parser, CPP_NAME)); - c_parser_consume_token (parser); - gcc_assert (c_parser_next_token_is (parser, CPP_COLON)); - c_parser_consume_token (parser); - tree label = define_label (loc1, name); - gimple_seq_add_stmt (seq, gimple_build_label (label)); - return; -} - -/* Parse gimple pass list. - - gimple-pass-list: - startwith("pass-name") - */ - -static void -c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass, - bool *startwith_p) -{ - if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - return; - - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - return; - - if (c_parser_next_token_is (parser, CPP_NAME)) - { - const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - if (! strcmp (op, "startwith")) - { - *pass = c_parser_gimple_pass_list_params (parser, pass); - if (! *pass) - return; - - *startwith_p = true; - if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) - return; - } - else - { - error_at (c_parser_peek_token (parser)->location, - "invalid operation"); - return; - } - } - else if (c_parser_next_token_is (parser, CPP_EOF)) - { - c_parser_error (parser, "expected parameters"); - return; - } - - return; -} - -/* Support function for c_parser_gimple_pass_list. */ - -static opt_pass * -c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass) -{ - opt_pass *pass_start = NULL, *new_pass; - if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - return NULL; - - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - return NULL; - - while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) - { - if (c_parser_next_token_is (parser, CPP_EOF)) - { - error_at (c_parser_peek_token (parser)->location, - "expected pass names"); - return NULL; - } - - if (c_parser_next_token_is (parser, CPP_STRING)) - { - const char *name = NULL; - name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - new_pass = g->get_passes ()->get_pass_by_name (name); - - if (! new_pass) - { - error_at (c_parser_peek_token (parser)->location, - "invalid pass name"); - parser->error = true; - c_parser_consume_token (parser); - return NULL; - } - if (*pass) - { - (*pass)->next = new_pass; - (*pass) = (*pass)->next; - } - else - { - *pass = new_pass; - pass_start = *pass; - } - } - else if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); - else - { - error_at (c_parser_peek_token (parser)->location, - "invalid pass name"); - c_parser_consume_token (parser); - return NULL; - } - } - return pass_start; -} - -/* Parse gimple local declaration. - - declaration-specifiers: - storage-class-specifier declaration-specifiers[opt] - type-specifier declaration-specifiers[opt] - type-qualifier declaration-specifiers[opt] - function-specifier declaration-specifiers[opt] - alignment-specifier declaration-specifiers[opt] - - storage-class-specifier: - typedef - extern - static - auto - register - - type-specifier: - void - char - short - int - long - float - double - signed - unsigned - _Bool - _Complex - - type-qualifier: - const - restrict - volatile - address-space-qualifier - _Atomic - - */ - -static void -c_parser_gimple_declaration (c_parser *parser) -{ - struct c_declarator *declarator; - struct c_declspecs *specs = build_null_declspecs (); - c_parser_declspecs (parser, specs, true, true, true, - true, true, cla_nonabstract_decl); - finish_declspecs (specs); - - /* Provide better error recovery. Note that a type name here is usually - better diagnosed as a redeclaration. */ - if (c_parser_next_token_starts_declspecs (parser) - && ! c_parser_next_token_is (parser, CPP_NAME)) - { - c_parser_error (parser, "expected %<;%>"); - parser->error = false; - return; - } - - bool dummy = false; - declarator = c_parser_declarator (parser, - specs->typespec_kind != ctsk_none, - C_DTR_NORMAL, &dummy); - - if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - tree postfix_attrs = NULL_TREE; - tree all_prefix_attrs = specs->attrs; - specs->attrs = NULL; - tree decl = start_decl (declarator, specs, false, - chainon (postfix_attrs, all_prefix_attrs)); - if (decl) - finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE, NULL_TREE); - } - else - { - c_parser_error (parser, "expected %<;%>"); - return; - } -} - -/* Parse gimple goto statement. */ - -static void -c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq) -{ - tree decl = lookup_label_for_goto (loc, label); - gimple_seq_add_stmt (seq, gimple_build_goto (decl)); - return; -} - -/* Parse a parenthesized condition. - gimple-condition: - ( gimple-binary-expression ) */ - -static tree -c_parser_gimple_paren_condition (c_parser *parser) -{ - enum tree_code subcode = NOP_EXPR; - location_t loc = c_parser_peek_token (parser)->location; - if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - return error_mark_node; - tree cond = c_parser_gimple_binary_expression (parser, &subcode).value; - cond = c_objc_common_truthvalue_conversion (loc, cond); - if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) - return error_mark_node; - return cond; -} - -/* Parse gimple if-else statement. - - if-statement: - if ( gimple-binary-expression ) gimple-goto-statement - if ( gimple-binary-expression ) gimple-goto-statement \ - else gimple-goto-statement - */ - -static void -c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq) -{ - tree t_label, f_label, label; - location_t loc; - c_parser_consume_token (parser); - tree cond = c_parser_gimple_paren_condition (parser); - - if (c_parser_next_token_is_keyword (parser, RID_GOTO)) - { - loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - label = c_parser_peek_token (parser)->value; - t_label = lookup_label_for_goto (loc, label); - c_parser_consume_token (parser); - if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) - return; - } - else - { - c_parser_error (parser, "expected goto expression"); - return; - } - - if (c_parser_next_token_is_keyword (parser, RID_ELSE)) - c_parser_consume_token (parser); - else - { - c_parser_error (parser, "expected else statement"); - return; - } - - if (c_parser_next_token_is_keyword (parser, RID_GOTO)) - { - loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - label = c_parser_peek_token (parser)->value; - f_label = lookup_label_for_goto (loc, label); - c_parser_consume_token (parser); - if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) - return; - } - else - { - c_parser_error (parser, "expected goto expression"); - return; - } - - gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label, - f_label)); -} - -/* Parse gimple switch-statement. - - gimple-switch-statement: - switch (gimple-unary-expression) gimple-case-statement - - gimple-case-statement: - gimple-case-statement - gimple-label-statement : gimple-goto-statment -*/ - -static void -c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq) -{ - c_expr cond_expr; - tree case_label, label; - auto_vec<tree> labels; - tree default_label = NULL_TREE; - gimple_seq switch_body = NULL; - location_t loc; - c_parser_consume_token (parser); - - if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - cond_expr = c_parser_gimple_unary_expression (parser); - if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) - return; - } - - if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) - { - while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) - { - if (c_parser_next_token_is (parser, CPP_EOF)) - { - c_parser_error (parser, "expected statement"); - return; - } - - switch (c_parser_peek_token (parser)->keyword) - { - case RID_CASE: - { - c_expr exp1; - loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - - if (c_parser_next_token_is (parser, CPP_NAME) - || c_parser_peek_token (parser)->type == CPP_NUMBER) - exp1 = c_parser_gimple_unary_expression (parser); - else - c_parser_error (parser, "expected expression"); - - if (c_parser_next_token_is (parser, CPP_COLON)) - { - c_parser_consume_token (parser); - label = create_artificial_label (loc); - case_label = build_case_label (exp1.value, NULL_TREE, - label); - labels.safe_push (case_label); - gimple_seq_add_stmt (&switch_body, - gimple_build_label - (CASE_LABEL (case_label))); - } - else if (! c_parser_require (parser, CPP_SEMICOLON, - "expected %<:%>")) - return; - break; - } - case RID_DEFAULT: - { - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_COLON)) - { - c_parser_consume_token (parser); - default_label = build_case_label (NULL_TREE, NULL_TREE, - create_artificial_label - (UNKNOWN_LOCATION)); - gimple_seq_add_stmt (&switch_body, - gimple_build_label - (CASE_LABEL (default_label))); - } - else if (! c_parser_require (parser, CPP_SEMICOLON, - "expected %<:%>")) - return; - break; - } - case RID_GOTO: - { - loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_NAME)) - { - c_parser_gimple_goto_stmt (loc, - c_parser_peek_token - (parser)->value, - &switch_body); - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - c_parser_consume_token (parser); - else - { - c_parser_error (parser, "expected semicolon"); - return; - } - } - else if (! c_parser_require (parser, CPP_NAME, - "expected label")) - return; - break; - } - default: - c_parser_error (parser, "expected case label or goto statement"); - return; - } - - } - } - if (! c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>")) - return; - gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value, - default_label, labels)); - gimple_seq_add_seq (seq, switch_body); - labels.release(); -} - -/* Parse gimple return statement. */ - -static void -c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq) -{ - location_t loc = c_parser_peek_token (parser)->location; - gimple *ret = NULL; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - c_finish_gimple_return (loc, NULL_TREE); - ret = gimple_build_return (NULL); - gimple_seq_add_stmt (seq, ret); - } - else - { - location_t xloc = c_parser_peek_token (parser)->location; - c_expr expr = c_parser_gimple_unary_expression (parser); - c_finish_gimple_return (xloc, expr.value); - ret = gimple_build_return (expr.value); - gimple_seq_add_stmt (seq, ret); - } -} - -/* Support function for c_parser_gimple_return_stmt. */ - -static void -c_finish_gimple_return (location_t loc, tree retval) -{ - tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); - - /* Use the expansion point to handle cases such as returning NULL - in a function returning void. */ - source_location xloc = expansion_point_location_if_in_system_header (loc); - - if (TREE_THIS_VOLATILE (current_function_decl)) - warning_at (xloc, 0, - "function declared %<noreturn%> has a %<return%> statement"); - - if (! retval) - current_function_returns_null = 1; - else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE) - { - current_function_returns_null = 1; - if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) - { - error_at - (xloc, "%<return%> with a value, in function returning void"); - inform (DECL_SOURCE_LOCATION (current_function_decl), - "declared here"); - } - } - else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval))) - { - error_at - (xloc, "invalid conversion in return statement"); - inform (DECL_SOURCE_LOCATION (current_function_decl), - "declared here"); - } - return; -} - #include "gt-c-c-parser.h" diff --git a/gcc/c/c-parser.h b/gcc/c/c-parser.h new file mode 100644 index 0000000..d178254 --- /dev/null +++ b/gcc/c/c-parser.h @@ -0,0 +1,230 @@ +/* Declarations for the parser for C and Objective-C. + Copyright (C) 1987-2016 Free Software Foundation, Inc. + + Parser actions based on the old Bison parser; structure somewhat + influenced by and fragments based on the C++ parser. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_C_PARSER_H +#define GCC_C_PARSER_H + +/* The C lexer intermediates between the lexer in cpplib and c-lex.c + and the C parser. Unlike the C++ lexer, the parser structure + stores the lexer information instead of using a separate structure. + Identifiers are separated into ordinary identifiers, type names, + keywords and some other Objective-C types of identifiers, and some + look-ahead is maintained. + + ??? It might be a good idea to lex the whole file up front (as for + C++). It would then be possible to share more of the C and C++ + lexer code, if desired. */ + +/* More information about the type of a CPP_NAME token. */ +enum c_id_kind { + /* An ordinary identifier. */ + C_ID_ID, + /* An identifier declared as a typedef name. */ + C_ID_TYPENAME, + /* An identifier declared as an Objective-C class name. */ + C_ID_CLASSNAME, + /* An address space identifier. */ + C_ID_ADDRSPACE, + /* Not an identifier. */ + C_ID_NONE +}; + +/* A single C token after string literal concatenation and conversion + of preprocessing tokens to tokens. */ +typedef struct GTY (()) c_token { + /* The kind of token. */ + ENUM_BITFIELD (cpp_ttype) type : 8; + /* If this token is a CPP_NAME, this value indicates whether also + declared as some kind of type. Otherwise, it is C_ID_NONE. */ + ENUM_BITFIELD (c_id_kind) id_kind : 8; + /* If this token is a keyword, this value indicates which keyword. + Otherwise, this value is RID_MAX. */ + ENUM_BITFIELD (rid) keyword : 8; + /* If this token is a CPP_PRAGMA, this indicates the pragma that + was seen. Otherwise it is PRAGMA_NONE. */ + ENUM_BITFIELD (pragma_kind) pragma_kind : 8; + /* The location at which this token was found. */ + location_t location; + /* The value associated with this token, if any. */ + tree value; + /* Token flags. */ + unsigned char flags; + + source_range get_range () const + { + return get_range_from_loc (line_table, location); + } + + location_t get_finish () const + { + return get_range ().m_finish; + } +} c_token_; + +/* A parser structure recording information about the state and + context of parsing. Includes lexer information with up to two + tokens of look-ahead; more are not needed for C. */ +struct GTY(()) c_parser { + /* The look-ahead tokens. */ + struct c_token * GTY((skip)) tokens; + /* Buffer for look-ahead tokens. */ + struct c_token GTY(()) tokens_buf[4]; + /* How many look-ahead tokens are available (0 - 4, or + more if parsing from pre-lexed tokens). */ + unsigned int tokens_avail; + /* True if a syntax error is being recovered from; false otherwise. + c_parser_error sets this flag. It should clear this flag when + enough tokens have been consumed to recover from the error. */ + BOOL_BITFIELD error : 1; + /* True if we're processing a pragma, and shouldn't automatically + consume CPP_PRAGMA_EOL. */ + BOOL_BITFIELD in_pragma : 1; + /* True if we're parsing the outermost block of an if statement. */ + BOOL_BITFIELD in_if_block : 1; + /* True if we want to lex an untranslated string. */ + BOOL_BITFIELD lex_untranslated_string : 1; + + /* Objective-C specific parser/lexer information. */ + + /* True if we are in a context where the Objective-C "PQ" keywords + are considered keywords. */ + BOOL_BITFIELD objc_pq_context : 1; + /* True if we are parsing a (potential) Objective-C foreach + statement. This is set to true after we parsed 'for (' and while + we wait for 'in' or ';' to decide if it's a standard C for loop or an + Objective-C foreach loop. */ + BOOL_BITFIELD objc_could_be_foreach_context : 1; + /* The following flag is needed to contextualize Objective-C lexical + analysis. In some cases (e.g., 'int NSObject;'), it is + undesirable to bind an identifier to an Objective-C class, even + if a class with that name exists. */ + BOOL_BITFIELD objc_need_raw_identifier : 1; + /* Nonzero if we're processing a __transaction statement. The value + is 1 | TM_STMT_ATTR_*. */ + unsigned int in_transaction : 4; + /* True if we are in a context where the Objective-C "Property attribute" + keywords are valid. */ + BOOL_BITFIELD objc_property_attr_context : 1; + + /* Cilk Plus specific parser/lexer information. */ + + /* Buffer to hold all the tokens from parsing the vector attribute for the + SIMD-enabled functions (formerly known as elemental functions). */ + vec <c_token_, va_gc> *cilk_simd_fn_tokens; +}; + +/* Possibly kinds of declarator to parse. */ +enum c_dtr_syn { + /* A normal declarator with an identifier. */ + C_DTR_NORMAL, + /* An abstract declarator (maybe empty). */ + C_DTR_ABSTRACT, + /* A parameter declarator: may be either, but after a type name does + not redeclare a typedef name as an identifier if it can + alternatively be interpreted as a typedef name; see DR#009, + applied in C90 TC1, omitted from C99 and reapplied in C99 TC2 + following DR#249. For example, given a typedef T, "int T" and + "int *T" are valid parameter declarations redeclaring T, while + "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are + abstract declarators rather than involving redundant parentheses; + the same applies with attributes inside the parentheses before + "T". */ + C_DTR_PARM +}; + +/* The binary operation precedence levels, where 0 is a dummy lowest level + used for the bottom of the stack. */ +enum c_parser_prec { + PREC_NONE, + PREC_LOGOR, + PREC_LOGAND, + PREC_BITOR, + PREC_BITXOR, + PREC_BITAND, + PREC_EQ, + PREC_REL, + PREC_SHIFT, + PREC_ADD, + PREC_MULT, + NUM_PRECS +}; + +enum c_lookahead_kind { + /* Always treat unknown identifiers as typenames. */ + cla_prefer_type, + + /* Could be parsing a nonabstract declarator. Only treat an identifier + as a typename if followed by another identifier or a star. */ + cla_nonabstract_decl, + + /* Never treat identifiers as typenames. */ + cla_prefer_id +}; + + +extern c_token * c_parser_peek_token (c_parser *parser); +extern bool c_parser_require (c_parser *parser, enum cpp_ttype type, + const char *msgid); +extern void c_parser_error (c_parser *parser, const char *gmsgid); +extern void c_parser_consume_token (c_parser *parser); +extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type, + const char *msgid); +extern bool c_parser_next_token_starts_declspecs (c_parser *parser); +extern c_token * c_parser_peek_2nd_token (c_parser *parser); +bool c_parser_next_tokens_start_declaration (c_parser *parser); +bool c_token_starts_typename (c_token *token); + +/* Return true if the next token from PARSER has the indicated + TYPE. */ + +static inline bool +c_parser_next_token_is (c_parser *parser, enum cpp_ttype type) +{ + return c_parser_peek_token (parser)->type == type; +} + +/* Return true if the next token from PARSER does not have the + indicated TYPE. */ + +static inline bool +c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type) +{ + return !c_parser_next_token_is (parser, type); +} + +/* Return true if the next token from PARSER is the indicated + KEYWORD. */ + +static inline bool +c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword) +{ + return c_parser_peek_token (parser)->keyword == keyword; +} + +extern struct c_declarator * +c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, + bool *seen_id); +extern void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool, + bool, bool, bool, enum c_lookahead_kind); +extern struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *); + +#endif diff --git a/gcc/c/config-lang.in b/gcc/c/config-lang.in index b9cdc8e..51fbb53 100644 --- a/gcc/c/config-lang.in +++ b/gcc/c/config-lang.in @@ -29,4 +29,4 @@ compilers="cc1\$(exeext)" target_libs= -gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h" +gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h" diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c new file mode 100644 index 0000000..30e8d88 --- /dev/null +++ b/gcc/c/gimple-parser.c @@ -0,0 +1,1385 @@ +/* Parser for GIMPLE. + Copyright (C) 2016 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "target.h" +#include "function.h" +#include "c-tree.h" +#include "timevar.h" +#include "stringpool.h" +#include "cgraph.h" +#include "attribs.h" +#include "stor-layout.h" +#include "varasm.h" +#include "trans-mem.h" +#include "c-family/c-pragma.h" +#include "c-lang.h" +#include "c-family/c-objc.h" +#include "plugin.h" +#include "omp-low.h" +#include "builtins.h" +#include "gomp-constants.h" +#include "c-family/c-indentation.h" +#include "gimple-expr.h" +#include "context.h" +#include "gcc-rich-location.h" +#include "c-parser.h" +#include "tree-vrp.h" +#include "tree-pass.h" +#include "tree-pretty-print.h" +#include "tree.h" +#include "basic-block.h" +#include "gimple.h" +#include "gimple-pretty-print.h" +#include "tree-ssa.h" +#include "pass_manager.h" +#include "tree-ssanames.h" +#include "gimple-ssa.h" +#include "tree-dfa.h" + + +/* Gimple parsing functions. */ +static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *); +static void c_parser_gimple_label (c_parser *, gimple_seq *); +static void c_parser_gimple_expression (c_parser *, gimple_seq *); +static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *); +static struct c_expr c_parser_gimple_unary_expression (c_parser *); +static struct c_expr c_parser_gimple_postfix_expression (c_parser *); +static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *, + location_t, + struct c_expr); +static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **); +static void c_parser_gimple_declaration (c_parser *); +static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *); +static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *); +static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *); +static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *); +static void c_finish_gimple_return (location_t, tree); +static c_expr c_parser_parse_ssa_names (c_parser *); +static tree c_parser_gimple_paren_condition (c_parser *); +static vec<tree, va_gc> *c_parser_gimple_expr_list (c_parser *, + vec<tree, va_gc> **, vec<location_t> *); + + +/* Parse the body of a function declaration marked with "__GIMPLE". */ + +void +c_parser_parse_gimple_body (c_parser *parser) +{ + gimple_seq seq = NULL; + gimple_seq body = NULL; + tree stmt = push_stmt_list (); + push_scope (); + location_t loc1 = c_parser_peek_token (parser)->location; + + init_tree_ssa (cfun); + + if (! c_parser_gimple_compound_statement (parser, &seq)) + { + gimple *ret = gimple_build_return (NULL); + gimple_seq_add_stmt (&seq, ret); + } + + tree block = pop_scope (); + stmt = pop_stmt_list (stmt); + stmt = c_build_bind_expr (loc1, block, stmt); + + block = DECL_INITIAL (current_function_decl); + BLOCK_SUBBLOCKS (block) = NULL_TREE; + BLOCK_CHAIN (block) = NULL_TREE; + TREE_ASM_WRITTEN (block) = 1; + + gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL, + BIND_EXPR_BLOCK (stmt)); + gimple_bind_set_body (bind_stmt, seq); + gimple_seq_add_stmt (&body, bind_stmt); + gimple_set_body (current_function_decl, body); + cfun->curr_properties = PROP_gimple_any; + + return; +} + +/* Parse a compound statement in gimple function body. + + gimple-statement: + gimple-statement + gimple-declaration-statement + gimple-if-statement + gimple-switch-statement + gimple-labeled-statement + gimple-expression-statement + gimple-goto-statement + gimple-phi-statement + gimple-return-statement +*/ + +static bool +c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq) +{ + bool return_p = false; + + if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) + return false; + + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + c_parser_consume_token (parser); + return false; + } + + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + c_parser_error (parser, "expected declaration or statement"); + c_parser_consume_token (parser); + return false; + } + + while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) + { + if (parser->error) + { + c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); + return return_p; + } + + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON) + c_parser_gimple_label (parser, seq); + + else if (c_parser_next_tokens_start_declaration (parser)) + c_parser_gimple_declaration (parser); + + else if (c_parser_next_token_is (parser, CPP_EOF)) + { + c_parser_error (parser, "expected declaration or statement"); + return return_p; + } + + else + { + switch (c_parser_peek_token (parser)->type) + { + case CPP_KEYWORD: + switch (c_parser_peek_token (parser)->keyword) + { + case RID_IF: + c_parser_gimple_if_stmt (parser, seq); + break; + case RID_SWITCH: + c_parser_gimple_switch_stmt (parser, seq); + break; + case RID_GOTO: + { + location_t loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + c_parser_gimple_goto_stmt (loc, + c_parser_peek_token + (parser)->value, + seq); + c_parser_consume_token (parser); + if (! c_parser_require (parser, CPP_SEMICOLON, + "expected %<;%>")) + return return_p; + } + } + break; + case RID_RETURN: + return_p = true; + c_parser_gimple_return_stmt (parser, seq); + if (! c_parser_require (parser, CPP_SEMICOLON, + "expected %<;%>")) + return return_p; + break; + default: + goto expr_stmt; + } + break; + case CPP_SEMICOLON: + c_parser_consume_token (parser); + break; + default: + expr_stmt: + c_parser_gimple_expression (parser, seq); + if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) + return return_p; + } + } + } + c_parser_consume_token (parser); + return return_p; +} + +/* Parse a gimple expression. + + gimple-expression: + gimple-unary-expression + gimple-call-statement + gimple-binary-expression + gimple-assign-expression + gimple-cast-expression + +*/ + +static void +c_parser_gimple_expression (c_parser *parser, gimple_seq *seq) +{ + struct c_expr lhs, rhs; + gimple *assign = NULL; + enum tree_code subcode = NOP_EXPR; + location_t loc; + tree arg = NULL_TREE; + auto_vec<tree> vargs; + + lhs = c_parser_gimple_unary_expression (parser); + rhs.value = error_mark_node; + + if (c_parser_next_token_is (parser, CPP_EQ)) + c_parser_consume_token (parser); + + loc = EXPR_LOCATION (lhs.value); + + /* GIMPLE call expression. */ + if (c_parser_next_token_is (parser, CPP_SEMICOLON) + && TREE_CODE (lhs.value) == CALL_EXPR) + { + gimple *call; + call = gimple_build_call_from_tree (lhs.value); + gimple_seq_add_stmt (seq, call); + gimple_set_location (call, loc); + return; + } + + /* Cast expression. */ + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) + && c_token_starts_typename (c_parser_peek_2nd_token (parser))) + { + /* TODO: have a gimple_cast_expr function. */ + rhs = c_parser_cast_expression (parser, NULL); + if (lhs.value != error_mark_node && + rhs.value != error_mark_node) + { + assign = gimple_build_assign (lhs.value, rhs.value); + gimple_seq_add_stmt (seq, assign); + gimple_set_location (assign, loc); + return; + } + } + + if (POINTER_TYPE_P (TREE_TYPE (lhs.value))) + { + STRIP_USELESS_TYPE_CONVERSION (rhs.value); + if (! useless_type_conversion_p (TREE_TYPE (lhs.value), + TREE_TYPE (rhs.value))) + rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value); + } + + /* Pointer expression. */ + if (TREE_CODE (lhs.value) == INDIRECT_REF) + { + tree save_expr = lhs.value; + bool volatilep = TREE_THIS_VOLATILE (lhs.value); + bool notrap = TREE_THIS_NOTRAP (lhs.value); + tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0)); + + lhs.value = fold_indirect_ref_loc (loc, lhs.value); + if (lhs.value == save_expr) + { + lhs.value = fold_build2_loc (input_location, MEM_REF, + TREE_TYPE (lhs.value), + TREE_OPERAND (lhs.value, 0), + build_int_cst (saved_ptr_type, 0)); + TREE_THIS_VOLATILE (lhs.value) = volatilep; + TREE_THIS_NOTRAP (lhs.value) = notrap; + } + } + + if (c_parser_next_token_is (parser, CPP_AND) + || c_parser_next_token_is (parser, CPP_MULT) + || c_parser_next_token_is (parser, CPP_PLUS) + || c_parser_next_token_is (parser, CPP_MINUS) + || c_parser_next_token_is (parser, CPP_COMPL) + || c_parser_next_token_is (parser, CPP_NOT)) + { + rhs = c_parser_gimple_unary_expression (parser); + assign = gimple_build_assign (lhs.value, rhs.value); + gimple_set_location (assign, loc); + gimple_seq_add_stmt (seq, assign); + return; + } + + /* GIMPLE PHI expression. */ + if (c_parser_next_token_is_keyword (parser, RID_PHI)) + { + c_parser_consume_token (parser); + + if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return; + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + c_parser_consume_token (parser); + + while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) + { + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON) + { + arg = lookup_label_for_goto (loc, + c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + + if (c_parser_next_token_is (parser, CPP_COLON)) + c_parser_consume_token (parser); + vargs.safe_push (arg); + } + else if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + { + arg = c_parser_parse_ssa_names (parser).value; + vargs.safe_push (arg); + } + } + + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + + /* Build internal function for PHI. */ + gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs); + gimple_call_set_lhs (call_stmt, lhs.value); + gimple_set_location (call_stmt, UNKNOWN_LOCATION); + gimple_seq_add_stmt (seq, call_stmt); + return; + } + + /* GIMPLE call with lhs. */ + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN + && lookup_name (c_parser_peek_token (parser)->value)) + { + rhs = c_parser_gimple_unary_expression (parser); + gimple *call = gimple_build_call_from_tree (rhs.value); + gimple_call_set_lhs (call, lhs.value); + gimple_seq_add_stmt (seq, call); + gimple_set_location (call, loc); + return; + } + + rhs = c_parser_gimple_binary_expression (parser, &subcode); + + if (lhs.value != error_mark_node + && rhs.value != error_mark_node) + { + if (subcode == NOP_EXPR) + assign = gimple_build_assign (lhs.value, rhs.value); + else + assign = gimple_build_assign (lhs.value, subcode, + TREE_OPERAND (rhs.value, 0), + TREE_OPERAND (rhs.value, 1)); + gimple_seq_add_stmt (seq, assign); + gimple_set_location (assign, loc); + } + return; +} + +/* Parse gimple binary expr. + + gimple-multiplicative-expression: + gimple-unary-expression * gimple-unary-expression + gimple-unary-expression / gimple-unary-expression + gimple-unary-expression % gimple-unary-expression + + gimple-additive-expression: + gimple-unary-expression + gimple-unary-expression + gimple-unary-expression - gimple-unary-expression + + gimple-shift-expression: + gimple-unary-expression << gimple-unary-expression + gimple-unary-expression >> gimple-unary-expression + + gimple-relational-expression: + gimple-unary-expression < gimple-unary-expression + gimple-unary-expression > gimple-unary-expression + gimple-unary-expression <= gimple-unary-expression + gimple-unary-expression >= gimple-unary-expression + + gimple-equality-expression: + gimple-unary-expression == gimple-unary-expression + gimple-unary-expression != gimple-unary-expression + + gimple-AND-expression: + gimple-unary-expression & gimple-unary-expression + + gimple-exclusive-OR-expression: + gimple-unary-expression ^ gimple-unary-expression + + gimple-inclusive-OR-expression: + gimple-unary-expression | gimple-unary-expression + + gimple-logical-AND-expression: + gimple-unary-expression && gimple-unary-expression + + gimple-logical-OR-expression: + gimple-unary-expression || gimple-unary-expression + +*/ + +static c_expr +c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode) +{ + struct { + /* The expression at this stack level. */ + struct c_expr expr; + /* The operation on its left. */ + enum tree_code op; + /* The source location of this operation. */ + location_t loc; + } stack[2]; + int sp; + /* Location of the binary operator. */ + location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */ +#define POP \ + do { \ + if (sp == 1 \ + && c_parser_peek_token (parser)->type == CPP_SEMICOLON \ + && (((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \ + | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \ + && stack[sp].op != TRUNC_MOD_EXPR \ + && stack[0].expr.value != error_mark_node \ + && stack[1].expr.value != error_mark_node) \ + stack[0].expr.value \ + = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \ + stack[0].expr.value, stack[1].expr.value); \ + else \ + stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ + stack[sp].op, \ + stack[sp - 1].expr, \ + stack[sp].expr); \ + sp--; \ + } while (0) + stack[0].loc = c_parser_peek_token (parser)->location; + stack[0].expr = c_parser_gimple_unary_expression (parser); + sp = 0; + source_range src_range; + if (parser->error) + goto out; + switch (c_parser_peek_token (parser)->type) + { + case CPP_MULT: + *subcode = MULT_EXPR; + break; + case CPP_DIV: + *subcode = TRUNC_DIV_EXPR; + break; + case CPP_MOD: + *subcode = TRUNC_MOD_EXPR; + break; + case CPP_PLUS: + *subcode = PLUS_EXPR; + break; + case CPP_MINUS: + *subcode = MINUS_EXPR; + break; + case CPP_LSHIFT: + *subcode = LSHIFT_EXPR; + break; + case CPP_RSHIFT: + *subcode = RSHIFT_EXPR; + break; + case CPP_LESS: + *subcode = LT_EXPR; + break; + case CPP_GREATER: + *subcode = GT_EXPR; + break; + case CPP_LESS_EQ: + *subcode = LE_EXPR; + break; + case CPP_GREATER_EQ: + *subcode = GE_EXPR; + break; + case CPP_EQ_EQ: + *subcode = EQ_EXPR; + break; + case CPP_NOT_EQ: + *subcode = NE_EXPR; + break; + case CPP_AND: + *subcode = BIT_AND_EXPR; + break; + case CPP_XOR: + *subcode = BIT_XOR_EXPR; + break; + case CPP_OR: + *subcode = BIT_IOR_EXPR; + break; + case CPP_AND_AND: + *subcode = TRUTH_ANDIF_EXPR; + break; + case CPP_OR_OR: + *subcode = TRUTH_ORIF_EXPR; + break; + default: + /* Not a binary operator, so end of the binary expression. */ + *subcode = NOP_EXPR; + goto out; + } + binary_loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + switch (*subcode) + { + case TRUTH_ANDIF_EXPR: + src_range = stack[sp].expr.src_range; + stack[sp].expr.value = c_objc_common_truthvalue_conversion + (stack[sp].loc, default_conversion (stack[sp].expr.value)); + set_c_expr_source_range (&stack[sp].expr, src_range); + break; + case TRUTH_ORIF_EXPR: + src_range = stack[sp].expr.src_range; + stack[sp].expr.value = c_objc_common_truthvalue_conversion + (stack[sp].loc, default_conversion (stack[sp].expr.value)); + set_c_expr_source_range (&stack[sp].expr, src_range); + break; + default: + break; + } + sp++; + stack[sp].loc = binary_loc; + stack[sp].expr = c_parser_gimple_unary_expression (parser); + stack[sp].op = *subcode; +out: + while (sp > 0) + POP; + return stack[0].expr; +#undef POP +} + +/* Parse gimple unary expression. + + gimple-unary-expression: + gimple-postfix-expression + unary-operator cast-expression + + unary-operator: one of + & * + - ~ ! +*/ + +static c_expr +c_parser_gimple_unary_expression (c_parser *parser) +{ + struct c_expr ret, op; + if (c_parser_peek_token (parser)->value + && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE + && ! lookup_name (c_parser_peek_token (parser)->value)) + return c_parser_parse_ssa_names (parser); + + location_t op_loc = c_parser_peek_token (parser)->location; + location_t finish; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; + switch (c_parser_peek_token (parser)->type) + { + case CPP_AND: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + mark_exp_read (op.value); + return parser_build_unary_op (op_loc, ADDR_EXPR, op); + case CPP_MULT: + { + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + finish = op.get_finish (); + location_t combined_loc = make_location (op_loc, op_loc, finish); + ret.value = build_indirect_ref (combined_loc, op.value, + RO_UNARY_STAR); + ret.src_range.m_start = op_loc; + ret.src_range.m_finish = finish; + return ret; + } + case CPP_PLUS: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + return parser_build_unary_op (op_loc, CONVERT_EXPR, op); + case CPP_MINUS: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + return parser_build_unary_op (op_loc, NEGATE_EXPR, op); + case CPP_COMPL: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op); + case CPP_NOT: + c_parser_consume_token (parser); + op = c_parser_cast_expression (parser, NULL); + return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op); + default: + return c_parser_gimple_postfix_expression (parser); + } +} + +/* Parse gimple ssa names. */ + +static c_expr +c_parser_parse_ssa_names (c_parser *parser) +{ + tree id = NULL_TREE; + c_expr ret; + char *var_name = NULL, *var_version = NULL, *token = NULL; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; + + /* SSA token string. */ + const char *ssa_token + = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + token = new char [strlen (ssa_token) + 1]; + strcpy (token, ssa_token); + + /* Separate var name and version. */ + var_version = strrchr (token, '_'); + if (var_version) + { + var_name = new char[var_version - token + 1]; + memcpy (var_name, token, var_version - token); + var_name[var_version - token] = '\0'; + id = get_identifier (var_name); + + /* lookup for parent decl. */ + if (lookup_name (id)) + { + var_version++; + unsigned int version; + version = atoi (var_version); + if (var_version && version) + { + ret.value = NULL_TREE; + if (version < num_ssa_names) + ret.value = ssa_name (version); + if (! ret.value) + ret.value = make_ssa_name_fn (cfun, lookup_name (id), + gimple_build_nop (), version); + c_parser_consume_token (parser); + } + } + } + + /* For default definition SSA names. */ + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + c_parser_consume_token (parser); + ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (! strcmp ("D", ssa_token)) + { + set_ssa_default_def (cfun, lookup_name (id), ret.value); + c_parser_consume_token (parser); + } + if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + goto out; + } + + out: + free (var_name); + free (token); + return ret; +} + +/* Parse gimple postfix expression. + + gimple-postfix-expression: + gimple-primary-expression + gimple-primary-xpression [ gimple-primary-expression ] + gimple-primary-expression ( gimple-argument-expression-list[opt] ) + + gimple-argument-expression-list: + gimple-unary-expression + gimple-argument-expression-list , gimple-unary-expression + + gimple-primary-expression: + identifier + constant + string-literal + +*/ + +static struct c_expr +c_parser_gimple_postfix_expression (c_parser *parser) +{ + struct c_expr expr; + location_t loc = c_parser_peek_token (parser)->location; + source_range tok_range = c_parser_peek_token (parser)->get_range (); + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + switch (c_parser_peek_token (parser)->type) + { + case CPP_NUMBER: + expr.value = c_parser_peek_token (parser)->value; + set_c_expr_source_range (&expr, tok_range); + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + break; + case CPP_CHAR: + case CPP_CHAR16: + case CPP_CHAR32: + case CPP_WCHAR: + expr.value = c_parser_peek_token (parser)->value; + set_c_expr_source_range (&expr, tok_range); + c_parser_consume_token (parser); + break; + case CPP_STRING: + case CPP_STRING16: + case CPP_STRING32: + case CPP_WSTRING: + case CPP_UTF8STRING: + expr.value = c_parser_peek_token (parser)->value; + set_c_expr_source_range (&expr, tok_range); + expr.original_code = STRING_CST; + c_parser_consume_token (parser); + break; + case CPP_NAME: + if (c_parser_peek_token (parser)->id_kind == C_ID_ID) + { + tree id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + expr.value = build_external_ref (loc, id, + (c_parser_peek_token (parser)->type + == CPP_OPEN_PAREN), + &expr.original_type); + set_c_expr_source_range (&expr, tok_range); + break; + } + else + { + c_parser_error (parser, "expected expression"); + expr.set_error (); + break; + } + break; + default: + c_parser_error (parser, "expected expression"); + expr.set_error (); + break; + } + return c_parser_gimple_postfix_expression_after_primary + (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr); +} + +/* Parse a gimple postfix expression after the initial primary or compound + literal. */ + +static struct c_expr +c_parser_gimple_postfix_expression_after_primary (c_parser *parser, + location_t expr_loc, + struct c_expr expr) +{ + struct c_expr orig_expr; + vec<tree, va_gc> *exprlist; + vec<tree, va_gc> *origtypes = NULL; + vec<location_t> arg_loc = vNULL; + location_t start; + location_t finish; + + location_t op_loc = c_parser_peek_token (parser)->location; + + switch (c_parser_peek_token (parser)->type) + { + case CPP_OPEN_SQUARE: + { + c_parser_consume_token (parser); + tree idx = c_parser_gimple_unary_expression (parser).value; + + if (! c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>")) + break; + + start = expr.get_start (); + finish = parser->tokens_buf[0].location; + expr.value = build_array_ref (op_loc, expr.value, idx); + set_c_expr_source_range (&expr, start, finish); + + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + break; + } + case CPP_OPEN_PAREN: + { + /* Function call. */ + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + exprlist = NULL; + else + exprlist = c_parser_gimple_expr_list (parser, &origtypes, + &arg_loc); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + orig_expr = expr; + start = expr.get_start (); + finish = parser->tokens_buf[0].get_finish (); + expr.value = c_build_function_call_vec (expr_loc, arg_loc, expr.value, + exprlist, origtypes); + set_c_expr_source_range (&expr, start, finish); + + expr.original_code = ERROR_MARK; + if (TREE_CODE (expr.value) == INTEGER_CST + && TREE_CODE (orig_expr.value) == FUNCTION_DECL + && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P) + expr.original_code = C_MAYBE_CONST_EXPR; + expr.original_type = NULL; + if (exprlist) + { + release_tree_vector (exprlist); + release_tree_vector (origtypes); + } + arg_loc.release (); + break; + default: + return expr; + } + } + return expr; +} + +/* Parse expression list. + + gimple-expr-list: + gimple-unary-expression + gimple-expr-list , gimple-unary-expression + + */ + +static vec<tree, va_gc> * +c_parser_gimple_expr_list (c_parser *parser, vec<tree, va_gc> **p_orig_types, + vec<location_t> *locations) +{ + vec<tree, va_gc> *ret; + vec<tree, va_gc> *orig_types; + struct c_expr expr; + location_t loc = c_parser_peek_token (parser)->location; + + ret = make_tree_vector (); + if (p_orig_types == NULL) + orig_types = NULL; + else + orig_types = make_tree_vector (); + + expr = c_parser_gimple_unary_expression (parser); + vec_safe_push (ret, expr.value); + if (orig_types) + vec_safe_push (orig_types, expr.original_type); + if (locations) + locations->safe_push (loc); + while (c_parser_next_token_is (parser, CPP_COMMA)) + { + c_parser_consume_token (parser); + loc = c_parser_peek_token (parser)->location; + expr = c_parser_gimple_unary_expression (parser); + vec_safe_push (ret, expr.value); + if (orig_types) + vec_safe_push (orig_types, expr.original_type); + if (locations) + locations->safe_push (loc); + } + if (orig_types) + *p_orig_types = orig_types; + return ret; +} + +/* Parse gimple label. + + gimple-label: + identifier : + case constant-expression : + default : + +*/ + +static void +c_parser_gimple_label (c_parser *parser, gimple_seq *seq) +{ + tree name = c_parser_peek_token (parser)->value; + location_t loc1 = c_parser_peek_token (parser)->location; + gcc_assert (c_parser_next_token_is (parser, CPP_NAME)); + c_parser_consume_token (parser); + gcc_assert (c_parser_next_token_is (parser, CPP_COLON)); + c_parser_consume_token (parser); + tree label = define_label (loc1, name); + gimple_seq_add_stmt (seq, gimple_build_label (label)); + return; +} + +/* Parse gimple pass list. + + gimple-pass-list: + startwith("pass-name") + */ + +void +c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass, + bool *startwith_p) +{ + if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return; + + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + return; + + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + if (! strcmp (op, "startwith")) + { + *pass = c_parser_gimple_pass_list_params (parser, pass); + if (! *pass) + return; + + *startwith_p = true; + if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return; + } + else + { + error_at (c_parser_peek_token (parser)->location, + "invalid operation"); + return; + } + } + else if (c_parser_next_token_is (parser, CPP_EOF)) + { + c_parser_error (parser, "expected parameters"); + return; + } + + return; +} + +/* Support function for c_parser_gimple_pass_list. */ + +static opt_pass * +c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass) +{ + opt_pass *pass_start = NULL, *new_pass; + if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return NULL; + + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + return NULL; + + while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) + { + if (c_parser_next_token_is (parser, CPP_EOF)) + { + error_at (c_parser_peek_token (parser)->location, + "expected pass names"); + return NULL; + } + + if (c_parser_next_token_is (parser, CPP_STRING)) + { + const char *name = NULL; + name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + new_pass = g->get_passes ()->get_pass_by_name (name); + + if (! new_pass) + { + error_at (c_parser_peek_token (parser)->location, + "invalid pass name"); + parser->error = true; + c_parser_consume_token (parser); + return NULL; + } + if (*pass) + { + (*pass)->next = new_pass; + (*pass) = (*pass)->next; + } + else + { + *pass = new_pass; + pass_start = *pass; + } + } + else if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + { + error_at (c_parser_peek_token (parser)->location, + "invalid pass name"); + c_parser_consume_token (parser); + return NULL; + } + } + return pass_start; +} + +/* Parse gimple local declaration. + + declaration-specifiers: + storage-class-specifier declaration-specifiers[opt] + type-specifier declaration-specifiers[opt] + type-qualifier declaration-specifiers[opt] + function-specifier declaration-specifiers[opt] + alignment-specifier declaration-specifiers[opt] + + storage-class-specifier: + typedef + extern + static + auto + register + + type-specifier: + void + char + short + int + long + float + double + signed + unsigned + _Bool + _Complex + + type-qualifier: + const + restrict + volatile + address-space-qualifier + _Atomic + + */ + +static void +c_parser_gimple_declaration (c_parser *parser) +{ + struct c_declarator *declarator; + struct c_declspecs *specs = build_null_declspecs (); + c_parser_declspecs (parser, specs, true, true, true, + true, true, cla_nonabstract_decl); + finish_declspecs (specs); + + /* Provide better error recovery. Note that a type name here is usually + better diagnosed as a redeclaration. */ + if (c_parser_next_token_starts_declspecs (parser) + && ! c_parser_next_token_is (parser, CPP_NAME)) + { + c_parser_error (parser, "expected %<;%>"); + parser->error = false; + return; + } + + bool dummy = false; + declarator = c_parser_declarator (parser, + specs->typespec_kind != ctsk_none, + C_DTR_NORMAL, &dummy); + + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + tree postfix_attrs = NULL_TREE; + tree all_prefix_attrs = specs->attrs; + specs->attrs = NULL; + tree decl = start_decl (declarator, specs, false, + chainon (postfix_attrs, all_prefix_attrs)); + if (decl) + finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE, NULL_TREE); + } + else + { + c_parser_error (parser, "expected %<;%>"); + return; + } +} + +/* Parse gimple goto statement. */ + +static void +c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq) +{ + tree decl = lookup_label_for_goto (loc, label); + gimple_seq_add_stmt (seq, gimple_build_goto (decl)); + return; +} + +/* Parse a parenthesized condition. + gimple-condition: + ( gimple-binary-expression ) */ + +static tree +c_parser_gimple_paren_condition (c_parser *parser) +{ + enum tree_code subcode = NOP_EXPR; + location_t loc = c_parser_peek_token (parser)->location; + if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return error_mark_node; + tree cond = c_parser_gimple_binary_expression (parser, &subcode).value; + cond = c_objc_common_truthvalue_conversion (loc, cond); + if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return error_mark_node; + return cond; +} + +/* Parse gimple if-else statement. + + if-statement: + if ( gimple-binary-expression ) gimple-goto-statement + if ( gimple-binary-expression ) gimple-goto-statement \ + else gimple-goto-statement + */ + +static void +c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq) +{ + tree t_label, f_label, label; + location_t loc; + c_parser_consume_token (parser); + tree cond = c_parser_gimple_paren_condition (parser); + + if (c_parser_next_token_is_keyword (parser, RID_GOTO)) + { + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + label = c_parser_peek_token (parser)->value; + t_label = lookup_label_for_goto (loc, label); + c_parser_consume_token (parser); + if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) + return; + } + else + { + c_parser_error (parser, "expected goto expression"); + return; + } + + if (c_parser_next_token_is_keyword (parser, RID_ELSE)) + c_parser_consume_token (parser); + else + { + c_parser_error (parser, "expected else statement"); + return; + } + + if (c_parser_next_token_is_keyword (parser, RID_GOTO)) + { + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + label = c_parser_peek_token (parser)->value; + f_label = lookup_label_for_goto (loc, label); + c_parser_consume_token (parser); + if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) + return; + } + else + { + c_parser_error (parser, "expected goto expression"); + return; + } + + gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label, + f_label)); +} + +/* Parse gimple switch-statement. + + gimple-switch-statement: + switch (gimple-unary-expression) gimple-case-statement + + gimple-case-statement: + gimple-case-statement + gimple-label-statement : gimple-goto-statment +*/ + +static void +c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq) +{ + c_expr cond_expr; + tree case_label, label; + auto_vec<tree> labels; + tree default_label = NULL_TREE; + gimple_seq switch_body = NULL; + location_t loc; + c_parser_consume_token (parser); + + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + cond_expr = c_parser_gimple_unary_expression (parser); + if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) + return; + } + + if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) + { + while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) + { + if (c_parser_next_token_is (parser, CPP_EOF)) + { + c_parser_error (parser, "expected statement"); + return; + } + + switch (c_parser_peek_token (parser)->keyword) + { + case RID_CASE: + { + c_expr exp1; + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + + if (c_parser_next_token_is (parser, CPP_NAME) + || c_parser_peek_token (parser)->type == CPP_NUMBER) + exp1 = c_parser_gimple_unary_expression (parser); + else + c_parser_error (parser, "expected expression"); + + if (c_parser_next_token_is (parser, CPP_COLON)) + { + c_parser_consume_token (parser); + label = create_artificial_label (loc); + case_label = build_case_label (exp1.value, NULL_TREE, + label); + labels.safe_push (case_label); + gimple_seq_add_stmt (&switch_body, + gimple_build_label + (CASE_LABEL (case_label))); + } + else if (! c_parser_require (parser, CPP_SEMICOLON, + "expected %<:%>")) + return; + break; + } + case RID_DEFAULT: + { + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_COLON)) + { + c_parser_consume_token (parser); + default_label = build_case_label (NULL_TREE, NULL_TREE, + create_artificial_label + (UNKNOWN_LOCATION)); + gimple_seq_add_stmt (&switch_body, + gimple_build_label + (CASE_LABEL (default_label))); + } + else if (! c_parser_require (parser, CPP_SEMICOLON, + "expected %<:%>")) + return; + break; + } + case RID_GOTO: + { + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + c_parser_gimple_goto_stmt (loc, + c_parser_peek_token + (parser)->value, + &switch_body); + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + c_parser_consume_token (parser); + else + { + c_parser_error (parser, "expected semicolon"); + return; + } + } + else if (! c_parser_require (parser, CPP_NAME, + "expected label")) + return; + break; + } + default: + c_parser_error (parser, "expected case label or goto statement"); + return; + } + + } + } + if (! c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>")) + return; + gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value, + default_label, labels)); + gimple_seq_add_seq (seq, switch_body); + labels.release(); +} + +/* Parse gimple return statement. */ + +static void +c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq) +{ + location_t loc = c_parser_peek_token (parser)->location; + gimple *ret = NULL; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + c_finish_gimple_return (loc, NULL_TREE); + ret = gimple_build_return (NULL); + gimple_seq_add_stmt (seq, ret); + } + else + { + location_t xloc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_gimple_unary_expression (parser); + c_finish_gimple_return (xloc, expr.value); + ret = gimple_build_return (expr.value); + gimple_seq_add_stmt (seq, ret); + } +} + +/* Support function for c_parser_gimple_return_stmt. */ + +static void +c_finish_gimple_return (location_t loc, tree retval) +{ + tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)); + + /* Use the expansion point to handle cases such as returning NULL + in a function returning void. */ + source_location xloc = expansion_point_location_if_in_system_header (loc); + + if (TREE_THIS_VOLATILE (current_function_decl)) + warning_at (xloc, 0, + "function declared %<noreturn%> has a %<return%> statement"); + + if (! retval) + current_function_returns_null = 1; + else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE) + { + current_function_returns_null = 1; + if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) + { + error_at + (xloc, "%<return%> with a value, in function returning void"); + inform (DECL_SOURCE_LOCATION (current_function_decl), + "declared here"); + } + } + else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval))) + { + error_at + (xloc, "invalid conversion in return statement"); + inform (DECL_SOURCE_LOCATION (current_function_decl), + "declared here"); + } + return; +} diff --git a/gcc/c/gimple-parser.h b/gcc/c/gimple-parser.h new file mode 100644 index 0000000..d88d9e5 --- /dev/null +++ b/gcc/c/gimple-parser.h @@ -0,0 +1,27 @@ +/* Declarations for the parser for GIMPLE. + Copyright (C) 2016 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_GIMPLE_PARSER_H +#define GCC_GIMPLE_PARSER_H + +/* Gimple parsing functions. */ +extern void c_parser_parse_gimple_body (c_parser *); +extern void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *); + +#endif diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in index f5a74a7..912af22 100644 --- a/gcc/objc/config-lang.in +++ b/gcc/objc/config-lang.in @@ -35,4 +35,4 @@ lang_requires="c" # Order is important. If you change this list, make sure you test # building without C++ as well; that is, remove the gcc/cp directory, # and build with --enable-languages=c,objc. -gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c" +gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"