X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fc-parser.c;h=a0f1bea87e54d606f2845303c36f98314b9f6c8f;hp=d638a0b2537421b96222748ceeffe207f932eef6;hb=1e71b3148ebeba9ec268faca94fd38ba6827e988;hpb=d2764e2dd35b831576251722eb96958cd055227f diff --git a/gcc/c-parser.c b/gcc/c-parser.c index d638a0b2537..a0f1bea87e5 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -1,6 +1,6 @@ /* Parser for C and Objective-C. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Parser actions based on the old Bison parser; structure somewhat @@ -57,133 +57,10 @@ along with GCC; see the file COPYING3. If not see #include "vec.h" #include "target.h" #include "cgraph.h" +#include "plugin.h" +#include "except.h" -/* The reserved keyword table. */ -struct resword -{ - const char *word; - ENUM_BITFIELD(rid) rid : 16; - unsigned int disable : 16; -}; - -/* Disable mask. Keywords are disabled if (reswords[i].disable & - mask) is _true_. */ -#define D_C89 0x01 /* not in C89 */ -#define D_EXT 0x02 /* GCC extension */ -#define D_EXT89 0x04 /* GCC extension incorporated in C99 */ -#define D_OBJC 0x08 /* Objective C only */ - -static const struct resword reswords[] = -{ - { "_Bool", RID_BOOL, 0 }, - { "_Complex", RID_COMPLEX, 0 }, - { "_Decimal32", RID_DFLOAT32, D_EXT }, - { "_Decimal64", RID_DFLOAT64, D_EXT }, - { "_Decimal128", RID_DFLOAT128, D_EXT }, - { "_Fract", RID_FRACT, D_EXT }, - { "_Accum", RID_ACCUM, D_EXT }, - { "_Sat", RID_SAT, D_EXT }, - { "__FUNCTION__", RID_FUNCTION_NAME, 0 }, - { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, - { "__alignof", RID_ALIGNOF, 0 }, - { "__alignof__", RID_ALIGNOF, 0 }, - { "__asm", RID_ASM, 0 }, - { "__asm__", RID_ASM, 0 }, - { "__attribute", RID_ATTRIBUTE, 0 }, - { "__attribute__", RID_ATTRIBUTE, 0 }, - { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 }, - { "__builtin_offsetof", RID_OFFSETOF, 0 }, - { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 }, - { "__builtin_va_arg", RID_VA_ARG, 0 }, - { "__complex", RID_COMPLEX, 0 }, - { "__complex__", RID_COMPLEX, 0 }, - { "__const", RID_CONST, 0 }, - { "__const__", RID_CONST, 0 }, - { "__extension__", RID_EXTENSION, 0 }, - { "__func__", RID_C99_FUNCTION_NAME, 0 }, - { "__imag", RID_IMAGPART, 0 }, - { "__imag__", RID_IMAGPART, 0 }, - { "__inline", RID_INLINE, 0 }, - { "__inline__", RID_INLINE, 0 }, - { "__label__", RID_LABEL, 0 }, - { "__real", RID_REALPART, 0 }, - { "__real__", RID_REALPART, 0 }, - { "__restrict", RID_RESTRICT, 0 }, - { "__restrict__", RID_RESTRICT, 0 }, - { "__signed", RID_SIGNED, 0 }, - { "__signed__", RID_SIGNED, 0 }, - { "__thread", RID_THREAD, 0 }, - { "__typeof", RID_TYPEOF, 0 }, - { "__typeof__", RID_TYPEOF, 0 }, - { "__volatile", RID_VOLATILE, 0 }, - { "__volatile__", RID_VOLATILE, 0 }, - { "asm", RID_ASM, D_EXT }, - { "auto", RID_AUTO, 0 }, - { "break", RID_BREAK, 0 }, - { "case", RID_CASE, 0 }, - { "char", RID_CHAR, 0 }, - { "const", RID_CONST, 0 }, - { "continue", RID_CONTINUE, 0 }, - { "default", RID_DEFAULT, 0 }, - { "do", RID_DO, 0 }, - { "double", RID_DOUBLE, 0 }, - { "else", RID_ELSE, 0 }, - { "enum", RID_ENUM, 0 }, - { "extern", RID_EXTERN, 0 }, - { "float", RID_FLOAT, 0 }, - { "for", RID_FOR, 0 }, - { "goto", RID_GOTO, 0 }, - { "if", RID_IF, 0 }, - { "inline", RID_INLINE, D_EXT89 }, - { "int", RID_INT, 0 }, - { "long", RID_LONG, 0 }, - { "register", RID_REGISTER, 0 }, - { "restrict", RID_RESTRICT, D_C89 }, - { "return", RID_RETURN, 0 }, - { "short", RID_SHORT, 0 }, - { "signed", RID_SIGNED, 0 }, - { "sizeof", RID_SIZEOF, 0 }, - { "static", RID_STATIC, 0 }, - { "struct", RID_STRUCT, 0 }, - { "switch", RID_SWITCH, 0 }, - { "typedef", RID_TYPEDEF, 0 }, - { "typeof", RID_TYPEOF, D_EXT }, - { "union", RID_UNION, 0 }, - { "unsigned", RID_UNSIGNED, 0 }, - { "void", RID_VOID, 0 }, - { "volatile", RID_VOLATILE, 0 }, - { "while", RID_WHILE, 0 }, - /* These Objective-C keywords are recognized only immediately after - an '@'. */ - { "class", RID_AT_CLASS, D_OBJC }, - { "compatibility_alias", RID_AT_ALIAS, D_OBJC }, - { "defs", RID_AT_DEFS, D_OBJC }, - { "encode", RID_AT_ENCODE, D_OBJC }, - { "end", RID_AT_END, D_OBJC }, - { "implementation", RID_AT_IMPLEMENTATION, D_OBJC }, - { "interface", RID_AT_INTERFACE, D_OBJC }, - { "private", RID_AT_PRIVATE, D_OBJC }, - { "protected", RID_AT_PROTECTED, D_OBJC }, - { "protocol", RID_AT_PROTOCOL, D_OBJC }, - { "public", RID_AT_PUBLIC, D_OBJC }, - { "selector", RID_AT_SELECTOR, D_OBJC }, - { "throw", RID_AT_THROW, D_OBJC }, - { "try", RID_AT_TRY, D_OBJC }, - { "catch", RID_AT_CATCH, D_OBJC }, - { "finally", RID_AT_FINALLY, D_OBJC }, - { "synchronized", RID_AT_SYNCHRONIZED, D_OBJC }, - /* These are recognized only in protocol-qualifier context - (see above) */ - { "bycopy", RID_BYCOPY, D_OBJC }, - { "byref", RID_BYREF, D_OBJC }, - { "in", RID_IN, D_OBJC }, - { "inout", RID_INOUT, D_OBJC }, - { "oneway", RID_ONEWAY, D_OBJC }, - { "out", RID_OUT, D_OBJC }, -}; -#define N_reswords (sizeof reswords / sizeof (struct resword)) - /* Initialization routine for this file. */ void @@ -193,24 +70,45 @@ c_parse_init (void) identifiers. */ unsigned int i; tree id; - int mask = (flag_isoc99 ? 0 : D_C89) - | (flag_no_asm ? (flag_isoc99 ? D_EXT : D_EXT|D_EXT89) : 0); + 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; + if (flag_no_asm) + { + mask |= D_ASM | D_EXT; + if (!flag_isoc99) + mask |= D_EXT89; + } if (!c_dialect_objc ()) - mask |= D_OBJC; + mask |= D_OBJC | D_CXX_OBJC; ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX); - for (i = 0; i < N_reswords; i++) + 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. */ - if (reswords[i].disable & mask) - continue; + 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; + } - id = get_identifier (reswords[i].word); - C_RID_CODE (id) = reswords[i].rid; + id = get_identifier (c_common_reswords[i].word); + C_SET_RID_CODE (id, c_common_reswords[i].rid); C_IS_RESERVED_WORD (id) = 1; - ridpointers [(int) reswords[i].rid] = id; + ridpointers [(int) c_common_reswords[i].rid] = id; } } @@ -238,14 +136,15 @@ typedef enum c_id_kind { 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 @@ -256,20 +155,17 @@ typedef struct c_token GTY (()) ENUM_BITFIELD (rid) keyword : 8; /* If this token is a CPP_PRAGMA, this indicates the pragma that was seen. Otherwise it is PRAGMA_NONE. */ - ENUM_BITFIELD (pragma_kind) pragma_kind : 7; - /* True if this token is from a system header. */ - BOOL_BITFIELD in_system_header : 1; - /* The value associated with this token, if any. */ - tree value; + ENUM_BITFIELD (pragma_kind) pragma_kind : 8; /* The location at which this token was found. */ location_t location; + /* The value associated with this token, if any. */ + tree value; } c_token; /* A parser structure recording information about the state and context of parsing. Includes lexer information with up to two tokens of look-ahead; more are not needed for C. */ -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). */ @@ -314,7 +210,6 @@ c_lex_one_token (c_parser *parser, c_token *token) token->id_kind = C_ID_NONE; token->keyword = RID_MAX; token->pragma_kind = PRAGMA_NONE; - token->in_system_header = in_system_header; switch (token->type) { @@ -330,9 +225,23 @@ c_lex_one_token (c_parser *parser, c_token *token) { enum rid rid_code = C_RID_CODE (token->value); - if (c_dialect_objc ()) + if (rid_code == RID_CXX_COMPAT_WARN) { - if (!OBJC_IS_AT_KEYWORD (rid_code) + 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)) { @@ -345,8 +254,6 @@ c_lex_one_token (c_parser *parser, c_token *token) } else { - /* Return the canonical spelling for this keyword. */ - token->value = ridpointers[(int) rid_code]; token->type = CPP_KEYWORD; token->keyword = rid_code; break; @@ -396,7 +303,7 @@ c_lex_one_token (c_parser *parser, c_token *token) break; case CPP_PRAGMA: /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */ - token->pragma_kind = TREE_INT_CST_LOW (token->value); + token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value); token->value = NULL; break; default: @@ -458,6 +365,8 @@ c_token_starts_typename (c_token *token) { case C_ID_ID: return false; + case C_ID_ADDRSPACE: + return true; case C_ID_TYPENAME: return true; case C_ID_CLASSNAME: @@ -528,6 +437,8 @@ c_token_starts_declspecs (c_token *token) { case C_ID_ID: return false; + case C_ID_ADDRSPACE: + return true; case C_ID_TYPENAME: return true; case C_ID_CLASSNAME: @@ -646,7 +557,6 @@ c_parser_set_source_position_from_token (c_token *token) if (token->type != CPP_EOF) { input_location = token->location; - in_system_header = token->in_system_header; } } @@ -679,7 +589,11 @@ c_parser_error (c_parser *parser, const char *gmsgid) CPP_KEYWORD, keywords are treated like identifiers. */ (token->type == CPP_KEYWORD ? CPP_NAME : token->type), - token->value); + /* ??? 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, @@ -912,6 +826,9 @@ c_parser_skip_to_end_of_block_or_statement (c_parser *parser) parser->error = false; } +/* CPP's options (initialized by c-opts.c). */ +extern cpp_options *cpp_opts; + /* Save the warning flags which are controlled by __extension__. */ static inline int @@ -920,11 +837,15 @@ disable_extension_diagnostics (void) int ret = (pedantic | (warn_pointer_arith << 1) | (warn_traditional << 2) - | (flag_iso << 3)); - pedantic = 0; + | (flag_iso << 3) + | (warn_long_long << 4) + | (warn_cxx_compat << 5)); + cpp_opts->pedantic = pedantic = 0; warn_pointer_arith = 0; - warn_traditional = 0; + cpp_opts->warn_traditional = warn_traditional = 0; flag_iso = 0; + cpp_opts->warn_long_long = warn_long_long = 0; + warn_cxx_compat = 0; return ret; } @@ -934,10 +855,12 @@ disable_extension_diagnostics (void) static inline void restore_extension_diagnostics (int flags) { - pedantic = flags & 1; + cpp_opts->pedantic = pedantic = flags & 1; warn_pointer_arith = (flags >> 1) & 1; - warn_traditional = (flags >> 2) & 1; + cpp_opts->warn_traditional = warn_traditional = (flags >> 2) & 1; flag_iso = (flags >> 3) & 1; + cpp_opts->warn_long_long = warn_long_long = (flags >> 4) & 1; + warn_cxx_compat = (flags >> 5) & 1; } /* Possibly kinds of declarator to parse. */ @@ -983,8 +906,9 @@ static tree c_parser_attributes (c_parser *); static struct c_type_name *c_parser_type_name (c_parser *); static struct c_expr c_parser_initializer (c_parser *); static struct c_expr c_parser_braced_init (c_parser *, tree, bool); -static void c_parser_initelt (c_parser *); -static void c_parser_initval (c_parser *, struct c_expr *); +static void c_parser_initelt (c_parser *, struct obstack *); +static void c_parser_initval (c_parser *, struct c_expr *, + struct obstack *); static tree c_parser_compound_statement (c_parser *); static void c_parser_compound_statement_nostart (c_parser *); static void c_parser_label (c_parser *); @@ -997,6 +921,7 @@ static void c_parser_do_statement (c_parser *); 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 *, @@ -1008,16 +933,20 @@ static struct c_expr c_parser_sizeof_expression (c_parser *); 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 *, + 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 *); static void c_parser_omp_flush (c_parser *); +static void c_parser_omp_taskwait (c_parser *); enum pragma_context { pragma_external, pragma_stmt, pragma_compound }; static bool c_parser_pragma (c_parser *, enum pragma_context); @@ -1064,13 +993,13 @@ c_parser_translation_unit (c_parser *parser) { if (c_parser_next_token_is (parser, CPP_EOF)) { - if (pedantic) - pedwarn ("%HISO C forbids an empty translation unit", - &c_parser_peek_token (parser)->location); + 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 (); @@ -1128,7 +1057,7 @@ c_parser_external_declaration (c_parser *parser) gcc_assert (c_dialect_objc ()); c_parser_objc_class_definition (parser); break; - case RID_AT_CLASS: + case RID_CLASS: gcc_assert (c_dialect_objc ()); c_parser_objc_class_declaration (parser); break; @@ -1150,13 +1079,14 @@ c_parser_external_declaration (c_parser *parser) } break; case CPP_SEMICOLON: - if (pedantic) - pedwarn ("%HISO C does not allow extra %<;%> outside of a function", - &c_parser_peek_token (parser)->location); + 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: @@ -1229,9 +1159,9 @@ c_parser_external_declaration (c_parser *parser) 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 */ @@ -1266,7 +1196,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, else { shadow_tag_warned (specs, 1); - pedwarn ("%Hempty declaration", &here); + pedwarn (here, 0, "empty declaration"); } c_parser_consume_token (parser); return; @@ -1302,8 +1232,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, if (!diagnosed_no_specs && !specs->declspecs_seen_p) { diagnosed_no_specs = true; - pedwarn ("%Hdata definition has no type or storage class", - &here); + pedwarn (here, 0, "data definition has no type or storage class"); } /* Having seen a data definition, there cannot now be a function definition. */ @@ -1316,6 +1245,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, { 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. */ @@ -1324,12 +1254,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, 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.value, asm_name); + finish_decl (d, init_loc, init.value, + init.original_type, asm_name); } } else @@ -1338,7 +1270,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, chainon (postfix_attrs, all_prefix_attrs)); if (d) - finish_decl (d, NULL_TREE, asm_name); + finish_decl (d, UNKNOWN_LOCATION, NULL_TREE, + NULL_TREE, asm_name); } if (c_parser_next_token_is (parser, CPP_COMMA)) { @@ -1372,8 +1305,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, /* Function definition (nested or otherwise). */ if (nested) { - if (pedantic) - pedwarn ("%HISO C forbids nested functions", &here); + pedwarn (here, OPT_pedantic, "ISO C forbids nested functions"); c_push_function_context (); } if (!start_function (specs, declarator, all_prefix_attrs)) @@ -1402,17 +1334,22 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, 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); - DECL_SOURCE_LOCATION (current_function_decl) - = c_parser_peek_token (parser)->location; store_parm_decls (); + DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus + = c_parser_peek_token (parser)->location; fnbody = c_parser_compound_statement (parser); if (nested) { 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_EXPR, decl)); + add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl)); } else { @@ -1492,6 +1429,7 @@ c_parser_asm_definition (c_parser *parser) const restrict volatile + address-space-qualifier (restrict is new in C99.) @@ -1500,6 +1438,12 @@ c_parser_asm_definition (c_parser *parser) declaration-specifiers: attributes declaration-specifiers[opt] + type-qualifier: + address-space + + address-space: + identifier recognized by the target + storage-class-specifier: __thread @@ -1535,10 +1479,22 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, { 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; + + 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. */ @@ -1556,6 +1512,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, /* 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 { @@ -1565,8 +1523,10 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, 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 (specs, t); + declspecs_add_type (loc, specs, t); continue; } if (c_parser_next_token_is (parser, CPP_LESS)) @@ -1580,7 +1540,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, 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); + 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)); @@ -1627,7 +1589,9 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, parser->objc_need_raw_identifier = true; t.kind = ctsk_resword; t.spec = c_parser_peek_token (parser)->value; - declspecs_add_type (specs, t); + t.expr = NULL_TREE; + t.expr_const_operands = true; + declspecs_add_type (loc, specs, t); c_parser_consume_token (parser); break; case RID_ENUM: @@ -1636,7 +1600,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, attrs_ok = true; seen_type = true; t = c_parser_enum_specifier (parser); - declspecs_add_type (specs, t); + declspecs_add_type (loc, specs, t); break; case RID_STRUCT: case RID_UNION: @@ -1645,7 +1609,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, attrs_ok = true; seen_type = true; t = c_parser_struct_or_union_specifier (parser); - declspecs_add_type (specs, t); + 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 @@ -1656,7 +1621,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, attrs_ok = true; seen_type = true; t = c_parser_typeof_specifier (parser); - declspecs_add_type (specs, t); + declspecs_add_type (loc, specs, t); break; case RID_CONST: case RID_VOLATILE: @@ -1706,23 +1671,27 @@ c_parser_enum_specifier (c_parser *parser) struct c_typespec ret; tree attrs; tree ident = NULL_TREE; - location_t ident_loc; + 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. */ @@ -1735,7 +1704,8 @@ c_parser_enum_specifier (c_parser *parser) tree enum_decl; bool seen_comma; c_token *token; - location_t comma_loc; + 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"); @@ -1747,15 +1717,18 @@ c_parser_enum_specifier (c_parser *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); + enum_decl = build_enumerator (value_loc, + &the_enum, enum_id, enum_value); TREE_CHAIN (enum_decl) = values; values = enum_decl; seen_comma = false; @@ -1767,8 +1740,8 @@ c_parser_enum_specifier (c_parser *parser) } if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { - if (seen_comma && pedantic && !flag_isoc99) - pedwarn ("%Hcomma at end of enumerator list", &comma_loc); + if (seen_comma && !flag_isoc99) + pedwarn (comma_loc, OPT_pedantic, "comma at end of enumerator list"); c_parser_consume_token (parser); break; } @@ -1784,6 +1757,8 @@ c_parser_enum_specifier (c_parser *parser) ret.spec = finish_enum (type, nreverse (values), chainon (attrs, postfix_attrs)); ret.kind = ctsk_tagdef; + ret.expr = NULL_TREE; + ret.expr_const_operands = true; return ret; } else if (!ident) @@ -1791,16 +1766,18 @@ c_parser_enum_specifier (c_parser *parser) 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 ("%HISO C forbids forward references to % types", - &ident_loc); + pedwarn (enum_loc, OPT_pedantic, + "ISO C forbids forward references to % types"); } return ret; } @@ -1850,6 +1827,8 @@ c_parser_struct_or_union_specifier (c_parser *parser) 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) { @@ -1862,20 +1841,26 @@ c_parser_struct_or_union_specifier (c_parser *parser) 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); + 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 @@ -1924,9 +1909,8 @@ c_parser_struct_or_union_specifier (c_parser *parser) /* Parse any stray semicolon. */ if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { - if (pedantic) - pedwarn ("%Hextra semicolon in struct or union specified", - &c_parser_peek_token (parser)->location); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "extra semicolon in struct or union specified"); c_parser_consume_token (parser); continue; } @@ -1954,8 +1938,8 @@ c_parser_struct_or_union_specifier (c_parser *parser) else { if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - pedwarn ("%Hno semicolon at end of struct or union", - &c_parser_peek_token (parser)->location); + pedwarn (c_parser_peek_token (parser)->location, 0, + "no semicolon at end of struct or union"); else { c_parser_error (parser, "expected %<;%>"); @@ -1965,9 +1949,11 @@ c_parser_struct_or_union_specifier (c_parser *parser) } } 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) @@ -1975,9 +1961,11 @@ c_parser_struct_or_union_specifier (c_parser *parser) 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; } @@ -2046,9 +2034,8 @@ c_parser_struct_declaration (c_parser *parser) tree ret; if (!specs->type_seen_p) { - if (pedantic) - pedwarn ("%HISO C forbids member declarations with no members", - &decl_loc); + pedwarn (decl_loc, OPT_pedantic, + "ISO C forbids member declarations with no members"); shadow_tag_warned (specs, pedantic); ret = NULL_TREE; } @@ -2058,7 +2045,9 @@ c_parser_struct_declaration (c_parser *parser) structs or unions (which is [a] useful and [b] supports MS P-SDK). */ tree attrs = NULL; - ret = grokfield (build_id_declarator (NULL_TREE), specs, + + ret = grokfield (c_parser_peek_token (parser)->location, + build_id_declarator (NULL_TREE), specs, NULL_TREE, &attrs); if (ret) decl_attributes (&ret, attrs, 0); @@ -2101,7 +2090,8 @@ c_parser_struct_declaration (c_parser *parser) } if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) postfix_attrs = c_parser_attributes (parser); - d = grokfield (declarator, specs, width, &all_prefix_attrs); + 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; @@ -2149,24 +2139,26 @@ c_parser_typeof_specifier (c_parser *parser) 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); + ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands); pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE)); } } @@ -2175,30 +2167,18 @@ c_parser_typeof_specifier (c_parser *parser) 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 ("%H% applied to a bit-field", &here); + error_at (here, "% applied to a bit-field"); + mark_exp_read (expr.value); 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); - - if (CAN_HAVE_LOCATION_P (e)) - SET_EXPR_LOCATION (e, input_location); - - 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 %<)%>"); @@ -2436,6 +2416,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, /* 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; @@ -2493,8 +2474,10 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, "expected %<]%>"); return NULL; } - declarator = build_array_declarator (dimen, quals_attrs, static_seen, - star_seen); + if (dimen) + mark_exp_read (dimen); + declarator = build_array_declarator (brace_loc, dimen, quals_attrs, + static_seen, star_seen); if (declarator == NULL) return NULL; inner = set_array_declarator_inner (declarator, inner); @@ -2617,8 +2600,8 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs) ret->had_vla_unspec = 0; /* Suppress -Wold-style-definition for this case. */ ret->types = error_mark_node; - error ("%HISO C requires a named argument before %<...%>", - &c_parser_peek_token (parser)->location); + error_at (c_parser_peek_token (parser)->location, + "ISO C requires a named argument before %<...%>"); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) { @@ -2675,6 +2658,7 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs) "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)) @@ -2702,6 +2686,7 @@ c_parser_parms_list_declarator (c_parser *parser, tree attrs) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + get_pending_sizes (); return NULL; } } @@ -2774,8 +2759,8 @@ c_parser_asm_string_literal (c_parser *parser) } else if (c_parser_next_token_is (parser, CPP_WSTRING)) { - error ("%Hwide string literal in %", - &c_parser_peek_token (parser)->location); + error_at (c_parser_peek_token (parser)->location, + "wide string literal in %"); str = build_string (1, ""); c_parser_consume_token (parser); } @@ -2873,6 +2858,7 @@ c_parser_attributes (c_parser *parser) || 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); @@ -2920,8 +2906,13 @@ c_parser_attributes (c_parser *parser) } if (!ok) break; + /* Accept __attribute__((__const)) as __attribute__((const)) + etc. */ + attr_name + = ridpointers[(int) c_parser_peek_token (parser)->keyword]; } - attr_name = c_parser_peek_token (parser)->value; + 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)) { @@ -2946,9 +2937,12 @@ c_parser_attributes (c_parser *parser) attr_args = build_tree_list (NULL_TREE, arg1); else { + tree tree_list; c_parser_consume_token (parser); - attr_args = tree_cons (NULL_TREE, arg1, - c_parser_expr_list (parser, false)); + 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 @@ -2956,7 +2950,11 @@ c_parser_attributes (c_parser *parser) if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) attr_args = NULL_TREE; else - attr_args = c_parser_expr_list (parser, false); + { + 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)) @@ -3075,10 +3073,11 @@ c_parser_initializer (c_parser *parser) 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); + ret = default_function_array_read_conversion (loc, ret); return ret; } } @@ -3092,17 +3091,19 @@ c_parser_initializer (c_parser *parser) static struct c_expr c_parser_braced_init (c_parser *parser, tree type, bool nested_p) { + struct c_expr ret; + struct obstack braced_init_obstack; location_t brace_loc = c_parser_peek_token (parser)->location; + gcc_obstack_init (&braced_init_obstack); gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE)); c_parser_consume_token (parser); if (nested_p) - push_init_level (0); + push_init_level (0, &braced_init_obstack); else really_start_incremental_init (type); if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { - if (pedantic) - pedwarn ("%HISO C forbids empty initializer braces", &brace_loc); + pedwarn (brace_loc, OPT_pedantic, "ISO C forbids empty initializer braces"); } else { @@ -3110,7 +3111,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p) comma. */ while (true) { - c_parser_initelt (parser); + c_parser_initelt (parser, &braced_init_obstack); if (parser->error) break; if (c_parser_next_token_is (parser, CPP_COMMA)) @@ -3123,20 +3124,24 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p) } 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, &braced_init_obstack); + obstack_free (&braced_init_obstack, NULL); return ret; } c_parser_consume_token (parser); - return pop_init_level (0); + ret = pop_init_level (0, &braced_init_obstack); + obstack_free (&braced_init_obstack, NULL); + return ret; } /* Parse a nested initializer, including designators. */ static void -c_parser_initelt (c_parser *parser) +c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) { /* Parse any designator or designator list. A single array designator may have the subsequent "=" omitted in GNU C, but a @@ -3145,13 +3150,11 @@ c_parser_initelt (c_parser *parser) && c_parser_peek_2nd_token (parser)->type == CPP_COLON) { /* Old-style structure member designator. */ - set_init_label (c_parser_peek_token (parser)->value); - if (pedantic) - { - /* Use the colon as the error location. */ - pedwarn ("%Hobsolete use of designated initializer with %<:%>", - &c_parser_peek_2nd_token (parser)->location); - } + set_init_label (c_parser_peek_token (parser)->value, + braced_init_obstack); + /* Use the colon as the error location. */ + 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); } @@ -3161,7 +3164,7 @@ c_parser_initelt (c_parser *parser) has been a single array designator and 2 otherwise. */ int des_seen = 0; /* Location of a designator. */ - location_t des_loc; + 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)) { @@ -3176,7 +3179,8 @@ c_parser_initelt (c_parser *parser) c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_NAME)) { - set_init_label (c_parser_peek_token (parser)->value); + set_init_label (c_parser_peek_token (parser)->value, + braced_init_obstack); c_parser_consume_token (parser); } else @@ -3184,16 +3188,17 @@ c_parser_initelt (c_parser *parser) 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); + process_init_element (init, false, braced_init_obstack); return; } } else { tree first, second; - location_t ellipsis_loc; + 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 @@ -3235,6 +3240,7 @@ c_parser_initelt (c_parser *parser) goto parse_message_args; } first = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (first); if (c_parser_next_token_is (parser, CPP_ELLIPSIS) || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) goto array_desig_after_first; @@ -3245,10 +3251,14 @@ c_parser_initelt (c_parser *parser) 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 (next); - rec = build_compound_expr (rec, next.value); + next = default_function_array_read_conversion (exp_loc, + next); + rec = build_compound_expr (comma_loc, rec, next.value); } parse_message_args: /* Now parse the objc-message-args. */ @@ -3258,30 +3268,33 @@ c_parser_initelt (c_parser *parser) 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); + c_parser_initval (parser, &mexpr, braced_init_obstack); return; } c_parser_consume_token (parser); first = c_parser_expr_no_commas (parser, NULL).value; + mark_exp_read (first); 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; + mark_exp_read (second); } 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 (pedantic && second) - pedwarn ("%HISO C forbids specifying range of " - "elements to initialize", &ellipsis_loc); + set_init_index (first, second, braced_init_obstack); + 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, @@ -3292,34 +3305,31 @@ c_parser_initelt (c_parser *parser) { if (c_parser_next_token_is (parser, CPP_EQ)) { - if (pedantic && !flag_isoc99) - pedwarn ("%HISO C90 forbids specifying subobject " - "to initialize", &des_loc); + 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) - { - if (pedantic) - pedwarn ("%Hobsolete use of designated initializer " - "without %<=%>", - &c_parser_peek_token (parser)->location); - } + 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); + process_init_element (init, false, braced_init_obstack); return; } } } } - c_parser_initval (parser, NULL); + c_parser_initval (parser, NULL, braced_init_obstack); } /* Parse a nested initializer; as c_parser_initializer but parses @@ -3329,7 +3339,8 @@ c_parser_initelt (c_parser *parser) initializer. */ static void -c_parser_initval (c_parser *parser, struct c_expr *after) +c_parser_initval (c_parser *parser, struct c_expr *after, + struct obstack * braced_init_obstack) { struct c_expr init; gcc_assert (!after || c_dialect_objc ()); @@ -3337,13 +3348,14 @@ c_parser_initval (c_parser *parser, struct c_expr *after) 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); + init = default_function_array_read_conversion (loc, init); } - process_init_element (init); + process_init_element (init, false, braced_init_obstack); } /* Parse a compound statement (possibly a function body) (C90 6.6.2, @@ -3389,9 +3401,9 @@ c_parser_initval (c_parser *parser, struct c_expr *after) 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 @@ -3403,11 +3415,19 @@ static tree 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 %<{%>")) - return error_mark_node; + { + /* Ensure a scope is entered and left anyway to avoid confusion + if we have just prepared to enter a function body. */ + stmt = c_begin_compound_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 @@ -3419,19 +3439,22 @@ c_parser_compound_statement_nostart (c_parser *parser) { bool last_stmt = false; bool last_label = false; - location_t label_loc; + 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. */ + mark_valid_location_for_stdc_pragma (false); while (c_parser_next_token_is_keyword (parser, RID_LABEL)) { + label_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); /* Any identifiers, including those declared as type names, are OK here. */ @@ -3446,7 +3469,7 @@ c_parser_compound_statement_nostart (c_parser *parser) label = declare_label (c_parser_peek_token (parser)->value); C_DECLARED_LABEL_FLAG (label) = 1; - add_stmt (build_stmt (DECL_EXPR, label)); + 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); @@ -3455,12 +3478,12 @@ c_parser_compound_statement_nostart (c_parser *parser) } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } - if (pedantic) - pedwarn ("%HISO C forbids label declarations", &err_loc); + 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; @@ -3479,18 +3502,21 @@ c_parser_compound_statement_nostart (c_parser *parser) 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; + mark_valid_location_for_stdc_pragma (false); c_parser_declaration_or_fndef (parser, true, true, true, true); - if (last_stmt - && ((pedantic && !flag_isoc99) - || warn_declaration_after_statement)) - pedwarn_c90 ("%HISO C90 forbids mixed declarations and code", - &loc); + 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 @@ -3510,15 +3536,16 @@ c_parser_compound_statement_nostart (c_parser *parser) 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 - && ((pedantic && !flag_isoc99) - || warn_declaration_after_statement)) - pedwarn_c90 ("%HISO C90 forbids mixed declarations and code", - &loc); + 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 @@ -3536,19 +3563,21 @@ c_parser_compound_statement_nostart (c_parser *parser) } else if (c_parser_next_token_is (parser, CPP_EOF)) { + 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) { - error ("%H""expected %<}%> before %", &loc); + mark_valid_location_for_stdc_pragma (save_valid_for_pragma); + error_at (loc, """expected %<}%> before %"); return; } - else + else { - error ("%H% without a previous %", &loc); + error_at (loc, "% without a previous %"); c_parser_consume_token (parser); continue; } @@ -3558,14 +3587,17 @@ c_parser_compound_statement_nostart (c_parser *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 ("%Hlabel at end of compound statement", &label_loc); + 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). @@ -3597,14 +3629,14 @@ c_parser_label (c_parser *parser) if (c_parser_next_token_is (parser, CPP_COLON)) { c_parser_consume_token (parser); - label = do_case (exp1, NULL_TREE); + 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); + label = do_case (loc1, exp1, exp2); } else c_parser_error (parser, "expected %<:%> or %<...%>"); @@ -3613,7 +3645,7 @@ c_parser_label (c_parser *parser) { 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 { @@ -3630,20 +3662,19 @@ c_parser_label (c_parser *parser) if (tlab) { decl_attributes (&tlab, attrs, 0); - label = add_stmt (build_stmt (LABEL_EXPR, tlab)); + 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 ("%Ha label can only be part of a statement and " - "a declaration is not a statement", - &c_parser_peek_token (parser)->location); - c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, + 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); } @@ -3794,57 +3825,62 @@ c_parser_statement_after_labels (c_parser *parser) c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_NAME)) { - stmt = c_finish_goto_label (c_parser_peek_token (parser)->value); + 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 (c_parser_expression (parser).value); + stmt = c_finish_goto_ptr (loc, + c_parser_expression (parser).value); } else c_parser_error (parser, "expected identifier or %<*%>"); goto expect_semicolon; case RID_CONTINUE: c_parser_consume_token (parser); - stmt = c_finish_bc_stmt (&c_cont_label, false); + 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 (&c_break_label, true); + 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 (NULL_TREE); + stmt = c_finish_return (loc, NULL_TREE, NULL_TREE); c_parser_consume_token (parser); } else { - stmt = c_finish_return (c_parser_expression_conv (parser).value); + struct c_expr expr = c_parser_expression_conv (parser); + mark_exp_read (expr.value); + 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_AT_THROW: + 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); + stmt = objc_build_throw_stmt (loc, NULL_TREE); c_parser_consume_token (parser); } else { - stmt - = objc_build_throw_stmt (c_parser_expression (parser).value); + 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_AT_TRY: + case RID_TRY: gcc_assert (c_dialect_objc ()); c_parser_objc_try_catch_statement (parser); break; @@ -3873,7 +3909,7 @@ c_parser_statement_after_labels (c_parser *parser) 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; @@ -3888,12 +3924,28 @@ c_parser_statement_after_labels (c_parser *parser) (recursively) all of the component statements should already have line numbers assigned. ??? Can we discard no-op statements earlier? */ - if (stmt && CAN_HAVE_LOCATION_P (stmt)) + if (CAN_HAVE_LOCATION_P (stmt) + && EXPR_LOCATION (stmt) == UNKNOWN_LOCATION) SET_EXPR_LOCATION (stmt, loc); parser->in_if_block = in_if_block; } +/* Parse the condition from an if, do, while or for statements. */ + +static tree +c_parser_condition (c_parser *parser) +{ + location_t loc = c_parser_peek_token (parser)->location; + tree cond; + 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; +} + /* Parse a parenthesized condition from an if, do or while statement. condition: @@ -3902,15 +3954,10 @@ c_parser_statement_after_labels (c_parser *parser) static tree c_parser_paren_condition (c_parser *parser) { - location_t loc; tree cond; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) return error_mark_node; - loc = c_parser_peek_token (parser)->location; - cond = c_objc_common_truthvalue_conversion - (c_parser_expression_conv (parser).value); - if (CAN_HAVE_LOCATION_P (cond)) - SET_EXPR_LOCATION (cond, loc); + cond = c_parser_condition (parser); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); return cond; } @@ -3921,8 +3968,9 @@ static tree 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 @@ -3937,6 +3985,7 @@ static tree 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) @@ -3945,14 +3994,18 @@ c_parser_if_body (c_parser *parser, bool *if_p) *if_p = c_parser_next_token_is_keyword (parser, RID_IF); if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { - add_stmt (build_empty_stmt ()); + location_t loc = c_parser_peek_token (parser)->location; + 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 % 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 @@ -3962,6 +4015,7 @@ c_parser_if_body (c_parser *parser, bool *if_p) 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) @@ -3970,12 +4024,16 @@ c_parser_else_body (c_parser *parser) c_parser_label (parser); if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { - add_stmt (build_empty_stmt ()); + location_t loc = c_parser_peek_token (parser)->location; + warning_at (loc, + OPT_Wempty_body, + "suggest braces around empty body in an % statement"); + add_stmt (build_empty_stmt (loc)); c_parser_consume_token (parser); } - else + 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). @@ -4012,7 +4070,7 @@ c_parser_if_statement (c_parser *parser) 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). @@ -4025,25 +4083,36 @@ static void 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). @@ -4068,7 +4137,7 @@ c_parser_while_statement (c_parser *parser) 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; } @@ -4087,9 +4156,9 @@ c_parser_do_statement (c_parser *parser) gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO)); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_SEMICOLON)) - warning (OPT_Wempty_body, - "%Hsuggest braces around empty body in % statement", - &c_parser_peek_token (parser)->location); + warning_at (c_parser_peek_token (parser)->location, + OPT_Wempty_body, + "suggest braces around empty body in % statement"); block = c_begin_compound_stmt (flag_isoc99); loc = c_parser_peek_token (parser)->location; save_break = c_break_label; @@ -4106,7 +4175,7 @@ c_parser_do_statement (c_parser *parser) 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). @@ -4129,9 +4198,9 @@ static void 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 %<(%>")) @@ -4140,12 +4209,12 @@ c_parser_for_statement (c_parser *parser) if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { c_parser_consume_token (parser); - c_finish_expr_stmt (NULL_TREE); + 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 (); + check_for_loop_decls (for_loc); } else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) { @@ -4164,7 +4233,7 @@ c_parser_for_statement (c_parser *parser) c_parser_consume_token (parser); c_parser_declaration_or_fndef (parser, true, true, true, true); restore_extension_diagnostics (ext); - check_for_loop_decls (); + check_for_loop_decls (for_loc); } else goto init_expr; @@ -4172,11 +4241,10 @@ c_parser_for_statement (c_parser *parser) else { init_expr: - c_finish_expr_stmt (c_parser_expression (parser).value); + c_finish_expr_stmt (loc, c_parser_expression (parser).value); c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } /* Parse the loop condition. */ - loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { c_parser_consume_token (parser); @@ -4184,17 +4252,14 @@ c_parser_for_statement (c_parser *parser) } else { - tree ocond = c_parser_expression_conv (parser).value; - cond = c_objc_common_truthvalue_conversion (ocond); - if (CAN_HAVE_LOCATION_P (cond)) - SET_EXPR_LOCATION (cond, loc); + 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 @@ -4208,7 +4273,7 @@ c_parser_for_statement (c_parser *parser) 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; } @@ -4219,12 +4284,17 @@ c_parser_for_statement (c_parser *parser) 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. */ @@ -4232,8 +4302,11 @@ c_parser_for_statement (c_parser *parser) 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)) @@ -4244,87 +4317,105 @@ c_parser_asm_statement (c_parser *parser) else if (c_parser_next_token_is_keyword (parser, RID_CONST) || c_parser_next_token_is_keyword (parser, RID_RESTRICT)) { - warning (0, "%H%E qualifier ignored on asm", - &c_parser_peek_token (parser)->location, - c_parser_peek_token (parser)->value); + warning_at (c_parser_peek_token (parser)->location, + 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 (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; + if (str == NULL_TREE) + 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; } - /* Parse clobbers. */ - clobbers = c_parser_asm_clobbers (parser); + 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 @@ -4344,6 +4435,7 @@ static tree c_parser_asm_operands (c_parser *parser, bool convert_p) { tree list = NULL_TREE; + location_t loc; while (true) { tree name, str; @@ -4378,9 +4470,12 @@ c_parser_asm_operands (c_parser *parser, bool convert_p) parser->lex_untranslated_string = true; return NULL_TREE; } + loc = c_parser_peek_token (parser)->location; expr = c_parser_expression (parser); + mark_exp_read (expr.value); 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 %<)%>")) { @@ -4423,6 +4518,45 @@ c_parser_asm_clobbers (c_parser *parser) 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 @@ -4444,8 +4578,10 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after) { struct c_expr lhs, rhs, ret; enum tree_code code; + 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; switch (c_parser_peek_token (parser)->type) { case CPP_EQ: @@ -4485,9 +4621,12 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after) 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 (lhs.value, code, rhs.value); + rhs = default_function_array_read_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 @@ -4495,6 +4634,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after) TREE_NO_WARNING (ret.value) = 1; ret.original_code = ERROR_MARK; } + ret.original_type = NULL; return ret; } @@ -4516,44 +4656,86 @@ static struct c_expr c_parser_conditional_expression (c_parser *parser, struct c_expr *after) { struct c_expr cond, exp1, exp2, ret; + location_t cond_loc, colon_loc; + gcc_assert (!after || c_dialect_objc ()); + cond = c_parser_binary_expression (parser, after); + 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_read_conversion (cond_loc, cond); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_COLON)) { - if (pedantic) - pedwarn ("%HISO C forbids omitting the middle term of a ?: expression", - &c_parser_peek_token (parser)->location); + 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)); - cond.value = c_objc_common_truthvalue_conversion (exp1.value); - skip_evaluation += cond.value == truthvalue_true_node; + 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); + c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node; } else { cond.value = c_objc_common_truthvalue_conversion - (default_conversion (cond.value)); - skip_evaluation += cond.value == truthvalue_false_node; + (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)); + mark_exp_read (exp1.value); + 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_read_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; } @@ -4632,8 +4814,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) 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. */ @@ -4659,31 +4841,41 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) 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; \ + c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \ + == truthvalue_false_node); \ break; \ case TRUTH_ORIF_EXPR: \ - skip_evaluation -= stack[sp - 1].expr.value == truthvalue_true_node; \ + 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].expr); \ + = default_function_array_read_conversion (stack[sp - 1].loc, \ + stack[sp - 1].expr); \ stack[sp].expr \ - = default_function_array_conversion (stack[sp].expr); \ - stack[sp - 1].expr = parser_build_binary_op (stack[sp].op, \ + = default_function_array_read_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; @@ -4772,6 +4964,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) expression. */ goto out; } + binary_loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); while (oprec <= stack[sp].prec) POP; @@ -4779,25 +4972,31 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) { case TRUTH_ANDIF_EXPR: stack[sp].expr - = default_function_array_conversion (stack[sp].expr); + = default_function_array_read_conversion (stack[sp].loc, + stack[sp].expr); stack[sp].expr.value = c_objc_common_truthvalue_conversion - (default_conversion (stack[sp].expr.value)); - skip_evaluation += stack[sp].expr.value == truthvalue_false_node; + (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].expr); + = default_function_array_read_conversion (stack[sp].loc, + stack[sp].expr); stack[sp].expr.value = c_objc_common_truthvalue_conversion - (default_conversion (stack[sp].expr.value)); - skip_evaluation += stack[sp].expr.value == truthvalue_true_node; + (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) @@ -4818,9 +5017,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) 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 @@ -4838,6 +5039,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) { ret.value = error_mark_node; ret.original_code = ERROR_MARK; + ret.original_type = NULL; return ret; } @@ -4845,12 +5047,16 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) 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_read_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 @@ -4889,60 +5095,71 @@ c_parser_unary_expression (c_parser *parser) { int ext; struct c_expr ret, op; + 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); + op = default_function_array_read_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); + op = default_function_array_read_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)); + op = c_parser_cast_expression (parser, NULL); + mark_exp_read (op.value); + return parser_build_unary_op (op_loc, ADDR_EXPR, op); case CPP_MULT: c_parser_consume_token (parser); + 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 (op.value, "unary *"); - ret.original_code = ERROR_MARK; + op = default_function_array_read_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 (OPT_Wtraditional, - "%Htraditional C rejects the unary plus operator", - &c_parser_peek_token (parser)->location); + 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); + op = default_function_array_read_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); + op = default_function_array_read_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); + op = default_function_array_read_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); + op = default_function_array_read_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); + (c_parser_peek_token (parser)->value, op_loc); c_parser_consume_token (parser); } else @@ -4950,7 +5167,6 @@ c_parser_unary_expression (c_parser *parser) c_parser_error (parser, "expected identifier"); ret.value = error_mark_node; } - ret.original_code = ERROR_MARK; return ret; case CPP_KEYWORD: switch (c_parser_peek_token (parser)->keyword) @@ -4967,14 +5183,16 @@ c_parser_unary_expression (c_parser *parser) 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 (op); - return parser_build_unary_op (REALPART_EXPR, op); + 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 (op); - return parser_build_unary_op (IMAGPART_EXPR, op); + 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); } @@ -4992,7 +5210,7 @@ c_parser_sizeof_expression (c_parser *parser) 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))) @@ -5007,41 +5225,37 @@ c_parser_sizeof_expression (c_parser *parser) if (type_name == NULL) { struct c_expr ret; - skip_evaluation--; + 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); + type_name, + expr_loc); goto sizeof_expr; } /* sizeof ( type-name ). */ - skip_evaluation--; + c_inhibit_evaluation_warnings--; in_sizeof--; - if (type_name->declarator->kind == cdk_array - && type_name->declarator->u.array.vla_unspec_p) - { - /* C99 6.7.5.2p4 */ - error ("%H%<[*]%> not allowed in other than a declaration", - &expr_loc); - } - 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--; + mark_exp_read (expr.value); if (TREE_CODE (expr.value) == COMPONENT_REF && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) - error ("%H% applied to a bit-field", &expr_loc); - return c_expr_sizeof_expr (expr); + error_at (expr_loc, "% applied to a bit-field"); + return c_expr_sizeof_expr (expr_loc, expr); } } @@ -5051,40 +5265,46 @@ static struct c_expr 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. */ + 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--; + 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); + 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 @@ -5092,10 +5312,12 @@ c_parser_alignof_expression (c_parser *parser) struct c_expr ret; expr = c_parser_unary_expression (parser); alignof_expr: - skip_evaluation--; + mark_exp_read (expr.value); + 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; } } @@ -5158,18 +5380,34 @@ c_parser_postfix_expression (c_parser *parser) { struct c_expr expr, e1, e2, e3; struct c_type_name *t1, *t2; - location_t loc; + 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; + 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; + } + 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); @@ -5178,7 +5416,6 @@ c_parser_postfix_expression (c_parser *parser) gcc_assert (c_dialect_objc ()); expr.value = objc_build_string_object (c_parser_peek_token (parser)->value); - expr.original_code = ERROR_MARK; c_parser_consume_token (parser); break; case CPP_NAME: @@ -5186,17 +5423,15 @@ c_parser_postfix_expression (c_parser *parser) { c_parser_error (parser, "expected expression"); expr.value = error_mark_node; - expr.original_code = ERROR_MARK; 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, + expr.value = build_external_ref (loc, id, (c_parser_peek_token (parser)->type - == CPP_OPEN_PAREN), loc); - expr.original_code = ERROR_MARK; + == CPP_OPEN_PAREN), + &expr.original_type); } break; case CPP_OPEN_PAREN: @@ -5206,29 +5441,27 @@ c_parser_postfix_expression (c_parser *parser) { /* A statement expression. */ tree stmt; - location_t here = c_parser_peek_token (parser)->location; + 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 ("%Hbraced-group within expression allowed " - "only inside a function", &here); + 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; - 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 %<)%>"); - if (pedantic) - pedwarn ("%HISO C forbids braced-groups within expressions", - &here); - expr.value = c_finish_stmt_expr (stmt); - expr.original_code = ERROR_MARK; + 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))) { @@ -5236,19 +5469,21 @@ c_parser_postfix_expression (c_parser *parser) 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; - expr.original_code = ERROR_MARK; } else expr = c_parser_postfix_expression_after_paren_type (parser, - type_name); + type_name, + loc); } else { @@ -5257,7 +5492,9 @@ c_parser_postfix_expression (c_parser *parser) expr = c_parser_expression (parser); if (TREE_CODE (expr.value) == MODIFY_EXPR) TREE_NO_WARNING (expr.value) = 1; - expr.original_code = ERROR_MARK; + 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 %<)%>"); } @@ -5268,9 +5505,9 @@ c_parser_postfix_expression (c_parser *parser) case RID_FUNCTION_NAME: case RID_PRETTY_FUNCTION_NAME: case RID_C99_FUNCTION_NAME: - expr.value = fname_decl (c_parser_peek_token (parser)->keyword, + expr.value = fname_decl (loc, + 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: @@ -5278,29 +5515,37 @@ c_parser_postfix_expression (c_parser *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); + mark_exp_read (e1.value); + 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; - expr.original_code = ERROR_MARK; 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; - expr.original_code = ERROR_MARK; } else { - expr.value = build_va_arg (e1.value, groktypename (t1)); - expr.original_code = ERROR_MARK; + 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: @@ -5308,44 +5553,55 @@ c_parser_postfix_expression (c_parser *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 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); + { + 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 - (offsetof_ref, c_parser_peek_token (parser)->value); + (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)) + CPP_OPEN_SQUARE) + || c_parser_next_token_is (parser, + CPP_DEREF)) { - if (c_parser_next_token_is (parser, CPP_DOT)) + 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)) @@ -5354,18 +5610,20 @@ c_parser_postfix_expression (c_parser *parser) break; } offsetof_ref = build_component_ref - (offsetof_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 (offsetof_ref, idx); + offsetof_ref = build_array_ref (loc, offsetof_ref, idx); } } } @@ -5374,7 +5632,6 @@ c_parser_postfix_expression (c_parser *parser) 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: @@ -5382,7 +5639,6 @@ c_parser_postfix_expression (c_parser *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; @@ -5391,7 +5647,6 @@ c_parser_postfix_expression (c_parser *parser) { 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); @@ -5399,7 +5654,6 @@ c_parser_postfix_expression (c_parser *parser) { 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); @@ -5408,10 +5662,15 @@ c_parser_postfix_expression (c_parser *parser) { tree c; - c = fold (e1.value); - if (TREE_CODE (c) != INTEGER_CST) - error ("%Hfirst argument to %<__builtin_choose_expr%> not" - " a constant", &loc); + c = e1.value; + mark_exp_read (e2.value); + mark_exp_read (e3.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; @@ -5420,28 +5679,24 @@ c_parser_postfix_expression (c_parser *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, @@ -5449,13 +5704,12 @@ c_parser_postfix_expression (c_parser *parser) { tree e1, e2; - e1 = TYPE_MAIN_VARIANT (groktypename (t1)); - e2 = TYPE_MAIN_VARIANT (groktypename (t2)); + 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); - expr.original_code = ERROR_MARK; } break; case RID_AT_SELECTOR: @@ -5464,15 +5718,13 @@ c_parser_postfix_expression (c_parser *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; + expr.value = objc_build_selector_expr (loc, sel); } break; case RID_AT_PROTOCOL: @@ -5481,7 +5733,6 @@ c_parser_postfix_expression (c_parser *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)) @@ -5489,7 +5740,6 @@ c_parser_postfix_expression (c_parser *parser) 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; } { @@ -5498,7 +5748,6 @@ c_parser_postfix_expression (c_parser *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: @@ -5508,29 +5757,25 @@ c_parser_postfix_expression (c_parser *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); + tree type = groktypename (t1, NULL, NULL); expr.value = objc_build_encode_expr (type); - expr.original_code = ERROR_MARK; } break; default: c_parser_error (parser, "expected expression"); expr.value = error_mark_node; - expr.original_code = ERROR_MARK; break; } break; @@ -5545,17 +5790,15 @@ c_parser_postfix_expression (c_parser *parser) "expected %<]%>"); expr.value = objc_build_message_expr (build_tree_list (receiver, args)); - expr.original_code = ERROR_MARK; 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); + return c_parser_postfix_expression_after_primary (parser, loc, expr); } /* Parse a postfix expression after a parenthesized type name: the @@ -5564,45 +5807,86 @@ c_parser_postfix_expression (c_parser *parser) 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 ("%Hcompound literal has variable size", &start_loc); + 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 (pedantic && !flag_isoc99) - pedwarn ("%HISO C90 forbids compound literals", &start_loc); - expr.value = build_compound_literal (type, init.value); + 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"); + 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, + location_t expr_loc, struct c_expr expr) { - tree ident, idx, exprlist; + 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: @@ -5611,25 +5895,42 @@ c_parser_postfix_expression_after_primary (c_parser *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); + 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_TREE; + exprlist = NULL; else - exprlist = c_parser_expr_list (parser, true); + exprlist = c_parser_expr_list (parser, true, false, &origtypes); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); - expr.value = build_function_call (expr.value, exprlist); + orig_expr = expr; + mark_exp_read (expr.value); + /* 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); + 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 @@ -5637,16 +5938,28 @@ c_parser_postfix_expression_after_primary (c_parser *parser, 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 (expr.value, ident); + 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); + 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 @@ -5654,26 +5967,45 @@ c_parser_postfix_expression_after_primary (c_parser *parser, 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 (build_indirect_ref (expr.value, - "->"), ident); + 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); - expr.value = build_unary_op (POSTINCREMENT_EXPR, expr.value, 0); + expr = default_function_array_read_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); - expr.value = build_unary_op (POSTDECREMENT_EXPR, expr.value, 0); + expr = default_function_array_read_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; @@ -5696,11 +6028,21 @@ c_parser_expression (c_parser *parser) while (c_parser_next_token_is (parser, CPP_COMMA)) { struct c_expr next; + tree lhsval; + 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; + lhsval = expr.value; + while (TREE_CODE (lhsval) == COMPOUND_EXPR) + lhsval = TREE_OPERAND (lhsval, 1); + if (DECL_P (lhsval) || handled_component_p (lhsval)) + mark_exp_read (lhsval); 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; } @@ -5712,39 +6054,60 @@ static struct c_expr 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_read_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_read_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. */ @@ -5886,9 +6249,8 @@ c_parser_objc_class_instance_variables (c_parser *parser) /* Parse any stray semicolon. */ if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { - if (pedantic) - pedwarn ("%Hextra semicolon in struct or union specified", - &c_parser_peek_token (parser)->location); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "extra semicolon in struct or union specified"); c_parser_consume_token (parser); continue; } @@ -5899,19 +6261,19 @@ c_parser_objc_class_instance_variables (c_parser *parser) break; } /* Parse any objc-visibility-spec. */ - if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE)) + if (c_parser_next_token_is_keyword (parser, RID_PRIVATE)) { c_parser_consume_token (parser); objc_set_visibility (2); continue; } - else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED)) + else if (c_parser_next_token_is_keyword (parser, RID_PROTECTED)) { c_parser_consume_token (parser); objc_set_visibility (0); continue; } - else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC)) + else if (c_parser_next_token_is_keyword (parser, RID_PUBLIC)) { c_parser_consume_token (parser); objc_set_visibility (1); @@ -5946,7 +6308,7 @@ static void c_parser_objc_class_declaration (c_parser *parser) { tree list = NULL_TREE; - gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS)); + gcc_assert (c_parser_next_token_is_keyword (parser, RID_CLASS)); c_parser_consume_token (parser); /* Any identifiers, including those declared as type names, are OK here. */ @@ -6104,9 +6466,8 @@ c_parser_objc_method_definition (c_parser *parser) if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { c_parser_consume_token (parser); - if (pedantic) - pedwarn ("%Hextra semicolon in method definition specified", - &c_parser_peek_token (parser)->location); + 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)) { @@ -6142,10 +6503,8 @@ c_parser_objc_methodprotolist (c_parser *parser) switch (c_parser_peek_token (parser)->type) { case CPP_SEMICOLON: - if (pedantic) - pedwarn ("%HISO C does not allow extra %<;%> " - "outside of a function", - &c_parser_peek_token (parser)->location); + 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: @@ -6307,7 +6666,7 @@ static tree c_parser_objc_type_name (c_parser *parser) { tree quals = NULL_TREE; - struct c_type_name *typename = NULL; + struct c_type_name *type_name = NULL; tree type = NULL_TREE; while (true) { @@ -6327,9 +6686,9 @@ c_parser_objc_type_name (c_parser *parser) break; } if (c_parser_next_token_starts_typename (parser)) - typename = c_parser_type_name (parser); - if (typename) - type = groktypename (typename); + type_name = c_parser_type_name (parser); + if (type_name) + type = groktypename (type_name, NULL, NULL); return build_tree_list (quals, type); } @@ -6383,12 +6742,12 @@ c_parser_objc_try_catch_statement (c_parser *parser) { location_t loc; tree stmt; - gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY)); + gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRY)); c_parser_consume_token (parser); loc = c_parser_peek_token (parser)->location; stmt = c_parser_compound_statement (parser); objc_begin_try_stmt (loc, stmt); - while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH)) + while (c_parser_next_token_is_keyword (parser, RID_CATCH)) { struct c_parm *parm; c_parser_consume_token (parser); @@ -6435,6 +6794,7 @@ c_parser_objc_synchronized_statement (c_parser *parser) 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 @@ -6570,7 +6930,7 @@ c_parser_objc_receiver (c_parser *parser) 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. @@ -6599,7 +6959,7 @@ c_parser_objc_message_args (c_parser *parser) { tree keywordexpr; if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) - return list; + return error_mark_node; keywordexpr = c_parser_objc_keywordexpr (parser); list = chainon (list, build_tree_list (sel, keywordexpr)); sel = c_parser_objc_selector (parser); @@ -6618,18 +6978,21 @@ c_parser_objc_message_args (c_parser *parser) 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); + 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; } @@ -6670,14 +7033,25 @@ c_parser_pragma (c_parser *parser, enum pragma_context context) 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; + } + c_parser_omp_taskwait (parser); + return false; + case PRAGMA_OMP_THREADPRIVATE: c_parser_omp_threadprivate (parser); return false; case PRAGMA_OMP_SECTION: - error ("%H%<#pragma omp section%> may only be used in " - "%<#pragma omp sections%> construct", - &c_parser_peek_token (parser)->location); + error_at (c_parser_peek_token (parser)->location, + "%<#pragma omp section%> may only be used in " + "%<#pragma omp sections%> construct"); c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); return false; @@ -6705,7 +7079,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context) 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; @@ -6777,7 +7151,9 @@ c_parser_omp_clause_name (c_parser *parser) switch (p[0]) { case 'c': - if (!strcmp ("copyin", p)) + 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; @@ -6814,6 +7190,10 @@ c_parser_omp_clause_name (c_parser *parser) else if (!strcmp ("shared", p)) result = PRAGMA_OMP_CLAUSE_SHARED; break; + case 'u': + if (!strcmp ("untied", p)) + result = PRAGMA_OMP_CLAUSE_UNTIED; + break; } } @@ -6826,14 +7206,16 @@ c_parser_omp_clause_name (c_parser *parser) /* Validate that a clause of the given type does not already exist. */ static void -check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name) +check_no_duplicate_clause (tree clauses, enum omp_clause_code code, + 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); + location_t loc = OMP_CLAUSE_LOCATION (c); + error_at (loc, "too many %qs clauses", name); break; } } @@ -6843,14 +7225,17 @@ check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name) 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) @@ -6863,13 +7248,13 @@ c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind, 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); + tree u = build_omp_clause (clause_loc, kind); OMP_CLAUSE_DECL (u) = t; OMP_CLAUSE_CHAIN (u) = list; list = u; @@ -6892,16 +7277,55 @@ c_parser_omp_variable_list (c_parser *parser, enum omp_clause_code kind, common case for omp clauses. */ static tree -c_parser_omp_var_list_parens (c_parser *parser, enum tree_code kind, tree list) +c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, + 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; } +/* OpenMP 3.0: + collapse ( constant-expression ) */ + +static tree +c_parser_omp_clause_collapse (c_parser *parser, tree list) +{ + tree c, num = error_mark_node; + HOST_WIDE_INT n; + location_t loc; + + check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse"); + + loc = c_parser_peek_token (parser)->location; + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + num = c_parser_expr_no_commas (parser, NULL).value; + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + } + if (num == error_mark_node) + return list; + if (!INTEGRAL_TYPE_P (TREE_TYPE (num)) + || !host_integerp (num, 0) + || (n = tree_low_cst (num, 0)) <= 0 + || (int) n != n) + { + error_at (loc, + "collapse argument needs positive constant integer expression"); + return list; + } + c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE); + OMP_CLAUSE_COLLAPSE_EXPR (c) = num; + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + /* OpenMP 2.5: copyin ( variable-list ) */ @@ -6927,6 +7351,7 @@ static tree 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 %<(%>")) @@ -6966,7 +7391,7 @@ c_parser_omp_clause_default (c_parser *parser, tree list) 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; @@ -6988,6 +7413,7 @@ c_parser_omp_clause_firstprivate (c_parser *parser, tree list) 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); @@ -6995,7 +7421,7 @@ c_parser_omp_clause_if (c_parser *parser, tree list) 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; @@ -7022,10 +7448,11 @@ static tree 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; } @@ -7036,10 +7463,12 @@ c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list) 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 %<)%>"); @@ -7050,17 +7479,20 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) } /* Attempt to statically determine when the number isn't positive. */ - c = fold_build2 (LE_EXPR, boolean_type_node, t, + 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 (0, "%H% value must be positive", &expr_loc); + warning_at (expr_loc, 0, + "% 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; @@ -7073,14 +7505,16 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) 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; } @@ -7102,6 +7536,7 @@ c_parser_omp_clause_private (c_parser *parser, tree list) 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; @@ -7144,7 +7579,8 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list) { tree nl, c; - nl = c_parser_omp_variable_list (parser, OMP_CLAUSE_REDUCTION, list); + 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; @@ -7160,18 +7596,19 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list) schedule ( schedule-kind , expression ) schedule-kind: - static | dynamic | guided | runtime + static | dynamic | guided | runtime | auto */ static tree 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)) { @@ -7204,6 +7641,8 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) } else if (c_parser_next_token_is_keyword (parser, RID_STATIC)) OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC; + else if (c_parser_next_token_is_keyword (parser, RID_AUTO)) + OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO; else goto invalid_kind; @@ -7215,10 +7654,15 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list) 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 ("%Hschedule % does not take " - "a % parameter", &here); + error_at (here, "schedule % does not take " + "a % parameter"); + else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO) + error_at (here, + "schedule % does not take " + "a % parameter"); else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE) OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; else @@ -7249,6 +7693,24 @@ c_parser_omp_clause_shared (c_parser *parser, tree list) return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list); } +/* OpenMP 3.0: + untied */ + +static tree +c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list) +{ + tree c; + + /* FIXME: Should we allow duplicates? */ + check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied"); + + c = build_omp_clause (c_parser_peek_token (parser)->location, + OMP_CLAUSE_UNTIED); + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + /* Parse all OpenMP clauses. The set clauses allowed by the directive is a bitmask in MASK. Return the list of clauses found; the result of clause default goes in *pdefault. */ @@ -7276,6 +7738,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask, 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"; @@ -7328,6 +7794,10 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask, 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; @@ -7338,7 +7808,7 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask, /* Remove the invalid clause(s) from the list to avoid confusing the rest of the compiler. */ clauses = prev; - error ("%H%qs is not valid for %qs", &here, c_name, where); + error_at (here, "%qs is not valid for %qs", c_name, where); } } @@ -7373,18 +7843,22 @@ c_parser_omp_structured_block (c_parser *parser) 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; enum tree_code code; + struct c_expr rhs_expr; 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: @@ -7443,10 +7917,16 @@ c_parser_omp_atomic (c_parser *parser) } c_parser_consume_token (parser); - rhs = c_parser_expression (parser).value; + { + location_t rhs_loc = c_parser_peek_token (parser)->location; + rhs_expr = c_parser_expression (parser); + rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr); + } + rhs = rhs_expr.value; + rhs = c_fully_fold (rhs, false, NULL); break; } - stmt = c_finish_omp_atomic (code, lhs, rhs); + 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 %<;%>"); @@ -7460,19 +7940,21 @@ c_parser_omp_atomic (c_parser *parser) 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; @@ -7493,7 +7975,7 @@ c_parser_omp_critical (c_parser *parser) 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: @@ -7505,112 +7987,310 @@ c_parser_omp_critical (c_parser *parser) 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, 0, NULL); + c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL); 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); - c_finish_omp_flush (); + c_finish_omp_flush (loc); } -/* Parse the restricted form of the for statment allowed by OpenMP. +/* 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) +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; - location_t loc; + tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl; + tree declv, condv, incrv, initv, for_block = NULL, ret = NULL; + 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) + collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0); + + gcc_assert (collapse >= 1); + + declv = make_tree_vec (collapse); + initv = make_tree_vec (collapse); + condv = make_tree_vec (collapse); + incrv = make_tree_vec (collapse); if (!c_parser_next_token_is_keyword (parser, RID_FOR)) { 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); - if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) - return NULL; - - /* Parse the initialization declaration or expression. */ - if (c_parser_next_token_starts_declspecs (parser)) - { - 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; - } - else if (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_EQ) + for (i = 0; i < collapse; i++) { - decl = c_parser_postfix_expression (parser).value; + int bracecount = 0; - c_parser_require (parser, CPP_EQ, "expected %<=%>"); + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + goto pop_scopes; - init = c_parser_expr_no_commas (parser, NULL).value; - init = build_modify_expr (decl, NOP_EXPR, init); - init = c_process_expr_stmt (init); + /* 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 (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 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_read_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; + } + + /* 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); + 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 %<;%>"); - } - else - goto error_init; - /* Parse the loop condition. */ - cond = NULL_TREE; - if (c_parser_next_token_is_not (parser, CPP_SEMICOLON)) - { - cond = c_parser_expression_conv (parser).value; - cond = c_objc_common_truthvalue_conversion (cond); - if (CAN_HAVE_LOCATION_P (cond)) - SET_EXPR_LOCATION (cond, input_location); - } - 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; - /* Parse the increment expression. */ - incr = NULL_TREE; - if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) - incr = c_process_expr_stmt (c_parser_expression (parser).value); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + 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; + 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; + } + + parse_next: + if (i == collapse - 1) + 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. */ + 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; + } + } + while (1); + + nbraces += bracecount; + } - parse_body: save_break = c_break_label; c_break_label = size_one_node; save_cont = c_cont_label; c_cont_label = NULL_TREE; body = push_stmt_list (); - add_stmt (c_parser_c99_block_statement (parser)); + 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 (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; c_cont_label = save_cont; + while (nbraces) + { + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { + c_parser_consume_token (parser); + nbraces--; + } + else if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + c_parser_consume_token (parser); + else + { + 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 an error from the initialization parsing. */ - if (decl != NULL && decl != error_mark_node && init != error_mark_node) - return c_finish_omp_for (loc, decl, init, cond, incr, body, NULL); - return NULL; - - error_init: - c_parser_error (parser, "expected iteration declaration or initialization"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); - decl = init = cond = incr = NULL_TREE; - goto parse_body; + if (!fail) + { + 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_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) + { + /* 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); + } + return ret; } /* 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 \ @@ -7620,10 +8300,11 @@ c_parser_omp_for_loop (c_parser *parser) | (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; @@ -7631,10 +8312,8 @@ c_parser_omp_for (c_parser *parser) "#pragma omp for"); block = c_begin_compound_stmt (true); - ret = c_parser_omp_for_loop (parser); - if (ret) - OMP_FOR_CLAUSES (ret) = clauses; - 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; @@ -7643,25 +8322,29 @@ c_parser_omp_for (c_parser *parser) /* 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: @@ -7671,15 +8354,18 @@ c_parser_omp_ordered (c_parser *parser) 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. */ @@ -7689,7 +8375,6 @@ c_parser_omp_sections_scope (c_parser *parser) 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 (); @@ -7728,8 +8413,7 @@ c_parser_omp_sections_scope (c_parser *parser) } else if (!error_suppress) { - error ("%Hexpected %<#pragma omp section%> or %<}%>", - &loc); + error_at (loc, "expected %<#pragma omp section%> or %<}%>"); error_suppress = true; } @@ -7744,6 +8428,7 @@ c_parser_omp_sections_scope (c_parser *parser) 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; @@ -7753,6 +8438,8 @@ c_parser_omp_sections_scope (c_parser *parser) /* 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 \ @@ -7763,7 +8450,7 @@ c_parser_omp_sections_scope (c_parser *parser) | (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; @@ -7771,10 +8458,10 @@ c_parser_omp_sections (c_parser *parser) "#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; @@ -7784,6 +8471,8 @@ c_parser_omp_sections (c_parser *parser) # 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 \ @@ -7797,7 +8486,7 @@ c_parser_omp_sections (c_parser *parser) | (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"; @@ -7832,26 +8521,24 @@ c_parser_omp_parallel (c_parser *parser) 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); - stmt = c_parser_omp_for_loop (parser); - if (stmt) - OMP_FOR_CLAUSES (stmt) = ws_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); + stmt = c_finish_omp_parallel (loc, par_clause, block); OMP_PARALLEL_COMBINED (stmt) = 1; break; @@ -7865,6 +8552,8 @@ c_parser_omp_parallel (c_parser *parser) /* 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 \ @@ -7874,9 +8563,10 @@ c_parser_omp_parallel (c_parser *parser) | (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) @@ -7887,6 +8577,46 @@ c_parser_omp_single (c_parser *parser) return add_stmt (stmt); } +/* 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)) + +static tree +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"); + + block = c_begin_omp_task (); + c_parser_statement (parser); + return c_finish_omp_task (loc, clauses, block); +} + +/* OpenMP 3.0: + # pragma omp taskwait new-line +*/ + +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 (loc); +} /* Main entry point to parsing most OpenMP pragmas. */ @@ -7901,44 +8631,41 @@ c_parser_omp_construct (c_parser *parser) 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 (loc, parser); break; default: gcc_unreachable (); } if (stmt) - SET_EXPR_LOCATION (stmt, loc); + gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION); } @@ -7949,27 +8676,35 @@ static void c_parser_omp_threadprivate (c_parser *parser) { tree vars, t; + location_t loc; c_parser_consume_pragma (parser); - vars = c_parser_omp_var_list_parens (parser, 0, NULL); + 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. */ for (t = vars; t; t = TREE_CHAIN (t)) { 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. */ 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 % after first use", v); + error_at (loc, "%qE declared % after first use", v); else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v)) - error ("automatic variable %qE cannot be %", v); + error_at (loc, "automatic variable %qE cannot be %", v); else if (TREE_TYPE (v) == error_mark_node) ; else if (! COMPLETE_TYPE_P (TREE_TYPE (v))) - error ("% %qE has incomplete type", v); + error_at (loc, "% %qE has incomplete type", v); else { if (! DECL_THREAD_LOCAL_P (v)) @@ -8008,6 +8743,10 @@ c_parse_file (void) 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; }