Mercurial > hg > CbC > CbC_gcc
diff gcc/c-parser.c @ 57:326d9e06c2e3
modify c-parser.c
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 15 Feb 2010 00:54:17 +0900 |
parents | 9117c3b65bc3 77e2b8dfacca |
children | 5b5b9ea5b220 |
line wrap: on
line diff
--- a/gcc/c-parser.c Sun Feb 07 18:30:54 2010 +0900 +++ b/gcc/c-parser.c Mon Feb 15 00:54:17 2010 +0900 @@ -60,6 +60,8 @@ #ifndef noCbC #include "cbc-tree.h" #endif +#include "plugin.h" +#include "except.h" /* Initialization routine for this file. */ @@ -73,6 +75,10 @@ tree id; int mask = 0; + /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in + the c_token structure. */ + gcc_assert (RID_MAX <= 255); + mask |= D_CXXONLY; if (!flag_isoc99) mask |= D_C99; @@ -80,7 +86,7 @@ { mask |= D_ASM | D_EXT; if (!flag_isoc99) - mask |= D_EXT89; + mask |= D_EXT89; } if (!c_dialect_objc ()) mask |= D_OBJC | D_CXX_OBJC; @@ -89,18 +95,18 @@ for (i = 0; i < num_c_common_reswords; i++) { /* If a keyword is disabled, do not enter it into the table - and so create a canonical spelling that isn't a keyword. */ + and so create a canonical spelling that isn't a keyword. */ if (c_common_reswords[i].disable & mask) - { - if (warn_cxx_compat - && (c_common_reswords[i].disable & D_CXXWARN)) - { - id = get_identifier (c_common_reswords[i].word); - C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN); - C_IS_RESERVED_WORD (id) = 1; - } - continue; - } + { + if (warn_cxx_compat + && (c_common_reswords[i].disable & D_CXXWARN)) + { + id = get_identifier (c_common_reswords[i].word); + C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN); + C_IS_RESERVED_WORD (id) = 1; + } + continue; + } id = get_identifier (c_common_reswords[i].word); C_SET_RID_CODE (id, c_common_reswords[i].rid); @@ -133,14 +139,15 @@ 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 } c_id_kind; /* A single C token after string literal concatenation and conversion of preprocessing tokens to tokens. */ -typedef struct c_token GTY (()) -{ +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 @@ -161,8 +168,7 @@ /* 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. */ -typedef struct c_parser GTY(()) -{ +typedef struct GTY(()) c_parser { /* The look-ahead tokens. */ c_token tokens[2]; /* How many look-ahead tokens are available (0, 1 or 2). */ @@ -202,8 +208,8 @@ timevar_push (TV_LEX); token->type = c_lex_with_flags (&token->value, &token->location, NULL, - (parser->lex_untranslated_string - ? C_LEX_STRING_NO_TRANSLATE : 0)); + (parser->lex_untranslated_string + ? C_LEX_STRING_NO_TRANSLATE : 0)); token->id_kind = C_ID_NONE; token->keyword = RID_MAX; token->pragma_kind = PRAGMA_NONE; @@ -212,68 +218,75 @@ { case CPP_NAME: { - tree decl; - - bool objc_force_identifier = parser->objc_need_raw_identifier; - if (c_dialect_objc ()) - parser->objc_need_raw_identifier = false; - - if (C_IS_RESERVED_WORD (token->value)) - { - enum rid rid_code = C_RID_CODE (token->value); - - if (rid_code == RID_CXX_COMPAT_WARN) - { - warning_at (token->location, - OPT_Wc___compat, - "identifier %qs conflicts with C++ keyword", - IDENTIFIER_POINTER (token->value)); - } - else if (c_dialect_objc ()) - { - if (!objc_is_reserved_word (token->value) - && (!OBJC_IS_PQ_KEYWORD (rid_code) - || parser->objc_pq_context)) - { - /* Return the canonical spelling for this keyword. */ - token->value = ridpointers[(int) rid_code]; - token->type = CPP_KEYWORD; - token->keyword = rid_code; - break; - } - } - else - { - token->type = CPP_KEYWORD; - token->keyword = rid_code; - break; - } - } - - decl = lookup_name (token->value); - if (decl) - { - if (TREE_CODE (decl) == TYPE_DECL) - { - token->id_kind = C_ID_TYPENAME; - break; - } - } - else if (c_dialect_objc ()) - { - tree objc_interface_decl = objc_is_class_name (token->value); - /* Objective-C class names are in the same namespace as - variables and typedefs, and hence are shadowed by local - declarations. */ - if (objc_interface_decl - && (global_bindings_p () - || (!objc_force_identifier && !decl))) - { - token->value = objc_interface_decl; - token->id_kind = C_ID_CLASSNAME; - break; - } - } + tree decl; + + bool objc_force_identifier = parser->objc_need_raw_identifier; + if (c_dialect_objc ()) + parser->objc_need_raw_identifier = false; + + if (C_IS_RESERVED_WORD (token->value)) + { + enum rid rid_code = C_RID_CODE (token->value); + + if (rid_code == RID_CXX_COMPAT_WARN) + { + warning_at (token->location, + OPT_Wc___compat, + "identifier %qE conflicts with C++ keyword", + token->value); + } + else if (rid_code >= RID_FIRST_ADDR_SPACE + && rid_code <= RID_LAST_ADDR_SPACE) + { + token->id_kind = C_ID_ADDRSPACE; + token->keyword = rid_code; + break; + } + else if (c_dialect_objc ()) + { + if (!objc_is_reserved_word (token->value) + && (!OBJC_IS_PQ_KEYWORD (rid_code) + || parser->objc_pq_context)) + { + /* Return the canonical spelling for this keyword. */ + token->value = ridpointers[(int) rid_code]; + token->type = CPP_KEYWORD; + token->keyword = rid_code; + break; + } + } + else + { + token->type = CPP_KEYWORD; + token->keyword = rid_code; + break; + } + } + + decl = lookup_name (token->value); + if (decl) + { + if (TREE_CODE (decl) == TYPE_DECL) + { + token->id_kind = C_ID_TYPENAME; + break; + } + } + else if (c_dialect_objc ()) + { + tree objc_interface_decl = objc_is_class_name (token->value); + /* Objective-C class names are in the same namespace as + variables and typedefs, and hence are shadowed by local + declarations. */ + if (objc_interface_decl + && (global_bindings_p () + || (!objc_force_identifier && !decl))) + { + token->value = objc_interface_decl; + token->id_kind = C_ID_CLASSNAME; + break; + } + } token->id_kind = C_ID_ID; } break; @@ -287,9 +300,9 @@ case CPP_CLOSE_PAREN: case CPP_SEMICOLON: /* These tokens may affect the interpretation of any identifiers - following, if doing Objective-C. */ + following, if doing Objective-C. */ if (c_dialect_objc ()) - parser->objc_need_raw_identifier = false; + parser->objc_need_raw_identifier = false; break; case CPP_PRAGMA: /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */ @@ -352,52 +365,54 @@ { case CPP_NAME: switch (token->id_kind) - { - case C_ID_ID: - return false; - case C_ID_TYPENAME: - return true; - case C_ID_CLASSNAME: - gcc_assert (c_dialect_objc ()); - return true; - default: - gcc_unreachable (); - } + { + case C_ID_ID: + return false; + case C_ID_ADDRSPACE: + return true; + case C_ID_TYPENAME: + return true; + case C_ID_CLASSNAME: + gcc_assert (c_dialect_objc ()); + return true; + default: + gcc_unreachable (); + } case CPP_KEYWORD: switch (token->keyword) - { - case RID_UNSIGNED: - case RID_LONG: - case RID_SHORT: - case RID_SIGNED: - case RID_COMPLEX: - case RID_INT: - case RID_CHAR: - case RID_FLOAT: - case RID_DOUBLE: - case RID_VOID: - case RID_DFLOAT32: - case RID_DFLOAT64: - case RID_DFLOAT128: - case RID_BOOL: - case RID_ENUM: - case RID_STRUCT: - case RID_UNION: - case RID_TYPEOF: - case RID_CONST: - case RID_VOLATILE: - case RID_RESTRICT: - case RID_ATTRIBUTE: - case RID_FRACT: - case RID_ACCUM: - case RID_SAT: - return true; - default: - return false; - } + { + case RID_UNSIGNED: + case RID_LONG: + case RID_SHORT: + case RID_SIGNED: + case RID_COMPLEX: + case RID_INT: + case RID_CHAR: + case RID_FLOAT: + case RID_DOUBLE: + case RID_VOID: + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: + case RID_BOOL: + case RID_ENUM: + case RID_STRUCT: + case RID_UNION: + case RID_TYPEOF: + case RID_CONST: + case RID_VOLATILE: + case RID_RESTRICT: + case RID_ATTRIBUTE: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: + return true; + default: + return false; + } case CPP_LESS: if (c_dialect_objc ()) - return true; + return true; return false; default: return false; @@ -422,62 +437,64 @@ { case CPP_NAME: switch (token->id_kind) - { - case C_ID_ID: - return false; - case C_ID_TYPENAME: - return true; - case C_ID_CLASSNAME: - gcc_assert (c_dialect_objc ()); - return true; - default: - gcc_unreachable (); - } + { + case C_ID_ID: + return false; + case C_ID_ADDRSPACE: + return true; + case C_ID_TYPENAME: + return true; + case C_ID_CLASSNAME: + gcc_assert (c_dialect_objc ()); + return true; + default: + gcc_unreachable (); + } case CPP_KEYWORD: switch (token->keyword) - { - case RID_STATIC: - case RID_EXTERN: - case RID_REGISTER: - case RID_TYPEDEF: - case RID_INLINE: - case RID_AUTO: - case RID_THREAD: - case RID_UNSIGNED: - case RID_LONG: - case RID_SHORT: - case RID_SIGNED: - case RID_COMPLEX: - case RID_INT: - case RID_CHAR: - case RID_FLOAT: - case RID_DOUBLE: - case RID_VOID: - case RID_DFLOAT32: - case RID_DFLOAT64: - case RID_DFLOAT128: - case RID_BOOL: - case RID_ENUM: - case RID_STRUCT: - case RID_UNION: - case RID_TYPEOF: - case RID_CONST: - case RID_VOLATILE: - case RID_RESTRICT: - case RID_ATTRIBUTE: - case RID_FRACT: - case RID_ACCUM: - case RID_SAT: + { + case RID_STATIC: + case RID_EXTERN: + case RID_REGISTER: + case RID_TYPEDEF: + case RID_INLINE: + case RID_AUTO: + case RID_THREAD: + case RID_UNSIGNED: + case RID_LONG: + case RID_SHORT: + case RID_SIGNED: + case RID_COMPLEX: + case RID_INT: + case RID_CHAR: + case RID_FLOAT: + case RID_DOUBLE: + case RID_VOID: + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: + case RID_BOOL: + case RID_ENUM: + case RID_STRUCT: + case RID_UNION: + case RID_TYPEOF: + case RID_CONST: + case RID_VOLATILE: + case RID_RESTRICT: + case RID_ATTRIBUTE: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: #ifndef noCbC - case RID_CbC_CODE: + case RID_CbC_CODE: #endif - return true; - default: - return false; - } + return true; + default: + return false; + } case CPP_LESS: if (c_dialect_objc ()) - return true; + return true; return false; default: return false; @@ -574,11 +591,15 @@ the token we just peeked at. */ c_parser_set_source_position_from_token (token); c_parse_error (gmsgid, - /* Because c_parse_error does not understand - CPP_KEYWORD, keywords are treated like - identifiers. */ - (token->type == CPP_KEYWORD ? CPP_NAME : token->type), - token->value); + /* Because c_parse_error does not understand + CPP_KEYWORD, keywords are treated like + identifiers. */ + (token->type == CPP_KEYWORD ? CPP_NAME : token->type), + /* ??? The C parser does not save the cpp flags of a + token, we need to pass 0 here and we will not get + the source spelling of some tokens but rather the + canonical spelling. */ + token->value, /*flags=*/0); } /* If the next token is of the indicated TYPE, consume it. Otherwise, @@ -588,8 +609,8 @@ static bool c_parser_require (c_parser *parser, - enum cpp_ttype type, - const char *msgid) + enum cpp_ttype type, + const char *msgid) { if (c_parser_next_token_is (parser, type)) { @@ -608,8 +629,8 @@ static bool c_parser_require_keyword (c_parser *parser, - enum rid keyword, - const char *msgid) + enum rid keyword, + const char *msgid) { if (c_parser_next_token_is_keyword (parser, keyword)) { @@ -631,8 +652,8 @@ static void c_parser_skip_until_found (c_parser *parser, - enum cpp_ttype type, - const char *msgid) + enum cpp_ttype type, + const char *msgid) { unsigned nesting_depth = 0; @@ -646,27 +667,27 @@ c_token *token = c_parser_peek_token (parser); /* If we've reached the token we want, consume it and stop. */ if (token->type == type && !nesting_depth) - { - c_parser_consume_token (parser); - break; - } + { + c_parser_consume_token (parser); + break; + } /* If we've run out of tokens, stop. */ if (token->type == CPP_EOF) - return; + return; if (token->type == CPP_PRAGMA_EOL && parser->in_pragma) - return; + return; if (token->type == CPP_OPEN_BRACE - || token->type == CPP_OPEN_PAREN - || token->type == CPP_OPEN_SQUARE) - ++nesting_depth; + || token->type == CPP_OPEN_PAREN + || token->type == CPP_OPEN_SQUARE) + ++nesting_depth; else if (token->type == CPP_CLOSE_BRACE - || token->type == CPP_CLOSE_PAREN - || token->type == CPP_CLOSE_SQUARE) - { - if (nesting_depth-- == 0) - break; - } + || token->type == CPP_CLOSE_PAREN + || token->type == CPP_CLOSE_SQUARE) + { + if (nesting_depth-- == 0) + break; + } /* Consume this token. */ c_parser_consume_token (parser); } @@ -685,24 +706,24 @@ { c_token *token = c_parser_peek_token (parser); if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON) - && !nesting_depth) - break; + && !nesting_depth) + break; /* If we've run out of tokens, stop. */ if (token->type == CPP_EOF) - return; + return; if (token->type == CPP_PRAGMA_EOL && parser->in_pragma) - return; + return; if (token->type == CPP_OPEN_BRACE - || token->type == CPP_OPEN_PAREN - || token->type == CPP_OPEN_SQUARE) - ++nesting_depth; + || token->type == CPP_OPEN_PAREN + || token->type == CPP_OPEN_SQUARE) + ++nesting_depth; else if (token->type == CPP_CLOSE_BRACE - || token->type == CPP_CLOSE_PAREN - || token->type == CPP_CLOSE_SQUARE) - { - if (nesting_depth-- == 0) - break; - } + || token->type == CPP_CLOSE_PAREN + || token->type == CPP_CLOSE_SQUARE) + { + if (nesting_depth-- == 0) + break; + } /* Consume this token. */ c_parser_consume_token (parser); } @@ -721,15 +742,15 @@ if (!c_parser_require (parser, CPP_PRAGMA_EOL, "expected end of line")) while (true) { - c_token *token = c_parser_peek_token (parser); - if (token->type == CPP_EOF) - break; - if (token->type == CPP_PRAGMA_EOL) - { - c_parser_consume_token (parser); - break; - } - c_parser_consume_token (parser); + c_token *token = c_parser_peek_token (parser); + if (token->type == CPP_EOF) + break; + if (token->type == CPP_PRAGMA_EOL) + { + c_parser_consume_token (parser); + break; + } + c_parser_consume_token (parser); } parser->error = false; @@ -752,57 +773,57 @@ token = c_parser_peek_token (parser); switch (token->type) - { - case CPP_EOF: - return; - - case CPP_PRAGMA_EOL: - if (parser->in_pragma) - return; - break; - - case CPP_SEMICOLON: - /* If the next token is a ';', we have reached the - end of the statement. */ - if (!nesting_depth) - { - /* Consume the ';'. */ - c_parser_consume_token (parser); - goto finished; - } - break; - - case CPP_CLOSE_BRACE: - /* If the next token is a non-nested '}', then we have - reached the end of the current block. */ - if (nesting_depth == 0 || --nesting_depth == 0) - { - c_parser_consume_token (parser); - goto finished; - } - break; - - case CPP_OPEN_BRACE: - /* If it the next token is a '{', then we are entering a new - block. Consume the entire block. */ - ++nesting_depth; - break; - - case CPP_PRAGMA: - /* If we see a pragma, consume the whole thing at once. We - have some safeguards against consuming pragmas willy-nilly. - Normally, we'd expect to be here with parser->error set, - which disables these safeguards. But it's possible to get - here for secondary error recovery, after parser->error has - been cleared. */ - c_parser_consume_pragma (parser); - c_parser_skip_to_pragma_eol (parser); - parser->error = save_error; - continue; - - default: - break; - } + { + case CPP_EOF: + return; + + case CPP_PRAGMA_EOL: + if (parser->in_pragma) + return; + break; + + case CPP_SEMICOLON: + /* If the next token is a ';', we have reached the + end of the statement. */ + if (!nesting_depth) + { + /* Consume the ';'. */ + c_parser_consume_token (parser); + goto finished; + } + break; + + case CPP_CLOSE_BRACE: + /* If the next token is a non-nested '}', then we have + reached the end of the current block. */ + if (nesting_depth == 0 || --nesting_depth == 0) + { + c_parser_consume_token (parser); + goto finished; + } + break; + + case CPP_OPEN_BRACE: + /* If it the next token is a '{', then we are entering a new + block. Consume the entire block. */ + ++nesting_depth; + break; + + case CPP_PRAGMA: + /* If we see a pragma, consume the whole thing at once. We + have some safeguards against consuming pragmas willy-nilly. + Normally, we'd expect to be here with parser->error set, + which disables these safeguards. But it's possible to get + here for secondary error recovery, after parser->error has + been cleared. */ + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); + parser->error = save_error; + continue; + + default: + break; + } c_parser_consume_token (parser); } @@ -820,17 +841,17 @@ disable_extension_diagnostics (void) { int ret = (pedantic - | (warn_pointer_arith << 1) - | (warn_traditional << 2) - | (flag_iso << 3) - | (warn_long_long << 4) - | (cpp_opts->warn_long_long << 5)); + | (warn_pointer_arith << 1) + | (warn_traditional << 2) + | (flag_iso << 3) + | (warn_long_long << 4) + | (warn_cxx_compat << 5)); cpp_opts->pedantic = pedantic = 0; warn_pointer_arith = 0; cpp_opts->warn_traditional = warn_traditional = 0; flag_iso = 0; - warn_long_long = 0; - cpp_opts->warn_long_long = 0; + cpp_opts->warn_long_long = warn_long_long = 0; + warn_cxx_compat = 0; return ret; } @@ -844,8 +865,8 @@ warn_pointer_arith = (flags >> 1) & 1; cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1; flag_iso = (flags >> 3) & 1; - warn_long_long = (flags >> 4) & 1; - cpp_opts->warn_long_long = (flags >> 5) & 1; + cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1; + warn_cxx_compat = (flags >> 5) & 1; } /* Possibly kinds of declarator to parse. */ @@ -871,18 +892,18 @@ static void c_parser_asm_definition (c_parser *); static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool); static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool, - bool); + bool); 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 struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn, - bool *); + bool *); static struct c_declarator *c_parser_direct_declarator (c_parser *, bool, - c_dtr_syn, bool *); + c_dtr_syn, bool *); static struct c_declarator *c_parser_direct_declarator_inner (c_parser *, - bool, - struct c_declarator *); + bool, + struct c_declarator *); static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree); static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree); static struct c_parm *c_parser_parameter_declaration (c_parser *, tree); @@ -905,10 +926,11 @@ static void c_parser_for_statement (c_parser *); static tree c_parser_asm_statement (c_parser *); static tree c_parser_asm_operands (c_parser *, bool); +static tree c_parser_asm_goto_operands (c_parser *); static tree c_parser_asm_clobbers (c_parser *); static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *); static struct c_expr c_parser_conditional_expression (c_parser *, - struct c_expr *); + struct c_expr *); static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *); static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *); static struct c_expr c_parser_unary_expression (c_parser *); @@ -916,12 +938,15 @@ static struct c_expr c_parser_alignof_expression (c_parser *); static struct c_expr c_parser_postfix_expression (c_parser *); static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *, - struct c_type_name *); + struct c_type_name *, + location_t); static struct c_expr c_parser_postfix_expression_after_primary (c_parser *, - struct c_expr); + location_t loc, + struct c_expr); static struct c_expr c_parser_expression (c_parser *); static struct c_expr c_parser_expression_conv (c_parser *); -static tree c_parser_expr_list (c_parser *, bool); +static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool, + VEC(tree,gc) **); static void c_parser_omp_construct (c_parser *); static void c_parser_omp_threadprivate (c_parser *); static void c_parser_omp_barrier (c_parser *); @@ -973,18 +998,19 @@ { if (c_parser_next_token_is (parser, CPP_EOF)) { - pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, - "ISO C forbids an empty translation unit"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "ISO C forbids an empty translation unit"); } else { void *obstack_position = obstack_alloc (&parser_obstack, 0); + mark_valid_location_for_stdc_pragma (false); do - { - ggc_collect (); - c_parser_external_declaration (parser); - obstack_free (&parser_obstack, obstack_position); - } + { + ggc_collect (); + c_parser_external_declaration (parser); + obstack_free (&parser_obstack, obstack_position); + } while (c_parser_next_token_is_not (parser, CPP_EOF)); } } @@ -1021,64 +1047,66 @@ { case CPP_KEYWORD: switch (c_parser_peek_token (parser)->keyword) - { - case RID_EXTENSION: - ext = disable_extension_diagnostics (); - c_parser_consume_token (parser); - c_parser_external_declaration (parser); - restore_extension_diagnostics (ext); - break; - case RID_ASM: - c_parser_asm_definition (parser); - break; - case RID_AT_INTERFACE: - case RID_AT_IMPLEMENTATION: - gcc_assert (c_dialect_objc ()); - c_parser_objc_class_definition (parser); - break; - case RID_CLASS: - gcc_assert (c_dialect_objc ()); - c_parser_objc_class_declaration (parser); - break; - case RID_AT_ALIAS: - gcc_assert (c_dialect_objc ()); - c_parser_objc_alias_declaration (parser); - break; - case RID_AT_PROTOCOL: - gcc_assert (c_dialect_objc ()); - c_parser_objc_protocol_definition (parser); - break; - case RID_AT_END: - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - objc_finish_implementation (); - break; - default: - goto decl_or_fndef; - } + { + case RID_EXTENSION: + ext = disable_extension_diagnostics (); + c_parser_consume_token (parser); + c_parser_external_declaration (parser); + restore_extension_diagnostics (ext); + break; + case RID_ASM: + c_parser_asm_definition (parser); + break; + case RID_AT_INTERFACE: + case RID_AT_IMPLEMENTATION: + gcc_assert (c_dialect_objc ()); + c_parser_objc_class_definition (parser); + break; + case RID_CLASS: + gcc_assert (c_dialect_objc ()); + c_parser_objc_class_declaration (parser); + break; + case RID_AT_ALIAS: + gcc_assert (c_dialect_objc ()); + c_parser_objc_alias_declaration (parser); + break; + case RID_AT_PROTOCOL: + gcc_assert (c_dialect_objc ()); + c_parser_objc_protocol_definition (parser); + break; + case RID_AT_END: + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + objc_finish_implementation (); + break; + default: + goto decl_or_fndef; + } break; case CPP_SEMICOLON: - pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, - "ISO C does not allow extra %<;%> outside of a function"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "ISO C does not allow extra %<;%> outside of a function"); c_parser_consume_token (parser); break; case CPP_PRAGMA: + mark_valid_location_for_stdc_pragma (true); c_parser_pragma (parser, pragma_external); + mark_valid_location_for_stdc_pragma (false); break; case CPP_PLUS: case CPP_MINUS: if (c_dialect_objc ()) - { - c_parser_objc_method_definition (parser); - break; - } + { + c_parser_objc_method_definition (parser); + break; + } /* Else fall through, and yield a syntax error trying to parse - as a declaration or function definition. */ + as a declaration or function definition. */ default: decl_or_fndef: /* A declaration or a function definition. We can only tell - which after parsing the declaration specifiers, if any, and - the first declarator. */ + which after parsing the declaration specifiers, if any, and + the first declarator. */ c_parser_declaration_or_fndef (parser, true, true, false, true); break; } @@ -1136,15 +1164,15 @@ C we also allow but diagnose declarations without declaration specifiers, but only at top level (elsewhere they conflict with other syntax). - + OpenMP: - + declaration: threadprivate-directive */ static void c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, - bool nested, bool start_attr_ok) + bool nested, bool start_attr_ok) { struct c_declspecs *specs; tree prefix_attrs; @@ -1169,12 +1197,12 @@ if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { if (empty_ok) - shadow_tag (specs); + shadow_tag (specs); else - { - shadow_tag_warned (specs, 1); - pedwarn (here, 0, "empty declaration"); - } + { + shadow_tag_warned (specs, 1); + pedwarn (here, 0, "empty declaration"); + } c_parser_consume_token (parser); return; } @@ -1188,142 +1216,151 @@ bool dummy = false; tree fnbody; /* Declaring either one or more declarators (in which case we - should diagnose if there were no declaration specifiers) or a - function definition (in which case the diagnostic for - implicit int suffices). */ + should diagnose if there were no declaration specifiers) or a + function definition (in which case the diagnostic for + implicit int suffices). */ declarator = c_parser_declarator (parser, specs->type_seen_p, - C_DTR_NORMAL, &dummy); + C_DTR_NORMAL, &dummy); if (declarator == NULL) - { - c_parser_skip_to_end_of_block_or_statement (parser); - return; - } + { + c_parser_skip_to_end_of_block_or_statement (parser); + return; + } if (c_parser_next_token_is (parser, CPP_EQ) - || c_parser_next_token_is (parser, CPP_COMMA) - || c_parser_next_token_is (parser, CPP_SEMICOLON) - || c_parser_next_token_is_keyword (parser, RID_ASM) - || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) - { - tree asm_name = NULL_TREE; - tree postfix_attrs = NULL_TREE; - if (!diagnosed_no_specs && !specs->declspecs_seen_p) - { - diagnosed_no_specs = true; - pedwarn (here, 0, "data definition has no type or storage class"); - } - /* Having seen a data definition, there cannot now be a - function definition. */ - fndef_ok = false; - if (c_parser_next_token_is_keyword (parser, RID_ASM)) - asm_name = c_parser_simple_asm_expr (parser); - if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) - postfix_attrs = c_parser_attributes (parser); - if (c_parser_next_token_is (parser, CPP_EQ)) - { - tree d; - struct c_expr init; - c_parser_consume_token (parser); - /* The declaration of the variable is in effect while - its initializer is parsed. */ - d = start_decl (declarator, specs, true, - chainon (postfix_attrs, all_prefix_attrs)); - if (!d) - d = error_mark_node; - start_init (d, asm_name, global_bindings_p ()); - init = c_parser_initializer (parser); - finish_init (); - if (d != error_mark_node) - { - maybe_warn_string_init (TREE_TYPE (d), init); - finish_decl (d, init.value, asm_name); - } - } - else - { - tree d = start_decl (declarator, specs, false, - chainon (postfix_attrs, - all_prefix_attrs)); - if (d) - finish_decl (d, NULL_TREE, asm_name); - } - if (c_parser_next_token_is (parser, CPP_COMMA)) - { - c_parser_consume_token (parser); - if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) - all_prefix_attrs = chainon (c_parser_attributes (parser), - prefix_attrs); - else - all_prefix_attrs = prefix_attrs; - continue; - } - else if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - c_parser_consume_token (parser); - return; - } - else - { - c_parser_error (parser, "expected %<,%> or %<;%>"); - c_parser_skip_to_end_of_block_or_statement (parser); - return; - } - } + || c_parser_next_token_is (parser, CPP_COMMA) + || c_parser_next_token_is (parser, CPP_SEMICOLON) + || c_parser_next_token_is_keyword (parser, RID_ASM) + || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + { + tree asm_name = NULL_TREE; + tree postfix_attrs = NULL_TREE; + if (!diagnosed_no_specs && !specs->declspecs_seen_p) + { + diagnosed_no_specs = true; + pedwarn (here, 0, "data definition has no type or storage class"); + } + /* Having seen a data definition, there cannot now be a + function definition. */ + fndef_ok = false; + if (c_parser_next_token_is_keyword (parser, RID_ASM)) + asm_name = c_parser_simple_asm_expr (parser); + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + postfix_attrs = c_parser_attributes (parser); + if (c_parser_next_token_is (parser, CPP_EQ)) + { + tree d; + struct c_expr init; + location_t init_loc; + c_parser_consume_token (parser); + /* The declaration of the variable is in effect while + its initializer is parsed. */ + d = start_decl (declarator, specs, true, + chainon (postfix_attrs, all_prefix_attrs)); + if (!d) + d = error_mark_node; + start_init (d, asm_name, global_bindings_p ()); + init_loc = c_parser_peek_token (parser)->location; + init = c_parser_initializer (parser); + finish_init (); + if (d != error_mark_node) + { + maybe_warn_string_init (TREE_TYPE (d), init); + finish_decl (d, init_loc, init.value, + init.original_type, asm_name); + } + } + else + { + tree d = start_decl (declarator, specs, false, + chainon (postfix_attrs, + all_prefix_attrs)); + if (d) + finish_decl (d, UNKNOWN_LOCATION, NULL_TREE, + NULL_TREE, asm_name); + } + if (c_parser_next_token_is (parser, CPP_COMMA)) + { + c_parser_consume_token (parser); + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + all_prefix_attrs = chainon (c_parser_attributes (parser), + prefix_attrs); + else + all_prefix_attrs = prefix_attrs; + continue; + } + else if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + c_parser_consume_token (parser); + return; + } + else + { + c_parser_error (parser, "expected %<,%> or %<;%>"); + c_parser_skip_to_end_of_block_or_statement (parser); + return; + } + } else if (!fndef_ok) - { - c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, " - "%<asm%> or %<__attribute__%>"); - c_parser_skip_to_end_of_block_or_statement (parser); - return; - } + { + c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, " + "%<asm%> or %<__attribute__%>"); + c_parser_skip_to_end_of_block_or_statement (parser); + return; + } /* Function definition (nested or otherwise). */ if (nested) - { - pedwarn (here, OPT_pedantic, "ISO C forbids nested functions"); - c_push_function_context (); - } + { + pedwarn (here, OPT_pedantic, "ISO C forbids nested functions"); + c_push_function_context (); + } if (!start_function (specs, declarator, all_prefix_attrs)) - { - /* This can appear in many cases looking nothing like a - function definition, so we don't give a more specific - error suggesting there was one. */ - c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> " - "or %<__attribute__%>"); - if (nested) - c_pop_function_context (); - break; - } + { + /* This can appear in many cases looking nothing like a + function definition, so we don't give a more specific + error suggesting there was one. */ + c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> " + "or %<__attribute__%>"); + if (nested) + c_pop_function_context (); + break; + } /* Parse old-style parameter declarations. ??? Attributes are - not allowed to start declaration specifiers here because of a - syntax conflict between a function declaration with attribute - suffix and a function definition with an attribute prefix on - first old-style parameter declaration. Following the old - parser, they are not accepted on subsequent old-style - parameter declarations either. However, there is no - ambiguity after the first declaration, nor indeed on the - first as long as we don't allow postfix attributes after a - declarator with a nonempty identifier list in a definition; - and postfix attributes have never been accepted here in - function definitions either. */ + not allowed to start declaration specifiers here because of a + syntax conflict between a function declaration with attribute + suffix and a function definition with an attribute prefix on + first old-style parameter declaration. Following the old + parser, they are not accepted on subsequent old-style + parameter declarations either. However, there is no + ambiguity after the first declaration, nor indeed on the + first as long as we don't allow postfix attributes after a + declarator with a nonempty identifier list in a definition; + and postfix attributes have never been accepted here in + function definitions either. */ while (c_parser_next_token_is_not (parser, CPP_EOF) - && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE)) - c_parser_declaration_or_fndef (parser, false, false, true, false); + && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE)) + c_parser_declaration_or_fndef (parser, false, false, true, false); store_parm_decls (); DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus - = c_parser_peek_token (parser)->location; + = c_parser_peek_token (parser)->location; fnbody = c_parser_compound_statement (parser); if (nested) - { - tree decl = current_function_decl; - add_stmt (fnbody); - finish_function (); - c_pop_function_context (); - add_stmt (build_stmt (DECL_EXPR, decl)); - } + { + tree decl = current_function_decl; + /* Mark nested functions as needing static-chain initially. + lower_nested_functions will recompute it but the + DECL_STATIC_CHAIN flag is also used before that happens, + by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */ + DECL_STATIC_CHAIN (decl) = 1; + add_stmt (fnbody); + finish_function (); + c_pop_function_context (); + add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl)); + } else - { - add_stmt (fnbody); - finish_function (); - } + { + add_stmt (fnbody); + finish_function (); + } break; } } @@ -1397,6 +1434,7 @@ const restrict volatile + address-space-qualifier (restrict is new in C99.) @@ -1405,6 +1443,12 @@ declaration-specifiers: attributes declaration-specifiers[opt] + type-qualifier: + address-space + + address-space: + identifier recognized by the target + storage-class-specifier: __thread @@ -1430,179 +1474,200 @@ static void c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, - bool scspec_ok, bool typespec_ok, bool start_attr_ok) + bool scspec_ok, bool typespec_ok, bool start_attr_ok) { bool attrs_ok = start_attr_ok; bool seen_type = specs->type_seen_p; while (c_parser_next_token_is (parser, CPP_NAME) - || c_parser_next_token_is (parser, CPP_KEYWORD) - || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS))) + || c_parser_next_token_is (parser, CPP_KEYWORD) + || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS))) { struct c_typespec t; tree attrs; + location_t loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_NAME)) - { - tree value = c_parser_peek_token (parser)->value; - c_id_kind kind = c_parser_peek_token (parser)->id_kind; - /* This finishes the specifiers unless a type name is OK, it - is declared as a type name and a type name hasn't yet - been seen. */ - if (!typespec_ok || seen_type - || (kind != C_ID_TYPENAME && kind != C_ID_CLASSNAME)) - break; - c_parser_consume_token (parser); - seen_type = true; - attrs_ok = true; - if (kind == C_ID_TYPENAME - && (!c_dialect_objc () - || c_parser_next_token_is_not (parser, CPP_LESS))) - { - t.kind = ctsk_typedef; - /* For a typedef name, record the meaning, not the name. - In case of 'foo foo, bar;'. */ - t.spec = lookup_name (value); - } - else - { - tree proto = NULL_TREE; - gcc_assert (c_dialect_objc ()); - t.kind = ctsk_objc; - if (c_parser_next_token_is (parser, CPP_LESS)) - proto = c_parser_objc_protocol_refs (parser); - t.spec = objc_get_protocol_qualified_type (value, proto); - } - declspecs_add_type (specs, t); - continue; - } + { + tree value = c_parser_peek_token (parser)->value; + c_id_kind kind = c_parser_peek_token (parser)->id_kind; + + if (kind == C_ID_ADDRSPACE) + { + addr_space_t as + = c_parser_peek_token (parser)->keyword - RID_FIRST_ADDR_SPACE; + declspecs_add_addrspace (specs, as); + c_parser_consume_token (parser); + attrs_ok = true; + continue; + } + + /* This finishes the specifiers unless a type name is OK, it + is declared as a type name and a type name hasn't yet + been seen. */ + if (!typespec_ok || seen_type + || (kind != C_ID_TYPENAME && kind != C_ID_CLASSNAME)) + break; + c_parser_consume_token (parser); + seen_type = true; + attrs_ok = true; + if (kind == C_ID_TYPENAME + && (!c_dialect_objc () + || c_parser_next_token_is_not (parser, CPP_LESS))) + { + t.kind = ctsk_typedef; + /* For a typedef name, record the meaning, not the name. + In case of 'foo foo, bar;'. */ + t.spec = lookup_name (value); + t.expr = NULL_TREE; + t.expr_const_operands = true; + } + else + { + tree proto = NULL_TREE; + gcc_assert (c_dialect_objc ()); + t.kind = ctsk_objc; + if (c_parser_next_token_is (parser, CPP_LESS)) + proto = c_parser_objc_protocol_refs (parser); + t.spec = objc_get_protocol_qualified_type (value, proto); + t.expr = NULL_TREE; + t.expr_const_operands = true; + } + declspecs_add_type (loc, specs, t); + continue; + } if (c_parser_next_token_is (parser, CPP_LESS)) - { - /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" - - nisse@lysator.liu.se. */ - tree proto; - gcc_assert (c_dialect_objc ()); - if (!typespec_ok || seen_type) - break; - proto = c_parser_objc_protocol_refs (parser); - t.kind = ctsk_objc; - t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto); - declspecs_add_type (specs, t); - continue; - } + { + /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" - + nisse@lysator.liu.se. */ + tree proto; + gcc_assert (c_dialect_objc ()); + if (!typespec_ok || seen_type) + break; + proto = c_parser_objc_protocol_refs (parser); + t.kind = ctsk_objc; + t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto); + t.expr = NULL_TREE; + t.expr_const_operands = true; + declspecs_add_type (loc, specs, t); + continue; + } gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD)); switch (c_parser_peek_token (parser)->keyword) - { - case RID_STATIC: - case RID_EXTERN: - case RID_REGISTER: - case RID_TYPEDEF: - case RID_INLINE: - case RID_AUTO: - case RID_THREAD: - if (!scspec_ok) - goto out; - attrs_ok = true; - /* TODO: Distinguish between function specifiers (inline) - and storage class specifiers, either here or in - declspecs_add_scspec. */ - declspecs_add_scspec (specs, c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - break; - case RID_UNSIGNED: - case RID_LONG: - case RID_SHORT: - case RID_SIGNED: - case RID_COMPLEX: - case RID_INT: - case RID_CHAR: - case RID_FLOAT: - case RID_DOUBLE: - case RID_VOID: - case RID_DFLOAT32: - case RID_DFLOAT64: - case RID_DFLOAT128: - case RID_BOOL: - case RID_FRACT: - case RID_ACCUM: - case RID_SAT: - if (!typespec_ok) - goto out; - attrs_ok = true; - seen_type = true; - if (c_dialect_objc ()) - parser->objc_need_raw_identifier = true; - t.kind = ctsk_resword; - t.spec = c_parser_peek_token (parser)->value; - declspecs_add_type (specs, t); - c_parser_consume_token (parser); - break; + { + case RID_STATIC: + case RID_EXTERN: + case RID_REGISTER: + case RID_TYPEDEF: + case RID_INLINE: + case RID_AUTO: + case RID_THREAD: + if (!scspec_ok) + goto out; + attrs_ok = true; + /* TODO: Distinguish between function specifiers (inline) + and storage class specifiers, either here or in + declspecs_add_scspec. */ + declspecs_add_scspec (specs, c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + break; + case RID_UNSIGNED: + case RID_LONG: + case RID_SHORT: + case RID_SIGNED: + case RID_COMPLEX: + case RID_INT: + case RID_CHAR: + case RID_FLOAT: + case RID_DOUBLE: + case RID_VOID: + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: + case RID_BOOL: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: + if (!typespec_ok) + goto out; + attrs_ok = true; + seen_type = true; + if (c_dialect_objc ()) + parser->objc_need_raw_identifier = true; + t.kind = ctsk_resword; + t.spec = c_parser_peek_token (parser)->value; + t.expr = NULL_TREE; + t.expr_const_operands = true; + declspecs_add_type (loc, specs, t); + c_parser_consume_token (parser); + break; #ifndef noCbC - case RID_CbC_CODE: - if (!typespec_ok) - goto out; - attrs_ok = true; - seen_type = true; - if (c_dialect_objc ()) - parser->objc_need_raw_identifier = true; - t.kind = ctsk_resword; - t.spec = c_parser_peek_token (parser)->value; - declspecs_add_type (specs, t); - - /* - attrs = get_identifier("fastcall"); - attrs = build_tree_list(attrs, NULL_TREE); - declspecs_add_attrs(specs, attrs); - */ - attrs = build_tree_list (get_identifier("fastcall"), NULL_TREE); - /*attrs = build_tree_list (get_identifier("noreturn"), attrs);*/ - declspecs_add_attrs(specs, attrs); - - c_parser_consume_token (parser); - break; + case RID_CbC_CODE: + if (!typespec_ok) + goto out; + attrs_ok = true; + seen_type = true; + if (c_dialect_objc ()) + parser->objc_need_raw_identifier = true; + t.kind = ctsk_resword; + t.spec = c_parser_peek_token (parser)->value; + declspecs_add_type (loc, specs, t); + + /* + attrs = get_identifier("fastcall"); + attrs = build_tree_list(attrs, NULL_TREE); + declspecs_add_attrs(specs, attrs); + */ + attrs = build_tree_list (get_identifier("fastcall"), NULL_TREE); + /*attrs = build_tree_list (get_identifier("noreturn"), attrs);*/ + declspecs_add_attrs(specs, attrs); + + c_parser_consume_token (parser); + break; #endif - case RID_ENUM: - if (!typespec_ok) - goto out; - attrs_ok = true; - seen_type = true; - t = c_parser_enum_specifier (parser); - declspecs_add_type (specs, t); - break; - case RID_STRUCT: - case RID_UNION: - if (!typespec_ok) - goto out; - attrs_ok = true; - seen_type = true; - t = c_parser_struct_or_union_specifier (parser); - declspecs_add_type (specs, t); - break; - case RID_TYPEOF: - /* ??? The old parser rejected typeof after other type - specifiers, but is a syntax error the best way of - handling this? */ - if (!typespec_ok || seen_type) - goto out; - attrs_ok = true; - seen_type = true; - t = c_parser_typeof_specifier (parser); - declspecs_add_type (specs, t); - break; - case RID_CONST: - case RID_VOLATILE: - case RID_RESTRICT: - attrs_ok = true; - declspecs_add_qual (specs, c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - break; - case RID_ATTRIBUTE: - if (!attrs_ok) - goto out; - attrs = c_parser_attributes (parser); - declspecs_add_attrs (specs, attrs); - break; - default: - goto out; - } + case RID_ENUM: + if (!typespec_ok) + goto out; + attrs_ok = true; + seen_type = true; + t = c_parser_enum_specifier (parser); + declspecs_add_type (loc, specs, t); + break; + case RID_STRUCT: + case RID_UNION: + if (!typespec_ok) + goto out; + attrs_ok = true; + seen_type = true; + t = c_parser_struct_or_union_specifier (parser); + invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec); + declspecs_add_type (loc, specs, t); + break; + case RID_TYPEOF: + /* ??? The old parser rejected typeof after other type + specifiers, but is a syntax error the best way of + handling this? */ + if (!typespec_ok || seen_type) + goto out; + attrs_ok = true; + seen_type = true; + t = c_parser_typeof_specifier (parser); + declspecs_add_type (loc, specs, t); + break; + case RID_CONST: + case RID_VOLATILE: + case RID_RESTRICT: + attrs_ok = true; + declspecs_add_qual (specs, c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + break; + case RID_ATTRIBUTE: + if (!attrs_ok) + goto out; + attrs = c_parser_attributes (parser); + declspecs_add_attrs (specs, attrs); + break; + default: + goto out; + } } out: ; } @@ -1635,88 +1700,94 @@ struct c_typespec ret; tree attrs; tree ident = NULL_TREE; + location_t enum_loc; location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */ gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM)); + enum_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); attrs = c_parser_attributes (parser); + enum_loc = c_parser_peek_token (parser)->location; /* Set the location in case we create a decl now. */ c_parser_set_source_position_from_token (c_parser_peek_token (parser)); if (c_parser_next_token_is (parser, CPP_NAME)) { ident = c_parser_peek_token (parser)->value; ident_loc = c_parser_peek_token (parser)->location; + enum_loc = ident_loc; c_parser_consume_token (parser); } if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) { /* Parse an enum definition. */ struct c_enum_contents the_enum; - tree type = start_enum (&the_enum, ident); + tree type = start_enum (enum_loc, &the_enum, ident); tree postfix_attrs; /* We chain the enumerators in reverse order, then put them in - forward order at the end. */ + forward order at the end. */ tree values = NULL_TREE; c_parser_consume_token (parser); while (true) - { - tree enum_id; - tree enum_value; - tree enum_decl; - bool seen_comma; - c_token *token; - location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */ - location_t value_loc; - if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); - values = error_mark_node; - break; - } - token = c_parser_peek_token (parser); - enum_id = token->value; - /* Set the location in case we create a decl now. */ - c_parser_set_source_position_from_token (token); - value_loc = token->location; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_EQ)) - { - c_parser_consume_token (parser); - value_loc = c_parser_peek_token (parser)->location; - enum_value = c_parser_expr_no_commas (parser, NULL).value; - } - else - enum_value = NULL_TREE; - enum_decl = build_enumerator (&the_enum, enum_id, enum_value, - value_loc); - TREE_CHAIN (enum_decl) = values; - values = enum_decl; - seen_comma = false; - if (c_parser_next_token_is (parser, CPP_COMMA)) - { - comma_loc = c_parser_peek_token (parser)->location; - seen_comma = true; - c_parser_consume_token (parser); - } - if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - { - if (seen_comma && !flag_isoc99) - pedwarn (comma_loc, OPT_pedantic, "comma at end of enumerator list"); - c_parser_consume_token (parser); - break; - } - if (!seen_comma) - { - c_parser_error (parser, "expected %<,%> or %<}%>"); - c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); - values = error_mark_node; - break; - } - } + { + tree enum_id; + tree enum_value; + tree enum_decl; + bool seen_comma; + c_token *token; + location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */ + location_t value_loc; + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); + values = error_mark_node; + break; + } + token = c_parser_peek_token (parser); + enum_id = token->value; + /* Set the location in case we create a decl now. */ + c_parser_set_source_position_from_token (token); + value_loc = token->location; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_EQ)) + { + c_parser_consume_token (parser); + value_loc = c_parser_peek_token (parser)->location; + enum_value = c_parser_expr_no_commas (parser, NULL).value; + } + else + enum_value = NULL_TREE; + enum_decl = build_enumerator (value_loc, + &the_enum, enum_id, enum_value); + TREE_CHAIN (enum_decl) = values; + values = enum_decl; + seen_comma = false; + if (c_parser_next_token_is (parser, CPP_COMMA)) + { + comma_loc = c_parser_peek_token (parser)->location; + seen_comma = true; + c_parser_consume_token (parser); + } + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + if (seen_comma && !flag_isoc99) + pedwarn (comma_loc, OPT_pedantic, "comma at end of enumerator list"); + c_parser_consume_token (parser); + break; + } + if (!seen_comma) + { + c_parser_error (parser, "expected %<,%> or %<}%>"); + c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); + values = error_mark_node; + break; + } + } postfix_attrs = c_parser_attributes (parser); ret.spec = finish_enum (type, nreverse (values), - chainon (attrs, postfix_attrs)); + chainon (attrs, postfix_attrs)); ret.kind = ctsk_tagdef; + ret.expr = NULL_TREE; + ret.expr_const_operands = true; return ret; } else if (!ident) @@ -1724,16 +1795,18 @@ c_parser_error (parser, "expected %<{%>"); ret.spec = error_mark_node; ret.kind = ctsk_tagref; + ret.expr = NULL_TREE; + ret.expr_const_operands = true; return ret; } - ret = parser_xref_tag (ENUMERAL_TYPE, ident); + ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident); /* In ISO C, enumerated types can be referred to only if already defined. */ if (pedantic && !COMPLETE_TYPE_P (ret.spec)) { gcc_assert (ident); - pedwarn (ident_loc, OPT_pedantic, - "ISO C forbids forward references to %<enum%> types"); + pedwarn (enum_loc, OPT_pedantic, + "ISO C forbids forward references to %<enum%> types"); } return ret; } @@ -1783,6 +1856,8 @@ struct c_typespec ret; tree attrs; tree ident = NULL_TREE; + location_t struct_loc; + location_t ident_loc = UNKNOWN_LOCATION; enum tree_code code; switch (c_parser_peek_token (parser)->keyword) { @@ -1795,111 +1870,119 @@ default: gcc_unreachable (); } + struct_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); attrs = c_parser_attributes (parser); + /* Set the location in case we create a decl now. */ c_parser_set_source_position_from_token (c_parser_peek_token (parser)); + if (c_parser_next_token_is (parser, CPP_NAME)) { ident = c_parser_peek_token (parser)->value; + ident_loc = c_parser_peek_token (parser)->location; + struct_loc = ident_loc; c_parser_consume_token (parser); } if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) { /* Parse a struct or union definition. Start the scope of the - tag before parsing components. */ - tree type = start_struct (code, ident); + tag before parsing components. */ + struct c_struct_parse_info *struct_info; + tree type = start_struct (struct_loc, code, ident, &struct_info); tree postfix_attrs; /* We chain the components in reverse order, then put them in - forward order at the end. Each struct-declaration may - declare multiple components (comma-separated), so we must use - chainon to join them, although when parsing each - struct-declaration we can use TREE_CHAIN directly. - - The theory behind all this is that there will be more - semicolon separated fields than comma separated fields, and - so we'll be minimizing the number of node traversals required - by chainon. */ + forward order at the end. Each struct-declaration may + declare multiple components (comma-separated), so we must use + chainon to join them, although when parsing each + struct-declaration we can use TREE_CHAIN directly. + + The theory behind all this is that there will be more + semicolon separated fields than comma separated fields, and + so we'll be minimizing the number of node traversals required + by chainon. */ tree contents = NULL_TREE; c_parser_consume_token (parser); /* Handle the Objective-C @defs construct, - e.g. foo(sizeof(struct{ @defs(ClassName) }));. */ + e.g. foo(sizeof(struct{ @defs(ClassName) }));. */ if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS)) - { - tree name; - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - goto end_at_defs; - if (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME) - { - name = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - } - else - { - c_parser_error (parser, "expected class name"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - goto end_at_defs; - } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - contents = nreverse (objc_get_class_ivars (name)); - } + { + tree name; + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + goto end_at_defs; + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME) + { + name = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + } + else + { + c_parser_error (parser, "expected class name"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + goto end_at_defs; + } + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + contents = nreverse (objc_get_class_ivars (name)); + } end_at_defs: /* Parse the struct-declarations and semicolons. Problems with - semicolons are diagnosed here; empty structures are diagnosed - elsewhere. */ + semicolons are diagnosed here; empty structures are diagnosed + elsewhere. */ while (true) - { - tree decls; - /* Parse any stray semicolon. */ - if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, - "extra semicolon in struct or union specified"); - c_parser_consume_token (parser); - continue; - } - /* Stop if at the end of the struct or union contents. */ - if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - { - c_parser_consume_token (parser); - break; - } - /* Accept #pragmas at struct scope. */ - if (c_parser_next_token_is (parser, CPP_PRAGMA)) - { - c_parser_pragma (parser, pragma_external); - continue; - } - /* Parse some comma-separated declarations, but not the - trailing semicolon if any. */ - decls = c_parser_struct_declaration (parser); - contents = chainon (decls, contents); - /* If no semicolon follows, either we have a parse error or - are at the end of the struct or union and should - pedwarn. */ - if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - c_parser_consume_token (parser); - else - { - if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - pedwarn (c_parser_peek_token (parser)->location, 0, - "no semicolon at end of struct or union"); - else - { - c_parser_error (parser, "expected %<;%>"); - c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); - break; - } - } - } + { + tree decls; + /* Parse any stray semicolon. */ + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "extra semicolon in struct or union specified"); + c_parser_consume_token (parser); + continue; + } + /* Stop if at the end of the struct or union contents. */ + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + c_parser_consume_token (parser); + break; + } + /* Accept #pragmas at struct scope. */ + if (c_parser_next_token_is (parser, CPP_PRAGMA)) + { + c_parser_pragma (parser, pragma_external); + continue; + } + /* Parse some comma-separated declarations, but not the + trailing semicolon if any. */ + decls = c_parser_struct_declaration (parser); + contents = chainon (decls, contents); + /* If no semicolon follows, either we have a parse error or + are at the end of the struct or union and should + pedwarn. */ + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + c_parser_consume_token (parser); + else + { + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + pedwarn (c_parser_peek_token (parser)->location, 0, + "no semicolon at end of struct or union"); + else + { + c_parser_error (parser, "expected %<;%>"); + c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); + break; + } + } + } postfix_attrs = c_parser_attributes (parser); - ret.spec = finish_struct (type, nreverse (contents), - chainon (attrs, postfix_attrs)); + ret.spec = finish_struct (struct_loc, type, nreverse (contents), + chainon (attrs, postfix_attrs), struct_info); ret.kind = ctsk_tagdef; + ret.expr = NULL_TREE; + ret.expr_const_operands = true; return ret; } else if (!ident) @@ -1907,9 +1990,11 @@ c_parser_error (parser, "expected %<{%>"); ret.spec = error_mark_node; ret.kind = ctsk_tagref; + ret.expr = NULL_TREE; + ret.expr_const_operands = true; return ret; } - ret = parser_xref_tag (code, ident); + ret = parser_xref_tag (ident_loc, code, ident); return ret; } @@ -1977,25 +2062,25 @@ { tree ret; if (!specs->type_seen_p) - { - pedwarn (decl_loc, OPT_pedantic, - "ISO C forbids member declarations with no members"); - shadow_tag_warned (specs, pedantic); - ret = NULL_TREE; - } + { + pedwarn (decl_loc, OPT_pedantic, + "ISO C forbids member declarations with no members"); + shadow_tag_warned (specs, pedantic); + ret = NULL_TREE; + } else - { - /* Support for unnamed structs or unions as members of - structs or unions (which is [a] useful and [b] supports - MS P-SDK). */ - tree attrs = NULL; - - ret = grokfield (c_parser_peek_token (parser)->location, - build_id_declarator (NULL_TREE), specs, - NULL_TREE, &attrs); - if (ret) - decl_attributes (&ret, attrs, 0); - } + { + /* Support for unnamed structs or unions as members of + structs or unions (which is [a] useful and [b] supports + MS P-SDK). */ + tree attrs = NULL; + + ret = grokfield (c_parser_peek_token (parser)->location, + build_id_declarator (NULL_TREE), specs, + NULL_TREE, &attrs); + if (ret) + decl_attributes (&ret, attrs, 0); + } return ret; } pending_xref_error (); @@ -2009,63 +2094,63 @@ struct c_declarator *declarator; bool dummy = false; if (c_parser_next_token_is (parser, CPP_COLON)) - declarator = build_id_declarator (NULL_TREE); + declarator = build_id_declarator (NULL_TREE); else - declarator = c_parser_declarator (parser, specs->type_seen_p, - C_DTR_NORMAL, &dummy); + declarator = c_parser_declarator (parser, specs->type_seen_p, + C_DTR_NORMAL, &dummy); if (declarator == NULL) - { - c_parser_skip_to_end_of_block_or_statement (parser); - break; - } + { + c_parser_skip_to_end_of_block_or_statement (parser); + break; + } if (c_parser_next_token_is (parser, CPP_COLON) - || c_parser_next_token_is (parser, CPP_COMMA) - || c_parser_next_token_is (parser, CPP_SEMICOLON) - || c_parser_next_token_is (parser, CPP_CLOSE_BRACE) - || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) - { - tree postfix_attrs = NULL_TREE; - tree width = NULL_TREE; - tree d; - if (c_parser_next_token_is (parser, CPP_COLON)) - { - c_parser_consume_token (parser); - width = c_parser_expr_no_commas (parser, NULL).value; - } - if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) - postfix_attrs = c_parser_attributes (parser); - d = grokfield (c_parser_peek_token (parser)->location, - declarator, specs, width, &all_prefix_attrs); - decl_attributes (&d, chainon (postfix_attrs, - all_prefix_attrs), 0); - TREE_CHAIN (d) = decls; - decls = d; - if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) - all_prefix_attrs = chainon (c_parser_attributes (parser), - prefix_attrs); - else - all_prefix_attrs = prefix_attrs; - if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); - else if (c_parser_next_token_is (parser, CPP_SEMICOLON) - || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - { - /* Semicolon consumed in caller. */ - break; - } - else - { - c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>"); - break; - } - } + || c_parser_next_token_is (parser, CPP_COMMA) + || c_parser_next_token_is (parser, CPP_SEMICOLON) + || c_parser_next_token_is (parser, CPP_CLOSE_BRACE) + || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + { + tree postfix_attrs = NULL_TREE; + tree width = NULL_TREE; + tree d; + if (c_parser_next_token_is (parser, CPP_COLON)) + { + c_parser_consume_token (parser); + width = c_parser_expr_no_commas (parser, NULL).value; + } + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + postfix_attrs = c_parser_attributes (parser); + d = grokfield (c_parser_peek_token (parser)->location, + declarator, specs, width, &all_prefix_attrs); + decl_attributes (&d, chainon (postfix_attrs, + all_prefix_attrs), 0); + TREE_CHAIN (d) = decls; + decls = d; + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + all_prefix_attrs = chainon (c_parser_attributes (parser), + prefix_attrs); else - { - c_parser_error (parser, - "expected %<:%>, %<,%>, %<;%>, %<}%> or " - "%<__attribute__%>"); - break; - } + all_prefix_attrs = prefix_attrs; + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else if (c_parser_next_token_is (parser, CPP_SEMICOLON) + || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + /* Semicolon consumed in caller. */ + break; + } + else + { + c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>"); + break; + } + } + else + { + c_parser_error (parser, + "expected %<:%>, %<,%>, %<;%>, %<}%> or " + "%<__attribute__%>"); + break; + } } return decls; } @@ -2083,55 +2168,45 @@ struct c_typespec ret; ret.kind = ctsk_typeof; ret.spec = error_mark_node; + ret.expr = NULL_TREE; + ret.expr_const_operands = true; gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF)); c_parser_consume_token (parser); - skip_evaluation++; + c_inhibit_evaluation_warnings++; in_typeof++; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_typeof--; return ret; } if (c_parser_next_token_starts_typename (parser)) { struct c_type_name *type = c_parser_type_name (parser); - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_typeof--; if (type != NULL) - { - ret.spec = groktypename (type); - pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE)); - } + { + ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands); + pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE)); + } } else { bool was_vm; location_t here = c_parser_peek_token (parser)->location; struct c_expr expr = c_parser_expression (parser); - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_typeof--; if (TREE_CODE (expr.value) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) - error_at (here, "%<typeof%> applied to a bit-field"); + && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) + error_at (here, "%<typeof%> applied to a bit-field"); ret.spec = TREE_TYPE (expr.value); was_vm = variably_modified_type_p (ret.spec, NULL_TREE); - /* This should be returned with the type so that when the type - is evaluated, this can be evaluated. For now, we avoid - evaluation when the context might. */ - if (!skip_evaluation && was_vm) - { - tree e = expr.value; - - /* If the expression is not of a type to which we cannot assign a line - number, wrap the thing in a no-op NOP_EXPR. */ - if (DECL_P (e) || CONSTANT_CLASS_P (e)) - e = build1 (NOP_EXPR, void_type_node, e); - - protected_set_expr_location (e, here); - - add_stmt (e); - } + /* This is returned with the type so that when the type is + evaluated, this can be evaluated. */ + if (was_vm) + ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands); pop_maybe_used (was_vm); } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -2196,11 +2271,11 @@ direct-declarator: direct-declarator ( parameter-forward-declarations - parameter-type-list[opt] ) + parameter-type-list[opt] ) direct-abstract-declarator: direct-abstract-declarator[opt] ( parameter-forward-declarations - parameter-type-list[opt] ) + parameter-type-list[opt] ) parameter-forward-declarations: parameter-list ; @@ -2217,7 +2292,7 @@ static struct c_declarator * c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, - bool *seen_id) + bool *seen_id) { /* Parse any initial pointer part. */ if (c_parser_next_token_is (parser, CPP_MULT)) @@ -2228,9 +2303,9 @@ c_parser_declspecs (parser, quals_attrs, false, false, true); inner = c_parser_declarator (parser, type_seen_p, kind, seen_id); if (inner == NULL) - return NULL; + return NULL; else - return make_pointer_declarator (quals_attrs, inner); + return make_pointer_declarator (quals_attrs, inner); } /* Now we have a direct declarator, direct abstract declarator or nothing (which counts as a direct abstract declarator here). */ @@ -2242,7 +2317,7 @@ static struct c_declarator * c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, - bool *seen_id) + bool *seen_id) { /* The direct declarator must start with an identifier (possibly omitted) or a parenthesized declarator (possibly abstract). In @@ -2281,11 +2356,11 @@ if (kind != C_DTR_ABSTRACT && c_parser_next_token_is (parser, CPP_NAME) && ((type_seen_p - && c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME) - || c_parser_peek_token (parser)->id_kind == C_ID_ID)) + && c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME) + || c_parser_peek_token (parser)->id_kind == C_ID_ID)) { struct c_declarator *inner - = build_id_declarator (c_parser_peek_token (parser)->value); + = build_id_declarator (c_parser_peek_token (parser)->value); *seen_id = true; inner->id_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); @@ -2309,51 +2384,51 @@ c_parser_consume_token (parser); attrs = c_parser_attributes (parser); if (kind != C_DTR_NORMAL - && (c_parser_next_token_starts_declspecs (parser) - || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) - { - struct c_arg_info *args - = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL, - attrs); - if (args == NULL) - return NULL; - else - { - inner - = build_function_declarator (args, - build_id_declarator (NULL_TREE)); - return c_parser_direct_declarator_inner (parser, *seen_id, - inner); - } - } + && (c_parser_next_token_starts_declspecs (parser) + || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) + { + struct c_arg_info *args + = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL, + attrs); + if (args == NULL) + return NULL; + else + { + inner + = build_function_declarator (args, + build_id_declarator (NULL_TREE)); + return c_parser_direct_declarator_inner (parser, *seen_id, + inner); + } + } /* A parenthesized declarator. */ inner = c_parser_declarator (parser, type_seen_p, kind, seen_id); if (inner != NULL && attrs != NULL) - inner = build_attrs_declarator (attrs, inner); + inner = build_attrs_declarator (attrs, inner); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - { - c_parser_consume_token (parser); - if (inner == NULL) - return NULL; - else - return c_parser_direct_declarator_inner (parser, *seen_id, inner); - } + { + c_parser_consume_token (parser); + if (inner == NULL) + return NULL; else - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - return NULL; - } + return c_parser_direct_declarator_inner (parser, *seen_id, inner); + } + else + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + return NULL; + } } else { if (kind == C_DTR_NORMAL) - { - c_parser_error (parser, "expected identifier or %<(%>"); - return NULL; - } + { + c_parser_error (parser, "expected identifier or %<(%>"); + return NULL; + } else - return build_id_declarator (NULL_TREE); + return build_id_declarator (NULL_TREE); } } @@ -2364,11 +2439,12 @@ static struct c_declarator * c_parser_direct_declarator_inner (c_parser *parser, bool id_present, - struct c_declarator *inner) + struct c_declarator *inner) { /* Parse a sequence of array declarators and parameter lists. */ if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) { + location_t brace_loc = c_parser_peek_token (parser)->location; struct c_declarator *declarator; struct c_declspecs *quals_attrs = build_null_declspecs (); bool static_seen; @@ -2378,58 +2454,58 @@ c_parser_declspecs (parser, quals_attrs, false, false, true); static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC); if (static_seen) - c_parser_consume_token (parser); + c_parser_consume_token (parser); if (static_seen && !quals_attrs->declspecs_seen_p) - c_parser_declspecs (parser, quals_attrs, false, false, true); + c_parser_declspecs (parser, quals_attrs, false, false, true); if (!quals_attrs->declspecs_seen_p) - quals_attrs = NULL; + quals_attrs = NULL; /* If "static" is present, there must be an array dimension. - Otherwise, there may be a dimension, "*", or no - dimension. */ + Otherwise, there may be a dimension, "*", or no + dimension. */ if (static_seen) - { - star_seen = false; - dimen = c_parser_expr_no_commas (parser, NULL).value; - } + { + star_seen = false; + dimen = c_parser_expr_no_commas (parser, NULL).value; + } else - { - if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) - { - dimen = NULL_TREE; - star_seen = false; - } - else if (c_parser_next_token_is (parser, CPP_MULT)) - { - if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE) - { - dimen = NULL_TREE; - star_seen = true; - c_parser_consume_token (parser); - } - else - { - star_seen = false; - dimen = c_parser_expr_no_commas (parser, NULL).value; - } - } - else - { - star_seen = false; - dimen = c_parser_expr_no_commas (parser, NULL).value; - } - } + { if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) - c_parser_consume_token (parser); + { + dimen = NULL_TREE; + star_seen = false; + } + else if (c_parser_next_token_is (parser, CPP_MULT)) + { + if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE) + { + dimen = NULL_TREE; + star_seen = true; + c_parser_consume_token (parser); + } + else + { + star_seen = false; + dimen = c_parser_expr_no_commas (parser, NULL).value; + } + } else - { - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, - "expected %<]%>"); - return NULL; - } - declarator = build_array_declarator (dimen, quals_attrs, static_seen, - star_seen); + { + star_seen = false; + dimen = c_parser_expr_no_commas (parser, NULL).value; + } + } + if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) + c_parser_consume_token (parser); + else + { + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + return NULL; + } + declarator = build_array_declarator (brace_loc, dimen, quals_attrs, + static_seen, star_seen); if (declarator == NULL) - return NULL; + return NULL; inner = set_array_declarator_inner (declarator, inner); return c_parser_direct_declarator_inner (parser, id_present, inner); } @@ -2441,12 +2517,12 @@ attrs = c_parser_attributes (parser); args = c_parser_parms_declarator (parser, id_present, attrs); if (args == NULL) - return NULL; + return NULL; else - { - inner = build_function_declarator (args, inner); - return c_parser_direct_declarator_inner (parser, id_present, inner); - } + { + inner = build_function_declarator (args, inner); + return c_parser_direct_declarator_inner (parser, id_present, inner); + } } return inner; } @@ -2470,41 +2546,41 @@ { tree list = NULL_TREE, *nextp = &list; while (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_token (parser)->id_kind == C_ID_ID) - { - *nextp = build_tree_list (NULL_TREE, - c_parser_peek_token (parser)->value); - nextp = & TREE_CHAIN (*nextp); - c_parser_consume_token (parser); - if (c_parser_next_token_is_not (parser, CPP_COMMA)) - break; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - { - c_parser_error (parser, "expected identifier"); - break; - } - } + && c_parser_peek_token (parser)->id_kind == C_ID_ID) + { + *nextp = build_tree_list (NULL_TREE, + c_parser_peek_token (parser)->value); + nextp = & TREE_CHAIN (*nextp); + c_parser_consume_token (parser); + if (c_parser_next_token_is_not (parser, CPP_COMMA)) + break; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + { + c_parser_error (parser, "expected identifier"); + break; + } + } if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - { - struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info); - ret->parms = 0; - ret->tags = 0; - ret->types = list; - ret->others = 0; - ret->pending_sizes = 0; - ret->had_vla_unspec = 0; - c_parser_consume_token (parser); - pop_scope (); - return ret; - } + { + struct c_arg_info *ret = XOBNEW (&parser_obstack, struct c_arg_info); + ret->parms = 0; + ret->tags = 0; + ret->types = list; + ret->others = 0; + ret->pending_sizes = 0; + ret->had_vla_unspec = 0; + c_parser_consume_token (parser); + pop_scope (); + return ret; + } else - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - pop_scope (); - return NULL; - } + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + pop_scope (); + return NULL; + } } else { @@ -2551,19 +2627,19 @@ /* Suppress -Wold-style-definition for this case. */ ret->types = error_mark_node; error_at (c_parser_peek_token (parser)->location, - "ISO C requires a named argument before %<...%>"); + "ISO C requires a named argument before %<...%>"); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - { - c_parser_consume_token (parser); - return ret; - } + { + c_parser_consume_token (parser); + return ret; + } else - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - return NULL; - } + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + return NULL; + } } /* Nonempty list of parameters, either terminated with semicolon (forward declarations; recurse) or with close parenthesis (normal @@ -2574,72 +2650,72 @@ struct c_parm *parm = c_parser_parameter_declaration (parser, attrs); attrs = NULL_TREE; if (parm != NULL) - { - good_parm = true; - push_parm_decl (parm); - } + { + good_parm = true; + push_parm_decl (parm); + } if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - tree new_attrs; - c_parser_consume_token (parser); - mark_forward_parm_decls (); - new_attrs = c_parser_attributes (parser); - return c_parser_parms_list_declarator (parser, new_attrs); - } + { + tree new_attrs; + c_parser_consume_token (parser); + mark_forward_parm_decls (); + new_attrs = c_parser_attributes (parser); + return c_parser_parms_list_declarator (parser, new_attrs); + } if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - { - c_parser_consume_token (parser); - if (good_parm) - return get_parm_info (false); - else - { - struct c_arg_info *ret - = XOBNEW (&parser_obstack, struct c_arg_info); - ret->parms = 0; - ret->tags = 0; - ret->types = 0; - ret->others = 0; - ret->pending_sizes = 0; - ret->had_vla_unspec = 0; - return ret; - } - } + { + c_parser_consume_token (parser); + if (good_parm) + return get_parm_info (false); + else + { + struct c_arg_info *ret + = XOBNEW (&parser_obstack, struct c_arg_info); + ret->parms = 0; + ret->tags = 0; + ret->types = 0; + ret->others = 0; + ret->pending_sizes = 0; + ret->had_vla_unspec = 0; + return ret; + } + } if (!c_parser_require (parser, CPP_COMMA, - "expected %<;%>, %<,%> or %<)%>")) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - get_pending_sizes (); - return NULL; - } + "expected %<;%>, %<,%> or %<)%>")) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + get_pending_sizes (); + return NULL; + } if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) - { - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - { - c_parser_consume_token (parser); - if (good_parm) - return get_parm_info (true); - else - { - struct c_arg_info *ret - = XOBNEW (&parser_obstack, struct c_arg_info); - ret->parms = 0; - ret->tags = 0; - ret->types = 0; - ret->others = 0; - ret->pending_sizes = 0; - ret->had_vla_unspec = 0; - return ret; - } - } - else - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - get_pending_sizes (); - return NULL; - } - } + { + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + { + c_parser_consume_token (parser); + if (good_parm) + return get_parm_info (true); + else + { + struct c_arg_info *ret + = XOBNEW (&parser_obstack, struct c_arg_info); + ret->parms = 0; + ret->tags = 0; + ret->types = 0; + ret->others = 0; + ret->pending_sizes = 0; + ret->had_vla_unspec = 0; + return ret; + } + } + else + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + get_pending_sizes (); + return NULL; + } + } } } @@ -2657,9 +2733,9 @@ if (!c_parser_next_token_starts_declspecs (parser)) { /* ??? In some Objective-C cases '...' isn't applicable so there - should be a different message. */ + should be a different message. */ c_parser_error (parser, - "expected declaration specifiers or %<...%>"); + "expected declaration specifiers or %<...%>"); c_parser_skip_to_end_of_parameter (parser); return NULL; } @@ -2675,7 +2751,7 @@ prefix_attrs = specs->attrs; specs->attrs = NULL_TREE; declarator = c_parser_declarator (parser, specs->type_seen_p, - C_DTR_PARM, &dummy); + C_DTR_PARM, &dummy); if (declarator == NULL) { c_parser_skip_until_found (parser, CPP_COMMA, NULL); @@ -2684,7 +2760,7 @@ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) postfix_attrs = c_parser_attributes (parser); return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs), - declarator); + declarator); } /* Parse a string literal in an asm expression. It should not be @@ -2710,7 +2786,7 @@ else if (c_parser_next_token_is (parser, CPP_WSTRING)) { error_at (c_parser_peek_token (parser)->location, - "wide string literal in %<asm%>"); + "wide string literal in %<asm%>"); str = build_string (1, ""); c_parser_consume_token (parser); } @@ -2788,146 +2864,154 @@ while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) { /* ??? Follow the C++ parser rather than using the - lex_untranslated_string kludge. */ + lex_untranslated_string kludge. */ parser->lex_untranslated_string = true; c_parser_consume_token (parser); if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - parser->lex_untranslated_string = false; - return attrs; - } + { + parser->lex_untranslated_string = false; + return attrs; + } if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - parser->lex_untranslated_string = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return attrs; - } + { + parser->lex_untranslated_string = false; + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + return attrs; + } /* Parse the attribute list. */ while (c_parser_next_token_is (parser, CPP_COMMA) - || c_parser_next_token_is (parser, CPP_NAME) - || c_parser_next_token_is (parser, CPP_KEYWORD)) - { - tree attr, attr_name, attr_args; - if (c_parser_next_token_is (parser, CPP_COMMA)) - { - c_parser_consume_token (parser); - continue; - } - if (c_parser_next_token_is (parser, CPP_KEYWORD)) - { - /* ??? See comment above about what keywords are - accepted here. */ - bool ok; - switch (c_parser_peek_token (parser)->keyword) - { - case RID_STATIC: - case RID_UNSIGNED: - case RID_LONG: - case RID_CONST: - case RID_EXTERN: - case RID_REGISTER: - case RID_TYPEDEF: - case RID_SHORT: - case RID_INLINE: - case RID_VOLATILE: - case RID_SIGNED: - case RID_AUTO: - case RID_RESTRICT: - case RID_COMPLEX: - case RID_THREAD: - case RID_INT: - case RID_CHAR: - case RID_FLOAT: - case RID_DOUBLE: - case RID_VOID: - case RID_DFLOAT32: - case RID_DFLOAT64: - case RID_DFLOAT128: - case RID_BOOL: - case RID_FRACT: - case RID_ACCUM: - case RID_SAT: - ok = true; - break; - default: - ok = false; - break; - } - if (!ok) - break; - /* Accept __attribute__((__const)) as __attribute__((const)) - etc. */ - attr_name - = ridpointers[(int) c_parser_peek_token (parser)->keyword]; - } - else - attr_name = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) - { - attr = build_tree_list (attr_name, NULL_TREE); - attrs = chainon (attrs, attr); - continue; - } - c_parser_consume_token (parser); - /* Parse the attribute contents. If they start with an - identifier which is followed by a comma or close - parenthesis, then the arguments start with that - identifier; otherwise they are an expression list. */ - if (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_token (parser)->id_kind == C_ID_ID - && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA) - || (c_parser_peek_2nd_token (parser)->type - == CPP_CLOSE_PAREN))) - { - tree arg1 = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - attr_args = build_tree_list (NULL_TREE, arg1); - else - { - c_parser_consume_token (parser); - attr_args = tree_cons (NULL_TREE, arg1, - c_parser_expr_list (parser, false)); - } - } - else - { - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - attr_args = NULL_TREE; - else - attr_args = c_parser_expr_list (parser, false); - } - attr = build_tree_list (attr_name, attr_args); - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - c_parser_consume_token (parser); - else - { - parser->lex_untranslated_string = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - return attrs; - } - attrs = chainon (attrs, attr); - } + || c_parser_next_token_is (parser, CPP_NAME) + || c_parser_next_token_is (parser, CPP_KEYWORD)) + { + tree attr, attr_name, attr_args; + VEC(tree,gc) *expr_list; + if (c_parser_next_token_is (parser, CPP_COMMA)) + { + c_parser_consume_token (parser); + continue; + } + if (c_parser_next_token_is (parser, CPP_KEYWORD)) + { + /* ??? See comment above about what keywords are + accepted here. */ + bool ok; + switch (c_parser_peek_token (parser)->keyword) + { + case RID_STATIC: + case RID_UNSIGNED: + case RID_LONG: + case RID_CONST: + case RID_EXTERN: + case RID_REGISTER: + case RID_TYPEDEF: + case RID_SHORT: + case RID_INLINE: + case RID_VOLATILE: + case RID_SIGNED: + case RID_AUTO: + case RID_RESTRICT: + case RID_COMPLEX: + case RID_THREAD: + case RID_INT: + case RID_CHAR: + case RID_FLOAT: + case RID_DOUBLE: + case RID_VOID: + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: + case RID_BOOL: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: + ok = true; + break; + default: + ok = false; + break; + } + if (!ok) + break; + /* Accept __attribute__((__const)) as __attribute__((const)) + etc. */ + attr_name + = ridpointers[(int) c_parser_peek_token (parser)->keyword]; + } + else + attr_name = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) + { + attr = build_tree_list (attr_name, NULL_TREE); + attrs = chainon (attrs, attr); + continue; + } + c_parser_consume_token (parser); + /* Parse the attribute contents. If they start with an + identifier which is followed by a comma or close + parenthesis, then the arguments start with that + identifier; otherwise they are an expression list. */ + if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_token (parser)->id_kind == C_ID_ID + && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA) + || (c_parser_peek_2nd_token (parser)->type + == CPP_CLOSE_PAREN))) + { + tree arg1 = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + attr_args = build_tree_list (NULL_TREE, arg1); + else + { + tree tree_list; + c_parser_consume_token (parser); + expr_list = c_parser_expr_list (parser, false, true, NULL); + tree_list = build_tree_list_vec (expr_list); + attr_args = tree_cons (NULL_TREE, arg1, tree_list); + release_tree_vector (expr_list); + } + } + else + { + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + attr_args = NULL_TREE; + else + { + expr_list = c_parser_expr_list (parser, false, true, NULL); + attr_args = build_tree_list_vec (expr_list); + release_tree_vector (expr_list); + } + } + attr = build_tree_list (attr_name, attr_args); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - c_parser_consume_token (parser); + c_parser_consume_token (parser); else - { - parser->lex_untranslated_string = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - return attrs; - } + { + parser->lex_untranslated_string = false; + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + return attrs; + } + attrs = chainon (attrs, attr); + } if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - c_parser_consume_token (parser); + c_parser_consume_token (parser); else - { - parser->lex_untranslated_string = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - return attrs; - } + { + parser->lex_untranslated_string = false; + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + return attrs; + } + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + c_parser_consume_token (parser); + else + { + parser->lex_untranslated_string = false; + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + return attrs; + } parser->lex_untranslated_string = false; } return attrs; @@ -2955,7 +3039,7 @@ pending_xref_error (); finish_declspecs (specs); declarator = c_parser_declarator (parser, specs->type_seen_p, - C_DTR_ABSTRACT, &dummy); + C_DTR_ABSTRACT, &dummy); if (declarator == NULL) return NULL; ret = XOBNEW (&parser_obstack, struct c_type_name); @@ -3015,10 +3099,11 @@ else { struct c_expr ret; + location_t loc = c_parser_peek_token (parser)->location; ret = c_parser_expr_no_commas (parser, NULL); if (TREE_CODE (ret.value) != STRING_CST - && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR) - ret = default_function_array_conversion (ret); + && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR) + ret = default_function_array_conversion (loc, ret); return ret; } } @@ -3046,25 +3131,26 @@ else { /* Parse a non-empty initializer list, possibly with a trailing - comma. */ + comma. */ while (true) - { - c_parser_initelt (parser); - if (parser->error) - break; - if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); - else - break; - if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - break; - } + { + c_parser_initelt (parser); + if (parser->error) + break; + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + break; + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + break; + } } if (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE)) { struct c_expr ret; ret.value = error_mark_node; ret.original_code = ERROR_MARK; + ret.original_type = NULL; c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>"); pop_init_level (0); return ret; @@ -3087,170 +3173,176 @@ /* Old-style structure member designator. */ set_init_label (c_parser_peek_token (parser)->value); /* Use the colon as the error location. */ - pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_pedantic, - "obsolete use of designated initializer with %<:%>"); + pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_pedantic, + "obsolete use of designated initializer with %<:%>"); c_parser_consume_token (parser); c_parser_consume_token (parser); } else { /* des_seen is 0 if there have been no designators, 1 if there - has been a single array designator and 2 otherwise. */ + has been a single array designator and 2 otherwise. */ int des_seen = 0; /* Location of a designator. */ location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */ while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE) - || c_parser_next_token_is (parser, CPP_DOT)) - { - int des_prev = des_seen; - if (!des_seen) - des_loc = c_parser_peek_token (parser)->location; - if (des_seen < 2) - des_seen++; - if (c_parser_next_token_is (parser, CPP_DOT)) - { - des_seen = 2; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_NAME)) - { - set_init_label (c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - } - else - { - struct c_expr init; - init.value = error_mark_node; - init.original_code = ERROR_MARK; - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_COMMA, NULL); - process_init_element (init, false); - return; - } - } - else - { - tree first, second; - location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */ - /* ??? Following the old parser, [ objc-receiver - objc-message-args ] is accepted as an initializer, - being distinguished from a designator by what follows - the first assignment expression inside the square - brackets, but after a first array designator a - subsequent square bracket is for Objective-C taken to - start an expression, using the obsolete form of - designated initializer without '=', rather than - possibly being a second level of designation: in LALR - terms, the '[' is shifted rather than reducing - designator to designator-list. */ - if (des_prev == 1 && c_dialect_objc ()) - { - des_seen = des_prev; - break; - } - if (des_prev == 0 && c_dialect_objc ()) - { - /* This might be an array designator or an - Objective-C message expression. If the former, - continue parsing here; if the latter, parse the - remainder of the initializer given the starting - primary-expression. ??? It might make sense to - distinguish when des_prev == 1 as well; see - previous comment. */ - tree rec, args; - struct c_expr mexpr; - c_parser_consume_token (parser); - if (c_parser_peek_token (parser)->type == CPP_NAME - && ((c_parser_peek_token (parser)->id_kind - == C_ID_TYPENAME) - || (c_parser_peek_token (parser)->id_kind - == C_ID_CLASSNAME))) - { - /* Type name receiver. */ - tree id = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - rec = objc_get_class_reference (id); - goto parse_message_args; - } - first = c_parser_expr_no_commas (parser, NULL).value; - if (c_parser_next_token_is (parser, CPP_ELLIPSIS) - || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) - goto array_desig_after_first; - /* Expression receiver. So far only one part - without commas has been parsed; there might be - more of the expression. */ - rec = first; - while (c_parser_next_token_is (parser, CPP_COMMA)) - { - struct c_expr next; - c_parser_consume_token (parser); - next = c_parser_expr_no_commas (parser, NULL); - next = default_function_array_conversion (next); - rec = build_compound_expr (rec, next.value); - } - parse_message_args: - /* Now parse the objc-message-args. */ - args = c_parser_objc_message_args (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, - "expected %<]%>"); - mexpr.value - = objc_build_message_expr (build_tree_list (rec, args)); - mexpr.original_code = ERROR_MARK; - /* Now parse and process the remainder of the - initializer, starting with this message - expression as a primary-expression. */ - c_parser_initval (parser, &mexpr); - return; - } - c_parser_consume_token (parser); - first = c_parser_expr_no_commas (parser, NULL).value; - array_desig_after_first: - if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) - { - ellipsis_loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - second = c_parser_expr_no_commas (parser, NULL).value; - } - else - second = NULL_TREE; - if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) - { - c_parser_consume_token (parser); - set_init_index (first, second); - if (second) - pedwarn (ellipsis_loc, OPT_pedantic, - "ISO C forbids specifying range of elements to initialize"); - } - else - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, - "expected %<]%>"); - } - } + || c_parser_next_token_is (parser, CPP_DOT)) + { + int des_prev = des_seen; + if (!des_seen) + des_loc = c_parser_peek_token (parser)->location; + if (des_seen < 2) + des_seen++; + if (c_parser_next_token_is (parser, CPP_DOT)) + { + des_seen = 2; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + set_init_label (c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + } + else + { + struct c_expr init; + init.value = error_mark_node; + init.original_code = ERROR_MARK; + init.original_type = NULL; + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_COMMA, NULL); + process_init_element (init, false); + return; + } + } + else + { + tree first, second; + location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */ + /* ??? Following the old parser, [ objc-receiver + objc-message-args ] is accepted as an initializer, + being distinguished from a designator by what follows + the first assignment expression inside the square + brackets, but after a first array designator a + subsequent square bracket is for Objective-C taken to + start an expression, using the obsolete form of + designated initializer without '=', rather than + possibly being a second level of designation: in LALR + terms, the '[' is shifted rather than reducing + designator to designator-list. */ + if (des_prev == 1 && c_dialect_objc ()) + { + des_seen = des_prev; + break; + } + if (des_prev == 0 && c_dialect_objc ()) + { + /* This might be an array designator or an + Objective-C message expression. If the former, + continue parsing here; if the latter, parse the + remainder of the initializer given the starting + primary-expression. ??? It might make sense to + distinguish when des_prev == 1 as well; see + previous comment. */ + tree rec, args; + struct c_expr mexpr; + c_parser_consume_token (parser); + if (c_parser_peek_token (parser)->type == CPP_NAME + && ((c_parser_peek_token (parser)->id_kind + == C_ID_TYPENAME) + || (c_parser_peek_token (parser)->id_kind + == C_ID_CLASSNAME))) + { + /* Type name receiver. */ + tree id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + rec = objc_get_class_reference (id); + goto parse_message_args; + } + first = c_parser_expr_no_commas (parser, NULL).value; + if (c_parser_next_token_is (parser, CPP_ELLIPSIS) + || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) + goto array_desig_after_first; + /* Expression receiver. So far only one part + without commas has been parsed; there might be + more of the expression. */ + rec = first; + while (c_parser_next_token_is (parser, CPP_COMMA)) + { + struct c_expr next; + location_t comma_loc, exp_loc; + comma_loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; + next = c_parser_expr_no_commas (parser, NULL); + next = default_function_array_conversion (exp_loc, next); + rec = build_compound_expr (comma_loc, rec, next.value); + } + parse_message_args: + /* Now parse the objc-message-args. */ + args = c_parser_objc_message_args (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + mexpr.value + = objc_build_message_expr (build_tree_list (rec, args)); + mexpr.original_code = ERROR_MARK; + mexpr.original_type = NULL; + /* Now parse and process the remainder of the + initializer, starting with this message + expression as a primary-expression. */ + c_parser_initval (parser, &mexpr); + return; + } + c_parser_consume_token (parser); + first = c_parser_expr_no_commas (parser, NULL).value; + array_desig_after_first: + if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) + { + ellipsis_loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + second = c_parser_expr_no_commas (parser, NULL).value; + } + else + second = NULL_TREE; + if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) + { + c_parser_consume_token (parser); + set_init_index (first, second); + if (second) + pedwarn (ellipsis_loc, OPT_pedantic, + "ISO C forbids specifying range of elements to initialize"); + } + else + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + } + } if (des_seen >= 1) - { - if (c_parser_next_token_is (parser, CPP_EQ)) - { - if (!flag_isoc99) - pedwarn (des_loc, OPT_pedantic, - "ISO C90 forbids specifying subobject to initialize"); - c_parser_consume_token (parser); - } - else - { - if (des_seen == 1) - pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, - "obsolete use of designated initializer without %<=%>"); - else - { - struct c_expr init; - init.value = error_mark_node; - init.original_code = ERROR_MARK; - c_parser_error (parser, "expected %<=%>"); - c_parser_skip_until_found (parser, CPP_COMMA, NULL); - process_init_element (init, false); - return; - } - } - } + { + if (c_parser_next_token_is (parser, CPP_EQ)) + { + if (!flag_isoc99) + pedwarn (des_loc, OPT_pedantic, + "ISO C90 forbids specifying subobject to initialize"); + c_parser_consume_token (parser); + } + else + { + if (des_seen == 1) + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "obsolete use of designated initializer without %<=%>"); + else + { + struct c_expr init; + init.value = error_mark_node; + init.original_code = ERROR_MARK; + init.original_type = NULL; + c_parser_error (parser, "expected %<=%>"); + c_parser_skip_until_found (parser, CPP_COMMA, NULL); + process_init_element (init, false); + return; + } + } + } } c_parser_initval (parser, NULL); } @@ -3270,11 +3362,12 @@ init = c_parser_braced_init (parser, NULL_TREE, true); else { + location_t loc = c_parser_peek_token (parser)->location; init = c_parser_expr_no_commas (parser, after); if (init.value != NULL_TREE - && TREE_CODE (init.value) != STRING_CST - && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR) - init = default_function_array_conversion (init); + && TREE_CODE (init.value) != STRING_CST + && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR) + init = default_function_array_conversion (loc, init); } process_init_element (init, false); } @@ -3322,9 +3415,9 @@ old parser in requiring something after label declarations. Although they are erroneous if the labels declared aren't defined, is it useful for the syntax to be this way? - + OpenMP: - + block-item: openmp-directive @@ -3336,17 +3429,19 @@ c_parser_compound_statement (c_parser *parser) { tree stmt; + location_t brace_loc; + brace_loc = c_parser_peek_token (parser)->location; if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) { /* Ensure a scope is entered and left anyway to avoid confusion - if we have just prepared to enter a function body. */ + if we have just prepared to enter a function body. */ stmt = c_begin_compound_stmt (true); - c_end_compound_stmt (stmt, true); + c_end_compound_stmt (brace_loc, stmt, true); return error_mark_node; } stmt = c_begin_compound_stmt (true); c_parser_compound_statement_nostart (parser); - return c_end_compound_stmt (stmt, true); + return c_end_compound_stmt (brace_loc, stmt, true); } /* Parse a compound statement except for the opening brace. This is @@ -3358,47 +3453,51 @@ { bool last_stmt = false; bool last_label = false; + bool save_valid_for_pragma = valid_location_for_stdc_pragma_p (); location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { c_parser_consume_token (parser); return; } + mark_valid_location_for_stdc_pragma (true); if (c_parser_next_token_is_keyword (parser, RID_LABEL)) { - location_t err_loc = c_parser_peek_token (parser)->location; /* Read zero or more forward-declarations for labels that nested - functions can jump to. */ + functions can jump to. */ + mark_valid_location_for_stdc_pragma (false); while (c_parser_next_token_is_keyword (parser, RID_LABEL)) - { - c_parser_consume_token (parser); - /* Any identifiers, including those declared as type names, - are OK here. */ - while (true) - { - tree label; - if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - break; - } - label - = declare_label (c_parser_peek_token (parser)->value); - C_DECLARED_LABEL_FLAG (label) = 1; - add_stmt (build_stmt (DECL_EXPR, label)); - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); - else - break; - } - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); - } - pedwarn (err_loc, OPT_pedantic, "ISO C forbids label declarations"); + { + label_loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + /* Any identifiers, including those declared as type names, + are OK here. */ + while (true) + { + tree label; + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + break; + } + label + = declare_label (c_parser_peek_token (parser)->value); + C_DECLARED_LABEL_FLAG (label) = 1; + add_stmt (build_stmt (label_loc, DECL_EXPR, label)); + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + break; + } + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + } + pedwarn (label_loc, OPT_pedantic, "ISO C forbids label declarations"); } /* We must now have at least one statement, label or declaration. */ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { + mark_valid_location_for_stdc_pragma (save_valid_for_pragma); c_parser_error (parser, "expected declaration or statement"); c_parser_consume_token (parser); return; @@ -3407,85 +3506,90 @@ { location_t loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is_keyword (parser, RID_CASE) - || c_parser_next_token_is_keyword (parser, RID_DEFAULT) - || (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) - { - if (c_parser_next_token_is_keyword (parser, RID_CASE)) - label_loc = c_parser_peek_2nd_token (parser)->location; - else - label_loc = c_parser_peek_token (parser)->location; - last_label = true; - last_stmt = false; - c_parser_label (parser); - } + || c_parser_next_token_is_keyword (parser, RID_DEFAULT) + || (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + { + if (c_parser_next_token_is_keyword (parser, RID_CASE)) + label_loc = c_parser_peek_2nd_token (parser)->location; + else + label_loc = c_parser_peek_token (parser)->location; + last_label = true; + last_stmt = false; + mark_valid_location_for_stdc_pragma (false); + c_parser_label (parser); + } else if (!last_label - && c_parser_next_token_starts_declspecs (parser)) - { - last_label = false; - c_parser_declaration_or_fndef (parser, true, true, true, true); - if (last_stmt) - pedwarn_c90 (loc, - (pedantic && !flag_isoc99) - ? OPT_pedantic - : OPT_Wdeclaration_after_statement, - "ISO C90 forbids mixed declarations and code"); - last_stmt = false; - } + && c_parser_next_token_starts_declspecs (parser)) + { + last_label = false; + mark_valid_location_for_stdc_pragma (false); + c_parser_declaration_or_fndef (parser, true, true, true, true); + if (last_stmt) + pedwarn_c90 (loc, + (pedantic && !flag_isoc99) + ? OPT_pedantic + : OPT_Wdeclaration_after_statement, + "ISO C90 forbids mixed declarations and code"); + last_stmt = false; + } else if (!last_label - && c_parser_next_token_is_keyword (parser, RID_EXTENSION)) - { - /* __extension__ can start a declaration, but is also an - unary operator that can start an expression. Consume all - but the last of a possible series of __extension__ to - determine which. */ - while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD - && (c_parser_peek_2nd_token (parser)->keyword - == RID_EXTENSION)) - c_parser_consume_token (parser); - if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser))) - { - int ext; - ext = disable_extension_diagnostics (); - c_parser_consume_token (parser); - last_label = false; - c_parser_declaration_or_fndef (parser, true, true, true, true); - /* Following the old parser, __extension__ does not - disable this diagnostic. */ - restore_extension_diagnostics (ext); - if (last_stmt) - pedwarn_c90 (loc, (pedantic && !flag_isoc99) - ? OPT_pedantic - : OPT_Wdeclaration_after_statement, - "ISO C90 forbids mixed declarations and code"); - last_stmt = false; - } - else - goto statement; - } + && c_parser_next_token_is_keyword (parser, RID_EXTENSION)) + { + /* __extension__ can start a declaration, but is also an + unary operator that can start an expression. Consume all + but the last of a possible series of __extension__ to + determine which. */ + while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD + && (c_parser_peek_2nd_token (parser)->keyword + == RID_EXTENSION)) + c_parser_consume_token (parser); + if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser))) + { + int ext; + ext = disable_extension_diagnostics (); + c_parser_consume_token (parser); + last_label = false; + mark_valid_location_for_stdc_pragma (false); + c_parser_declaration_or_fndef (parser, true, true, true, true); + /* Following the old parser, __extension__ does not + disable this diagnostic. */ + restore_extension_diagnostics (ext); + if (last_stmt) + pedwarn_c90 (loc, (pedantic && !flag_isoc99) + ? OPT_pedantic + : OPT_Wdeclaration_after_statement, + "ISO C90 forbids mixed declarations and code"); + last_stmt = false; + } + else + goto statement; + } else if (c_parser_next_token_is (parser, CPP_PRAGMA)) - { - /* External pragmas, and some omp pragmas, are not associated - with regular c code, and so are not to be considered statements - syntactically. This ensures that the user doesn't put them - places that would turn into syntax errors if the directive - were ignored. */ - if (c_parser_pragma (parser, pragma_compound)) - last_label = false, last_stmt = true; - } + { + /* External pragmas, and some omp pragmas, are not associated + with regular c code, and so are not to be considered statements + syntactically. This ensures that the user doesn't put them + places that would turn into syntax errors if the directive + were ignored. */ + if (c_parser_pragma (parser, pragma_compound)) + last_label = false, last_stmt = true; + } else if (c_parser_next_token_is (parser, CPP_EOF)) - { - c_parser_error (parser, "expected declaration or statement"); - return; - } + { + mark_valid_location_for_stdc_pragma (save_valid_for_pragma); + c_parser_error (parser, "expected declaration or statement"); + return; + } else if (c_parser_next_token_is_keyword (parser, RID_ELSE)) { - if (parser->in_if_block) + if (parser->in_if_block) { + mark_valid_location_for_stdc_pragma (save_valid_for_pragma); error_at (loc, """expected %<}%> before %<else%>"); return; } - else + else { error_at (loc, "%<else%> without a previous %<if%>"); c_parser_consume_token (parser); @@ -3493,18 +3597,21 @@ } } else - { - statement: - last_label = false; - last_stmt = true; - c_parser_statement_after_labels (parser); - } + { + statement: + last_label = false; + last_stmt = true; + mark_valid_location_for_stdc_pragma (false); + c_parser_statement_after_labels (parser); + } parser->error = false; } if (last_label) error_at (label_loc, "label at end of compound statement"); c_parser_consume_token (parser); + /* Restore the value we started with. */ + mark_valid_location_for_stdc_pragma (save_valid_for_pragma); } /* Parse a label (C90 6.6.1, C99 6.8.1). @@ -3534,25 +3641,25 @@ c_parser_consume_token (parser); exp1 = c_parser_expr_no_commas (parser, NULL).value; if (c_parser_next_token_is (parser, CPP_COLON)) - { - c_parser_consume_token (parser); - label = do_case (exp1, NULL_TREE); - } + { + c_parser_consume_token (parser); + label = do_case (loc1, exp1, NULL_TREE); + } else if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) - { - c_parser_consume_token (parser); - exp2 = c_parser_expr_no_commas (parser, NULL).value; - if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) - label = do_case (exp1, exp2); - } + { + c_parser_consume_token (parser); + exp2 = c_parser_expr_no_commas (parser, NULL).value; + if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) + label = do_case (loc1, exp1, exp2); + } else - c_parser_error (parser, "expected %<:%> or %<...%>"); + c_parser_error (parser, "expected %<:%> or %<...%>"); } else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)) { c_parser_consume_token (parser); if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) - label = do_case (NULL_TREE, NULL_TREE); + label = do_case (loc1, NULL_TREE, NULL_TREE); } else { @@ -3567,25 +3674,24 @@ attrs = c_parser_attributes (parser); tlab = define_label (loc2, name); if (tlab) - { - decl_attributes (&tlab, attrs, 0); - label = add_stmt (build_stmt (LABEL_EXPR, tlab)); - } + { + decl_attributes (&tlab, attrs, 0); + label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab)); + } } if (label) { - SET_EXPR_LOCATION (label, loc1); if (c_parser_next_token_starts_declspecs (parser) - && !(c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) - { - error_at (c_parser_peek_token (parser)->location, - "a label can only be part of a statement and " - "a declaration is not a statement"); - c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, - /*nested*/ true, /*empty_ok*/ false, - /*start_attr_ok*/ true); - } + && !(c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + { + error_at (c_parser_peek_token (parser)->location, + "a label can only be part of a statement and " + "a declaration is not a statement"); + c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, + /*nested*/ true, /*empty_ok*/ false, + /*start_attr_ok*/ true); + } } } @@ -3690,9 +3796,9 @@ c_parser_statement (c_parser *parser) { while (c_parser_next_token_is_keyword (parser, RID_CASE) - || c_parser_next_token_is_keyword (parser, RID_DEFAULT) - || (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + || c_parser_next_token_is_keyword (parser, RID_DEFAULT) + || (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) c_parser_label (parser); c_parser_statement_after_labels (parser); } @@ -3744,10 +3850,10 @@ fn = CALL_EXPR_FN (call); if ( TREE_CODE (fn)==PARM_DECL || !TREE_CONSTANT (fn) ) { - tmp_decl = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE(fn)); + tmp_decl = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE(fn)); pushdecl (tmp_decl); - add_stmt (build_modify_expr (loc, tmp_decl, NOP_EXPR, fn)); + add_stmt (build_modify_expr (loc, tmp_decl, NULL_TREE, NOP_EXPR, loc, fn, NULL_TREE)); CALL_EXPR_FN (call) = tmp_decl; } @@ -3758,13 +3864,13 @@ //if ( !CONSTANT_CLASS_P (arg) && !VAR_OR_FUNCTION_DECL_P (arg) ) if ( TREE_CODE (arg)==PARM_DECL || !TREE_CONSTANT (arg) ) - { - tmp_decl = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE(arg)); - pushdecl (tmp_decl); - - add_stmt (build_modify_expr (loc, tmp_decl, NOP_EXPR, arg)); - CALL_EXPR_ARG (call, i) = tmp_decl; - } + { + tmp_decl = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE(arg)); + pushdecl (tmp_decl); + + add_stmt (build_modify_expr (loc, tmp_decl, NULL_TREE, NOP_EXPR, loc, arg, NULL_TREE)); + CALL_EXPR_ARG (call, i) = tmp_decl; + } } return call; @@ -3786,120 +3892,125 @@ break; case CPP_KEYWORD: switch (c_parser_peek_token (parser)->keyword) - { - case RID_IF: - c_parser_if_statement (parser); - break; - case RID_SWITCH: - c_parser_switch_statement (parser); - break; - case RID_WHILE: - c_parser_while_statement (parser); - break; - case RID_DO: - c_parser_do_statement (parser); - break; - case RID_FOR: - c_parser_for_statement (parser); - break; - case RID_GOTO: - c_parser_consume_token (parser); + { + case RID_IF: + c_parser_if_statement (parser); + break; + case RID_SWITCH: + c_parser_switch_statement (parser); + break; + case RID_WHILE: + c_parser_while_statement (parser); + break; + case RID_DO: + c_parser_do_statement (parser); + break; + case RID_FOR: + c_parser_for_statement (parser); + break; + case RID_GOTO: + c_parser_consume_token (parser); #ifndef noCbC - if ( c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON ) - { + if ( c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON ) + { #else - if (c_parser_next_token_is (parser, CPP_NAME)) - { + if (c_parser_next_token_is (parser, CPP_NAME)) + { #endif - stmt = c_finish_goto_label (c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - } - else if (c_parser_next_token_is (parser, CPP_MULT)) - { - c_parser_consume_token (parser); - stmt = c_finish_goto_ptr (c_parser_expression (parser).value); - } - else + stmt = c_finish_goto_label (loc, + c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + } + else if (c_parser_next_token_is (parser, CPP_MULT)) + { + c_parser_consume_token (parser); + stmt = c_finish_goto_ptr (loc, + c_parser_expression (parser).value); + } + else #ifndef noCbC - { - struct c_expr expr; - if (c_parser_next_token_is (parser, CPP_NAME)) - { - tree id = c_parser_peek_token (parser)->value; + { + struct c_expr expr; + if (c_parser_next_token_is (parser, CPP_NAME)) + { + tree id = c_parser_peek_token (parser)->value; location_t loc = c_parser_peek_token (parser)->location; - build_external_ref (id,RID_CbC_CODE , loc); - } - expr = c_parser_expr_no_commas (parser, NULL); - if (TREE_CODE(expr.value) == CALL_EXPR ) - { - location_t loc = c_parser_peek_token (parser)->location; - cbc_replace_arguments (loc, expr.value); - - TREE_TYPE(expr.value) = void_type_node; - /*tree env = NULL_TREE;**/ - CbC_IS_CbC_GOTO (expr.value) = 1; - CALL_EXPR_TAILCALL (expr.value) = 1; - add_stmt(expr.value); - stmt = c_finish_return (0); - } - else - c_parser_error (parser, "expected code segment jump or %<*%>"); - } + /** build_external_ref (id,RID_CbC_CODE , loc); **/ + build_external_ref (loc, id, RID_CbC_CODE, &expr.original_type); + } + expr = c_parser_expr_no_commas (parser, NULL); + if (TREE_CODE(expr.value) == CALL_EXPR ) + { + location_t loc = c_parser_peek_token (parser)->location; + cbc_replace_arguments (loc, expr.value); + + TREE_TYPE(expr.value) = void_type_node; + /*tree env = NULL_TREE;**/ + CbC_IS_CbC_GOTO (expr.value) = 1; + CALL_EXPR_TAILCALL (expr.value) = 1; + add_stmt(expr.value); + stmt = c_finish_return(loc, expr.value, expr.original_type); /* stmt = c_finish_return (0); */ + } + else + c_parser_error (parser, "expected code segment jump or %<*%>"); + } #else - c_parser_error (parser, "expected identifier or %<*%>"); + c_parser_error (parser, "expected identifier or %<*%>"); #endif - goto expect_semicolon; - case RID_CONTINUE: - c_parser_consume_token (parser); - stmt = c_finish_bc_stmt (&c_cont_label, false); - goto expect_semicolon; - case RID_BREAK: - c_parser_consume_token (parser); - stmt = c_finish_bc_stmt (&c_break_label, true); - goto expect_semicolon; - case RID_RETURN: - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - stmt = c_finish_return (NULL_TREE); - c_parser_consume_token (parser); - } - else - { - stmt = c_finish_return (c_parser_expression_conv (parser).value); - goto expect_semicolon; - } - break; - case RID_ASM: - stmt = c_parser_asm_statement (parser); - break; - case RID_THROW: - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - stmt = objc_build_throw_stmt (NULL_TREE); - c_parser_consume_token (parser); - } - else - { - stmt - = objc_build_throw_stmt (c_parser_expression (parser).value); - goto expect_semicolon; - } - break; - case RID_TRY: - gcc_assert (c_dialect_objc ()); - c_parser_objc_try_catch_statement (parser); - break; - case RID_AT_SYNCHRONIZED: - gcc_assert (c_dialect_objc ()); - c_parser_objc_synchronized_statement (parser); - break; - default: - goto expr_stmt; - } + goto expect_semicolon; + case RID_CONTINUE: + c_parser_consume_token (parser); + stmt = c_finish_bc_stmt (loc, &c_cont_label, false); + goto expect_semicolon; + case RID_BREAK: + c_parser_consume_token (parser); + stmt = c_finish_bc_stmt (loc, &c_break_label, true); + goto expect_semicolon; + case RID_RETURN: + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + stmt = c_finish_return (loc, NULL_TREE, NULL_TREE); + c_parser_consume_token (parser); + } + else + { + struct c_expr expr = c_parser_expression_conv (parser); + stmt = c_finish_return (loc, expr.value, expr.original_type); + goto expect_semicolon; + } + break; + case RID_ASM: + stmt = c_parser_asm_statement (parser); + break; + case RID_THROW: + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + stmt = objc_build_throw_stmt (loc, NULL_TREE); + c_parser_consume_token (parser); + } + else + { + tree expr = c_parser_expression (parser).value; + expr = c_fully_fold (expr, false, NULL); + stmt = objc_build_throw_stmt (loc, expr); + goto expect_semicolon; + } + break; + case RID_TRY: + gcc_assert (c_dialect_objc ()); + c_parser_objc_try_catch_statement (parser); + break; + case RID_AT_SYNCHRONIZED: + gcc_assert (c_dialect_objc ()); + c_parser_objc_synchronized_statement (parser); + break; + default: + goto expr_stmt; + } break; case CPP_SEMICOLON: c_parser_consume_token (parser); @@ -3907,9 +4018,9 @@ case CPP_CLOSE_PAREN: case CPP_CLOSE_SQUARE: /* Avoid infinite loop in error recovery: - c_parser_skip_until_found stops at a closing nesting - delimiter without consuming it, but here we need to consume - it to proceed further. */ + c_parser_skip_until_found stops at a closing nesting + delimiter without consuming it, but here we need to consume + it to proceed further. */ c_parser_error (parser, "expected statement"); c_parser_consume_token (parser); break; @@ -3918,7 +4029,7 @@ break; default: expr_stmt: - stmt = c_finish_expr_stmt (c_parser_expression_conv (parser).value); + stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value); expect_semicolon: c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); break; @@ -3933,7 +4044,9 @@ (recursively) all of the component statements should already have line numbers assigned. ??? Can we discard no-op statements earlier? */ - protected_set_expr_location (stmt, loc); + if (CAN_HAVE_LOCATION_P (stmt) + && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION) + SET_EXPR_LOCATION (stmt, loc); parser->in_if_block = in_if_block; } @@ -3943,12 +4056,11 @@ static tree c_parser_condition (c_parser *parser) { - location_t loc; + location_t loc = c_parser_peek_token (parser)->location; tree cond; - loc = c_parser_peek_token (parser)->location; - cond = c_objc_common_truthvalue_conversion - (loc, c_parser_expression_conv (parser).value); - protected_set_expr_location (cond, loc); + cond = c_parser_expression_conv (parser).value; + cond = c_objc_common_truthvalue_conversion (loc, cond); + cond = c_fully_fold (cond, false, NULL); if (warn_sequence_point) verify_sequence_points (cond); return cond; @@ -3976,8 +4088,9 @@ c_parser_c99_block_statement (c_parser *parser) { tree block = c_begin_compound_stmt (flag_isoc99); + location_t loc = c_parser_peek_token (parser)->location; c_parser_statement (parser); - return c_end_compound_stmt (block, flag_isoc99); + return c_end_compound_stmt (loc, block, flag_isoc99); } /* Parse the body of an if statement. This is just parsing a @@ -3992,26 +4105,27 @@ c_parser_if_body (c_parser *parser, bool *if_p) { tree block = c_begin_compound_stmt (flag_isoc99); + location_t body_loc = c_parser_peek_token (parser)->location; while (c_parser_next_token_is_keyword (parser, RID_CASE) - || c_parser_next_token_is_keyword (parser, RID_DEFAULT) - || (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + || c_parser_next_token_is_keyword (parser, RID_DEFAULT) + || (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) c_parser_label (parser); *if_p = c_parser_next_token_is_keyword (parser, RID_IF); if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { location_t loc = c_parser_peek_token (parser)->location; - add_stmt (build_empty_stmt ()); + add_stmt (build_empty_stmt (loc)); c_parser_consume_token (parser); if (!c_parser_next_token_is_keyword (parser, RID_ELSE)) - warning_at (loc, OPT_Wempty_body, - "suggest braces around empty body in an %<if%> statement"); + warning_at (loc, OPT_Wempty_body, + "suggest braces around empty body in an %<if%> statement"); } else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) add_stmt (c_parser_compound_statement (parser)); else c_parser_statement_after_labels (parser); - return c_end_compound_stmt (block, flag_isoc99); + return c_end_compound_stmt (body_loc, block, flag_isoc99); } /* Parse the else body of an if statement. This is just parsing a @@ -4021,23 +4135,25 @@ static tree c_parser_else_body (c_parser *parser) { + location_t else_loc = c_parser_peek_token (parser)->location; tree block = c_begin_compound_stmt (flag_isoc99); while (c_parser_next_token_is_keyword (parser, RID_CASE) - || c_parser_next_token_is_keyword (parser, RID_DEFAULT) - || (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + || c_parser_next_token_is_keyword (parser, RID_DEFAULT) + || (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) c_parser_label (parser); if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { - warning_at (c_parser_peek_token (parser)->location, - OPT_Wempty_body, - "suggest braces around empty body in an %<else%> statement"); - add_stmt (build_empty_stmt ()); - c_parser_consume_token (parser); - } - else + location_t loc = c_parser_peek_token (parser)->location; + warning_at (loc, + OPT_Wempty_body, + "suggest braces around empty body in an %<else%> statement"); + add_stmt (build_empty_stmt (loc)); + c_parser_consume_token (parser); + } + else c_parser_statement_after_labels (parser); - return c_end_compound_stmt (block, flag_isoc99); + return c_end_compound_stmt (else_loc, block, flag_isoc99); } /* Parse an if statement (C90 6.6.4, C99 6.8.4). @@ -4074,7 +4190,7 @@ else second_body = NULL_TREE; c_finish_if_stmt (loc, cond, first_body, second_body, first_if); - add_stmt (c_end_compound_stmt (block, flag_isoc99)); + add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); } /* Parse a switch statement (C90 6.6.4, C99 6.8.4). @@ -4087,25 +4203,36 @@ c_parser_switch_statement (c_parser *parser) { tree block, expr, body, save_break; + location_t switch_loc = c_parser_peek_token (parser)->location; + location_t switch_cond_loc; gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH)); c_parser_consume_token (parser); block = c_begin_compound_stmt (flag_isoc99); if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { + switch_cond_loc = c_parser_peek_token (parser)->location; expr = c_parser_expression (parser).value; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } else - expr = error_mark_node; - c_start_case (expr); + { + switch_cond_loc = UNKNOWN_LOCATION; + expr = error_mark_node; + } + c_start_case (switch_loc, switch_cond_loc, expr); save_break = c_break_label; c_break_label = NULL_TREE; body = c_parser_c99_block_statement (parser); c_finish_case (body); if (c_break_label) - add_stmt (build1 (LABEL_EXPR, void_type_node, c_break_label)); + { + location_t here = c_parser_peek_token (parser)->location; + tree t = build1 (LABEL_EXPR, void_type_node, c_break_label); + SET_EXPR_LOCATION (t, here); + add_stmt (t); + } c_break_label = save_break; - add_stmt (c_end_compound_stmt (block, flag_isoc99)); + add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99)); } /* Parse a while statement (C90 6.6.5, C99 6.8.5). @@ -4130,7 +4257,7 @@ c_cont_label = NULL_TREE; body = c_parser_c99_block_statement (parser); c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true); - add_stmt (c_end_compound_stmt (block, flag_isoc99)); + add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); c_break_label = save_break; c_cont_label = save_cont; } @@ -4150,8 +4277,8 @@ c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_SEMICOLON)) warning_at (c_parser_peek_token (parser)->location, - OPT_Wempty_body, - "suggest braces around empty body in %<do%> statement"); + OPT_Wempty_body, + "suggest braces around empty body in %<do%> statement"); block = c_begin_compound_stmt (flag_isoc99); loc = c_parser_peek_token (parser)->location; save_break = c_break_label; @@ -4168,7 +4295,7 @@ if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) c_parser_skip_to_end_of_block_or_statement (parser); c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false); - add_stmt (c_end_compound_stmt (block, flag_isoc99)); + add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); } /* Parse a for statement (C90 6.6.5, C99 6.8.5). @@ -4191,68 +4318,68 @@ c_parser_for_statement (c_parser *parser) { tree block, cond, incr, save_break, save_cont, body; - location_t loc; + location_t loc = c_parser_peek_token (parser)->location; + location_t for_loc = c_parser_peek_token (parser)->location; gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR)); - loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); block = c_begin_compound_stmt (flag_isoc99); if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { /* Parse the initialization declaration or expression. */ if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - c_parser_consume_token (parser); - c_finish_expr_stmt (NULL_TREE); - } + { + c_parser_consume_token (parser); + c_finish_expr_stmt (loc, NULL_TREE); + } else if (c_parser_next_token_starts_declspecs (parser)) - { - c_parser_declaration_or_fndef (parser, true, true, true, true); - check_for_loop_decls (); - } + { + c_parser_declaration_or_fndef (parser, true, true, true, true); + check_for_loop_decls (for_loc); + } else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) - { - /* __extension__ can start a declaration, but is also an - unary operator that can start an expression. Consume all - but the last of a possible series of __extension__ to - determine which. */ - while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD - && (c_parser_peek_2nd_token (parser)->keyword - == RID_EXTENSION)) - c_parser_consume_token (parser); - if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser))) - { - int ext; - ext = disable_extension_diagnostics (); - c_parser_consume_token (parser); - c_parser_declaration_or_fndef (parser, true, true, true, true); - restore_extension_diagnostics (ext); - check_for_loop_decls (); - } - else - goto init_expr; - } + { + /* __extension__ can start a declaration, but is also an + unary operator that can start an expression. Consume all + but the last of a possible series of __extension__ to + determine which. */ + while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD + && (c_parser_peek_2nd_token (parser)->keyword + == RID_EXTENSION)) + c_parser_consume_token (parser); + if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser))) + { + int ext; + ext = disable_extension_diagnostics (); + c_parser_consume_token (parser); + c_parser_declaration_or_fndef (parser, true, true, true, true); + restore_extension_diagnostics (ext); + check_for_loop_decls (for_loc); + } else - { - init_expr: - c_finish_expr_stmt (c_parser_expression (parser).value); - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); - } + goto init_expr; + } + else + { + init_expr: + c_finish_expr_stmt (loc, c_parser_expression (parser).value); + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + } /* Parse the loop condition. */ if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - c_parser_consume_token (parser); - cond = NULL_TREE; - } + { + c_parser_consume_token (parser); + cond = NULL_TREE; + } else - { - cond = c_parser_condition (parser); - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); - } + { + cond = c_parser_condition (parser); + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + } /* Parse the increment expression. */ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - incr = c_process_expr_stmt (NULL_TREE); + incr = c_process_expr_stmt (loc, NULL_TREE); else - incr = c_process_expr_stmt (c_parser_expression (parser).value); + incr = c_process_expr_stmt (loc, c_parser_expression (parser).value); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } else @@ -4266,7 +4393,7 @@ c_cont_label = NULL_TREE; body = c_parser_c99_block_statement (parser); c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true); - add_stmt (c_end_compound_stmt (block, flag_isoc99)); + add_stmt (c_end_compound_stmt (loc, block, flag_isoc99)); c_break_label = save_break; c_cont_label = save_cont; } @@ -4277,12 +4404,17 @@ asm-statement: asm type-qualifier[opt] ( asm-argument ) ; + asm type-qualifier[opt] goto ( asm-goto-argument ) ; asm-argument: asm-string-literal asm-string-literal : asm-operands[opt] asm-string-literal : asm-operands[opt] : asm-operands[opt] - asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers + asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers[opt] + + asm-goto-argument: + asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \ + : asm-goto-operands Qualifiers other than volatile are accepted in the syntax but warned for. */ @@ -4290,8 +4422,11 @@ static tree c_parser_asm_statement (c_parser *parser) { - tree quals, str, outputs, inputs, clobbers, ret; - bool simple; + tree quals, str, outputs, inputs, clobbers, labels, ret; + bool simple, is_goto; + location_t asm_loc = c_parser_peek_token (parser)->location; + int section, nsections; + gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM)); c_parser_consume_token (parser); if (c_parser_next_token_is_keyword (parser, RID_VOLATILE)) @@ -4300,96 +4435,107 @@ c_parser_consume_token (parser); } else if (c_parser_next_token_is_keyword (parser, RID_CONST) - || c_parser_next_token_is_keyword (parser, RID_RESTRICT)) + || c_parser_next_token_is_keyword (parser, RID_RESTRICT)) { warning_at (c_parser_peek_token (parser)->location, - 0, - "%E qualifier ignored on asm", - c_parser_peek_token (parser)->value); + 0, + "%E qualifier ignored on asm", + c_parser_peek_token (parser)->value); quals = NULL_TREE; c_parser_consume_token (parser); } else quals = NULL_TREE; + + is_goto = false; + if (c_parser_next_token_is_keyword (parser, RID_GOTO)) + { + c_parser_consume_token (parser); + is_goto = true; + } + /* ??? Follow the C++ parser rather than using the lex_untranslated_string kludge. */ parser->lex_untranslated_string = true; + ret = NULL; + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - parser->lex_untranslated_string = false; - return NULL_TREE; - } + goto error; + str = c_parser_asm_string_literal (parser); if (str == NULL_TREE) - { - parser->lex_untranslated_string = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return NULL_TREE; - } - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - { - simple = true; - outputs = NULL_TREE; - inputs = NULL_TREE; - clobbers = NULL_TREE; - goto done_asm; - } - if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>")) - { - parser->lex_untranslated_string = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return NULL_TREE; - } - simple = false; - /* Parse outputs. */ - if (c_parser_next_token_is (parser, CPP_COLON) - || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - outputs = NULL_TREE; - else - outputs = c_parser_asm_operands (parser, false); - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - { - inputs = NULL_TREE; - clobbers = NULL_TREE; - goto done_asm; - } - if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>")) - { - parser->lex_untranslated_string = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return NULL_TREE; - } - /* Parse inputs. */ - if (c_parser_next_token_is (parser, CPP_COLON) - || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - inputs = NULL_TREE; - else - inputs = c_parser_asm_operands (parser, true); - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - { - clobbers = NULL_TREE; - goto done_asm; - } - if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>")) - { - parser->lex_untranslated_string = false; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return NULL_TREE; - } - /* Parse clobbers. */ - clobbers = c_parser_asm_clobbers (parser); + goto error_close_paren; + + simple = true; + outputs = NULL_TREE; + inputs = NULL_TREE; + clobbers = NULL_TREE; + labels = NULL_TREE; + + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto) + goto done_asm; + + /* Parse each colon-delimited section of operands. */ + nsections = 3 + is_goto; + for (section = 0; section < nsections; ++section) + { + if (!c_parser_require (parser, CPP_COLON, + is_goto + ? "expected %<:%>" + : "expected %<:%> or %<)%>")) + goto error_close_paren; + + /* Once past any colon, we're no longer a simple asm. */ + simple = false; + + if ((!c_parser_next_token_is (parser, CPP_COLON) + && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) + || section == 3) + switch (section) + { + case 0: + /* For asm goto, we don't allow output operands, but reserve + the slot for a future extension that does allow them. */ + if (!is_goto) + outputs = c_parser_asm_operands (parser, false); + break; + case 1: + inputs = c_parser_asm_operands (parser, true); + break; + case 2: + clobbers = c_parser_asm_clobbers (parser); + break; + case 3: + labels = c_parser_asm_goto_operands (parser); + break; + default: + gcc_unreachable (); + } + + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto) + goto done_asm; + } + done_asm: - parser->lex_untranslated_string = false; if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return NULL_TREE; - } + goto error; + } + if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) c_parser_skip_to_end_of_block_or_statement (parser); - ret = build_asm_stmt (quals, build_asm_expr (str, outputs, inputs, - clobbers, simple)); + + ret = build_asm_stmt (quals, build_asm_expr (asm_loc, str, outputs, inputs, + clobbers, labels, simple)); + + error: + parser->lex_untranslated_string = false; return ret; + + error_close_paren: + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + goto error; } /* Parse asm operands, a GNU extension. If CONVERT_P (for inputs but @@ -4409,55 +4555,58 @@ c_parser_asm_operands (c_parser *parser, bool convert_p) { tree list = NULL_TREE; + location_t loc; while (true) { tree name, str; struct c_expr expr; if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) - { - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_NAME)) - { - tree id = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - name = build_string (IDENTIFIER_LENGTH (id), - IDENTIFIER_POINTER (id)); - } - else - { - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); - return NULL_TREE; - } - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, - "expected %<]%>"); - } + { + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + tree id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + name = build_string (IDENTIFIER_LENGTH (id), + IDENTIFIER_POINTER (id)); + } else - name = NULL_TREE; + { + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL); + return NULL_TREE; + } + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + } + else + name = NULL_TREE; str = c_parser_asm_string_literal (parser); if (str == NULL_TREE) - return NULL_TREE; + return NULL_TREE; parser->lex_untranslated_string = false; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - parser->lex_untranslated_string = true; - return NULL_TREE; - } + { + parser->lex_untranslated_string = true; + return NULL_TREE; + } + loc = c_parser_peek_token (parser)->location; expr = c_parser_expression (parser); if (convert_p) - expr = default_function_array_conversion (expr); + expr = default_function_array_conversion (loc, expr); + expr.value = c_fully_fold (expr.value, false, NULL); parser->lex_untranslated_string = true; if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return NULL_TREE; - } + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + return NULL_TREE; + } list = chainon (list, build_tree_list (build_tree_list (name, str), - expr.value)); + expr.value)); if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); + c_parser_consume_token (parser); else - break; + break; } return list; } @@ -4477,17 +4626,56 @@ { tree str = c_parser_asm_string_literal (parser); if (str) - list = tree_cons (NULL_TREE, str, list); + list = tree_cons (NULL_TREE, str, list); else - return NULL_TREE; + return NULL_TREE; if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); + c_parser_consume_token (parser); else - break; + break; } return list; } +/* Parse asm goto labels, a GNU extension. + + asm-goto-operands: + identifier + asm-goto-operands , identifier +*/ + +static tree +c_parser_asm_goto_operands (c_parser *parser) +{ + tree list = NULL_TREE; + while (true) + { + tree name, label; + + if (c_parser_next_token_is (parser, CPP_NAME)) + { + c_token *tok = c_parser_peek_token (parser); + name = tok->value; + label = lookup_label_for_goto (tok->location, name); + c_parser_consume_token (parser); + TREE_USED (label) = 1; + } + else + { + c_parser_error (parser, "expected identifier"); + return NULL_TREE; + } + + name = build_string (IDENTIFIER_LENGTH (name), + IDENTIFIER_POINTER (name)); + list = tree_cons (name, label, list); + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + return nreverse (list); + } +} + /* Parse an expression other than a compound expression; that is, an assignment expression (C90 6.3.16, C99 6.5.16). If AFTER is not NULL then it is an Objective-C message expression which is the @@ -4509,7 +4697,7 @@ { struct c_expr lhs, rhs, ret; enum tree_code code; - location_t op_location; + location_t op_location, exp_location; gcc_assert (!after || c_dialect_objc ()); lhs = c_parser_conditional_expression (parser, after); op_location = c_parser_peek_token (parser)->location; @@ -4552,9 +4740,12 @@ return lhs; } c_parser_consume_token (parser); + exp_location = c_parser_peek_token (parser)->location; rhs = c_parser_expr_no_commas (parser, NULL); - rhs = default_function_array_conversion (rhs); - ret.value = build_modify_expr (op_location, lhs.value, code, rhs.value); + rhs = default_function_array_conversion (exp_location, rhs); + ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type, + code, exp_location, rhs.value, + rhs.original_type); if (code == NOP_EXPR) ret.original_code = MODIFY_EXPR; else @@ -4562,6 +4753,7 @@ TREE_NO_WARNING (ret.value) = 1; ret.original_code = ERROR_MARK; } + ret.original_type = NULL; return ret; } @@ -4583,49 +4775,85 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after) { struct c_expr cond, exp1, exp2, ret; - location_t cond_loc; + location_t cond_loc, colon_loc; gcc_assert (!after || c_dialect_objc ()); - cond_loc = c_parser_peek_token (parser)->location; cond = c_parser_binary_expression (parser, after); - protected_set_expr_location (cond.value, cond_loc); if (c_parser_next_token_is_not (parser, CPP_QUERY)) return cond; - cond = default_function_array_conversion (cond); + cond_loc = c_parser_peek_token (parser)->location; + cond = default_function_array_conversion (cond_loc, cond); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_COLON)) { - pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, - "ISO C forbids omitting the middle term of a ?: expression"); + tree eptype = NULL_TREE; + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "ISO C forbids omitting the middle term of a ?: expression"); + if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR) + { + eptype = TREE_TYPE (cond.value); + cond.value = TREE_OPERAND (cond.value, 0); + } /* Make sure first operand is calculated only once. */ - exp1.value = save_expr (default_conversion (cond.value)); + exp1.value = c_save_expr (default_conversion (cond.value)); + if (eptype) + exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value); + exp1.original_type = NULL; cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value); - skip_evaluation += cond.value == truthvalue_true_node; + c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node; } else { cond.value - = c_objc_common_truthvalue_conversion - (cond_loc, default_conversion (cond.value)); - skip_evaluation += cond.value == truthvalue_false_node; + = c_objc_common_truthvalue_conversion + (cond_loc, default_conversion (cond.value)); + c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node; exp1 = c_parser_expression_conv (parser); - skip_evaluation += ((cond.value == truthvalue_true_node) - - (cond.value == truthvalue_false_node)); - } + c_inhibit_evaluation_warnings += + ((cond.value == truthvalue_true_node) + - (cond.value == truthvalue_false_node)); + } + + colon_loc = c_parser_peek_token (parser)->location; if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) { - skip_evaluation -= cond.value == truthvalue_true_node; + c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node; ret.value = error_mark_node; ret.original_code = ERROR_MARK; + ret.original_type = NULL; return ret; } - exp2 = c_parser_conditional_expression (parser, NULL); - exp2 = default_function_array_conversion (exp2); - skip_evaluation -= cond.value == truthvalue_true_node; - ret.value = build_conditional_expr (cond.value, exp1.value, exp2.value); + { + location_t exp2_loc = c_parser_peek_token (parser)->location; + exp2 = c_parser_conditional_expression (parser, NULL); + exp2 = default_function_array_conversion (exp2_loc, exp2); + } + c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node; + ret.value = build_conditional_expr (colon_loc, cond.value, + cond.original_code == C_MAYBE_CONST_EXPR, + exp1.value, exp1.original_type, + exp2.value, exp2.original_type); ret.original_code = ERROR_MARK; + if (exp1.value == error_mark_node || exp2.value == error_mark_node) + ret.original_type = NULL; + else + { + tree t1, t2; + + /* If both sides are enum type, the default conversion will have + made the type of the result be an integer type. We want to + remember the enum types we started with. */ + t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value); + t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value); + ret.original_type = ((t1 != error_mark_node + && t2 != error_mark_node + && (TYPE_MAIN_VARIANT (t1) + == TYPE_MAIN_VARIANT (t2))) + ? t1 + : NULL); + } return ret; } @@ -4704,8 +4932,8 @@ the stack has lower precedence than the new operator or there is only one element on the stack; then the top expression is the LHS of the new operator. In the case of logical AND and OR - expressions, we also need to adjust skip_evaluation as - appropriate when the operators are pushed and popped. */ + expressions, we also need to adjust c_inhibit_evaluation_warnings + as appropriate when the operators are pushed and popped. */ /* The precedence levels, where 0 is a dummy lowest level used for the bottom of the stack. */ @@ -4731,34 +4959,40 @@ enum prec prec; /* The operation on its left. */ enum tree_code op; + /* The source location of this operation. */ + location_t loc; } stack[NUM_PRECS]; int sp; /* Location of the binary operator. */ location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */ -#define POP \ - do { \ - switch (stack[sp].op) \ - { \ - case TRUTH_ANDIF_EXPR: \ - skip_evaluation -= stack[sp - 1].expr.value == truthvalue_false_node; \ - break; \ - case TRUTH_ORIF_EXPR: \ - skip_evaluation -= stack[sp - 1].expr.value == truthvalue_true_node; \ - break; \ - default: \ - break; \ - } \ - stack[sp - 1].expr \ - = default_function_array_conversion (stack[sp - 1].expr); \ - stack[sp].expr \ - = default_function_array_conversion (stack[sp].expr); \ - stack[sp - 1].expr = parser_build_binary_op (binary_loc, \ - stack[sp].op, \ - stack[sp - 1].expr, \ - stack[sp].expr); \ - sp--; \ +#define POP \ + do { \ + switch (stack[sp].op) \ + { \ + case TRUTH_ANDIF_EXPR: \ + c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \ + == truthvalue_false_node); \ + break; \ + case TRUTH_ORIF_EXPR: \ + c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \ + == truthvalue_true_node); \ + break; \ + default: \ + break; \ + } \ + stack[sp - 1].expr \ + = default_function_array_conversion (stack[sp - 1].loc, \ + stack[sp - 1].expr); \ + stack[sp].expr \ + = default_function_array_conversion (stack[sp].loc, stack[sp].expr); \ + stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ + stack[sp].op, \ + stack[sp - 1].expr, \ + stack[sp].expr); \ + sp--; \ } while (0) gcc_assert (!after || c_dialect_objc ()); + stack[0].loc = c_parser_peek_token (parser)->location; stack[0].expr = c_parser_cast_expression (parser, after); stack[0].prec = PREC_NONE; sp = 0; @@ -4767,113 +5001,119 @@ enum prec oprec; enum tree_code ocode; if (parser->error) - goto out; + goto out; switch (c_parser_peek_token (parser)->type) - { - case CPP_MULT: - oprec = PREC_MULT; - ocode = MULT_EXPR; - break; - case CPP_DIV: - oprec = PREC_MULT; - ocode = TRUNC_DIV_EXPR; - break; - case CPP_MOD: - oprec = PREC_MULT; - ocode = TRUNC_MOD_EXPR; - break; - case CPP_PLUS: - oprec = PREC_ADD; - ocode = PLUS_EXPR; - break; - case CPP_MINUS: - oprec = PREC_ADD; - ocode = MINUS_EXPR; - break; - case CPP_LSHIFT: - oprec = PREC_SHIFT; - ocode = LSHIFT_EXPR; - break; - case CPP_RSHIFT: - oprec = PREC_SHIFT; - ocode = RSHIFT_EXPR; - break; - case CPP_LESS: - oprec = PREC_REL; - ocode = LT_EXPR; - break; - case CPP_GREATER: - oprec = PREC_REL; - ocode = GT_EXPR; - break; - case CPP_LESS_EQ: - oprec = PREC_REL; - ocode = LE_EXPR; - break; - case CPP_GREATER_EQ: - oprec = PREC_REL; - ocode = GE_EXPR; - break; - case CPP_EQ_EQ: - oprec = PREC_EQ; - ocode = EQ_EXPR; - break; - case CPP_NOT_EQ: - oprec = PREC_EQ; - ocode = NE_EXPR; - break; - case CPP_AND: - oprec = PREC_BITAND; - ocode = BIT_AND_EXPR; - break; - case CPP_XOR: - oprec = PREC_BITXOR; - ocode = BIT_XOR_EXPR; - break; - case CPP_OR: - oprec = PREC_BITOR; - ocode = BIT_IOR_EXPR; - break; - case CPP_AND_AND: - oprec = PREC_LOGAND; - ocode = TRUTH_ANDIF_EXPR; - break; - case CPP_OR_OR: - oprec = PREC_LOGOR; - ocode = TRUTH_ORIF_EXPR; - break; - default: - /* Not a binary operator, so end of the binary - expression. */ - goto out; - } + { + case CPP_MULT: + oprec = PREC_MULT; + ocode = MULT_EXPR; + break; + case CPP_DIV: + oprec = PREC_MULT; + ocode = TRUNC_DIV_EXPR; + break; + case CPP_MOD: + oprec = PREC_MULT; + ocode = TRUNC_MOD_EXPR; + break; + case CPP_PLUS: + oprec = PREC_ADD; + ocode = PLUS_EXPR; + break; + case CPP_MINUS: + oprec = PREC_ADD; + ocode = MINUS_EXPR; + break; + case CPP_LSHIFT: + oprec = PREC_SHIFT; + ocode = LSHIFT_EXPR; + break; + case CPP_RSHIFT: + oprec = PREC_SHIFT; + ocode = RSHIFT_EXPR; + break; + case CPP_LESS: + oprec = PREC_REL; + ocode = LT_EXPR; + break; + case CPP_GREATER: + oprec = PREC_REL; + ocode = GT_EXPR; + break; + case CPP_LESS_EQ: + oprec = PREC_REL; + ocode = LE_EXPR; + break; + case CPP_GREATER_EQ: + oprec = PREC_REL; + ocode = GE_EXPR; + break; + case CPP_EQ_EQ: + oprec = PREC_EQ; + ocode = EQ_EXPR; + break; + case CPP_NOT_EQ: + oprec = PREC_EQ; + ocode = NE_EXPR; + break; + case CPP_AND: + oprec = PREC_BITAND; + ocode = BIT_AND_EXPR; + break; + case CPP_XOR: + oprec = PREC_BITXOR; + ocode = BIT_XOR_EXPR; + break; + case CPP_OR: + oprec = PREC_BITOR; + ocode = BIT_IOR_EXPR; + break; + case CPP_AND_AND: + oprec = PREC_LOGAND; + ocode = TRUTH_ANDIF_EXPR; + break; + case CPP_OR_OR: + oprec = PREC_LOGOR; + ocode = TRUTH_ORIF_EXPR; + break; + default: + /* Not a binary operator, so end of the binary + expression. */ + goto out; + } binary_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); while (oprec <= stack[sp].prec) - POP; + POP; switch (ocode) - { - case TRUTH_ANDIF_EXPR: - stack[sp].expr - = default_function_array_conversion (stack[sp].expr); - stack[sp].expr.value = c_objc_common_truthvalue_conversion - (binary_loc, default_conversion (stack[sp].expr.value)); - skip_evaluation += stack[sp].expr.value == truthvalue_false_node; - break; - case TRUTH_ORIF_EXPR: - stack[sp].expr - = default_function_array_conversion (stack[sp].expr); - stack[sp].expr.value = c_objc_common_truthvalue_conversion - (binary_loc, default_conversion (stack[sp].expr.value)); - skip_evaluation += stack[sp].expr.value == truthvalue_true_node; - break; - default: - break; - } + { + case TRUTH_ANDIF_EXPR: + stack[sp].expr + = default_function_array_conversion (stack[sp].loc, + stack[sp].expr); + stack[sp].expr.value = c_objc_common_truthvalue_conversion + (stack[sp].loc, default_conversion (stack[sp].expr.value)); + c_inhibit_evaluation_warnings += (stack[sp].expr.value + == truthvalue_false_node); + break; + case TRUTH_ORIF_EXPR: + stack[sp].expr + = default_function_array_conversion (stack[sp].loc, + stack[sp].expr); + stack[sp].expr.value = c_objc_common_truthvalue_conversion + (stack[sp].loc, default_conversion (stack[sp].expr.value)); + c_inhibit_evaluation_warnings += (stack[sp].expr.value + == truthvalue_true_node); + break; + default: + break; + } sp++; + stack[sp].loc = binary_loc; stack[sp].expr = c_parser_cast_expression (parser, NULL); stack[sp].prec = oprec; stack[sp].op = ocode; + stack[sp].loc = binary_loc; } out: while (sp > 0) @@ -4894,9 +5134,11 @@ static struct c_expr c_parser_cast_expression (c_parser *parser, struct c_expr *after) { + location_t cast_loc = c_parser_peek_token (parser)->location; gcc_assert (!after || c_dialect_objc ()); if (after) - return c_parser_postfix_expression_after_primary (parser, *after); + return c_parser_postfix_expression_after_primary (parser, + cast_loc, *after); /* If the expression begins with a parenthesized type name, it may be either a cast or a compound literal; we need to see whether the next character is '{' to tell the difference. If not, it is @@ -4911,22 +5153,27 @@ type_name = c_parser_type_name (parser); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (type_name == NULL) - { - ret.value = error_mark_node; - ret.original_code = ERROR_MARK; - return ret; - } + { + ret.value = error_mark_node; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; + return ret; + } /* Save casted types in the function's used types hash table. */ used_types_insert (type_name->specs->type); if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) - return c_parser_postfix_expression_after_paren_type (parser, - type_name); - expr = c_parser_cast_expression (parser, NULL); - expr = default_function_array_conversion (expr); - ret.value = c_cast_expr (type_name, expr.value); + return c_parser_postfix_expression_after_paren_type (parser, type_name, + cast_loc); + { + location_t expr_loc = c_parser_peek_token (parser)->location; + expr = c_parser_cast_expression (parser, NULL); + expr = default_function_array_conversion (expr_loc, expr); + } + ret.value = c_cast_expr (cast_loc, type_name, expr.value); ret.original_code = ERROR_MARK; + ret.original_type = NULL; return ret; } else @@ -4965,97 +5212,106 @@ { int ext; struct c_expr ret, op; - location_t loc = c_parser_peek_token (parser)->location; + location_t op_loc = c_parser_peek_token (parser)->location; + location_t exp_loc; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; switch (c_parser_peek_token (parser)->type) { case CPP_PLUS_PLUS: c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - op = default_function_array_conversion (op); - return parser_build_unary_op (PREINCREMENT_EXPR, op, loc); + op = default_function_array_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op); case CPP_MINUS_MINUS: c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - op = default_function_array_conversion (op); - return parser_build_unary_op (PREDECREMENT_EXPR, op, loc); + op = default_function_array_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op); case CPP_AND: c_parser_consume_token (parser); - return parser_build_unary_op (ADDR_EXPR, - c_parser_cast_expression (parser, NULL), - loc); + return parser_build_unary_op (op_loc, ADDR_EXPR, + c_parser_cast_expression (parser, NULL)); case CPP_MULT: c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - op = default_function_array_conversion (op); - ret.value = build_indirect_ref (loc, op.value, "unary *"); - ret.original_code = ERROR_MARK; + op = default_function_array_conversion (exp_loc, op); + ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR); return ret; case CPP_PLUS: if (!c_dialect_objc () && !in_system_header) - warning_at (c_parser_peek_token (parser)->location, - OPT_Wtraditional, - "traditional C rejects the unary plus operator"); - c_parser_consume_token (parser); + warning_at (op_loc, + OPT_Wtraditional, + "traditional C rejects the unary plus operator"); + c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - op = default_function_array_conversion (op); - return parser_build_unary_op (CONVERT_EXPR, op, loc); + op = default_function_array_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, CONVERT_EXPR, op); case CPP_MINUS: c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - op = default_function_array_conversion (op); - return parser_build_unary_op (NEGATE_EXPR, op, loc); + op = default_function_array_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, NEGATE_EXPR, op); case CPP_COMPL: c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - op = default_function_array_conversion (op); - return parser_build_unary_op (BIT_NOT_EXPR, op, loc); + op = default_function_array_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op); case CPP_NOT: c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - op = default_function_array_conversion (op); - return parser_build_unary_op (TRUTH_NOT_EXPR, op, loc); + op = default_function_array_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op); case CPP_AND_AND: /* Refer to the address of a label as a pointer. */ c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_NAME)) - { - ret.value = finish_label_address_expr - (c_parser_peek_token (parser)->value, loc); - c_parser_consume_token (parser); - } + { + ret.value = finish_label_address_expr + (c_parser_peek_token (parser)->value, op_loc); + c_parser_consume_token (parser); + } else - { - c_parser_error (parser, "expected identifier"); - ret.value = error_mark_node; - } - ret.original_code = ERROR_MARK; - return ret; + { + c_parser_error (parser, "expected identifier"); + ret.value = error_mark_node; + } + return ret; case CPP_KEYWORD: switch (c_parser_peek_token (parser)->keyword) - { - case RID_SIZEOF: - return c_parser_sizeof_expression (parser); - case RID_ALIGNOF: - return c_parser_alignof_expression (parser); - case RID_EXTENSION: - c_parser_consume_token (parser); - ext = disable_extension_diagnostics (); - ret = c_parser_cast_expression (parser, NULL); - restore_extension_diagnostics (ext); - return ret; - case RID_REALPART: - c_parser_consume_token (parser); - op = c_parser_cast_expression (parser, NULL); - op = default_function_array_conversion (op); - return parser_build_unary_op (REALPART_EXPR, op, loc); - case RID_IMAGPART: - c_parser_consume_token (parser); - op = c_parser_cast_expression (parser, NULL); - op = default_function_array_conversion (op); - return parser_build_unary_op (IMAGPART_EXPR, op, loc); - default: - return c_parser_postfix_expression (parser); - } + { + case RID_SIZEOF: + return c_parser_sizeof_expression (parser); + case RID_ALIGNOF: + return c_parser_alignof_expression (parser); + case RID_EXTENSION: + c_parser_consume_token (parser); + ext = disable_extension_diagnostics (); + ret = c_parser_cast_expression (parser, NULL); + restore_extension_diagnostics (ext); + return ret; + case RID_REALPART: + c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; + op = c_parser_cast_expression (parser, NULL); + op = default_function_array_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, REALPART_EXPR, op); + case RID_IMAGPART: + c_parser_consume_token (parser); + exp_loc = c_parser_peek_token (parser)->location; + op = c_parser_cast_expression (parser, NULL); + op = default_function_array_conversion (exp_loc, op); + return parser_build_unary_op (op_loc, IMAGPART_EXPR, op); + default: + return c_parser_postfix_expression (parser); + } default: return c_parser_postfix_expression (parser); } @@ -5070,49 +5326,51 @@ location_t expr_loc; gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF)); c_parser_consume_token (parser); - skip_evaluation++; + c_inhibit_evaluation_warnings++; in_sizeof++; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) && c_token_starts_typename (c_parser_peek_2nd_token (parser))) { /* Either sizeof ( type-name ) or sizeof unary-expression - starting with a compound literal. */ + starting with a compound literal. */ struct c_type_name *type_name; c_parser_consume_token (parser); expr_loc = c_parser_peek_token (parser)->location; type_name = c_parser_type_name (parser); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (type_name == NULL) - { - struct c_expr ret; - skip_evaluation--; - in_sizeof--; - ret.value = error_mark_node; - ret.original_code = ERROR_MARK; - return ret; - } + { + struct c_expr ret; + c_inhibit_evaluation_warnings--; + in_sizeof--; + ret.value = error_mark_node; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; + return ret; + } if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) - { - expr = c_parser_postfix_expression_after_paren_type (parser, - type_name); - goto sizeof_expr; - } + { + expr = c_parser_postfix_expression_after_paren_type (parser, + type_name, + expr_loc); + goto sizeof_expr; + } /* sizeof ( type-name ). */ - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_sizeof--; - return c_expr_sizeof_type (type_name); + return c_expr_sizeof_type (expr_loc, type_name); } else { expr_loc = c_parser_peek_token (parser)->location; expr = c_parser_unary_expression (parser); sizeof_expr: - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_sizeof--; if (TREE_CODE (expr.value) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) - error_at (expr_loc, "%<sizeof%> applied to a bit-field"); - return c_expr_sizeof_expr (expr); + && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) + error_at (expr_loc, "%<sizeof%> applied to a bit-field"); + return c_expr_sizeof_expr (expr_loc, expr); } } @@ -5122,40 +5380,46 @@ c_parser_alignof_expression (c_parser *parser) { struct c_expr expr; + location_t loc = c_parser_peek_token (parser)->location; gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF)); c_parser_consume_token (parser); - skip_evaluation++; + c_inhibit_evaluation_warnings++; in_alignof++; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) && c_token_starts_typename (c_parser_peek_2nd_token (parser))) { /* Either __alignof__ ( type-name ) or __alignof__ - unary-expression starting with a compound literal. */ + unary-expression starting with a compound literal. */ + location_t loc; struct c_type_name *type_name; struct c_expr ret; c_parser_consume_token (parser); + loc = c_parser_peek_token (parser)->location; type_name = c_parser_type_name (parser); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (type_name == NULL) - { - struct c_expr ret; - skip_evaluation--; - in_alignof--; - ret.value = error_mark_node; - ret.original_code = ERROR_MARK; - return ret; - } + { + struct c_expr ret; + c_inhibit_evaluation_warnings--; + in_alignof--; + ret.value = error_mark_node; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; + return ret; + } if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) - { - expr = c_parser_postfix_expression_after_paren_type (parser, - type_name); - goto alignof_expr; - } + { + expr = c_parser_postfix_expression_after_paren_type (parser, + type_name, + loc); + goto alignof_expr; + } /* alignof ( type-name ). */ - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_alignof--; - ret.value = c_alignof (groktypename (type_name)); + ret.value = c_alignof (loc, groktypename (type_name, NULL, NULL)); ret.original_code = ERROR_MARK; + ret.original_type = NULL; return ret; } else @@ -5163,10 +5427,11 @@ struct c_expr ret; expr = c_parser_unary_expression (parser); alignof_expr: - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_alignof--; - ret.value = c_alignof_expr (expr.value); + ret.value = c_alignof_expr (loc, expr.value); ret.original_code = ERROR_MARK; + ret.original_type = NULL; return ret; } } @@ -5205,8 +5470,8 @@ __builtin_va_arg ( assignment-expression , type-name ) __builtin_offsetof ( type-name , offsetof-member-designator ) __builtin_choose_expr ( assignment-expression , - assignment-expression , - assignment-expression ) + assignment-expression , + assignment-expression ) __builtin_types_compatible_p ( type-name , type-name ) offsetof-member-designator: @@ -5242,13 +5507,13 @@ tlab = define_label (loc, label); gcc_assert (tlab); decl_attributes (&tlab, NULL_TREE, 0); - add_stmt (build_stmt (LABEL_EXPR, tlab)); - - tree ret = c_finish_return (retval); + add_stmt (build_stmt (loc, LABEL_EXPR, tlab)); + + tree ret = c_finish_return (loc, retval, retval); /*tree ret = c_finish_return (retval);*/ TREE_USED(ret) = 1; cond = integer_zero_node; - tree if_body = c_end_compound_stmt (cstmt, true); + tree if_body = c_end_compound_stmt (loc, cstmt, true); TREE_SIDE_EFFECTS (cstmt) = 1; c_finish_if_stmt (loc, cond, if_body, NULL_TREE, false); } @@ -5271,7 +5536,7 @@ tree fnbody; tree _retval_decl, _envp_decl; struct c_declarator *declarator; - tree ident; + //tree ident; struct c_arg_info *args; struct c_declspecs *specs; struct c_typespec t; @@ -5280,19 +5545,19 @@ declare_parm_level (); /*tree retval_type = TREE_TYPE(retval_decl);*/ - _retval_decl = build_decl (PARM_DECL, get_identifier ("_retval"), TREE_TYPE(retval_decl)); + _retval_decl = build_decl (loc, PARM_DECL, get_identifier ("_retval"), TREE_TYPE(retval_decl)); DECL_SOURCE_LOCATION (_retval_decl) = loc; DECL_ARTIFICIAL (_retval_decl) = 1; DECL_ARG_TYPE (_retval_decl) = TREE_TYPE(retval_decl); pushdecl (_retval_decl); - finish_decl (_retval_decl, NULL_TREE, NULL_TREE); - - _envp_decl = build_decl (PARM_DECL, get_identifier ("_envp"), ptr_type_node); + finish_decl (_retval_decl, loc, NULL_TREE, NULL_TREE, NULL_TREE); + + _envp_decl = build_decl (loc, PARM_DECL, get_identifier ("_envp"), ptr_type_node); DECL_SOURCE_LOCATION (_envp_decl) = loc; DECL_ARTIFICIAL (_envp_decl) = 1; DECL_ARG_TYPE (_envp_decl) = ptr_type_node; pushdecl (_envp_decl); - finish_decl (_envp_decl, NULL_TREE, NULL_TREE); + finish_decl (_envp_decl, loc, NULL_TREE, NULL_TREE, NULL_TREE); args = get_parm_info(false); pop_scope(); @@ -5301,7 +5566,7 @@ t.kind = ctsk_resword; t.spec = get_identifier("void"); specs = build_null_declspecs(); - declspecs_add_type (specs, t); + declspecs_add_type (loc, specs, t); finish_declspecs (specs); /* make nested function. */ @@ -5321,11 +5586,11 @@ /* start compound statement. */ tree cstmt = c_begin_compound_stmt (true); - add_stmt (build_modify_expr (loc, retval_decl, NOP_EXPR, _retval_decl)); - tree stmt = c_finish_goto_label (label); + add_stmt (build_modify_expr (loc, retval_decl, NULL_TREE, NOP_EXPR, loc, _retval_decl, NULL_TREE)); + //tree stmt = c_finish_goto_label (loc, label); /* end compound statement. */ - fnbody = c_end_compound_stmt (cstmt, true); + fnbody = c_end_compound_stmt (loc, cstmt, true); TREE_SIDE_EFFECTS (cstmt) = 1; /* finish declaration of nested function. */ @@ -5334,7 +5599,7 @@ finish_function (); c_pop_function_context (); - add_stmt (build_stmt (DECL_EXPR, decl)); + add_stmt (build_stmt (loc, DECL_EXPR, decl)); return decl; } @@ -5344,34 +5609,35 @@ { struct c_expr expr, e1, e2, e3; struct c_type_name *t1, *t2; - static tree return_label1; - location_t loc; + //cbc? static tree return_label1; + location_t loc = c_parser_peek_token (parser)->location;; + 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; - expr.original_code = ERROR_MARK; loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); if (TREE_CODE (expr.value) == FIXED_CST - && !targetm.fixed_point_supported_p ()) - { - error_at (loc, "fixed-point types not supported for this target"); - expr.value = error_mark_node; - } + && !targetm.fixed_point_supported_p ()) + { + error_at (loc, "fixed-point types not supported for this target"); + expr.value = error_mark_node; + } break; case CPP_CHAR: case CPP_CHAR16: case CPP_CHAR32: case CPP_WCHAR: expr.value = c_parser_peek_token (parser)->value; - expr.original_code = ERROR_MARK; 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; expr.original_code = STRING_CST; c_parser_consume_token (parser); @@ -5379,389 +5645,384 @@ case CPP_OBJC_STRING: gcc_assert (c_dialect_objc ()); expr.value - = objc_build_string_object (c_parser_peek_token (parser)->value); - expr.original_code = ERROR_MARK; + = objc_build_string_object (c_parser_peek_token (parser)->value); c_parser_consume_token (parser); break; case CPP_NAME: if (c_parser_peek_token (parser)->id_kind != C_ID_ID) - { - c_parser_error (parser, "expected expression"); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } + { + c_parser_error (parser, "expected expression"); + expr.value = error_mark_node; + break; + } { - tree id = c_parser_peek_token (parser)->value; - location_t loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - expr.value = build_external_ref (id, - (c_parser_peek_token (parser)->type - == CPP_OPEN_PAREN), loc); - expr.original_code = ERROR_MARK; + 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); } break; case CPP_OPEN_PAREN: /* A parenthesized expression, statement expression or compound - literal. */ + literal. */ if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE) - { - /* A statement expression. */ - tree stmt; - location_t here = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - c_parser_consume_token (parser); - if (cur_stmt_list == NULL) - { - error_at (here, "braced-group within expression allowed " - "only inside a function"); - parser->error = true; - c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - stmt = c_begin_stmt_expr (); - c_parser_compound_statement_nostart (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - pedwarn (here, OPT_pedantic, - "ISO C forbids braced-groups within expressions"); - expr.value = c_finish_stmt_expr (stmt); - expr.original_code = ERROR_MARK; - } + { + /* A statement expression. */ + tree stmt; + location_t brace_loc; + c_parser_consume_token (parser); + brace_loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + if (cur_stmt_list == NULL) + { + error_at (loc, "braced-group within expression allowed " + "only inside a function"); + parser->error = true; + c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.value = error_mark_node; + break; + } + stmt = c_begin_stmt_expr (); + c_parser_compound_statement_nostart (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + pedwarn (loc, OPT_pedantic, + "ISO C forbids braced-groups within expressions"); + expr.value = c_finish_stmt_expr (brace_loc, stmt); + } else if (c_token_starts_typename (c_parser_peek_2nd_token (parser))) - { - /* A compound literal. ??? Can we actually get here rather - than going directly to - c_parser_postfix_expression_after_paren_type from - elsewhere? */ - struct c_type_name *type_name; - c_parser_consume_token (parser); - type_name = c_parser_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - if (type_name == NULL) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - } - else - expr = c_parser_postfix_expression_after_paren_type (parser, - type_name); - } + { + /* A compound literal. ??? Can we actually get here rather + than going directly to + c_parser_postfix_expression_after_paren_type from + elsewhere? */ + location_t loc; + struct c_type_name *type_name; + c_parser_consume_token (parser); + loc = c_parser_peek_token (parser)->location; + type_name = c_parser_type_name (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + if (type_name == NULL) + { + expr.value = error_mark_node; + } else - { - /* A parenthesized expression. */ - c_parser_consume_token (parser); - expr = c_parser_expression (parser); - if (TREE_CODE (expr.value) == MODIFY_EXPR) - TREE_NO_WARNING (expr.value) = 1; - expr.original_code = ERROR_MARK; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - } + expr = c_parser_postfix_expression_after_paren_type (parser, + type_name, + loc); + } + else + { + /* A parenthesized expression. */ + c_parser_consume_token (parser); + expr = c_parser_expression (parser); + if (TREE_CODE (expr.value) == MODIFY_EXPR) + TREE_NO_WARNING (expr.value) = 1; + if (expr.original_code != C_MAYBE_CONST_EXPR) + expr.original_code = ERROR_MARK; + /* Don't change EXPR.ORIGINAL_TYPE. */ + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + } break; case CPP_KEYWORD: switch (c_parser_peek_token (parser)->keyword) - { - case RID_FUNCTION_NAME: - case RID_PRETTY_FUNCTION_NAME: - case RID_C99_FUNCTION_NAME: - expr.value = fname_decl (c_parser_peek_token (parser)->location, - c_parser_peek_token (parser)->keyword, - c_parser_peek_token (parser)->value); - expr.original_code = ERROR_MARK; - c_parser_consume_token (parser); - break; - case RID_VA_ARG: - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - e1 = c_parser_expr_no_commas (parser, NULL); - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - t1 = c_parser_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - if (t1 == NULL) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - } - else - { - expr.value = build_va_arg (e1.value, groktypename (t1)); - expr.original_code = ERROR_MARK; - } - break; - case RID_OFFSETOF: - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - t1 = c_parser_type_name (parser); - if (t1 == NULL) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - { - tree type = groktypename (t1); - tree offsetof_ref; - if (type == error_mark_node) - offsetof_ref = error_mark_node; - else - offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node); - /* Parse the second argument to __builtin_offsetof. We - must have one identifier, and beyond that we want to - accept sub structure and sub array references. */ - if (c_parser_next_token_is (parser, CPP_NAME)) - { - offsetof_ref = build_component_ref - (offsetof_ref, c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - while (c_parser_next_token_is (parser, CPP_DOT) - || c_parser_next_token_is (parser, - CPP_OPEN_SQUARE) - || c_parser_next_token_is (parser, - CPP_DEREF)) - { - if (c_parser_next_token_is (parser, CPP_DEREF)) - { - loc = c_parser_peek_token (parser)->location; - offsetof_ref = build_array_ref (offsetof_ref, - integer_zero_node, - loc); - goto do_dot; - } - else if (c_parser_next_token_is (parser, CPP_DOT)) - { - do_dot: - c_parser_consume_token (parser); - if (c_parser_next_token_is_not (parser, - CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - break; - } - offsetof_ref = build_component_ref - (offsetof_ref, - c_parser_peek_token (parser)->value); - c_parser_consume_token (parser); - } - else - { - tree idx; - loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - idx = c_parser_expression (parser).value; - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, - "expected %<]%>"); - offsetof_ref = build_array_ref (offsetof_ref, idx, loc); - } - } - } - else - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - expr.value = fold_offsetof (offsetof_ref, NULL_TREE); - expr.original_code = ERROR_MARK; - } - break; - case RID_CHOOSE_EXPR: - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - loc = c_parser_peek_token (parser)->location; - e1 = c_parser_expr_no_commas (parser, NULL); - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - e2 = c_parser_expr_no_commas (parser, NULL); - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - e3 = c_parser_expr_no_commas (parser, NULL); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - { - tree c; - - c = fold (e1.value); - if (TREE_CODE (c) != INTEGER_CST) - error_at (loc, - "first argument to %<__builtin_choose_expr%> not" - " a constant"); - expr = integer_zerop (c) ? e3 : e2; - } - break; - case RID_TYPES_COMPATIBLE_P: - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - t1 = c_parser_type_name (parser); - if (t1 == NULL) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - t2 = c_parser_type_name (parser); - if (t2 == NULL) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - { - tree e1, e2; - - e1 = TYPE_MAIN_VARIANT (groktypename (t1)); - e2 = TYPE_MAIN_VARIANT (groktypename (t2)); - - expr.value = comptypes (e1, e2) - ? build_int_cst (NULL_TREE, 1) - : build_int_cst (NULL_TREE, 0); - expr.original_code = ERROR_MARK; - } - break; - case RID_AT_SELECTOR: - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - { - tree sel = c_parser_objc_selector_arg (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - expr.value = objc_build_selector_expr (sel); - expr.original_code = ERROR_MARK; - } - break; - case RID_AT_PROTOCOL: - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - { - tree id = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - expr.value = objc_build_protocol_expr (id); - expr.original_code = ERROR_MARK; - } - break; - case RID_AT_ENCODE: - /* Extension to support C-structures in the archiver. */ - gcc_assert (c_dialect_objc ()); - c_parser_consume_token (parser); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - t1 = c_parser_type_name (parser); - if (t1 == NULL) - { - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - break; - } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - { - tree type = groktypename (t1); - expr.value = objc_build_encode_expr (type); - expr.original_code = ERROR_MARK; - } - break; + { + case RID_FUNCTION_NAME: + case RID_PRETTY_FUNCTION_NAME: + case RID_C99_FUNCTION_NAME: + expr.value = fname_decl (loc, + c_parser_peek_token (parser)->keyword, + c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + break; + case RID_VA_ARG: + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + expr.value = error_mark_node; + break; + } + e1 = c_parser_expr_no_commas (parser, NULL); + e1.value = c_fully_fold (e1.value, false, NULL); + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.value = error_mark_node; + break; + } + loc = c_parser_peek_token (parser)->location; + t1 = c_parser_type_name (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + if (t1 == NULL) + { + expr.value = error_mark_node; + } + else + { + tree type_expr = NULL_TREE; + expr.value = c_build_va_arg (loc, e1.value, + groktypename (t1, &type_expr, NULL)); + if (type_expr) + { + expr.value = build2 (C_MAYBE_CONST_EXPR, + TREE_TYPE (expr.value), type_expr, + expr.value); + C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true; + } + } + break; + case RID_OFFSETOF: + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + expr.value = error_mark_node; + break; + } + t1 = c_parser_type_name (parser); + if (t1 == NULL) + { + expr.value = error_mark_node; + break; + } + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.value = error_mark_node; + break; + } + { + tree type = groktypename (t1, NULL, NULL); + tree offsetof_ref; + if (type == error_mark_node) + offsetof_ref = error_mark_node; + else + { + offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node); + SET_EXPR_LOCATION (offsetof_ref, loc); + } + /* Parse the second argument to __builtin_offsetof. We + must have one identifier, and beyond that we want to + accept sub structure and sub array references. */ + if (c_parser_next_token_is (parser, CPP_NAME)) + { + offsetof_ref = build_component_ref + (loc, offsetof_ref, c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + while (c_parser_next_token_is (parser, CPP_DOT) + || c_parser_next_token_is (parser, + CPP_OPEN_SQUARE) + || c_parser_next_token_is (parser, + CPP_DEREF)) + { + if (c_parser_next_token_is (parser, CPP_DEREF)) + { + loc = c_parser_peek_token (parser)->location; + offsetof_ref = build_array_ref (loc, + offsetof_ref, + integer_zero_node); + goto do_dot; + } + else if (c_parser_next_token_is (parser, CPP_DOT)) + { + do_dot: + c_parser_consume_token (parser); + if (c_parser_next_token_is_not (parser, + CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + break; + } + offsetof_ref = build_component_ref + (loc, offsetof_ref, + c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + } + else + { + tree idx; + loc = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + idx = c_parser_expression (parser).value; + idx = c_fully_fold (idx, false, NULL); + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + offsetof_ref = build_array_ref (loc, offsetof_ref, idx); + } + } + } + else + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + expr.value = fold_offsetof (offsetof_ref, NULL_TREE); + } + break; + case RID_CHOOSE_EXPR: + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + expr.value = error_mark_node; + break; + } + loc = c_parser_peek_token (parser)->location; + e1 = c_parser_expr_no_commas (parser, NULL); + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.value = error_mark_node; + break; + } + e2 = c_parser_expr_no_commas (parser, NULL); + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.value = error_mark_node; + break; + } + e3 = c_parser_expr_no_commas (parser, NULL); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + { + tree c; + + c = e1.value; + if (TREE_CODE (c) != INTEGER_CST + || !INTEGRAL_TYPE_P (TREE_TYPE (c))) + error_at (loc, + "first argument to %<__builtin_choose_expr%> not" + " a constant"); + constant_expression_warning (c); + expr = integer_zerop (c) ? e3 : e2; + } + break; + case RID_TYPES_COMPATIBLE_P: + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + expr.value = error_mark_node; + break; + } + t1 = c_parser_type_name (parser); + if (t1 == NULL) + { + expr.value = error_mark_node; + break; + } + if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.value = error_mark_node; + break; + } + t2 = c_parser_type_name (parser); + if (t2 == NULL) + { + expr.value = error_mark_node; + break; + } + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + { + tree e1, e2; + + e1 = TYPE_MAIN_VARIANT (groktypename (t1, NULL, NULL)); + e2 = TYPE_MAIN_VARIANT (groktypename (t2, NULL, NULL)); + + expr.value = comptypes (e1, e2) + ? build_int_cst (NULL_TREE, 1) + : build_int_cst (NULL_TREE, 0); + } + break; + case RID_AT_SELECTOR: + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + expr.value = error_mark_node; + break; + } + { + tree sel = c_parser_objc_selector_arg (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + expr.value = objc_build_selector_expr (loc, sel); + } + break; + case RID_AT_PROTOCOL: + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + expr.value = error_mark_node; + break; + } + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + expr.value = error_mark_node; + break; + } + { + tree id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + expr.value = objc_build_protocol_expr (id); + } + break; + case RID_AT_ENCODE: + /* Extension to support C-structures in the archiver. */ + gcc_assert (c_dialect_objc ()); + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + expr.value = error_mark_node; + break; + } + t1 = c_parser_type_name (parser); + if (t1 == NULL) + { + expr.value = error_mark_node; + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + break; + } + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + { + tree type = groktypename (t1, NULL, NULL); + expr.value = objc_build_encode_expr (type); + } + break; #ifndef noCbC - case RID_CbC_ENV: + case RID_CbC_ENV: { - c_parser_consume_token (parser); - /* get value of %ebp. */ - tree env_tree = build_external_ref ( - get_identifier ("__builtin_frame_address"), 0, - c_parser_peek_token (parser)->location); - expr.value = build_function_call(env_tree, - build_tree_list (NULL_TREE, build_int_cst (NULL_TREE,0))); - expr.original_code = ERROR_MARK; + c_parser_consume_token (parser); + /* get value of %ebp. */ + /*tree env_tree = build_external_ref ( + get_identifier ("__builtin_frame_address"), 0, + c_parser_peek_token (parser)->location);*/ + loc = c_parser_peek_token (parser)->location; + tree env_tree = build_external_ref (loc, + get_identifier ("__builtin_frame_address"), 0, NULL); + expr.value = build_function_call(loc, env_tree, + build_tree_list (NULL_TREE, build_int_cst (NULL_TREE,0))); + expr.original_code = ERROR_MARK; } - break; - case RID_CbC_RET: - case RID_RETURN: + break; + case RID_CbC_RET: + case RID_RETURN: #if 0 - if (cbc_return_f==0) - { tree retval; + if (cbc_return_f==0) + { tree retval; /* Generates something like... @@ -5786,171 +6047,168 @@ */ - tree stmt = c_begin_stmt_expr (); + tree stmt = c_begin_stmt_expr (); cbc_return_f = c_parser_peek_token (parser)->value; cbc_return = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); + c_parser_consume_token (parser); location_t next = c_parser_peek_token (parser)->location; // dummy variable for hidden condition - struct c_expr cexpr; - tree cond; - location_t loc; - loc = next; - tree decl_cond = - build_decl (VAR_DECL, get_identifier ("__return"), - intHI_type_node); + struct c_expr cexpr; + tree cond; + location_t loc; + loc = next; + tree decl_cond = + build_decl (VAR_DECL, get_identifier ("__return"), + intHI_type_node); TREE_STATIC (decl_cond) = 1; - cexpr.value = lang_hooks.decls.pushdecl(decl_cond); - - cexpr.original_code = ERROR_MARK; - cond = c_objc_common_truthvalue_conversion(loc, cexpr.value); - if (EXPR_P (cond)) - SET_EXPR_LOCATION (cond, loc); - - - - - tree fwlabel = create_artificial_label (); - //TREE_USED(fwlabel) = 1; - - //add_stmt (build1 (GOTO_EXPR, void_type_node, fwlabel)); - tree block = c_begin_compound_stmt (flag_isoc99); - - tree tlab = lookup_label(cbc_return_f); - - tree decl= build_stmt (LABEL_EXPR, tlab); - //TREE_USED(decl) = 1; - add_stmt(decl); - - //tree hoge = build_int_cst(NULL_TREE,55); - retval = build_component_ref (cbc_env, get_identifier("retval")); - tree ret = c_finish_return (retval); - TREE_USED(ret) = 1; - tree first_body = c_end_compound_stmt (block, flag_isoc99); + cexpr.value = lang_hooks.decls.pushdecl(decl_cond); + + cexpr.original_code = ERROR_MARK; + cond = c_objc_common_truthvalue_conversion(loc, cexpr.value); + if (EXPR_P (cond)) + SET_EXPR_LOCATION (cond, loc); + + + + + tree fwlabel = create_artificial_label (); + //TREE_USED(fwlabel) = 1; + + //add_stmt (build1 (GOTO_EXPR, void_type_node, fwlabel)); + tree block = c_begin_compound_stmt (flag_isoc99); + + tree tlab = lookup_label(cbc_return_f); + + tree decl= build_stmt (LABEL_EXPR, tlab); + //TREE_USED(decl) = 1; + add_stmt(decl); + + //tree hoge = build_int_cst(NULL_TREE,55); + retval = build_component_ref (cbc_env, get_identifier("retval")); + tree ret = c_finish_return (retval); + TREE_USED(ret) = 1; + tree first_body = c_end_compound_stmt (block, flag_isoc99); c_finish_if_stmt (loc, cond, first_body, NULL_TREE, false); - // define_label(EXPR_LOCATION(decl) ,cbc_return_f); - return_label1 = - define_label(cbc_return ,cbc_return_f); - tree fwdef= build_stmt (LABEL_EXPR, fwlabel); - - //TREE_USED(fwdef) = 1; - add_stmt(fwdef); - TREE_SIDE_EFFECTS (block) = 1; - - // tree label = lookup_label(c_parser_peek_token (parser)->value); - //TREE_USED(label) = 1; - - tree value = build1(ADDR_EXPR, ptr_type_node, return_label1); + // define_label(EXPR_LOCATION(decl) ,cbc_return_f); + return_label1 = + define_label(cbc_return ,cbc_return_f); + tree fwdef= build_stmt (LABEL_EXPR, fwlabel); + + //TREE_USED(fwdef) = 1; + add_stmt(fwdef); + TREE_SIDE_EFFECTS (block) = 1; + + // tree label = lookup_label(c_parser_peek_token (parser)->value); + //TREE_USED(label) = 1; + + tree value = build1(ADDR_EXPR, ptr_type_node, return_label1); SET_EXPR_LOCATION (value, next); - TREE_SIDE_EFFECTS (value) = 1; - add_stmt(value); - - TREE_SIDE_EFFECTS (stmt) = 1; - expr.value = c_finish_stmt_expr (stmt); - expr.original_code = ERROR_MARK; - - - } - else - { - //tree label = lookup_label(c_parser_peek_token (parser)->value); - //TREE_USED(label) = 1; - //expr.value = build1(ADDR_EXPR, ptr_type_node, label); - expr.value = build1(ADDR_EXPR, ptr_type_node, return_label1); - c_parser_consume_token (parser); + TREE_SIDE_EFFECTS (value) = 1; + add_stmt(value); + + TREE_SIDE_EFFECTS (stmt) = 1; + expr.value = c_finish_stmt_expr (stmt); + expr.original_code = ERROR_MARK; + + + } + else + { + //tree label = lookup_label(c_parser_peek_token (parser)->value); + //TREE_USED(label) = 1; + //expr.value = build1(ADDR_EXPR, ptr_type_node, label); + expr.value = build1(ADDR_EXPR, ptr_type_node, return_label1); + c_parser_consume_token (parser); } #else //by KENT. - { - /* - ({ - __label__ _cbc_exit0; - void __return_func(int retval_, void *_envp){ - retval = retval_; - goto exit0; - } - if (0) { - _cbc_exit0: - return retval; - } - __return_func; - }); - */ - tree value, stmt, label, tlab, decl; - c_parser_consume_token (parser); - - stmt = c_begin_stmt_expr (); - cbc_return_f = c_parser_peek_token (parser)->value; - location_t location = c_parser_peek_token (parser)->location; - - /* create label. (__label__ _cbc_exit0;) */ - label = get_identifier ("_cbc_exit0"); - tlab = declare_label (label); - C_DECLARED_LABEL_FLAG (tlab) = 1; - add_stmt (build_stmt (DECL_EXPR, tlab)); - - /* declare retval. (int retval;) */ - tree decl_cond = - build_decl (VAR_DECL, get_identifier ("retval"), - TREE_TYPE (TREE_TYPE (current_function_decl))); - TREE_STATIC (decl_cond) = 1; - DECL_ARTIFICIAL (decl_cond) = 1; - pushdecl (decl_cond); - - /* define nested function. */ - decl = - cbc_finish_nested_function (location, label, decl_cond); - - /* define if-ed goto label and return statement. */ - cbc_finish_labeled_goto (location, label, decl_cond); - - /* get pointer to nested function. */ - value = build_addr (decl , current_function_decl); - SET_EXPR_LOCATION (value, location); - add_stmt (value); - /*value = build_external_ref (get_identifier("_cbc_internal_return"), false, location);*/ - /*value = build_unary_op (location, ADDR_EXPR, value, 0);*/ - /*add_stmt (value);*/ - - TREE_SIDE_EFFECTS (stmt) = 1; - expr.value = c_finish_stmt_expr (stmt); - expr.original_code = ERROR_MARK; - } - + { + /* + ({ + __label__ _cbc_exit0; + void __return_func(int retval_, void *_envp){ + retval = retval_; + goto exit0; + } + if (0) { + _cbc_exit0: + return retval; + } + __return_func; + }); + */ + tree value, stmt, label, tlab, decl; + c_parser_consume_token (parser); + + stmt = c_begin_stmt_expr (); + cbc_return_f = c_parser_peek_token (parser)->value; + location_t location = c_parser_peek_token (parser)->location; + + /* create label. (__label__ _cbc_exit0;) */ + label = get_identifier ("_cbc_exit0"); + tlab = declare_label (label); + C_DECLARED_LABEL_FLAG (tlab) = 1; + add_stmt (build_stmt (location, DECL_EXPR, tlab)); + + /* declare retval. (int retval;) */ + tree decl_cond = + build_decl (location, VAR_DECL, get_identifier ("retval"), + TREE_TYPE (TREE_TYPE (current_function_decl))); + TREE_STATIC (decl_cond) = 1; + DECL_ARTIFICIAL (decl_cond) = 1; + pushdecl (decl_cond); + + /* define nested function. */ + decl = + cbc_finish_nested_function (location, label, decl_cond); + + /* define if-ed goto label and return statement. */ + cbc_finish_labeled_goto (location, label, decl_cond); + + /* get pointer to nested function. */ + value = build_addr (decl , current_function_decl); + SET_EXPR_LOCATION (value, location); + add_stmt (value); + /*value = build_external_ref (get_identifier("_cbc_internal_return"), false, location);*/ + /*value = build_unary_op (location, ADDR_EXPR, value, 0);*/ + /*add_stmt (value);*/ + + TREE_SIDE_EFFECTS (stmt) = 1; + expr.value = c_finish_stmt_expr (location, stmt); + expr.original_code = ERROR_MARK; + } + #endif //0 - break; + break; #endif //noCbC - default: - c_parser_error (parser, "expected expression"); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } + default: + c_parser_error (parser, "expected expression"); + expr.value = error_mark_node; + break; + } break; case CPP_OPEN_SQUARE: if (c_dialect_objc ()) - { - tree receiver, args; - c_parser_consume_token (parser); - receiver = c_parser_objc_receiver (parser); - args = c_parser_objc_message_args (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, - "expected %<]%>"); - expr.value = objc_build_message_expr (build_tree_list (receiver, - args)); - expr.original_code = ERROR_MARK; - break; - } + { + tree receiver, args; + c_parser_consume_token (parser); + receiver = c_parser_objc_receiver (parser); + args = c_parser_objc_message_args (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + expr.value = objc_build_message_expr (build_tree_list (receiver, + args)); + break; + } /* Else fall through to report error. */ default: c_parser_error (parser, "expected expression"); expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - break; - } - return c_parser_postfix_expression_after_primary (parser, expr); + break; + } + return c_parser_postfix_expression_after_primary (parser, loc, expr); } /* Parse a postfix expression after a parenthesized type name: the @@ -5959,126 +6217,208 @@ possible to tell until after the type name whether a cast expression has a cast or a compound literal, or whether the operand of sizeof is a parenthesized type name or starts with a compound - literal. */ + literal. TYPE_LOC is the location where TYPE_NAME starts--the + location of the first token after the parentheses around the type + name. */ static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *parser, - struct c_type_name *type_name) + struct c_type_name *type_name, + location_t type_loc) { tree type; struct c_expr init; + bool non_const; struct c_expr expr; location_t start_loc; + tree type_expr = NULL_TREE; + bool type_expr_const = true; + check_compound_literal_type (type_loc, type_name); start_init (NULL_TREE, NULL, 0); - type = groktypename (type_name); + type = groktypename (type_name, &type_expr, &type_expr_const); start_loc = c_parser_peek_token (parser)->location; if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type)) { - error_at (start_loc, "compound literal has variable size"); + error_at (type_loc, "compound literal has variable size"); type = error_mark_node; } init = c_parser_braced_init (parser, type, false); finish_init (); maybe_warn_string_init (type, init); + if (type != error_mark_node + && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type)) + && current_function_decl) + { + error ("compound literal qualified by address-space qualifier"); + type = error_mark_node; + } + if (!flag_isoc99) pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals"); - expr.value = build_compound_literal (type, init.value); + non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR) + ? CONSTRUCTOR_NON_CONST (init.value) + : init.original_code == C_MAYBE_CONST_EXPR); + non_const |= !type_expr_const; + expr.value = build_compound_literal (start_loc, type, init.value, non_const); expr.original_code = ERROR_MARK; - return c_parser_postfix_expression_after_primary (parser, expr); + expr.original_type = NULL; + if (type_expr) + { + if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR) + { + gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE); + C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr; + } + else + { + gcc_assert (!non_const); + expr.value = build2 (C_MAYBE_CONST_EXPR, type, + type_expr, expr.value); + } + } + return c_parser_postfix_expression_after_primary (parser, start_loc, expr); } /* Parse a postfix expression after the initial primary or compound - literal; that is, parse a series of postfix operators. */ + literal; that is, parse a series of postfix operators. + + EXPR_LOC is the location of the primary expression. */ static struct c_expr c_parser_postfix_expression_after_primary (c_parser *parser, - struct c_expr expr) -{ - tree ident, idx, exprlist; - location_t loc = c_parser_peek_token (parser)->location; + location_t expr_loc, + struct c_expr expr) +{ + struct c_expr orig_expr; + tree ident, idx; + VEC(tree,gc) *exprlist; + VEC(tree,gc) *origtypes; while (true) { + location_t op_loc = c_parser_peek_token (parser)->location; switch (c_parser_peek_token (parser)->type) - { - case CPP_OPEN_SQUARE: - /* Array reference. */ - loc = c_parser_peek_token (parser)->location; - c_parser_consume_token (parser); - idx = c_parser_expression (parser).value; - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, - "expected %<]%>"); - expr.value = build_array_ref (expr.value, idx, loc); - expr.original_code = ERROR_MARK; - break; - case CPP_OPEN_PAREN: - /* Function call. */ - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - exprlist = NULL_TREE; - else - exprlist = c_parser_expr_list (parser, true); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - expr.value = build_function_call (expr.value, exprlist); - expr.original_code = ERROR_MARK; - break; - case CPP_DOT: - /* Structure element reference. */ - c_parser_consume_token (parser); - expr = default_function_array_conversion (expr); - if (c_parser_next_token_is (parser, CPP_NAME)) - ident = c_parser_peek_token (parser)->value; - else - { - c_parser_error (parser, "expected identifier"); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - return expr; - } - c_parser_consume_token (parser); - expr.value = build_component_ref (expr.value, ident); - expr.original_code = ERROR_MARK; - break; - case CPP_DEREF: - /* Structure element reference. */ - c_parser_consume_token (parser); - expr = default_function_array_conversion (expr); - if (c_parser_next_token_is (parser, CPP_NAME)) - ident = c_parser_peek_token (parser)->value; - else - { - c_parser_error (parser, "expected identifier"); - expr.value = error_mark_node; - expr.original_code = ERROR_MARK; - return expr; - } - c_parser_consume_token (parser); - expr.value = build_component_ref (build_indirect_ref (loc, - expr.value, - "->"), - ident); - expr.original_code = ERROR_MARK; - break; - case CPP_PLUS_PLUS: - /* Postincrement. */ - c_parser_consume_token (parser); - expr = default_function_array_conversion (expr); - expr.value = build_unary_op (loc, - POSTINCREMENT_EXPR, expr.value, 0); - expr.original_code = ERROR_MARK; - break; - case CPP_MINUS_MINUS: - /* Postdecrement. */ - c_parser_consume_token (parser); - expr = default_function_array_conversion (expr); - expr.value = build_unary_op (loc, - POSTDECREMENT_EXPR, expr.value, 0); - expr.original_code = ERROR_MARK; - break; - default: - return expr; - } + { + case CPP_OPEN_SQUARE: + /* Array reference. */ + c_parser_consume_token (parser); + idx = c_parser_expression (parser).value; + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + expr.value = build_array_ref (op_loc, expr.value, idx); + 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_expr_list (parser, true, false, &origtypes); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + orig_expr = expr; + /* FIXME diagnostics: Ideally we want the FUNCNAME, not the + "(" after the FUNCNAME, which is what we have now. */ + expr.value = build_function_call_vec (op_loc, expr.value, exprlist, + origtypes); + 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 != NULL) + { + release_tree_vector (exprlist); + release_tree_vector (origtypes); + } + break; + case CPP_DOT: + /* Structure element reference. */ + c_parser_consume_token (parser); + expr = default_function_array_conversion (expr_loc, expr); + if (c_parser_next_token_is (parser, CPP_NAME)) + ident = c_parser_peek_token (parser)->value; + else + { + c_parser_error (parser, "expected identifier"); + expr.value = error_mark_node; + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + return expr; + } + c_parser_consume_token (parser); + expr.value = build_component_ref (op_loc, expr.value, ident); + expr.original_code = ERROR_MARK; + if (TREE_CODE (expr.value) != COMPONENT_REF) + expr.original_type = NULL; + else + { + /* Remember the original type of a bitfield. */ + tree field = TREE_OPERAND (expr.value, 1); + if (TREE_CODE (field) != FIELD_DECL) + expr.original_type = NULL; + else + expr.original_type = DECL_BIT_FIELD_TYPE (field); + } + break; + case CPP_DEREF: + /* Structure element reference. */ + c_parser_consume_token (parser); + expr = default_function_array_conversion (expr_loc, expr); + if (c_parser_next_token_is (parser, CPP_NAME)) + ident = c_parser_peek_token (parser)->value; + else + { + c_parser_error (parser, "expected identifier"); + expr.value = error_mark_node; + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + return expr; + } + c_parser_consume_token (parser); + expr.value = build_component_ref (op_loc, + build_indirect_ref (op_loc, + expr.value, + RO_ARROW), + ident); + expr.original_code = ERROR_MARK; + if (TREE_CODE (expr.value) != COMPONENT_REF) + expr.original_type = NULL; + else + { + /* Remember the original type of a bitfield. */ + tree field = TREE_OPERAND (expr.value, 1); + if (TREE_CODE (field) != FIELD_DECL) + expr.original_type = NULL; + else + expr.original_type = DECL_BIT_FIELD_TYPE (field); + } + break; + case CPP_PLUS_PLUS: + /* Postincrement. */ + c_parser_consume_token (parser); + expr = default_function_array_conversion (expr_loc, expr); + expr.value = build_unary_op (op_loc, + POSTINCREMENT_EXPR, expr.value, 0); + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + break; + case CPP_MINUS_MINUS: + /* Postdecrement. */ + c_parser_consume_token (parser); + expr = default_function_array_conversion (expr_loc, expr); + expr.value = build_unary_op (op_loc, + POSTDECREMENT_EXPR, expr.value, 0); + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + break; + default: + return expr; + } } } @@ -6097,11 +6437,15 @@ while (c_parser_next_token_is (parser, CPP_COMMA)) { struct c_expr next; - c_parser_consume_token (parser); + location_t loc = c_parser_peek_token (parser)->location; + location_t expr_loc; + c_parser_consume_token (parser); + expr_loc = c_parser_peek_token (parser)->location; next = c_parser_expr_no_commas (parser, NULL); - next = default_function_array_conversion (next); - expr.value = build_compound_expr (expr.value, next.value); + next = default_function_array_conversion (expr_loc, next); + expr.value = build_compound_expr (loc, expr.value, next.value); expr.original_code = COMPOUND_EXPR; + expr.original_type = next.original_type; } return expr; } @@ -6113,39 +6457,60 @@ c_parser_expression_conv (c_parser *parser) { struct c_expr expr; + location_t loc = c_parser_peek_token (parser)->location; expr = c_parser_expression (parser); - expr = default_function_array_conversion (expr); + expr = default_function_array_conversion (loc, expr); return expr; } /* Parse a non-empty list of expressions. If CONVERT_P, convert - functions and arrays to pointers. + functions and arrays to pointers. If FOLD_P, fold the expressions. nonempty-expr-list: assignment-expression nonempty-expr-list , assignment-expression */ -static tree -c_parser_expr_list (c_parser *parser, bool convert_p) -{ +static VEC(tree,gc) * +c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, + VEC(tree,gc) **p_orig_types) +{ + VEC(tree,gc) *ret; + VEC(tree,gc) *orig_types; struct c_expr expr; - tree ret, cur; + 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_expr_no_commas (parser, NULL); if (convert_p) - expr = default_function_array_conversion (expr); - ret = cur = build_tree_list (NULL_TREE, expr.value); + expr = default_function_array_conversion (loc, expr); + if (fold_p) + expr.value = c_fully_fold (expr.value, false, NULL); + VEC_quick_push (tree, ret, expr.value); + if (orig_types != NULL) + VEC_quick_push (tree, orig_types, expr.original_type); while (c_parser_next_token_is (parser, CPP_COMMA)) { c_parser_consume_token (parser); + loc = c_parser_peek_token (parser)->location; expr = c_parser_expr_no_commas (parser, NULL); if (convert_p) - expr = default_function_array_conversion (expr); - cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value); - } + expr = default_function_array_conversion (loc, expr); + if (fold_p) + expr.value = c_fully_fold (expr.value, false, NULL); + VEC_safe_push (tree, gc, ret, expr.value); + if (orig_types != NULL) + VEC_safe_push (tree, gc, orig_types, expr.original_type); + } + if (orig_types != NULL) + *p_orig_types = orig_types; return ret; } - /* Parse Objective-C-specific constructs. */ @@ -6195,21 +6560,21 @@ tree proto = NULL_TREE; c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return; - } + { + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + return; + } id2 = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (!iface_p) - { - objc_start_category_implementation (id1, id2); - return; - } + { + objc_start_category_implementation (id1, id2); + return; + } if (c_parser_next_token_is (parser, CPP_LESS)) - proto = c_parser_objc_protocol_refs (parser); + proto = c_parser_objc_protocol_refs (parser); objc_start_category_interface (id1, id2, proto); c_parser_objc_methodprotolist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); @@ -6220,10 +6585,10 @@ { c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - return; - } + { + c_parser_error (parser, "expected identifier"); + return; + } superclass = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); } @@ -6233,7 +6598,7 @@ { tree proto = NULL_TREE; if (c_parser_next_token_is (parser, CPP_LESS)) - proto = c_parser_objc_protocol_refs (parser); + proto = c_parser_objc_protocol_refs (parser); objc_start_class_interface (id1, superclass, proto); } else @@ -6286,51 +6651,51 @@ tree decls; /* Parse any stray semicolon. */ if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - { - pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, - "extra semicolon in struct or union specified"); - c_parser_consume_token (parser); - continue; - } + { + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "extra semicolon in struct or union specified"); + c_parser_consume_token (parser); + continue; + } /* Stop if at the end of the instance variables. */ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - { - c_parser_consume_token (parser); - break; - } + { + c_parser_consume_token (parser); + break; + } /* Parse any objc-visibility-spec. */ if (c_parser_next_token_is_keyword (parser, RID_PRIVATE)) - { - c_parser_consume_token (parser); - objc_set_visibility (2); - continue; - } + { + c_parser_consume_token (parser); + objc_set_visibility (2); + continue; + } else if (c_parser_next_token_is_keyword (parser, RID_PROTECTED)) - { - c_parser_consume_token (parser); - objc_set_visibility (0); - continue; - } + { + c_parser_consume_token (parser); + objc_set_visibility (0); + continue; + } else if (c_parser_next_token_is_keyword (parser, RID_PUBLIC)) - { - c_parser_consume_token (parser); - objc_set_visibility (1); - continue; - } + { + c_parser_consume_token (parser); + objc_set_visibility (1); + continue; + } else if (c_parser_next_token_is (parser, CPP_PRAGMA)) - { - c_parser_pragma (parser, pragma_external); - continue; - } + { + c_parser_pragma (parser, pragma_external); + continue; + } /* Parse some comma-separated declarations. */ decls = c_parser_struct_declaration (parser); { - /* Comma-separated instance variables are chained together in - reverse order; add them one by one. */ - tree ivar = nreverse (decls); - for (; ivar; ivar = TREE_CHAIN (ivar)) - objc_add_instance_variable (copy_node (ivar)); + /* Comma-separated instance variables are chained together in + reverse order; add them one by one. */ + tree ivar = nreverse (decls); + for (; ivar; ivar = TREE_CHAIN (ivar)) + objc_add_instance_variable (copy_node (ivar)); } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } @@ -6354,17 +6719,17 @@ { tree id; if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - break; - } + { + c_parser_error (parser, "expected identifier"); + break; + } id = c_parser_peek_token (parser)->value; list = chainon (list, build_tree_list (NULL_TREE, id)); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); + c_parser_consume_token (parser); else - break; + break; } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); objc_declare_class (list); @@ -6428,23 +6793,23 @@ { tree list = NULL_TREE; /* Any identifiers, including those declared as type names, are - OK here. */ + OK here. */ while (true) - { - tree id; - if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - break; - } - id = c_parser_peek_token (parser)->value; - list = chainon (list, build_tree_list (NULL_TREE, id)); - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); - else - break; - } + { + tree id; + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + break; + } + id = c_parser_peek_token (parser)->value; + list = chainon (list, build_tree_list (NULL_TREE, id)); + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + break; + } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); objc_declare_protocols (list); } @@ -6454,7 +6819,7 @@ tree proto = NULL_TREE; c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_LESS)) - proto = c_parser_objc_protocol_refs (parser); + proto = c_parser_objc_protocol_refs (parser); parser->objc_pq_context = true; objc_start_protocol (id, proto); c_parser_objc_methodprotolist (parser); @@ -6504,8 +6869,8 @@ if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { c_parser_consume_token (parser); - pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, - "extra semicolon in method definition specified"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "extra semicolon in method definition specified"); } if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE)) { @@ -6539,27 +6904,27 @@ { /* The list is terminated by @end. */ switch (c_parser_peek_token (parser)->type) - { - case CPP_SEMICOLON: - pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, - "ISO C does not allow extra %<;%> outside of a function"); - c_parser_consume_token (parser); - break; - case CPP_PLUS: - case CPP_MINUS: - c_parser_objc_methodproto (parser); - break; - case CPP_PRAGMA: - c_parser_pragma (parser, pragma_external); - break; - case CPP_EOF: - return; - default: - if (c_parser_next_token_is_keyword (parser, RID_AT_END)) - return; - c_parser_declaration_or_fndef (parser, false, true, false, true); - break; - } + { + case CPP_SEMICOLON: + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "ISO C does not allow extra %<;%> outside of a function"); + c_parser_consume_token (parser); + break; + case CPP_PLUS: + case CPP_MINUS: + c_parser_objc_methodproto (parser); + break; + case CPP_PRAGMA: + c_parser_pragma (parser, pragma_external); + break; + case CPP_EOF: + return; + default: + if (c_parser_next_token_is_keyword (parser, RID_AT_END)) + return; + c_parser_declaration_or_fndef (parser, false, true, false, true); + break; + } } } @@ -6637,50 +7002,50 @@ tree tsel = sel; tree list = NULL_TREE; while (true) - { - tree atype = NULL_TREE, id, keyworddecl; - if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) - break; - if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) - { - c_parser_consume_token (parser); - atype = c_parser_objc_type_name (parser); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - } - if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - return error_mark_node; - } - id = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - keyworddecl = objc_build_keyword_decl (tsel, atype, id); - list = chainon (list, keyworddecl); - tsel = c_parser_objc_selector (parser); - if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON)) - break; - } + { + tree atype = NULL_TREE, id, keyworddecl; + if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) + break; + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + c_parser_consume_token (parser); + atype = c_parser_objc_type_name (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + } + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + return error_mark_node; + } + id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + keyworddecl = objc_build_keyword_decl (tsel, atype, id); + list = chainon (list, keyworddecl); + tsel = c_parser_objc_selector (parser); + if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON)) + break; + } /* Parse the optional parameter list. Optional Objective-C - method parameters follow the C syntax, and may include '...' - to denote a variable number of arguments. */ + method parameters follow the C syntax, and may include '...' + to denote a variable number of arguments. */ parms = make_node (TREE_LIST); while (c_parser_next_token_is (parser, CPP_COMMA)) - { - struct c_parm *parm; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) - { - ellipsis = true; - c_parser_consume_token (parser); - break; - } - parm = c_parser_parameter_declaration (parser, NULL_TREE); - if (parm == NULL) - break; - parms = chainon (parms, - build_tree_list (NULL_TREE, grokparm (parm))); - } + { + struct c_parm *parm; + c_parser_consume_token (parser); + if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) + { + ellipsis = true; + c_parser_consume_token (parser); + break; + } + parm = c_parser_parameter_declaration (parser, NULL_TREE); + if (parm == NULL) + break; + parms = chainon (parms, + build_tree_list (NULL_TREE, grokparm (parm))); + } sel = list; } return objc_build_method_signature (type, sel, parms, ellipsis); @@ -6710,23 +7075,23 @@ { c_token *token = c_parser_peek_token (parser); if (token->type == CPP_KEYWORD - && (token->keyword == RID_IN - || token->keyword == RID_OUT - || token->keyword == RID_INOUT - || token->keyword == RID_BYCOPY - || token->keyword == RID_BYREF - || token->keyword == RID_ONEWAY)) - { - quals = chainon (quals, build_tree_list (NULL_TREE, token->value)); - c_parser_consume_token (parser); - } + && (token->keyword == RID_IN + || token->keyword == RID_OUT + || token->keyword == RID_INOUT + || token->keyword == RID_BYCOPY + || token->keyword == RID_BYREF + || token->keyword == RID_ONEWAY)) + { + quals = chainon (quals, build_tree_list (NULL_TREE, token->value)); + c_parser_consume_token (parser); + } else - break; + break; } if (c_parser_next_token_starts_typename (parser)) type_name = c_parser_type_name (parser); if (type_name) - type = groktypename (type_name); + type = groktypename (type_name, NULL, NULL); return build_tree_list (quals, type); } @@ -6748,17 +7113,17 @@ { tree id; if (c_parser_next_token_is_not (parser, CPP_NAME)) - { - c_parser_error (parser, "expected identifier"); - break; - } + { + c_parser_error (parser, "expected identifier"); + break; + } id = c_parser_peek_token (parser)->value; list = chainon (list, build_tree_list (NULL_TREE, id)); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); + c_parser_consume_token (parser); else - break; + break; } c_parser_require (parser, CPP_GREATER, "expected %<>%>"); return list; @@ -6790,17 +7155,17 @@ struct c_parm *parm; c_parser_consume_token (parser); if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - break; + break; parm = c_parser_parameter_declaration (parser, NULL_TREE); if (parm == NULL) - { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - break; - } + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + break; + } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); objc_begin_catch_clause (grokparm (parm)); if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) - c_parser_compound_statement_nostart (parser); + c_parser_compound_statement_nostart (parser); objc_finish_catch_clause (); } if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY)) @@ -6832,6 +7197,7 @@ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { expr = c_parser_expression (parser).value; + expr = c_fully_fold (expr, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } else @@ -6939,11 +7305,11 @@ while (true) { if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) - return list; + return list; list = chainon (list, build_tree_list (sel, NULL_TREE)); sel = c_parser_objc_selector (parser); if (!sel && c_parser_next_token_is_not (parser, CPP_COLON)) - break; + break; } return list; } @@ -6961,13 +7327,13 @@ { if (c_parser_peek_token (parser)->type == CPP_NAME && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME - || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)) + || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)) { tree id = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); return objc_get_class_reference (id); } - return c_parser_expression (parser).value; + return c_fully_fold (c_parser_expression (parser).value, false, NULL); } /* Parse objc-message-args. @@ -6996,12 +7362,12 @@ { tree keywordexpr; if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) - return error_mark_node; + return error_mark_node; keywordexpr = c_parser_objc_keywordexpr (parser); list = chainon (list, build_tree_list (sel, keywordexpr)); sel = c_parser_objc_selector (parser); if (!sel && c_parser_next_token_is_not (parser, CPP_COLON)) - break; + break; } return list; } @@ -7015,18 +7381,21 @@ static tree c_parser_objc_keywordexpr (c_parser *parser) { - tree list = c_parser_expr_list (parser, true); - if (TREE_CHAIN (list) == NULL_TREE) + tree ret; + VEC(tree,gc) *expr_list = c_parser_expr_list (parser, true, true, NULL); + if (VEC_length (tree, expr_list) == 1) { /* Just return the expression, remove a level of - indirection. */ - return TREE_VALUE (list); + indirection. */ + ret = VEC_index (tree, expr_list, 0); } else { /* We have a comma expression, we will collapse later. */ - return list; - } + ret = build_tree_list_vec (expr_list); + } + release_tree_vector (expr_list); + return ret; } @@ -7047,34 +7416,34 @@ { case PRAGMA_OMP_BARRIER: if (context != pragma_compound) - { - if (context == pragma_stmt) - c_parser_error (parser, "%<#pragma omp barrier%> may only be " - "used in compound statements"); - goto bad_stmt; - } + { + if (context == pragma_stmt) + c_parser_error (parser, "%<#pragma omp barrier%> may only be " + "used in compound statements"); + goto bad_stmt; + } c_parser_omp_barrier (parser); return false; case PRAGMA_OMP_FLUSH: if (context != pragma_compound) - { - if (context == pragma_stmt) - c_parser_error (parser, "%<#pragma omp flush%> may only be " - "used in compound statements"); - goto bad_stmt; - } + { + if (context == pragma_stmt) + c_parser_error (parser, "%<#pragma omp flush%> may only be " + "used in compound statements"); + goto bad_stmt; + } c_parser_omp_flush (parser); return false; case PRAGMA_OMP_TASKWAIT: if (context != pragma_compound) - { - if (context == pragma_stmt) - c_parser_error (parser, "%<#pragma omp taskwait%> may only be " - "used in compound statements"); - goto bad_stmt; - } + { + if (context == pragma_stmt) + c_parser_error (parser, "%<#pragma omp taskwait%> may only be " + "used in compound statements"); + goto bad_stmt; + } c_parser_omp_taskwait (parser); return false; @@ -7084,8 +7453,8 @@ case PRAGMA_OMP_SECTION: error_at (c_parser_peek_token (parser)->location, - "%<#pragma omp section%> may only be used in " - "%<#pragma omp sections%> construct"); + "%<#pragma omp section%> may only be used in " + "%<#pragma omp sections%> construct"); c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); return false; @@ -7096,24 +7465,24 @@ default: if (id < PRAGMA_FIRST_EXTERNAL) - { - if (context == pragma_external) - { - bad_stmt: - c_parser_error (parser, "expected declaration specifiers"); - c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); - return false; - } - c_parser_omp_construct (parser); - return true; - } + { + if (context == pragma_external) + { + bad_stmt: + c_parser_error (parser, "expected declaration specifiers"); + c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); + return false; + } + c_parser_omp_construct (parser); + return true; + } break; } c_parser_consume_pragma (parser); c_invoke_pragma_handler (id); - /* Skip to EOL, but suppress any error message. Those will have been + /* Skip to EOL, but suppress any error message. Those will have been generated by the handler routine through calling error, as opposed to calling c_parser_error. */ parser->error = true; @@ -7136,7 +7505,7 @@ else { if (ret == CPP_KEYWORD) - ret = CPP_NAME; + ret = CPP_NAME; c_parser_consume_token (the_parser); } @@ -7183,52 +7552,52 @@ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); switch (p[0]) - { - case 'c': - if (!strcmp ("collapse", p)) - result = PRAGMA_OMP_CLAUSE_COLLAPSE; - else if (!strcmp ("copyin", p)) - result = PRAGMA_OMP_CLAUSE_COPYIN; + { + case 'c': + if (!strcmp ("collapse", p)) + result = PRAGMA_OMP_CLAUSE_COLLAPSE; + else if (!strcmp ("copyin", p)) + result = PRAGMA_OMP_CLAUSE_COPYIN; else if (!strcmp ("copyprivate", p)) - result = PRAGMA_OMP_CLAUSE_COPYPRIVATE; - break; - case 'f': - if (!strcmp ("firstprivate", p)) - result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; - break; - case 'l': - if (!strcmp ("lastprivate", p)) - result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; - break; - case 'n': - if (!strcmp ("nowait", p)) - result = PRAGMA_OMP_CLAUSE_NOWAIT; - else if (!strcmp ("num_threads", p)) - result = PRAGMA_OMP_CLAUSE_NUM_THREADS; - break; - case 'o': - if (!strcmp ("ordered", p)) - result = PRAGMA_OMP_CLAUSE_ORDERED; - break; - case 'p': - if (!strcmp ("private", p)) - result = PRAGMA_OMP_CLAUSE_PRIVATE; - break; - case 'r': - if (!strcmp ("reduction", p)) - result = PRAGMA_OMP_CLAUSE_REDUCTION; - break; - case 's': - if (!strcmp ("schedule", p)) - result = PRAGMA_OMP_CLAUSE_SCHEDULE; - else if (!strcmp ("shared", p)) - result = PRAGMA_OMP_CLAUSE_SHARED; - break; - case 'u': - if (!strcmp ("untied", p)) - result = PRAGMA_OMP_CLAUSE_UNTIED; - break; - } + result = PRAGMA_OMP_CLAUSE_COPYPRIVATE; + break; + case 'f': + if (!strcmp ("firstprivate", p)) + result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; + break; + case 'l': + if (!strcmp ("lastprivate", p)) + result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; + break; + case 'n': + if (!strcmp ("nowait", p)) + result = PRAGMA_OMP_CLAUSE_NOWAIT; + else if (!strcmp ("num_threads", p)) + result = PRAGMA_OMP_CLAUSE_NUM_THREADS; + break; + case 'o': + if (!strcmp ("ordered", p)) + result = PRAGMA_OMP_CLAUSE_ORDERED; + break; + case 'p': + if (!strcmp ("private", p)) + result = PRAGMA_OMP_CLAUSE_PRIVATE; + break; + case 'r': + if (!strcmp ("reduction", p)) + result = PRAGMA_OMP_CLAUSE_REDUCTION; + break; + case 's': + if (!strcmp ("schedule", p)) + result = PRAGMA_OMP_CLAUSE_SCHEDULE; + else if (!strcmp ("shared", p)) + result = PRAGMA_OMP_CLAUSE_SHARED; + break; + case 'u': + if (!strcmp ("untied", p)) + result = PRAGMA_OMP_CLAUSE_UNTIED; + break; + } } if (result != PRAGMA_OMP_CLAUSE_NONE) @@ -7241,15 +7610,16 @@ static void check_no_duplicate_clause (tree clauses, enum omp_clause_code code, - const char *name) + const char *name) { tree c; for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == code) { - error ("too many %qs clauses", name); - break; + location_t loc = OMP_CLAUSE_LOCATION (c); + error_at (loc, "too many %qs clauses", name); + break; } } @@ -7258,14 +7628,17 @@ identifier variable-list , identifier - If KIND is nonzero, create the appropriate node and install the decl - in OMP_CLAUSE_DECL and add the node to the head of the list. + If KIND is nonzero, create the appropriate node and install the + decl in OMP_CLAUSE_DECL and add the node to the head of the list. + If KIND is nonzero, CLAUSE_LOC is the location of the clause. If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE; return the list created. */ static tree -c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind, +c_parser_omp_variable_list (c_parser *parser, + location_t clause_loc, + enum omp_clause_code kind, tree list) { if (c_parser_next_token_is_not (parser, CPP_NAME) @@ -7273,29 +7646,29 @@ c_parser_error (parser, "expected identifier"); while (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_token (parser)->id_kind == C_ID_ID) + && c_parser_peek_token (parser)->id_kind == C_ID_ID) { tree t = lookup_name (c_parser_peek_token (parser)->value); if (t == NULL_TREE) - undeclared_variable (c_parser_peek_token (parser)->value, - c_parser_peek_token (parser)->location); + undeclared_variable (c_parser_peek_token (parser)->location, + c_parser_peek_token (parser)->value); else if (t == error_mark_node) - ; + ; else if (kind != 0) - { - tree u = build_omp_clause (kind); - OMP_CLAUSE_DECL (u) = t; - OMP_CLAUSE_CHAIN (u) = list; - list = u; - } + { + tree u = build_omp_clause (clause_loc, kind); + OMP_CLAUSE_DECL (u) = t; + OMP_CLAUSE_CHAIN (u) = list; + list = u; + } else - list = tree_cons (t, NULL_TREE, list); + list = tree_cons (t, NULL_TREE, list); c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_COMMA)) - break; + break; c_parser_consume_token (parser); } @@ -7308,11 +7681,14 @@ static tree c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, - tree list) -{ + tree list) +{ + /* The clauses location. */ + location_t loc = c_parser_peek_token (parser)->location; + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - list = c_parser_omp_variable_list (parser, kind, list); + list = c_parser_omp_variable_list (parser, loc, kind, list); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } return list; @@ -7344,10 +7720,10 @@ || (int) n != n) { error_at (loc, - "collapse argument needs positive constant integer expression"); + "collapse argument needs positive constant integer expression"); return list; } - c = build_omp_clause (OMP_CLAUSE_COLLAPSE); + c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE); OMP_CLAUSE_COLLAPSE_EXPR (c) = num; OMP_CLAUSE_CHAIN (c) = list; return c; @@ -7378,6 +7754,7 @@ c_parser_omp_clause_default (c_parser *parser, tree list) { enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED; + location_t loc = c_parser_peek_token (parser)->location; tree c; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) @@ -7387,22 +7764,22 @@ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); switch (p[0]) - { - case 'n': - if (strcmp ("none", p) != 0) - goto invalid_kind; - kind = OMP_CLAUSE_DEFAULT_NONE; - break; - - case 's': - if (strcmp ("shared", p) != 0) - goto invalid_kind; - kind = OMP_CLAUSE_DEFAULT_SHARED; - break; - - default: - goto invalid_kind; - } + { + case 'n': + if (strcmp ("none", p) != 0) + goto invalid_kind; + kind = OMP_CLAUSE_DEFAULT_NONE; + break; + + case 's': + if (strcmp ("shared", p) != 0) + goto invalid_kind; + kind = OMP_CLAUSE_DEFAULT_SHARED; + break; + + default: + goto invalid_kind; + } c_parser_consume_token (parser); } @@ -7417,7 +7794,7 @@ return list; check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default"); - c = build_omp_clause (OMP_CLAUSE_DEFAULT); + c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT); OMP_CLAUSE_CHAIN (c) = list; OMP_CLAUSE_DEFAULT_KIND (c) = kind; @@ -7439,6 +7816,7 @@ static tree c_parser_omp_clause_if (c_parser *parser, tree list) { + location_t loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) { tree t = c_parser_paren_condition (parser); @@ -7446,7 +7824,7 @@ check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if"); - c = build_omp_clause (OMP_CLAUSE_IF); + c = build_omp_clause (loc, OMP_CLAUSE_IF); OMP_CLAUSE_IF_EXPR (c) = t; OMP_CLAUSE_CHAIN (c) = list; list = c; @@ -7473,10 +7851,11 @@ c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list) { tree c; + location_t loc = c_parser_peek_token (parser)->location; check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait"); - c = build_omp_clause (OMP_CLAUSE_NOWAIT); + c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); OMP_CLAUSE_CHAIN (c) = list; return c; } @@ -7487,32 +7866,36 @@ static tree c_parser_omp_clause_num_threads (c_parser *parser, tree list) { + location_t num_threads_loc = c_parser_peek_token (parser)->location; if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { location_t expr_loc = c_parser_peek_token (parser)->location; tree c, t = c_parser_expression (parser).value; + t = c_fully_fold (t, false, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (!INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - c_parser_error (parser, "expected integer expression"); - return list; - } + { + c_parser_error (parser, "expected integer expression"); + return list; + } /* Attempt to statically determine when the number isn't positive. */ - c = fold_build2 (LE_EXPR, boolean_type_node, t, - build_int_cst (TREE_TYPE (t), 0)); + c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t, + build_int_cst (TREE_TYPE (t), 0)); + if (CAN_HAVE_LOCATION_P (c)) + SET_EXPR_LOCATION (c, expr_loc); if (c == boolean_true_node) - { - warning_at (expr_loc, 0, - "%<num_threads%> value must be positive"); - t = integer_one_node; - } + { + warning_at (expr_loc, 0, + "%<num_threads%> value must be positive"); + t = integer_one_node; + } check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads"); - c = build_omp_clause (OMP_CLAUSE_NUM_THREADS); + c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS); OMP_CLAUSE_NUM_THREADS_EXPR (c) = t; OMP_CLAUSE_CHAIN (c) = list; list = c; @@ -7525,14 +7908,16 @@ ordered */ static tree -c_parser_omp_clause_ordered (c_parser *parser ATTRIBUTE_UNUSED, tree list) +c_parser_omp_clause_ordered (c_parser *parser, tree list) { tree c; check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered"); - c = build_omp_clause (OMP_CLAUSE_ORDERED); + c = build_omp_clause (c_parser_peek_token (parser)->location, + OMP_CLAUSE_ORDERED); OMP_CLAUSE_CHAIN (c) = list; + return c; } @@ -7554,54 +7939,56 @@ static tree c_parser_omp_clause_reduction (c_parser *parser, tree list) { + location_t clause_loc = c_parser_peek_token (parser)->location; if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { enum tree_code code; switch (c_parser_peek_token (parser)->type) - { - case CPP_PLUS: - code = PLUS_EXPR; - break; - case CPP_MULT: - code = MULT_EXPR; - break; - case CPP_MINUS: - code = MINUS_EXPR; - break; - case CPP_AND: - code = BIT_AND_EXPR; - break; - case CPP_XOR: - code = BIT_XOR_EXPR; - break; - case CPP_OR: - code = BIT_IOR_EXPR; - break; - case CPP_AND_AND: - code = TRUTH_ANDIF_EXPR; - break; - case CPP_OR_OR: - code = TRUTH_ORIF_EXPR; - break; - default: - c_parser_error (parser, - "expected %<+%>, %<*%>, %<-%>, %<&%>, " - "%<^%>, %<|%>, %<&&%>, or %<||%>"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0); - return list; - } + { + case CPP_PLUS: + code = PLUS_EXPR; + break; + case CPP_MULT: + code = MULT_EXPR; + break; + case CPP_MINUS: + code = MINUS_EXPR; + break; + case CPP_AND: + code = BIT_AND_EXPR; + break; + case CPP_XOR: + code = BIT_XOR_EXPR; + break; + case CPP_OR: + code = BIT_IOR_EXPR; + break; + case CPP_AND_AND: + code = TRUTH_ANDIF_EXPR; + break; + case CPP_OR_OR: + code = TRUTH_ORIF_EXPR; + break; + default: + c_parser_error (parser, + "expected %<+%>, %<*%>, %<-%>, %<&%>, " + "%<^%>, %<|%>, %<&&%>, or %<||%>"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0); + return list; + } c_parser_consume_token (parser); if (c_parser_require (parser, CPP_COLON, "expected %<:%>")) - { - tree nl, c; - - nl = c_parser_omp_variable_list (parser, OMP_CLAUSE_REDUCTION, list); - for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) - OMP_CLAUSE_REDUCTION_CODE (c) = code; - - list = nl; - } + { + tree nl, c; + + nl = c_parser_omp_variable_list (parser, clause_loc, + OMP_CLAUSE_REDUCTION, list); + for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_REDUCTION_CODE (c) = code; + + list = nl; + } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } return list; @@ -7619,11 +8006,12 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) { tree c, t; + location_t loc = c_parser_peek_token (parser)->location; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) return list; - c = build_omp_clause (OMP_CLAUSE_SCHEDULE); + c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE); if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -7631,28 +8019,28 @@ const char *p = IDENTIFIER_POINTER (kind); switch (p[0]) - { - case 'd': - if (strcmp ("dynamic", p) != 0) - goto invalid_kind; - OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC; - break; + { + case 'd': + if (strcmp ("dynamic", p) != 0) + goto invalid_kind; + OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC; + break; case 'g': - if (strcmp ("guided", p) != 0) - goto invalid_kind; - OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED; - break; - - case 'r': - if (strcmp ("runtime", p) != 0) - goto invalid_kind; - OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME; - break; - - default: - goto invalid_kind; - } + if (strcmp ("guided", p) != 0) + goto invalid_kind; + OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED; + break; + + case 'r': + if (strcmp ("runtime", p) != 0) + goto invalid_kind; + OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME; + break; + + default: + goto invalid_kind; + } } else if (c_parser_next_token_is_keyword (parser, RID_STATIC)) OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC; @@ -7669,24 +8057,25 @@ here = c_parser_peek_token (parser)->location; t = c_parser_expr_no_commas (parser, NULL).value; + t = c_fully_fold (t, false, NULL); if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME) - error_at (here, "schedule %<runtime%> does not take " - "a %<chunk_size%> parameter"); + error_at (here, "schedule %<runtime%> does not take " + "a %<chunk_size%> parameter"); else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO) - error_at (here, - "schedule %<auto%> does not take " - "a %<chunk_size%> parameter"); + error_at (here, + "schedule %<auto%> does not take " + "a %<chunk_size%> parameter"); else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE) - OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; + OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; else - c_parser_error (parser, "expected integer expression"); + c_parser_error (parser, "expected integer expression"); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } else c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<,%> or %<)%>"); + "expected %<,%> or %<)%>"); check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule"); OMP_CLAUSE_CHAIN (c) = list; @@ -7718,8 +8107,10 @@ /* FIXME: Should we allow duplicates? */ check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied"); - c = build_omp_clause (OMP_CLAUSE_UNTIED); + c = build_omp_clause (c_parser_peek_token (parser)->location, + OMP_CLAUSE_UNTIED); OMP_CLAUSE_CHAIN (c) = list; + return c; } @@ -7729,7 +8120,7 @@ static tree c_parser_omp_all_clauses (c_parser *parser, unsigned int mask, - const char *where) + const char *where) { tree clauses = NULL; bool first = true; @@ -7742,86 +8133,86 @@ tree prev = clauses; if (!first && c_parser_next_token_is (parser, CPP_COMMA)) - c_parser_consume_token (parser); + c_parser_consume_token (parser); first = false; here = c_parser_peek_token (parser)->location; c_kind = c_parser_omp_clause_name (parser); switch (c_kind) - { - case PRAGMA_OMP_CLAUSE_COLLAPSE: - clauses = c_parser_omp_clause_collapse (parser, clauses); - c_name = "collapse"; - break; - case PRAGMA_OMP_CLAUSE_COPYIN: - clauses = c_parser_omp_clause_copyin (parser, clauses); - c_name = "copyin"; - break; - case PRAGMA_OMP_CLAUSE_COPYPRIVATE: - clauses = c_parser_omp_clause_copyprivate (parser, clauses); - c_name = "copyprivate"; - break; - case PRAGMA_OMP_CLAUSE_DEFAULT: - clauses = c_parser_omp_clause_default (parser, clauses); - c_name = "default"; - break; - case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: - clauses = c_parser_omp_clause_firstprivate (parser, clauses); - c_name = "firstprivate"; - break; - case PRAGMA_OMP_CLAUSE_IF: - clauses = c_parser_omp_clause_if (parser, clauses); - c_name = "if"; - break; - case PRAGMA_OMP_CLAUSE_LASTPRIVATE: - clauses = c_parser_omp_clause_lastprivate (parser, clauses); - c_name = "lastprivate"; - break; - case PRAGMA_OMP_CLAUSE_NOWAIT: - clauses = c_parser_omp_clause_nowait (parser, clauses); - c_name = "nowait"; - break; - case PRAGMA_OMP_CLAUSE_NUM_THREADS: - clauses = c_parser_omp_clause_num_threads (parser, clauses); - c_name = "num_threads"; - break; - case PRAGMA_OMP_CLAUSE_ORDERED: - clauses = c_parser_omp_clause_ordered (parser, clauses); - c_name = "ordered"; - break; - case PRAGMA_OMP_CLAUSE_PRIVATE: - clauses = c_parser_omp_clause_private (parser, clauses); - c_name = "private"; - break; - case PRAGMA_OMP_CLAUSE_REDUCTION: - clauses = c_parser_omp_clause_reduction (parser, clauses); - c_name = "reduction"; - break; - case PRAGMA_OMP_CLAUSE_SCHEDULE: - clauses = c_parser_omp_clause_schedule (parser, clauses); - c_name = "schedule"; - break; - case PRAGMA_OMP_CLAUSE_SHARED: - clauses = c_parser_omp_clause_shared (parser, clauses); - c_name = "shared"; - break; - case PRAGMA_OMP_CLAUSE_UNTIED: - clauses = c_parser_omp_clause_untied (parser, clauses); - c_name = "untied"; - break; - default: - c_parser_error (parser, "expected %<#pragma omp%> clause"); - goto saw_error; - } + { + case PRAGMA_OMP_CLAUSE_COLLAPSE: + clauses = c_parser_omp_clause_collapse (parser, clauses); + c_name = "collapse"; + break; + case PRAGMA_OMP_CLAUSE_COPYIN: + clauses = c_parser_omp_clause_copyin (parser, clauses); + c_name = "copyin"; + break; + case PRAGMA_OMP_CLAUSE_COPYPRIVATE: + clauses = c_parser_omp_clause_copyprivate (parser, clauses); + c_name = "copyprivate"; + break; + case PRAGMA_OMP_CLAUSE_DEFAULT: + clauses = c_parser_omp_clause_default (parser, clauses); + c_name = "default"; + break; + case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: + clauses = c_parser_omp_clause_firstprivate (parser, clauses); + c_name = "firstprivate"; + break; + case PRAGMA_OMP_CLAUSE_IF: + clauses = c_parser_omp_clause_if (parser, clauses); + c_name = "if"; + break; + case PRAGMA_OMP_CLAUSE_LASTPRIVATE: + clauses = c_parser_omp_clause_lastprivate (parser, clauses); + c_name = "lastprivate"; + break; + case PRAGMA_OMP_CLAUSE_NOWAIT: + clauses = c_parser_omp_clause_nowait (parser, clauses); + c_name = "nowait"; + break; + case PRAGMA_OMP_CLAUSE_NUM_THREADS: + clauses = c_parser_omp_clause_num_threads (parser, clauses); + c_name = "num_threads"; + break; + case PRAGMA_OMP_CLAUSE_ORDERED: + clauses = c_parser_omp_clause_ordered (parser, clauses); + c_name = "ordered"; + break; + case PRAGMA_OMP_CLAUSE_PRIVATE: + clauses = c_parser_omp_clause_private (parser, clauses); + c_name = "private"; + break; + case PRAGMA_OMP_CLAUSE_REDUCTION: + clauses = c_parser_omp_clause_reduction (parser, clauses); + c_name = "reduction"; + break; + case PRAGMA_OMP_CLAUSE_SCHEDULE: + clauses = c_parser_omp_clause_schedule (parser, clauses); + c_name = "schedule"; + break; + case PRAGMA_OMP_CLAUSE_SHARED: + clauses = c_parser_omp_clause_shared (parser, clauses); + c_name = "shared"; + break; + case PRAGMA_OMP_CLAUSE_UNTIED: + clauses = c_parser_omp_clause_untied (parser, clauses); + c_name = "untied"; + break; + default: + c_parser_error (parser, "expected %<#pragma omp%> clause"); + goto saw_error; + } if (((mask >> c_kind) & 1) == 0 && !parser->error) - { - /* Remove the invalid clause(s) from the list to avoid - confusing the rest of the compiler. */ - clauses = prev; - error_at (here, "%qs is not valid for %qs", c_name, where); - } + { + /* Remove the invalid clause(s) from the list to avoid + confusing the rest of the compiler. */ + clauses = prev; + error_at (here, "%qs is not valid for %qs", c_name, where); + } } saw_error: @@ -7855,10 +8246,12 @@ binop: +, *, -, /, &, ^, |, <<, >> - where x is an lvalue expression with scalar type. */ + where x is an lvalue expression with scalar type. + + LOC is the location of the #pragma token. */ static void -c_parser_omp_atomic (c_parser *parser) +c_parser_omp_atomic (location_t loc, c_parser *parser) { tree lhs, rhs; tree stmt; @@ -7868,6 +8261,7 @@ c_parser_skip_to_pragma_eol (parser); lhs = c_parser_unary_expression (parser).value; + lhs = c_fully_fold (lhs, false, NULL); switch (TREE_CODE (lhs)) { case ERROR_MARK: @@ -7891,47 +8285,51 @@ default: switch (c_parser_peek_token (parser)->type) - { - case CPP_MULT_EQ: - code = MULT_EXPR; - break; - case CPP_DIV_EQ: - code = TRUNC_DIV_EXPR; - break; - case CPP_PLUS_EQ: - code = PLUS_EXPR; - break; - case CPP_MINUS_EQ: - code = MINUS_EXPR; - break; - case CPP_LSHIFT_EQ: - code = LSHIFT_EXPR; - break; - case CPP_RSHIFT_EQ: - code = RSHIFT_EXPR; - break; - case CPP_AND_EQ: - code = BIT_AND_EXPR; - break; - case CPP_OR_EQ: - code = BIT_IOR_EXPR; - break; - case CPP_XOR_EQ: - code = BIT_XOR_EXPR; - break; - default: - c_parser_error (parser, - "invalid operator for %<#pragma omp atomic%>"); - goto saw_error; - } - - c_parser_consume_token (parser); - rhs_expr = c_parser_expression (parser); - rhs_expr = default_function_array_conversion (rhs_expr); + { + case CPP_MULT_EQ: + code = MULT_EXPR; + break; + case CPP_DIV_EQ: + code = TRUNC_DIV_EXPR; + break; + case CPP_PLUS_EQ: + code = PLUS_EXPR; + break; + case CPP_MINUS_EQ: + code = MINUS_EXPR; + break; + case CPP_LSHIFT_EQ: + code = LSHIFT_EXPR; + break; + case CPP_RSHIFT_EQ: + code = RSHIFT_EXPR; + break; + case CPP_AND_EQ: + code = BIT_AND_EXPR; + break; + case CPP_OR_EQ: + code = BIT_IOR_EXPR; + break; + case CPP_XOR_EQ: + code = BIT_XOR_EXPR; + break; + default: + c_parser_error (parser, + "invalid operator for %<#pragma omp atomic%>"); + goto saw_error; + } + + c_parser_consume_token (parser); + { + location_t rhs_loc = c_parser_peek_token (parser)->location; + rhs_expr = c_parser_expression (parser); + rhs_expr = default_function_array_conversion (rhs_loc, rhs_expr); + } rhs = rhs_expr.value; - break; - } - stmt = c_finish_omp_atomic (code, lhs, rhs); + rhs = c_fully_fold (rhs, false, NULL); + break; + } + stmt = c_finish_omp_atomic (loc, code, lhs, rhs); if (stmt != error_mark_node) add_stmt (stmt); c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); @@ -7945,19 +8343,21 @@ static void c_parser_omp_barrier (c_parser *parser) { + location_t loc = c_parser_peek_token (parser)->location; c_parser_consume_pragma (parser); c_parser_skip_to_pragma_eol (parser); - c_finish_omp_barrier (); + c_finish_omp_barrier (loc); } /* OpenMP 2.5: # pragma omp critical [(name)] new-line structured-block -*/ + + LOC is the location of the #pragma itself. */ static tree -c_parser_omp_critical (c_parser *parser) +c_parser_omp_critical (location_t loc, c_parser *parser) { tree stmt, name = NULL; @@ -7965,20 +8365,20 @@ { c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_NAME)) - { - name = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); - } + { + name = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + } else - c_parser_error (parser, "expected identifier"); + c_parser_error (parser, "expected identifier"); } else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) c_parser_error (parser, "expected %<(%> or end of line"); c_parser_skip_to_pragma_eol (parser); stmt = c_parser_omp_structured_block (parser); - return c_finish_omp_critical (stmt, name); + return c_finish_omp_critical (loc, stmt, name); } /* OpenMP 2.5: @@ -7990,6 +8390,7 @@ static void c_parser_omp_flush (c_parser *parser) { + location_t loc = c_parser_peek_token (parser)->location; c_parser_consume_pragma (parser); if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL); @@ -7997,21 +8398,23 @@ c_parser_error (parser, "expected %<(%> or end of line"); c_parser_skip_to_pragma_eol (parser); - c_finish_omp_flush (); + c_finish_omp_flush (loc); } /* Parse the restricted form of the for statement allowed by OpenMP. The real trick here is to determine the loop control variable early - so that we can push a new decl if necessary to make it private. */ + so that we can push a new decl if necessary to make it private. + LOC is the location of the OMP in "#pragma omp". */ static tree -c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) +c_parser_omp_for_loop (location_t loc, + c_parser *parser, tree clauses, tree *par_clauses) { tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl; tree declv, condv, incrv, initv, for_block = NULL, ret = NULL; - location_t loc; bool fail = false, open_brace_parsed = false; int i, collapse = 1, nbraces = 0; + location_t for_loc; for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl)) if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE) @@ -8029,7 +8432,7 @@ c_parser_error (parser, "for statement expected"); return NULL; } - loc = c_parser_peek_token (parser)->location; + for_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); for (i = 0; i < collapse; i++) @@ -8037,135 +8440,139 @@ int bracecount = 0; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - goto pop_scopes; + goto pop_scopes; /* Parse the initialization declaration or expression. */ if (c_parser_next_token_starts_declspecs (parser)) - { - if (i > 0) - for_block - = tree_cons (NULL, c_begin_compound_stmt (true), for_block); - c_parser_declaration_or_fndef (parser, true, true, true, true); - decl = check_for_loop_decls (); - if (decl == NULL) - goto error_init; - if (DECL_INITIAL (decl) == error_mark_node) - decl = error_mark_node; - init = decl; - } + { + if (i > 0) + for_block + = tree_cons (NULL, c_begin_compound_stmt (true), for_block); + c_parser_declaration_or_fndef (parser, true, true, true, true); + decl = check_for_loop_decls (for_loc); + if (decl == NULL) + goto error_init; + if (DECL_INITIAL (decl) == error_mark_node) + decl = error_mark_node; + init = decl; + } else if (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_EQ) - { - struct c_expr init_exp; - location_t init_loc; - - decl = c_parser_postfix_expression (parser).value; - - c_parser_require (parser, CPP_EQ, "expected %<=%>"); - init_loc = c_parser_peek_token (parser)->location; - - init_exp = c_parser_expr_no_commas (parser, NULL); - init_exp = default_function_array_conversion (init_exp); - init = build_modify_expr (init_loc, - decl, NOP_EXPR, init_exp.value); - init = c_process_expr_stmt (init); - - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); - } + && c_parser_peek_2nd_token (parser)->type == CPP_EQ) + { + struct c_expr decl_exp; + struct c_expr init_exp; + location_t init_loc; + + decl_exp = c_parser_postfix_expression (parser); + decl = decl_exp.value; + + c_parser_require (parser, CPP_EQ, "expected %<=%>"); + + init_loc = c_parser_peek_token (parser)->location; + init_exp = c_parser_expr_no_commas (parser, NULL); + init_exp = default_function_array_conversion (init_loc, init_exp); + init = build_modify_expr (init_loc, decl, decl_exp.original_type, + NOP_EXPR, init_loc, init_exp.value, + init_exp.original_type); + init = c_process_expr_stmt (init_loc, init); + + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + } else - { - error_init: - c_parser_error (parser, - "expected iteration declaration or initialization"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, - "expected %<)%>"); - fail = true; - goto parse_next; - } + { + error_init: + c_parser_error (parser, + "expected iteration declaration or initialization"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, + "expected %<)%>"); + fail = true; + goto parse_next; + } /* Parse the loop condition. */ cond = NULL_TREE; if (c_parser_next_token_is_not (parser, CPP_SEMICOLON)) - { - location_t cond_loc = c_parser_peek_token (parser)->location; - struct c_expr cond_expr = c_parser_binary_expression (parser, NULL); - - cond = cond_expr.value; - cond = c_objc_common_truthvalue_conversion (cond_loc, cond); - switch (cond_expr.original_code) - { - case GT_EXPR: - case GE_EXPR: - case LT_EXPR: - case LE_EXPR: - break; - default: - /* Can't be cond = error_mark_node, because we want to preserve - the location until c_finish_omp_for. */ - cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node); - break; - } - protected_set_expr_location (cond, cond_loc); - } + { + location_t cond_loc = c_parser_peek_token (parser)->location; + struct c_expr cond_expr = c_parser_binary_expression (parser, NULL); + + cond = cond_expr.value; + cond = c_objc_common_truthvalue_conversion (cond_loc, cond); + cond = c_fully_fold (cond, false, NULL); + switch (cond_expr.original_code) + { + case GT_EXPR: + case GE_EXPR: + case LT_EXPR: + case LE_EXPR: + break; + default: + /* Can't be cond = error_mark_node, because we want to preserve + the location until c_finish_omp_for. */ + cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node); + break; + } + protected_set_expr_location (cond, cond_loc); + } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); /* Parse the increment expression. */ incr = NULL_TREE; if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) - { - location_t incr_loc = c_parser_peek_token (parser)->location; - - incr = c_process_expr_stmt (c_parser_expression (parser).value); - protected_set_expr_location (incr, incr_loc); - } + { + location_t incr_loc = c_parser_peek_token (parser)->location; + + incr = c_process_expr_stmt (incr_loc, + c_parser_expression (parser).value); + } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (decl == NULL || decl == error_mark_node || init == error_mark_node) - fail = true; + fail = true; else - { - TREE_VEC_ELT (declv, i) = decl; - TREE_VEC_ELT (initv, i) = init; - TREE_VEC_ELT (condv, i) = cond; - TREE_VEC_ELT (incrv, i) = incr; - } + { + TREE_VEC_ELT (declv, i) = decl; + TREE_VEC_ELT (initv, i) = init; + TREE_VEC_ELT (condv, i) = cond; + TREE_VEC_ELT (incrv, i) = incr; + } parse_next: if (i == collapse - 1) - break; + break; /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed - in between the collapsed for loops to be still considered perfectly - nested. Hopefully the final version clarifies this. - For now handle (multiple) {'s and empty statements. */ + in between the collapsed for loops to be still considered perfectly + nested. Hopefully the final version clarifies this. + For now handle (multiple) {'s and empty statements. */ do - { - if (c_parser_next_token_is_keyword (parser, RID_FOR)) - { - c_parser_consume_token (parser); - break; - } - else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) - { - c_parser_consume_token (parser); - bracecount++; - } - else if (bracecount - && c_parser_next_token_is (parser, CPP_SEMICOLON)) - c_parser_consume_token (parser); - else - { - c_parser_error (parser, "not enough perfectly nested loops"); - if (bracecount) - { - open_brace_parsed = true; - bracecount--; - } - fail = true; - collapse = 0; - break; - } - } + { + if (c_parser_next_token_is_keyword (parser, RID_FOR)) + { + c_parser_consume_token (parser); + break; + } + else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) + { + c_parser_consume_token (parser); + bracecount++; + } + else if (bracecount + && c_parser_next_token_is (parser, CPP_SEMICOLON)) + c_parser_consume_token (parser); + else + { + c_parser_error (parser, "not enough perfectly nested loops"); + if (bracecount) + { + open_brace_parsed = true; + bracecount--; + } + fail = true; + collapse = 0; + break; + } + } while (1); nbraces += bracecount; @@ -8179,14 +8586,19 @@ if (open_brace_parsed) { + location_t here = c_parser_peek_token (parser)->location; stmt = c_begin_compound_stmt (true); c_parser_compound_statement_nostart (parser); - add_stmt (c_end_compound_stmt (stmt, true)); + add_stmt (c_end_compound_stmt (here, stmt, true)); } else add_stmt (c_parser_c99_block_statement (parser)); if (c_cont_label) - add_stmt (build1 (LABEL_EXPR, void_type_node, c_cont_label)); + { + tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label); + SET_EXPR_LOCATION (t, loc); + add_stmt (t); + } body = pop_stmt_list (body); c_break_label = save_break; @@ -8195,25 +8607,26 @@ while (nbraces) { if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - { - c_parser_consume_token (parser); - nbraces--; - } + { + c_parser_consume_token (parser); + nbraces--; + } else if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - c_parser_consume_token (parser); + c_parser_consume_token (parser); else - { - c_parser_error (parser, "collapsed loops not perfectly nested"); - while (nbraces) - { - stmt = c_begin_compound_stmt (true); - add_stmt (body); - c_parser_compound_statement_nostart (parser); - body = c_end_compound_stmt (stmt, true); - nbraces--; - } - goto pop_scopes; - } + { + c_parser_error (parser, "collapsed loops not perfectly nested"); + while (nbraces) + { + location_t here = c_parser_peek_token (parser)->location; + stmt = c_begin_compound_stmt (true); + add_stmt (body); + c_parser_compound_statement_nostart (parser); + body = c_end_compound_stmt (here, stmt, true); + nbraces--; + } + goto pop_scopes; + } } /* Only bother calling c_finish_omp_for if we haven't already generated @@ -8222,49 +8635,53 @@ { stmt = c_finish_omp_for (loc, declv, initv, condv, incrv, body, NULL); if (stmt) - { - if (par_clauses != NULL) - { - tree *c; - for (c = par_clauses; *c ; ) - if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE - && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE) - c = &OMP_CLAUSE_CHAIN (*c); - else - { - for (i = 0; i < collapse; i++) - if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c)) - break; - if (i == collapse) - c = &OMP_CLAUSE_CHAIN (*c); - else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE) - { - error_at (loc, - "iteration variable %qD should not be firstprivate", - OMP_CLAUSE_DECL (*c)); - *c = OMP_CLAUSE_CHAIN (*c); - } - else - { - /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES, - change it to shared (decl) in - OMP_PARALLEL_CLAUSES. */ - tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE); - OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c); - OMP_CLAUSE_CHAIN (l) = clauses; - clauses = l; - OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED); - } - } - } - OMP_FOR_CLAUSES (stmt) = clauses; - } + { + if (par_clauses != NULL) + { + tree *c; + for (c = par_clauses; *c ; ) + if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE + && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE) + c = &OMP_CLAUSE_CHAIN (*c); + else + { + for (i = 0; i < collapse; i++) + if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c)) + break; + if (i == collapse) + c = &OMP_CLAUSE_CHAIN (*c); + else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE) + { + error_at (loc, + "iteration variable %qD should not be firstprivate", + OMP_CLAUSE_DECL (*c)); + *c = OMP_CLAUSE_CHAIN (*c); + } + else + { + /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES, + change it to shared (decl) in + OMP_PARALLEL_CLAUSES. */ + tree l = build_omp_clause (OMP_CLAUSE_LOCATION (*c), + OMP_CLAUSE_LASTPRIVATE); + OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c); + OMP_CLAUSE_CHAIN (l) = clauses; + clauses = l; + OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED); + } + } + } + OMP_FOR_CLAUSES (stmt) = clauses; + } ret = stmt; } pop_scopes: while (for_block) { - stmt = c_end_compound_stmt (TREE_VALUE (for_block), true); + /* FIXME diagnostics: LOC below should be the actual location of + this particular for block. We need to build a list of + locations to go along with FOR_BLOCK. */ + stmt = c_end_compound_stmt (loc, TREE_VALUE (for_block), true); add_stmt (stmt); for_block = TREE_CHAIN (for_block); } @@ -8274,29 +8691,31 @@ /* OpenMP 2.5: #pragma omp for for-clause[optseq] new-line for-loop + + LOC is the location of the #pragma token. */ -#define OMP_FOR_CLAUSE_MASK \ - ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \ - | (1u << PRAGMA_OMP_CLAUSE_ORDERED) \ - | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE) \ - | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE) \ - | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) +#define OMP_FOR_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (1u << PRAGMA_OMP_CLAUSE_ORDERED) \ + | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE) \ + | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE) \ + | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) static tree -c_parser_omp_for (c_parser *parser) +c_parser_omp_for (location_t loc, c_parser *parser) { tree block, clauses, ret; clauses = c_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK, - "#pragma omp for"); + "#pragma omp for"); block = c_begin_compound_stmt (true); - ret = c_parser_omp_for_loop (parser, clauses, NULL); - block = c_end_compound_stmt (block, true); + ret = c_parser_omp_for_loop (loc, parser, clauses, NULL); + block = c_end_compound_stmt (loc, block, true); add_stmt (block); return ret; @@ -8305,25 +8724,29 @@ /* OpenMP 2.5: # pragma omp master new-line structured-block + + LOC is the location of the #pragma token. */ static tree -c_parser_omp_master (c_parser *parser) +c_parser_omp_master (location_t loc, c_parser *parser) { c_parser_skip_to_pragma_eol (parser); - return c_finish_omp_master (c_parser_omp_structured_block (parser)); + return c_finish_omp_master (loc, c_parser_omp_structured_block (parser)); } /* OpenMP 2.5: # pragma omp ordered new-line structured-block + + LOC is the location of the #pragma itself. */ static tree -c_parser_omp_ordered (c_parser *parser) +c_parser_omp_ordered (location_t loc, c_parser *parser) { c_parser_skip_to_pragma_eol (parser); - return c_finish_omp_ordered (c_parser_omp_structured_block (parser)); + return c_finish_omp_ordered (loc, c_parser_omp_structured_block (parser)); } /* OpenMP 2.5: @@ -8333,15 +8756,18 @@ section-sequence: section-directive[opt] structured-block - section-sequence section-directive structured-block */ + section-sequence section-directive structured-block + + SECTIONS_LOC is the location of the #pragma omp sections. */ static tree -c_parser_omp_sections_scope (c_parser *parser) +c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser) { tree stmt, substmt; bool error_suppress = false; location_t loc; + loc = c_parser_peek_token (parser)->location; if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) { /* Avoid skipping until the end of the block. */ @@ -8351,22 +8777,21 @@ stmt = push_stmt_list (); - loc = c_parser_peek_token (parser)->location; if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION) { substmt = push_stmt_list (); while (1) - { + { c_parser_statement (parser); - if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION) - break; - if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - break; - if (c_parser_next_token_is (parser, CPP_EOF)) - break; - } + if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION) + break; + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + break; + if (c_parser_next_token_is (parser, CPP_EOF)) + break; + } substmt = pop_stmt_list (substmt); substmt = build1 (OMP_SECTION, void_type_node, substmt); @@ -8377,22 +8802,22 @@ while (1) { if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - break; + break; if (c_parser_next_token_is (parser, CPP_EOF)) - break; + break; loc = c_parser_peek_token (parser)->location; if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION) - { - c_parser_consume_pragma (parser); - c_parser_skip_to_pragma_eol (parser); - error_suppress = false; - } + { + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); + error_suppress = false; + } else if (!error_suppress) - { - error_at (loc, "expected %<#pragma omp section%> or %<}%>"); - error_suppress = true; - } + { + error_at (loc, "expected %<#pragma omp section%> or %<}%>"); + error_suppress = true; + } substmt = c_parser_omp_structured_block (parser); substmt = build1 (OMP_SECTION, void_type_node, substmt); @@ -8400,11 +8825,12 @@ add_stmt (substmt); } c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, - "expected %<#pragma omp section%> or %<}%>"); + "expected %<#pragma omp section%> or %<}%>"); substmt = pop_stmt_list (stmt); stmt = make_node (OMP_SECTIONS); + SET_EXPR_LOCATION (stmt, sections_loc); TREE_TYPE (stmt) = void_type_node; OMP_SECTIONS_BODY (stmt) = substmt; @@ -8414,28 +8840,30 @@ /* OpenMP 2.5: # pragma omp sections sections-clause[optseq] newline sections-scope + + LOC is the location of the #pragma token. */ -#define OMP_SECTIONS_CLAUSE_MASK \ - ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \ - | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) +#define OMP_SECTIONS_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) static tree -c_parser_omp_sections (c_parser *parser) +c_parser_omp_sections (location_t loc, c_parser *parser) { tree block, clauses, ret; clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK, - "#pragma omp sections"); + "#pragma omp sections"); block = c_begin_compound_stmt (true); - ret = c_parser_omp_sections_scope (parser); + ret = c_parser_omp_sections_scope (loc, parser); if (ret) OMP_SECTIONS_CLAUSES (ret) = clauses; - block = c_end_compound_stmt (block, true); + block = c_end_compound_stmt (loc, block, true); add_stmt (block); return ret; @@ -8445,20 +8873,22 @@ # pragma parallel parallel-clause new-line # pragma parallel for parallel-for-clause new-line # pragma parallel sections parallel-sections-clause new-line + + LOC is the location of the #pragma token. */ -#define OMP_PARALLEL_CLAUSE_MASK \ - ( (1u << PRAGMA_OMP_CLAUSE_IF) \ - | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \ - | (1u << PRAGMA_OMP_CLAUSE_SHARED) \ - | (1u << PRAGMA_OMP_CLAUSE_COPYIN) \ - | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \ - | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS)) +#define OMP_PARALLEL_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_IF) \ + | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \ + | (1u << PRAGMA_OMP_CLAUSE_SHARED) \ + | (1u << PRAGMA_OMP_CLAUSE_COPYIN) \ + | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS)) static tree -c_parser_omp_parallel (c_parser *parser) +c_parser_omp_parallel (location_t loc, c_parser *parser) { enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL; const char *p_name = "#pragma omp parallel"; @@ -8477,13 +8907,13 @@ { const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); if (strcmp (p, "sections") == 0) - { - c_parser_consume_token (parser); - p_kind = PRAGMA_OMP_PARALLEL_SECTIONS; - p_name = "#pragma omp parallel sections"; - mask |= OMP_SECTIONS_CLAUSE_MASK; - mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT); - } + { + c_parser_consume_token (parser); + p_kind = PRAGMA_OMP_PARALLEL_SECTIONS; + p_name = "#pragma omp parallel sections"; + mask |= OMP_SECTIONS_CLAUSE_MASK; + mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT); + } } clauses = c_parser_omp_all_clauses (parser, mask, p_name); @@ -8493,24 +8923,24 @@ case PRAGMA_OMP_PARALLEL: block = c_begin_omp_parallel (); c_parser_statement (parser); - stmt = c_finish_omp_parallel (clauses, block); + stmt = c_finish_omp_parallel (loc, clauses, block); break; case PRAGMA_OMP_PARALLEL_FOR: block = c_begin_omp_parallel (); - c_split_parallel_clauses (clauses, &par_clause, &ws_clause); - c_parser_omp_for_loop (parser, ws_clause, &par_clause); - stmt = c_finish_omp_parallel (par_clause, block); + c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); + c_parser_omp_for_loop (loc, parser, ws_clause, &par_clause); + stmt = c_finish_omp_parallel (loc, par_clause, block); OMP_PARALLEL_COMBINED (stmt) = 1; break; case PRAGMA_OMP_PARALLEL_SECTIONS: block = c_begin_omp_parallel (); - c_split_parallel_clauses (clauses, &par_clause, &ws_clause); - stmt = c_parser_omp_sections_scope (parser); + c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause); + stmt = c_parser_omp_sections_scope (loc, parser); if (stmt) - OMP_SECTIONS_CLAUSES (stmt) = ws_clause; - stmt = c_finish_omp_parallel (par_clause, block); + OMP_SECTIONS_CLAUSES (stmt) = ws_clause; + stmt = c_finish_omp_parallel (loc, par_clause, block); OMP_PARALLEL_COMBINED (stmt) = 1; break; @@ -8524,23 +8954,26 @@ /* OpenMP 2.5: # pragma omp single single-clause[optseq] new-line structured-block + + LOC is the location of the #pragma. */ -#define OMP_SINGLE_CLAUSE_MASK \ - ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) +#define OMP_SINGLE_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) static tree -c_parser_omp_single (c_parser *parser) +c_parser_omp_single (location_t loc, c_parser *parser) { tree stmt = make_node (OMP_SINGLE); + SET_EXPR_LOCATION (stmt, loc); TREE_TYPE (stmt) = void_type_node; OMP_SINGLE_CLAUSES (stmt) = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK, - "#pragma omp single"); + "#pragma omp single"); OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser); return add_stmt (stmt); @@ -8548,27 +8981,29 @@ /* OpenMP 3.0: # pragma omp task task-clause[optseq] new-line + + LOC is the location of the #pragma. */ -#define OMP_TASK_CLAUSE_MASK \ - ( (1u << PRAGMA_OMP_CLAUSE_IF) \ - | (1u << PRAGMA_OMP_CLAUSE_UNTIED) \ - | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \ - | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_SHARED)) +#define OMP_TASK_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_IF) \ + | (1u << PRAGMA_OMP_CLAUSE_UNTIED) \ + | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \ + | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_SHARED)) static tree -c_parser_omp_task (c_parser *parser) +c_parser_omp_task (location_t loc, c_parser *parser) { tree clauses, block; clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK, - "#pragma omp task"); + "#pragma omp task"); block = c_begin_omp_task (); c_parser_statement (parser); - return c_finish_omp_task (clauses, block); + return c_finish_omp_task (loc, clauses, block); } /* OpenMP 3.0: @@ -8578,10 +9013,11 @@ static void c_parser_omp_taskwait (c_parser *parser) { + location_t loc = c_parser_peek_token (parser)->location; c_parser_consume_pragma (parser); c_parser_skip_to_pragma_eol (parser); - c_finish_omp_taskwait (); + c_finish_omp_taskwait (loc); } /* Main entry point to parsing most OpenMP pragmas. */ @@ -8597,47 +9033,41 @@ p_kind = c_parser_peek_token (parser)->pragma_kind; c_parser_consume_pragma (parser); - /* For all constructs below except #pragma omp atomic - MUST_NOT_THROW catch handlers are needed when exceptions - are enabled. */ - if (p_kind != PRAGMA_OMP_ATOMIC) - c_maybe_initialize_eh (); - switch (p_kind) { case PRAGMA_OMP_ATOMIC: - c_parser_omp_atomic (parser); + c_parser_omp_atomic (loc, parser); return; case PRAGMA_OMP_CRITICAL: - stmt = c_parser_omp_critical (parser); + stmt = c_parser_omp_critical (loc, parser); break; case PRAGMA_OMP_FOR: - stmt = c_parser_omp_for (parser); + stmt = c_parser_omp_for (loc, parser); break; case PRAGMA_OMP_MASTER: - stmt = c_parser_omp_master (parser); + stmt = c_parser_omp_master (loc, parser); break; case PRAGMA_OMP_ORDERED: - stmt = c_parser_omp_ordered (parser); + stmt = c_parser_omp_ordered (loc, parser); break; case PRAGMA_OMP_PARALLEL: - stmt = c_parser_omp_parallel (parser); + stmt = c_parser_omp_parallel (loc, parser); break; case PRAGMA_OMP_SECTIONS: - stmt = c_parser_omp_sections (parser); + stmt = c_parser_omp_sections (loc, parser); break; case PRAGMA_OMP_SINGLE: - stmt = c_parser_omp_single (parser); + stmt = c_parser_omp_single (loc, parser); break; case PRAGMA_OMP_TASK: - stmt = c_parser_omp_task (parser); + stmt = c_parser_omp_task (loc, parser); break; default: gcc_unreachable (); } if (stmt) - SET_EXPR_LOCATION (stmt, loc); + gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION); } @@ -8648,8 +9078,10 @@ c_parser_omp_threadprivate (c_parser *parser) { tree vars, t; + location_t loc; c_parser_consume_pragma (parser); + loc = c_parser_peek_token (parser)->location; vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL); /* Mark every variable in VARS to be assigned thread local storage. */ @@ -8657,31 +9089,37 @@ { tree v = TREE_PURPOSE (t); + /* FIXME diagnostics: Ideally we should keep individual + locations for all the variables in the var list to make the + following errors more precise. Perhaps + c_parser_omp_var_list_parens() should construct a list of + locations to go along with the var list. */ + /* If V had already been marked threadprivate, it doesn't matter - whether it had been used prior to this point. */ + whether it had been used prior to this point. */ if (TREE_CODE (v) != VAR_DECL) - error ("%qD is not a variable", v); + error_at (loc, "%qD is not a variable", v); else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v)) - error ("%qE declared %<threadprivate%> after first use", v); + error_at (loc, "%qE declared %<threadprivate%> after first use", v); else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v)) - error ("automatic variable %qE cannot be %<threadprivate%>", v); + error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v); else if (TREE_TYPE (v) == error_mark_node) - ; + ; else if (! COMPLETE_TYPE_P (TREE_TYPE (v))) - error ("%<threadprivate%> %qE has incomplete type", v); + error_at (loc, "%<threadprivate%> %qE has incomplete type", v); else - { - if (! DECL_THREAD_LOCAL_P (v)) - { - DECL_TLS_MODEL (v) = decl_default_tls_model (v); - /* If rtl has been already set for this var, call - make_decl_rtl once again, so that encode_section_info - has a chance to look at the new decl flags. */ - if (DECL_RTL_SET_P (v)) - make_decl_rtl (v); - } - C_DECL_THREADPRIVATE_P (v) = 1; - } + { + if (! DECL_THREAD_LOCAL_P (v)) + { + DECL_TLS_MODEL (v) = decl_default_tls_model (v); + /* If rtl has been already set for this var, call + make_decl_rtl once again, so that encode_section_info + has a chance to look at the new decl flags. */ + if (DECL_RTL_SET_P (v)) + make_decl_rtl (v); + } + C_DECL_THREADPRIVATE_P (v) = 1; + } } c_parser_skip_to_pragma_eol (parser); @@ -8707,6 +9145,10 @@ the_parser = GGC_NEW (c_parser); *the_parser = tparser; + /* Initialize EH, if we've been told to do so. */ + if (flag_exceptions) + using_eh_for_cleanups (); + c_parser_translation_unit (the_parser); the_parser = NULL; }