X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-parser.c;h=43ef655495e4d165c6cb1f094094695179d38f62;hb=bf3e1520c00cff0abcd998aac1c85f084f162d3e;hp=a54674ff01dad4c2a47b7a2125d039bb4328dc46;hpb=35cc02b5c80ac6738c1a3362a822e3d7e4d0c587;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-parser.c b/gcc/c-parser.c index a54674ff01d..43ef655495e 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -1,6 +1,7 @@ /* 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 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 + Free Software Foundation, Inc. Parser actions based on the old Bison parser; structure somewhat influenced by and fragments based on the C++ parser. @@ -9,7 +10,7 @@ This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -18,9 +19,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* TODO: @@ -59,167 +59,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "cgraph.h" -/* Miscellaneous data and functions needed for the parser. */ - -int yydebug; - -/* Objective-C specific parser/lexer information. */ - -static int objc_pq_context = 0; - -/* The following flag is needed to contextualize Objective-C lexical - analysis. In some cases (e.g., 'int NSObject;'), it is undesirable - to bind an identifier to an Objective-C class, even if a class with - that name exists. */ -static int objc_need_raw_identifier = 0; -#define OBJC_NEED_RAW_IDENTIFIER(VAL) \ - do { \ - if (c_dialect_objc ()) \ - objc_need_raw_identifier = VAL; \ - } while (0) - -/* 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 }, - { "__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)) - -/* All OpenMP clauses. OpenMP 2.5. */ -typedef enum pragma_omp_clause { - PRAGMA_OMP_CLAUSE_NONE = 0, - - PRAGMA_OMP_CLAUSE_COPYIN, - PRAGMA_OMP_CLAUSE_COPYPRIVATE, - PRAGMA_OMP_CLAUSE_DEFAULT, - PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, - PRAGMA_OMP_CLAUSE_IF, - PRAGMA_OMP_CLAUSE_LASTPRIVATE, - PRAGMA_OMP_CLAUSE_NOWAIT, - PRAGMA_OMP_CLAUSE_NUM_THREADS, - PRAGMA_OMP_CLAUSE_ORDERED, - PRAGMA_OMP_CLAUSE_PRIVATE, - PRAGMA_OMP_CLAUSE_REDUCTION, - PRAGMA_OMP_CLAUSE_SCHEDULE, - PRAGMA_OMP_CLAUSE_SHARED -} pragma_omp_clause; - - /* Initialization routine for this file. */ void @@ -229,24 +68,41 @@ 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; + 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; } } @@ -293,8 +149,6 @@ typedef struct c_token GTY (()) /* 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; /* The location at which this token was found. */ @@ -317,6 +171,17 @@ typedef struct c_parser GTY(()) /* True if we're processing a pragma, and shouldn't automatically consume CPP_PRAGMA_EOL. */ BOOL_BITFIELD in_pragma : 1; + /* True if we're parsing the outermost block of an if statement. */ + BOOL_BITFIELD in_if_block : 1; + /* True if we want to lex an untranslated string. */ + BOOL_BITFIELD lex_untranslated_string : 1; + /* Objective-C specific parser/lexer information. */ + BOOL_BITFIELD objc_pq_context : 1; + /* The following flag is needed to contextualize Objective-C lexical + analysis. In some cases (e.g., 'int NSObject;'), it is + undesirable to bind an identifier to an Objective-C class, even + if a class with that name exists. */ + BOOL_BITFIELD objc_need_raw_identifier : 1; } c_parser; @@ -329,15 +194,16 @@ static GTY (()) c_parser *the_parser; /* Read in and lex a single token, storing it in *TOKEN. */ static void -c_lex_one_token (c_token *token) +c_lex_one_token (c_parser *parser, c_token *token) { timevar_push (TV_LEX); - token->type = c_lex_with_flags (&token->value, &token->location, NULL); + token->type = c_lex_with_flags (&token->value, &token->location, NULL, + (parser->lex_untranslated_string + ? C_LEX_STRING_NO_TRANSLATE : 0)); token->id_kind = C_ID_NONE; token->keyword = RID_MAX; token->pragma_kind = PRAGMA_NONE; - token->in_system_header = in_system_header; switch (token->type) { @@ -345,17 +211,26 @@ c_lex_one_token (c_token *token) { tree decl; - int objc_force_identifier = objc_need_raw_identifier; - OBJC_NEED_RAW_IDENTIFIER (0); + bool objc_force_identifier = parser->objc_need_raw_identifier; + if (c_dialect_objc ()) + parser->objc_need_raw_identifier = false; if (C_IS_RESERVED_WORD (token->value)) { enum rid rid_code = C_RID_CODE (token->value); - if (c_dialect_objc ()) + if (rid_code == RID_CXX_COMPAT_WARN) + { + warning (OPT_Wc___compat, + "%Hidentifier %qs conflicts with C++ keyword", + &token->location, + IDENTIFIER_POINTER (token->value)); + } + else if (c_dialect_objc ()) { - if (!OBJC_IS_AT_KEYWORD (rid_code) - && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context)) + if (!objc_is_reserved_word (token->value) + && (!OBJC_IS_PQ_KEYWORD (rid_code) + || parser->objc_pq_context)) { /* Return the canonical spelling for this keyword. */ token->value = ridpointers[(int) rid_code]; @@ -366,8 +241,6 @@ c_lex_one_token (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; @@ -412,11 +285,12 @@ c_lex_one_token (c_token *token) case CPP_SEMICOLON: /* These tokens may affect the interpretation of any identifiers following, if doing Objective-C. */ - OBJC_NEED_RAW_IDENTIFIER (0); + if (c_dialect_objc ()) + parser->objc_need_raw_identifier = false; 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: @@ -433,7 +307,7 @@ c_parser_peek_token (c_parser *parser) { if (parser->tokens_avail == 0) { - c_lex_one_token (&parser->tokens[0]); + c_lex_one_token (parser, &parser->tokens[0]); parser->tokens_avail = 1; } return &parser->tokens[0]; @@ -463,12 +337,7 @@ c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type) static inline bool c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword) { - c_token *token; - - /* Peek at the next token. */ - token = c_parser_peek_token (parser); - /* Check to see if it is the indicated keyword. */ - return token->keyword == keyword; + return c_parser_peek_token (parser)->keyword == keyword; } /* Return true if TOKEN can start a type name, @@ -516,6 +385,9 @@ c_token_starts_typename (c_token *token) case RID_VOLATILE: case RID_RESTRICT: case RID_ATTRIBUTE: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: return true; default: return false; @@ -590,6 +462,9 @@ c_token_starts_declspecs (c_token *token) case RID_VOLATILE: case RID_RESTRICT: case RID_ATTRIBUTE: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: return true; default: return false; @@ -623,7 +498,7 @@ c_parser_peek_2nd_token (c_parser *parser) gcc_assert (parser->tokens_avail == 1); gcc_assert (parser->tokens[0].type != CPP_EOF); gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL); - c_lex_one_token (&parser->tokens[1]); + c_lex_one_token (parser, &parser->tokens[1]); parser->tokens_avail = 2; return &parser->tokens[1]; } @@ -665,7 +540,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; } } @@ -931,6 +805,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 @@ -939,11 +816,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) + | (cpp_opts->warn_long_long << 5)); + cpp_opts->pedantic = pedantic = 0; warn_pointer_arith = 0; - warn_traditional = 0; + cpp_opts->warn_traditional = warn_traditional = 0; flag_iso = 0; + warn_long_long = 0; + cpp_opts->warn_long_long = 0; return ret; } @@ -953,10 +834,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; + warn_long_long = (flags >> 4) & 1; + cpp_opts->warn_long_long = (flags >> 5) & 1; } /* Possibly kinds of declarator to parse. */ @@ -1037,6 +920,7 @@ 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); @@ -1083,8 +967,8 @@ c_parser_translation_unit (c_parser *parser) { if (c_parser_next_token_is (parser, CPP_EOF)) { - if (pedantic) - pedwarn ("ISO C forbids an empty source file"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "ISO C forbids an empty translation unit"); } else { @@ -1146,7 +1030,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; @@ -1168,8 +1052,8 @@ c_parser_external_declaration (c_parser *parser) } break; case CPP_SEMICOLON: - if (pedantic) - pedwarn ("ISO C does not allow extra %<;%> outside of a function"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "ISO C does not allow extra %<;%> outside of a function"); c_parser_consume_token (parser); break; case CPP_PRAGMA: @@ -1260,6 +1144,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, tree prefix_attrs; tree all_prefix_attrs; bool diagnosed_no_specs = false; + location_t here = c_parser_peek_token (parser)->location; specs = build_null_declspecs (); c_parser_declspecs (parser, specs, true, true, start_attr_ok); @@ -1282,7 +1167,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, else { shadow_tag_warned (specs, 1); - pedwarn ("empty declaration"); + pedwarn (here, 0, "empty declaration"); } c_parser_consume_token (parser); return; @@ -1318,7 +1203,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 ("data definition has no type or storage class"); + pedwarn (here, 0, "data definition has no type or storage class"); } /* Having seen a data definition, there cannot now be a function definition. */ @@ -1387,9 +1272,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, /* Function definition (nested or otherwise). */ if (nested) { - if (pedantic) - pedwarn ("ISO C forbids nested functions"); - push_function_context (); + pedwarn (here, OPT_pedantic, "ISO C forbids nested functions"); + c_push_function_context (); } if (!start_function (specs, declarator, all_prefix_attrs)) { @@ -1399,7 +1283,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, % " "or %<__attribute__%>"); if (nested) - pop_function_context (); + c_pop_function_context (); break; } /* Parse old-style parameter declarations. ??? Attributes are @@ -1417,16 +1301,16 @@ 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; add_stmt (fnbody); finish_function (); - pop_function_context (); + c_pop_function_context (); add_stmt (build_stmt (DECL_EXPR, decl)); } else @@ -1523,6 +1407,12 @@ c_parser_asm_definition (c_parser *parser) _Decimal32 _Decimal64 _Decimal128 + _Fract + _Accum + _Sat + + (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037: + http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf) Objective-C: @@ -1625,11 +1515,15 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, case RID_DFLOAT64: case RID_DFLOAT128: case RID_BOOL: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: if (!typespec_ok) goto out; attrs_ok = true; seen_type = true; - OBJC_NEED_RAW_IDENTIFIER (1); + if (c_dialect_objc ()) + parser->objc_need_raw_identifier = true; t.kind = ctsk_resword; t.spec = c_parser_peek_token (parser)->value; declspecs_add_type (specs, t); @@ -1711,18 +1605,23 @@ c_parser_enum_specifier (c_parser *parser) struct c_typespec ret; tree attrs; tree ident = NULL_TREE; + location_t ident_loc; gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM)); 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; c_parser_consume_token (parser); } if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) { /* Parse an enum definition. */ - tree type = start_enum (ident); + struct c_enum_contents the_enum; + tree type = start_enum (&the_enum, ident); tree postfix_attrs; /* We chain the enumerators in reverse order, then put them in forward order at the end. */ @@ -1734,6 +1633,9 @@ c_parser_enum_specifier (c_parser *parser) tree enum_value; tree enum_decl; bool seen_comma; + c_token *token; + location_t comma_loc; + location_t value_loc; if (c_parser_next_token_is_not (parser, CPP_NAME)) { c_parser_error (parser, "expected identifier"); @@ -1741,28 +1643,36 @@ c_parser_enum_specifier (c_parser *parser) values = error_mark_node; break; } - enum_id = c_parser_peek_token (parser)->value; + token = c_parser_peek_token (parser); + enum_id = token->value; + /* Set the location in case we create a decl now. */ + c_parser_set_source_position_from_token (token); + value_loc = token->location; c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_EQ)) { c_parser_consume_token (parser); + value_loc = c_parser_peek_token (parser)->location; + /* This may call cb_line_change and alter the input_location. */ enum_value = c_parser_expr_no_commas (parser, NULL).value; } else enum_value = NULL_TREE; - enum_decl = build_enumerator (enum_id, enum_value); + enum_decl = build_enumerator (&the_enum, enum_id, enum_value, + value_loc); TREE_CHAIN (enum_decl) = values; values = enum_decl; seen_comma = false; if (c_parser_next_token_is (parser, CPP_COMMA)) { + comma_loc = c_parser_peek_token (parser)->location; seen_comma = true; c_parser_consume_token (parser); } if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { - if (seen_comma && pedantic && !flag_isoc99) - pedwarn ("comma at end of enumerator list"); + if (seen_comma && !flag_isoc99) + pedwarn (comma_loc, OPT_pedantic, "comma at end of enumerator list"); c_parser_consume_token (parser); break; } @@ -1791,7 +1701,11 @@ c_parser_enum_specifier (c_parser *parser) /* In ISO C, enumerated types can be referred to only if already defined. */ if (pedantic && !COMPLETE_TYPE_P (ret.spec)) - pedwarn ("ISO C forbids forward references to % types"); + { + gcc_assert (ident); + pedwarn (ident_loc, OPT_pedantic, + "ISO C forbids forward references to % types"); + } return ret; } @@ -1854,6 +1768,8 @@ c_parser_struct_or_union_specifier (c_parser *parser) } 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; @@ -1912,8 +1828,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 ("extra semicolon in struct or union specified"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "extra semicolon in struct or union specified"); c_parser_consume_token (parser); continue; } @@ -1941,7 +1857,8 @@ c_parser_struct_or_union_specifier (c_parser *parser) else { if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) - pedwarn ("no semicolon at end of struct or union"); + pedwarn (c_parser_peek_token (parser)->location, 0, + "no semicolon at end of struct or union"); else { c_parser_error (parser, "expected %<;%>"); @@ -2005,6 +1922,7 @@ c_parser_struct_declaration (c_parser *parser) tree prefix_attrs; tree all_prefix_attrs; tree decls; + location_t decl_loc; if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) { int ext; @@ -2016,6 +1934,7 @@ c_parser_struct_declaration (c_parser *parser) return decl; } specs = build_null_declspecs (); + decl_loc = c_parser_peek_token (parser)->location; c_parser_declspecs (parser, specs, false, true, true); if (parser->error) return NULL_TREE; @@ -2030,8 +1949,8 @@ c_parser_struct_declaration (c_parser *parser) tree ret; if (!specs->type_seen_p) { - if (pedantic) - pedwarn ("ISO C forbids member declarations with no members"); + pedwarn (decl_loc, OPT_pedantic, + "ISO C forbids member declarations with no members"); shadow_tag_warned (specs, pedantic); ret = NULL_TREE; } @@ -2040,7 +1959,13 @@ c_parser_struct_declaration (c_parser *parser) /* Support for unnamed structs or unions as members of structs or unions (which is [a] useful and [b] supports MS P-SDK). */ - ret = grokfield (build_id_declarator (NULL_TREE), specs, NULL_TREE); + tree attrs = NULL; + + ret = grokfield (c_parser_peek_token (parser)->location, + build_id_declarator (NULL_TREE), specs, + NULL_TREE, &attrs); + if (ret) + decl_attributes (&ret, attrs, 0); } return ret; } @@ -2080,7 +2005,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); + 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; @@ -2152,12 +2078,13 @@ c_parser_typeof_specifier (c_parser *parser) else { bool was_vm; + location_t here = c_parser_peek_token (parser)->location; struct c_expr expr = c_parser_expression (parser); skip_evaluation--; in_typeof--; if (TREE_CODE (expr.value) == COMPONENT_REF && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) - error ("% applied to a bit-field"); + error ("%H% applied to a bit-field", &here); 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 @@ -2475,7 +2402,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present, star_seen); if (declarator == NULL) return NULL; - inner = set_array_declarator_inner (declarator, inner, !id_present); + inner = set_array_declarator_inner (declarator, inner); return c_parser_direct_declarator_inner (parser, id_present, inner); } else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) @@ -2595,7 +2522,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 ("ISO C requires a named argument before %<...%>"); + error ("%HISO C requires a named argument before %<...%>", + &c_parser_peek_token (parser)->location); c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) { @@ -2737,8 +2665,8 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs) string-literal ??? At present, following the old parser, the caller needs to have - set c_lex_string_translate to 0. It would be better to follow the - C++ parser rather than using the c_lex_string_translate kludge. */ + set lex_untranslated_string to 1. It would be better to follow the + C++ parser rather than using this kludge. */ static tree c_parser_asm_string_literal (c_parser *parser) @@ -2751,7 +2679,8 @@ c_parser_asm_string_literal (c_parser *parser) } else if (c_parser_next_token_is (parser, CPP_WSTRING)) { - error ("wide string literal in %"); + error ("%Hwide string literal in %", + &c_parser_peek_token (parser)->location); str = build_string (1, ""); c_parser_consume_token (parser); } @@ -2777,16 +2706,16 @@ c_parser_simple_asm_expr (c_parser *parser) tree str; gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM)); /* ??? Follow the C++ parser rather than using the - c_lex_string_translate kludge. */ - c_lex_string_translate = 0; + lex_untranslated_string kludge. */ + parser->lex_untranslated_string = true; c_parser_consume_token (parser); if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; return NULL_TREE; } str = c_parser_asm_string_literal (parser); - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); @@ -2829,17 +2758,17 @@ c_parser_attributes (c_parser *parser) while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) { /* ??? Follow the C++ parser rather than using the - c_lex_string_translate kludge. */ - c_lex_string_translate = 0; + lex_untranslated_string kludge. */ + parser->lex_untranslated_string = true; c_parser_consume_token (parser); if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; return attrs; } if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return attrs; } @@ -2885,6 +2814,9 @@ c_parser_attributes (c_parser *parser) case RID_DFLOAT64: case RID_DFLOAT128: case RID_BOOL: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: ok = true; break; default: @@ -2893,8 +2825,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)) { @@ -2936,7 +2873,7 @@ c_parser_attributes (c_parser *parser) c_parser_consume_token (parser); else { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); return attrs; @@ -2947,7 +2884,7 @@ c_parser_attributes (c_parser *parser) c_parser_consume_token (parser); else { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); return attrs; @@ -2956,12 +2893,12 @@ c_parser_attributes (c_parser *parser) c_parser_consume_token (parser); else { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); return attrs; } - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; } return attrs; } @@ -3065,6 +3002,7 @@ c_parser_initializer (c_parser *parser) static struct c_expr c_parser_braced_init (c_parser *parser, tree type, bool nested_p) { + location_t brace_loc = c_parser_peek_token (parser)->location; gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE)); c_parser_consume_token (parser); if (nested_p) @@ -3073,8 +3011,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p) really_start_incremental_init (type); if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { - if (pedantic) - pedwarn ("ISO C forbids empty initializer braces"); + pedwarn (brace_loc, OPT_pedantic, "ISO C forbids empty initializer braces"); } else { @@ -3118,8 +3055,9 @@ c_parser_initelt (c_parser *parser) { /* Old-style structure member designator. */ set_init_label (c_parser_peek_token (parser)->value); - if (pedantic) - pedwarn ("obsolete use of designated initializer with %<:%>"); + /* 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); } @@ -3128,10 +3066,14 @@ c_parser_initelt (c_parser *parser) /* des_seen is 0 if there have been no designators, 1 if there has been a single array designator and 2 otherwise. */ int des_seen = 0; + /* Location of a designator. */ + location_t des_loc; while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE) || c_parser_next_token_is (parser, CPP_DOT)) { int des_prev = des_seen; + if (!des_seen) + des_loc = c_parser_peek_token (parser)->location; if (des_seen < 2) des_seen++; if (c_parser_next_token_is (parser, CPP_DOT)) @@ -3157,6 +3099,7 @@ c_parser_initelt (c_parser *parser) else { tree first, second; + location_t ellipsis_loc; /* ??? Following the old parser, [ objc-receiver objc-message-args ] is accepted as an initializer, being distinguished from a designator by what follows @@ -3232,6 +3175,7 @@ c_parser_initelt (c_parser *parser) 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; } @@ -3241,9 +3185,9 @@ c_parser_initelt (c_parser *parser) { c_parser_consume_token (parser); set_init_index (first, second); - if (pedantic && second) - pedwarn ("ISO C forbids specifying range of " - "elements to initialize"); + 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, @@ -3254,18 +3198,16 @@ c_parser_initelt (c_parser *parser) { if (c_parser_next_token_is (parser, CPP_EQ)) { - if (pedantic && !flag_isoc99) - pedwarn ("ISO C90 forbids specifying subobject to initialize"); + 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 ("obsolete use of designated initializer " - "without %<=%>"); - } + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "obsolete use of designated initializer without %<=%>"); else { struct c_expr init; @@ -3379,6 +3321,7 @@ c_parser_compound_statement_nostart (c_parser *parser) { bool last_stmt = false; bool last_label = false; + location_t label_loc; if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { c_parser_consume_token (parser); @@ -3386,6 +3329,7 @@ c_parser_compound_statement_nostart (c_parser *parser) } 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. */ while (c_parser_next_token_is_keyword (parser, RID_LABEL)) @@ -3413,11 +3357,7 @@ c_parser_compound_statement_nostart (c_parser *parser) } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } - /* ??? Locating this diagnostic on the token after the - declarations end follows the old parser, but it might be - better to locate it where the declarations start instead. */ - if (pedantic) - pedwarn ("ISO C forbids label declarations"); + pedwarn (err_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)) @@ -3434,6 +3374,10 @@ c_parser_compound_statement_nostart (c_parser *parser) || (c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) { + if (c_parser_next_token_is_keyword (parser, RID_CASE)) + label_loc = c_parser_peek_2nd_token (parser)->location; + else + label_loc = c_parser_peek_token (parser)->location; last_label = true; last_stmt = false; c_parser_label (parser); @@ -3443,11 +3387,12 @@ c_parser_compound_statement_nostart (c_parser *parser) { last_label = 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 @@ -3471,11 +3416,11 @@ c_parser_compound_statement_nostart (c_parser *parser) /* 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 @@ -3496,6 +3441,20 @@ c_parser_compound_statement_nostart (c_parser *parser) 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) + { + error ("%H""expected %<}%> before %", &loc); + return; + } + else + { + error ("%H% without a previous %", &loc); + c_parser_consume_token (parser); + continue; + } + } else { statement: @@ -3507,7 +3466,7 @@ c_parser_compound_statement_nostart (c_parser *parser) parser->error = false; } if (last_label) - error ("label at end of compound statement"); + error ("%Hlabel at end of compound statement", &label_loc); c_parser_consume_token (parser); } @@ -3562,12 +3521,11 @@ c_parser_label (c_parser *parser) { tree name = c_parser_peek_token (parser)->value; tree tlab; - location_t loc2; tree attrs; + location_t loc2 = c_parser_peek_token (parser)->location; gcc_assert (c_parser_next_token_is (parser, CPP_NAME)); c_parser_consume_token (parser); gcc_assert (c_parser_next_token_is (parser, CPP_COLON)); - loc2 = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); attrs = c_parser_attributes (parser); tlab = define_label (loc2, name); @@ -3578,7 +3536,20 @@ c_parser_label (c_parser *parser) } } if (label) - SET_EXPR_LOCATION (label, loc1); + { + 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, + /*nested*/ true, /*empty_ok*/ false, + /*start_attr_ok*/ true); + } + } } /* Parse a statement (C90 6.6, C99 6.8). @@ -3696,6 +3667,8 @@ c_parser_statement_after_labels (c_parser *parser) { location_t loc = c_parser_peek_token (parser)->location; tree stmt = NULL_TREE; + bool in_if_block = parser->in_if_block; + parser->in_if_block = false; switch (c_parser_peek_token (parser)->type) { case CPP_OPEN_BRACE: @@ -3758,7 +3731,7 @@ c_parser_statement_after_labels (c_parser *parser) 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)) @@ -3773,7 +3746,7 @@ c_parser_statement_after_labels (c_parser *parser) goto expect_semicolon; } break; - case RID_AT_TRY: + case RID_TRY: gcc_assert (c_dialect_objc ()); c_parser_objc_try_catch_statement (parser); break; @@ -3819,6 +3792,25 @@ c_parser_statement_after_labels (c_parser *parser) earlier? */ if (stmt && CAN_HAVE_LOCATION_P (stmt)) 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; + tree cond; + 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); + if (warn_sequence_point) + verify_sequence_points (cond); + return cond; } /* Parse a parenthesized condition from an if, do or while statement. @@ -3829,15 +3821,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; } @@ -3852,11 +3839,13 @@ c_parser_c99_block_statement (c_parser *parser) return c_end_compound_stmt (block, flag_isoc99); } -/* Parse the body of an if statement or the else half thereof. This - is just parsing a statement but (a) it is a block in C99, (b) we - track whether the body is an if statement for the sake of - -Wparentheses warnings, (c) we handle an empty body specially for - the sake of -Wextra warnings. */ +/* Parse the body of an if statement. This is just parsing a + statement but (a) it is a block in C99, (b) we track whether the + body is an if statement for the sake of -Wparentheses warnings, (c) + we handle an empty body specially for the sake of -Wempty-body + warnings, and (d) we call parser_compound_statement directly + because c_parser_statement_after_labels resets + parser->in_if_block. */ static tree c_parser_if_body (c_parser *parser, bool *if_p) @@ -3868,9 +3857,38 @@ c_parser_if_body (c_parser *parser, bool *if_p) && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) c_parser_label (parser); *if_p = c_parser_next_token_is_keyword (parser, RID_IF); - if (extra_warnings && c_parser_next_token_is (parser, CPP_SEMICOLON)) - add_stmt (build_empty_stmt ()); - c_parser_statement_after_labels (parser); + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + add_stmt (build_empty_stmt ()); + c_parser_consume_token (parser); + } + 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); +} + +/* Parse the else body of an if statement. This is just parsing a + statement but (a) it is a block in C99, (b) we handle an empty body + specially for the sake of -Wempty-body warnings. */ + +static tree +c_parser_else_body (c_parser *parser) +{ + tree block = c_begin_compound_stmt (flag_isoc99); + while (c_parser_next_token_is_keyword (parser, RID_CASE) + || c_parser_next_token_is_keyword (parser, RID_DEFAULT) + || (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + c_parser_label (parser); + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) + { + add_stmt (build_empty_stmt ()); + c_parser_consume_token (parser); + } + else + c_parser_statement_after_labels (parser); return c_end_compound_stmt (block, flag_isoc99); } @@ -3887,18 +3905,23 @@ c_parser_if_statement (c_parser *parser) tree block; location_t loc; tree cond; - bool first_if = false, second_if = false; + bool first_if = false; tree first_body, second_body; + bool in_if_block; + gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF)); c_parser_consume_token (parser); block = c_begin_compound_stmt (flag_isoc99); loc = c_parser_peek_token (parser)->location; cond = c_parser_paren_condition (parser); + in_if_block = parser->in_if_block; + parser->in_if_block = true; first_body = c_parser_if_body (parser, &first_if); + parser->in_if_block = in_if_block; if (c_parser_next_token_is_keyword (parser, RID_ELSE)) { c_parser_consume_token (parser); - second_body = c_parser_if_body (parser, &second_if); + second_body = c_parser_else_body (parser); } else second_body = NULL_TREE; @@ -3977,6 +4000,10 @@ c_parser_do_statement (c_parser *parser) location_t loc; 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); block = c_begin_compound_stmt (flag_isoc99); loc = c_parser_peek_token (parser)->location; save_break = c_break_label; @@ -4063,7 +4090,6 @@ c_parser_for_statement (c_parser *parser) 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); @@ -4071,10 +4097,7 @@ 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. */ @@ -4131,7 +4154,8 @@ 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, "%E qualifier ignored on asm", + warning (0, "%H%E qualifier ignored on asm", + &c_parser_peek_token (parser)->location, c_parser_peek_token (parser)->value); quals = NULL_TREE; c_parser_consume_token (parser); @@ -4139,11 +4163,11 @@ c_parser_asm_statement (c_parser *parser) else quals = NULL_TREE; /* ??? Follow the C++ parser rather than using the - c_lex_string_translate kludge. */ - c_lex_string_translate = 0; + lex_untranslated_string kludge. */ + parser->lex_untranslated_string = true; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; return NULL_TREE; } str = c_parser_asm_string_literal (parser); @@ -4157,7 +4181,7 @@ c_parser_asm_statement (c_parser *parser) } if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>")) { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return NULL_TREE; } @@ -4176,7 +4200,7 @@ c_parser_asm_statement (c_parser *parser) } if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>")) { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return NULL_TREE; } @@ -4193,14 +4217,14 @@ c_parser_asm_statement (c_parser *parser) } if (!c_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>")) { - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); return NULL_TREE; } /* Parse clobbers. */ clobbers = c_parser_asm_clobbers (parser); done_asm: - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); @@ -4258,16 +4282,16 @@ c_parser_asm_operands (c_parser *parser, bool convert_p) str = c_parser_asm_string_literal (parser); if (str == NULL_TREE) return NULL_TREE; - c_lex_string_translate = 1; + parser->lex_untranslated_string = false; if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - c_lex_string_translate = 0; + parser->lex_untranslated_string = true; return NULL_TREE; } expr = c_parser_expression (parser); if (convert_p) expr = default_function_array_conversion (expr); - c_lex_string_translate = 0; + parser->lex_untranslated_string = true; if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>")) { c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); @@ -4410,8 +4434,8 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after) c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_COLON)) { - if (pedantic) - pedwarn ("ISO C forbids omitting the middle term of a ?: expression"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "ISO C forbids omitting the middle term of a ?: expression"); /* 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); @@ -4774,59 +4798,62 @@ c_parser_unary_expression (c_parser *parser) { int ext; struct c_expr ret, op; + location_t loc = c_parser_peek_token (parser)->location; switch (c_parser_peek_token (parser)->type) { case CPP_PLUS_PLUS: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - return parser_build_unary_op (PREINCREMENT_EXPR, op); + return parser_build_unary_op (PREINCREMENT_EXPR, op, loc); case CPP_MINUS_MINUS: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - return parser_build_unary_op (PREDECREMENT_EXPR, op); + return parser_build_unary_op (PREDECREMENT_EXPR, op, loc); case CPP_AND: c_parser_consume_token (parser); return parser_build_unary_op (ADDR_EXPR, - c_parser_cast_expression (parser, NULL)); + c_parser_cast_expression (parser, NULL), + loc); case CPP_MULT: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - ret.value = build_indirect_ref (op.value, "unary *"); + ret.value = build_indirect_ref (op.value, "unary *", loc); ret.original_code = ERROR_MARK; return ret; case CPP_PLUS: - c_parser_consume_token (parser); if (!c_dialect_objc () && !in_system_header) warning (OPT_Wtraditional, - "traditional C rejects the unary plus operator"); + "%Htraditional C rejects the unary plus operator", + &c_parser_peek_token (parser)->location); + c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - return parser_build_unary_op (CONVERT_EXPR, op); + return parser_build_unary_op (CONVERT_EXPR, op, loc); case CPP_MINUS: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - return parser_build_unary_op (NEGATE_EXPR, op); + return parser_build_unary_op (NEGATE_EXPR, op, loc); case CPP_COMPL: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - return parser_build_unary_op (BIT_NOT_EXPR, op); + return parser_build_unary_op (BIT_NOT_EXPR, op, loc); case CPP_NOT: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - return parser_build_unary_op (TRUTH_NOT_EXPR, op); + return parser_build_unary_op (TRUTH_NOT_EXPR, op, loc); 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, loc); c_parser_consume_token (parser); } else @@ -4853,12 +4880,12 @@ c_parser_unary_expression (c_parser *parser) c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - return parser_build_unary_op (REALPART_EXPR, op); + return parser_build_unary_op (REALPART_EXPR, op, loc); case RID_IMAGPART: c_parser_consume_token (parser); op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (op); - return parser_build_unary_op (IMAGPART_EXPR, op); + return parser_build_unary_op (IMAGPART_EXPR, op, loc); default: return c_parser_postfix_expression (parser); } @@ -4873,6 +4900,7 @@ static struct c_expr c_parser_sizeof_expression (c_parser *parser) { struct c_expr expr; + location_t expr_loc; gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF)); c_parser_consume_token (parser); skip_evaluation++; @@ -4884,6 +4912,7 @@ c_parser_sizeof_expression (c_parser *parser) starting with a compound literal. */ struct c_type_name *type_name; c_parser_consume_token (parser); + expr_loc = c_parser_peek_token (parser)->location; type_name = c_parser_type_name (parser); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (type_name == NULL) @@ -4908,19 +4937,21 @@ c_parser_sizeof_expression (c_parser *parser) && type_name->declarator->u.array.vla_unspec_p) { /* C99 6.7.5.2p4 */ - error ("%<[*]%> not allowed in other than a declaration"); + error ("%H%<[*]%> not allowed in other than a declaration", + &expr_loc); } return c_expr_sizeof_type (type_name); } else { + expr_loc = c_parser_peek_token (parser)->location; expr = c_parser_unary_expression (parser); sizeof_expr: skip_evaluation--; in_sizeof--; if (TREE_CODE (expr.value) == COMPONENT_REF && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1))) - error ("% applied to a bit-field"); + error ("%H% applied to a bit-field", &expr_loc); return c_expr_sizeof_expr (expr); } } @@ -5038,16 +5069,21 @@ c_parser_postfix_expression (c_parser *parser) { struct c_expr expr, e1, e2, e3; struct c_type_name *t1, *t2; + location_t loc; switch (c_parser_peek_token (parser)->type) { case CPP_NUMBER: 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: expr.value = c_parser_peek_token (parser)->value; expr.original_code = STRING_CST; @@ -5085,12 +5121,13 @@ c_parser_postfix_expression (c_parser *parser) { /* A statement expression. */ tree stmt; + location_t here = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); c_parser_consume_token (parser); if (cur_stmt_list == NULL) { - error ("braced-group within expression allowed " - "only inside a function"); + error ("%Hbraced-group within expression allowed " + "only inside a function", &here); parser->error = true; c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); @@ -5102,8 +5139,8 @@ c_parser_postfix_expression (c_parser *parser) c_parser_compound_statement_nostart (parser); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); - if (pedantic) - pedwarn ("ISO C forbids braced-groups within expressions"); + pedwarn (here, OPT_pedantic, + "ISO C forbids braced-groups within expressions"); expr.value = c_finish_stmt_expr (stmt); expr.original_code = ERROR_MARK; } @@ -5238,11 +5275,12 @@ c_parser_postfix_expression (c_parser *parser) else { tree idx; + loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); idx = c_parser_expression (parser).value; c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); - offsetof_ref = build_array_ref (offsetof_ref, idx); + offsetof_ref = build_array_ref (offsetof_ref, idx, loc); } } } @@ -5262,6 +5300,7 @@ c_parser_postfix_expression (c_parser *parser) expr.original_code = ERROR_MARK; break; } + loc = c_parser_peek_token (parser)->location; e1 = c_parser_expr_no_commas (parser, NULL); if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>")) { @@ -5286,8 +5325,8 @@ c_parser_postfix_expression (c_parser *parser) c = fold (e1.value); if (TREE_CODE (c) != INTEGER_CST) - error ("first argument to %<__builtin_choose_expr%> not" - " a constant"); + error ("%Hfirst argument to %<__builtin_choose_expr%> not" + " a constant", &loc); expr = integer_zerop (c) ? e3 : e2; } break; @@ -5449,19 +5488,21 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, tree type; struct c_expr init; struct c_expr expr; + location_t start_loc; start_init (NULL_TREE, NULL, 0); type = groktypename (type_name); + start_loc = c_parser_peek_token (parser)->location; if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type)) { - error ("compound literal has variable size"); + error ("%Hcompound literal has variable size", &start_loc); 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 ("ISO C90 forbids compound literals"); + if (!flag_isoc99) + pedwarn (start_loc, OPT_pedantic, "ISO C90 forbids compound literals"); expr.value = build_compound_literal (type, init.value); expr.original_code = ERROR_MARK; return c_parser_postfix_expression_after_primary (parser, expr); @@ -5475,17 +5516,19 @@ c_parser_postfix_expression_after_primary (c_parser *parser, struct c_expr expr) { tree ident, idx, exprlist; + location_t loc = c_parser_peek_token (parser)->location; while (true) { switch (c_parser_peek_token (parser)->type) { case CPP_OPEN_SQUARE: /* Array reference. */ + loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); idx = c_parser_expression (parser).value; c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); - expr.value = build_array_ref (expr.value, idx); + expr.value = build_array_ref (expr.value, idx, loc); expr.original_code = ERROR_MARK; break; case CPP_OPEN_PAREN: @@ -5499,6 +5542,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser, "expected %<)%>"); expr.value = build_function_call (expr.value, exprlist); expr.original_code = ERROR_MARK; + if (warn_disallowed_functions) + warn_if_disallowed_function_p (expr.value); break; case CPP_DOT: /* Structure element reference. */ @@ -5532,7 +5577,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser, } c_parser_consume_token (parser); expr.value = build_component_ref (build_indirect_ref (expr.value, - "->"), ident); + "->", loc), + ident); expr.original_code = ERROR_MARK; break; case CPP_PLUS_PLUS: @@ -5760,8 +5806,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 ("extra semicolon in struct or union specified"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "extra semicolon in struct or union specified"); c_parser_consume_token (parser); continue; } @@ -5772,19 +5818,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); @@ -5819,7 +5865,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. */ @@ -5928,11 +5974,11 @@ c_parser_objc_protocol_definition (c_parser *parser) c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); - objc_pq_context = 1; + parser->objc_pq_context = true; objc_start_protocol (id, proto); c_parser_objc_methodprotolist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); - objc_pq_context = 0; + parser->objc_pq_context = false; objc_finish_interface (); } } @@ -5972,20 +6018,20 @@ c_parser_objc_method_definition (c_parser *parser) enum tree_code type = c_parser_objc_method_type (parser); tree decl; objc_set_method_type (type); - objc_pq_context = 1; + parser->objc_pq_context = true; decl = c_parser_objc_method_decl (parser); if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { c_parser_consume_token (parser); - if (pedantic) - pedwarn ("extra semicolon in method definition specified"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "extra semicolon in method definition specified"); } if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE)) { c_parser_error (parser, "expected %<{%>"); return; } - objc_pq_context = 0; + parser->objc_pq_context = false; objc_start_method_definition (decl); add_stmt (c_parser_compound_statement (parser)); objc_finish_method_definition (current_function_decl); @@ -6014,8 +6060,8 @@ c_parser_objc_methodprotolist (c_parser *parser) switch (c_parser_peek_token (parser)->type) { case CPP_SEMICOLON: - if (pedantic) - pedwarn ("ISO C does not allow extra %<;%> outside of a function"); + pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, + "ISO C does not allow extra %<;%> outside of a function"); c_parser_consume_token (parser); break; case CPP_PLUS: @@ -6049,10 +6095,10 @@ c_parser_objc_methodproto (c_parser *parser) tree decl; objc_set_method_type (type); /* Remember protocol qualifiers in prototypes. */ - objc_pq_context = 1; + parser->objc_pq_context = true; decl = c_parser_objc_method_decl (parser); /* Forget protocol qualifiers here. */ - objc_pq_context = 0; + parser->objc_pq_context = false; objc_add_method_declaration (decl); c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } @@ -6177,7 +6223,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) { @@ -6197,9 +6243,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); return build_tree_list (quals, type); } @@ -6253,12 +6299,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); @@ -6540,13 +6586,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 ("%<#pragma omp section%> may only be used in " - "%<#pragma omp sections%> construct"); + error ("%H%<#pragma omp section%> may only be used in " + "%<#pragma omp sections%> construct", + &c_parser_peek_token (parser)->location); c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); return false; @@ -6646,7 +6704,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; @@ -6683,6 +6743,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; } } @@ -6695,7 +6759,8 @@ 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; @@ -6761,7 +6826,8 @@ 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) { if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { @@ -6771,6 +6837,41 @@ c_parser_omp_var_list_parens (c_parser *parser, enum tree_code kind, tree list) 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 ("%Hcollapse argument needs positive constant integer expression", + &loc); + return list; + } + c = build_omp_clause (OMP_CLAUSE_COLLAPSE); + OMP_CLAUSE_COLLAPSE_EXPR (c) = num; + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + /* OpenMP 2.5: copyin ( variable-list ) */ @@ -6907,6 +7008,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) { 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; c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -6922,7 +7024,7 @@ c_parser_omp_clause_num_threads (c_parser *parser, tree list) build_int_cst (TREE_TYPE (t), 0)); if (c == boolean_true_node) { - warning (0, "% value must be positive"); + warning (0, "%H% value must be positive", &expr_loc); t = integer_one_node; } @@ -7028,7 +7130,7 @@ 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 @@ -7072,19 +7174,26 @@ 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; c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_COMMA)) { + location_t here; c_parser_consume_token (parser); + here = c_parser_peek_token (parser)->location; t = c_parser_expr_no_commas (parser, NULL).value; if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME) - error ("schedule % does not take " - "a % parameter"); + error ("%Hschedule % does not take " + "a % parameter", &here); + else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO) + error ("%Hschedule % does not take " + "a % parameter", &here); else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE) OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; else @@ -7115,6 +7224,22 @@ 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 (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. */ @@ -7124,15 +7249,28 @@ c_parser_omp_all_clauses (c_parser *parser, unsigned int mask, const char *where) { tree clauses = NULL; + bool first = true; while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) { - const pragma_omp_clause c_kind = c_parser_omp_clause_name (parser); + location_t here; + pragma_omp_clause c_kind; const char *c_name; tree prev = clauses; + if (!first && c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + + first = false; + here = c_parser_peek_token (parser)->location; + c_kind = c_parser_omp_clause_name (parser); + switch (c_kind) { + case PRAGMA_OMP_CLAUSE_COLLAPSE: + clauses = c_parser_omp_clause_collapse (parser, clauses); + c_name = "collapse"; + break; case PRAGMA_OMP_CLAUSE_COPYIN: clauses = c_parser_omp_clause_copyin (parser, clauses); c_name = "copyin"; @@ -7185,6 +7323,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; @@ -7195,7 +7337,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 ("%qs is not valid for %qs", c_name, where); + error ("%H%qs is not valid for %qs", &here, c_name, where); } } @@ -7238,6 +7380,7 @@ c_parser_omp_atomic (c_parser *parser) tree lhs, rhs; tree stmt; enum tree_code code; + struct c_expr rhs_expr; c_parser_skip_to_pragma_eol (parser); @@ -7300,7 +7443,9 @@ c_parser_omp_atomic (c_parser *parser) } c_parser_consume_token (parser); - rhs = c_parser_expression (parser).value; + rhs_expr = c_parser_expression (parser); + rhs_expr = default_function_array_conversion (rhs_expr); + rhs = rhs_expr.value; break; } stmt = c_finish_omp_atomic (code, lhs, rhs); @@ -7364,7 +7509,7 @@ c_parser_omp_flush (c_parser *parser) { 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); @@ -7372,15 +7517,29 @@ c_parser_omp_flush (c_parser *parser) c_finish_omp_flush (); } -/* 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. */ static tree -c_parser_omp_for_loop (c_parser *parser) +c_parser_omp_for_loop (c_parser *parser, tree clauses, tree *par_clauses) { - tree decl, cond, incr, save_break, save_cont, body, init; + tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl; + tree declv, condv, incrv, initv, for_block = NULL, ret = NULL; location_t loc; + bool fail = false, open_brace_parsed = false; + int i, collapse = 1, nbraces = 0; + + 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)) { @@ -7390,59 +7549,136 @@ c_parser_omp_for_loop (c_parser *parser) 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; - 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; + + if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + goto pop_scopes; + + /* Parse the initialization declaration or expression. */ + if (c_parser_next_token_starts_declspecs (parser)) + { + if (i > 0) + for_block + = tree_cons (NULL, c_begin_compound_stmt (true), for_block); + c_parser_declaration_or_fndef (parser, true, true, true, true); + decl = check_for_loop_decls (); + if (decl == NULL) + goto error_init; + if (DECL_INITIAL (decl) == error_mark_node) + decl = error_mark_node; + init = decl; + } + else if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_EQ) + { + struct c_expr init_exp; - c_parser_require (parser, CPP_EQ, "expected %<=%>"); + decl = c_parser_postfix_expression (parser).value; - init = c_parser_expr_no_commas (parser, NULL).value; - init = build_modify_expr (decl, NOP_EXPR, init); - init = c_process_expr_stmt (init); + c_parser_require (parser, CPP_EQ, "expected %<=%>"); + init_exp = c_parser_expr_no_commas (parser, NULL); + init_exp = default_function_array_conversion (init_exp); + init = build_modify_expr (decl, NOP_EXPR, init_exp.value); + init = c_process_expr_stmt (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)) + { + 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 %<;%>"); - } - 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)) + incr = c_process_expr_stmt (c_parser_expression (parser).value); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); - /* 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 %<)%>"); + 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) + { + stmt = c_begin_compound_stmt (true); + c_parser_compound_statement_nostart (parser); + add_stmt (c_end_compound_stmt (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)); @@ -7450,17 +7686,82 @@ c_parser_omp_for_loop (c_parser *parser) c_break_label = save_break; c_cont_label = save_cont; - /* Only bother calling c_finish_omp_for if we havn'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; + 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) + { + stmt = c_begin_compound_stmt (true); + add_stmt (body); + c_parser_compound_statement_nostart (parser); + body = c_end_compound_stmt (stmt, true); + nbraces--; + } + goto pop_scopes; + } + } - 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; + /* Only bother calling c_finish_omp_for if we haven't already generated + an error from the initialization parsing. */ + 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 ("%Hiteration variable %qD should not be firstprivate", + &loc, OMP_CLAUSE_DECL (*c)); + *c = OMP_CLAUSE_CHAIN (*c); + } + else + { + /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES, + change it to shared (decl) in + OMP_PARALLEL_CLAUSES. */ + tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE); + OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c); + OMP_CLAUSE_CHAIN (l) = clauses; + clauses = l; + OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED); + } + } + } + OMP_FOR_CLAUSES (stmt) = clauses; + } + ret = stmt; + } +pop_scopes: + while (for_block) + { + stmt = c_end_compound_stmt (TREE_VALUE (for_block), true); + add_stmt (stmt); + for_block = TREE_CHAIN (for_block); + } + return ret; } /* OpenMP 2.5: @@ -7475,6 +7776,7 @@ 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 @@ -7486,9 +7788,7 @@ 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; + ret = c_parser_omp_for_loop (parser, clauses, NULL); block = c_end_compound_stmt (block, true); add_stmt (block); @@ -7583,7 +7883,8 @@ c_parser_omp_sections_scope (c_parser *parser) } else if (!error_suppress) { - error ("expected %<#pragma omp section%> or %<}%>"); + error ("%Hexpected %<#pragma omp section%> or %<}%>", + &loc); error_suppress = true; } @@ -7692,9 +7993,7 @@ c_parser_omp_parallel (c_parser *parser) 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; + c_parser_omp_for_loop (parser, ws_clause, &par_clause); stmt = c_finish_omp_parallel (par_clause, block); OMP_PARALLEL_COMBINED (stmt) = 1; break; @@ -7741,6 +8040,43 @@ c_parser_omp_single (c_parser *parser) return add_stmt (stmt); } +/* OpenMP 3.0: + # pragma omp task task-clause[optseq] new-line +*/ + +#define OMP_TASK_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_IF) \ + | (1u << PRAGMA_OMP_CLAUSE_UNTIED) \ + | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \ + | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_SHARED)) + +static tree +c_parser_omp_task (c_parser *parser) +{ + 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 (clauses, block); +} + +/* OpenMP 3.0: + # pragma omp taskwait new-line +*/ + +static void +c_parser_omp_taskwait (c_parser *parser) +{ + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); + + c_finish_omp_taskwait (); +} /* Main entry point to parsing most OpenMP pragmas. */ @@ -7787,6 +8123,9 @@ c_parser_omp_construct (c_parser *parser) case PRAGMA_OMP_SINGLE: stmt = c_parser_omp_single (parser); break; + case PRAGMA_OMP_TASK: + stmt = c_parser_omp_task (parser); + break; default: gcc_unreachable (); } @@ -7805,10 +8144,7 @@ c_parser_omp_threadprivate (c_parser *parser) tree vars, t; c_parser_consume_pragma (parser); - vars = c_parser_omp_var_list_parens (parser, 0, NULL); - - if (!targetm.have_tls) - sorry ("threadprivate variables not supported in this target"); + 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)) @@ -7817,10 +8153,14 @@ c_parser_omp_threadprivate (c_parser *parser) /* If V had already been marked threadprivate, it doesn't matter whether it had been used prior to this point. */ - if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v)) + if (TREE_CODE (v) != VAR_DECL) + error ("%qD is not a variable", v); + else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v)) error ("%qE declared % after first use", v); else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v)) error ("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); else