/* 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 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.
#include "cgraph.h"
\f
-/* 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
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;
}
}
\f
/* 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. */
/* 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. */
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)
{
{
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 %qs conflicts with C++ keyword",
+ IDENTIFIER_POINTER (token->value));
+ }
+ else if (c_dialect_objc ())
+ {
+ if (!objc_is_reserved_word (token->value)
&& (!OBJC_IS_PQ_KEYWORD (rid_code)
|| parser->objc_pq_context))
{
}
else
{
- /* Return the canonical spelling for this keyword. */
- token->value = ridpointers[(int) rid_code];
token->type = CPP_KEYWORD;
token->keyword = rid_code;
break;
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:
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,
if (token->type != CPP_EOF)
{
input_location = token->location;
- in_system_header = token->in_system_header;
}
}
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
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;
}
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. */
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);
{
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
{
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;
}
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:
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);
else
{
shadow_tag_warned (specs, 1);
- pedwarn ("empty declaration");
+ pedwarn (here, 0, "empty declaration");
}
c_parser_consume_token (parser);
return;
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. */
/* 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))
{
c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
"or %<__attribute__%>");
if (nested)
- pop_function_context ();
+ c_pop_function_context ();
break;
}
/* Parse old-style parameter declarations. ??? Attributes are
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
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))
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");
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;
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 (&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;
}
/* 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 %<enum%> types");
+ {
+ gcc_assert (ident);
+ pedwarn (ident_loc, OPT_pedantic,
+ "ISO C forbids forward references to %<enum%> types");
+ }
return ret;
}
}
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;
/* 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;
}
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 %<;%>");
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;
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;
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;
}
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);
}
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;
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 ("%<typeof%> applied to a bit-field");
+ error_at (here, "%<typeof%> applied to a bit-field");
ret.spec = TREE_TYPE (expr.value);
was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
/* This should be returned with the type so that when the type
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);
+ protected_set_expr_location (e, here);
add_stmt (e);
}
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))
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_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))
{
}
else if (c_parser_next_token_is (parser, CPP_WSTRING))
{
- error ("wide string literal in %<asm%>");
+ error_at (c_parser_peek_token (parser)->location,
+ "wide string literal in %<asm%>");
str = build_string (1, "");
c_parser_consume_token (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))
{
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)
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
{
{
/* 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);
}
/* 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))
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
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;
}
{
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,
{
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;
{
bool last_stmt = false;
bool last_label = false;
+ location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
{
c_parser_consume_token (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))
}
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))
|| (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);
{
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
/* 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
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_at (loc, """expected %<}%> before %<else%>");
+ return;
+ }
+ else
+ {
+ error_at (loc, "%<else%> without a previous %<if%>");
+ c_parser_consume_token (parser);
+ continue;
+ }
+ }
else
{
statement:
parser->error = false;
}
if (last_label)
- error ("label at end of compound statement");
+ error_at (label_loc, "label at end of compound statement");
c_parser_consume_token (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);
}
}
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_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);
+ }
+ }
}
/* Parse a statement (C90 6.6, C99 6.8).
{
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:
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))
goto expect_semicolon;
}
break;
- case RID_AT_TRY:
+ case RID_TRY:
gcc_assert (c_dialect_objc ());
c_parser_objc_try_catch_statement (parser);
break;
(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))
- SET_EXPR_LOCATION (stmt, loc);
+ protected_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
+ (loc, c_parser_expression_conv (parser).value);
+ protected_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.
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;
}
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 -Wempty-body 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)
c_parser_label (parser);
*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 ());
- c_parser_statement_after_labels (parser);
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ add_stmt (build_empty_stmt ());
+ c_parser_consume_token (parser);
+ if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
+ warning_at (loc, OPT_Wempty_body,
+ "suggest braces around empty body in an %<if%> statement");
+ }
+ 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))
+ {
+ warning_at (c_parser_peek_token (parser)->location,
+ OPT_Wempty_body,
+ "suggest braces around empty body in an %<else%> statement");
+ add_stmt (build_empty_stmt ());
+ c_parser_consume_token (parser);
+ }
+ else
+ c_parser_statement_after_labels (parser);
return c_end_compound_stmt (block, flag_isoc99);
}
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;
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,
- "suggest braces around empty body in %<do%> statement");
+ warning_at (c_parser_peek_token (parser)->location,
+ OPT_Wempty_body,
+ "suggest braces around empty body in %<do%> statement");
block = c_begin_compound_stmt (flag_isoc99);
loc = c_parser_peek_token (parser)->location;
save_break = c_break_label;
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);
}
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. */
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",
- 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);
}
{
struct c_expr lhs, rhs, ret;
enum tree_code code;
+ location_t op_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:
c_parser_consume_token (parser);
rhs = c_parser_expr_no_commas (parser, NULL);
rhs = default_function_array_conversion (rhs);
- ret.value = build_modify_expr (lhs.value, code, rhs.value);
+ ret.value = build_modify_expr (op_location, lhs.value, code, rhs.value);
if (code == NOP_EXPR)
ret.original_code = MODIFY_EXPR;
else
c_parser_conditional_expression (c_parser *parser, struct c_expr *after)
{
struct c_expr cond, exp1, exp2, ret;
+ location_t cond_loc;
+
gcc_assert (!after || c_dialect_objc ());
+
+ cond_loc = c_parser_peek_token (parser)->location;
cond = c_parser_binary_expression (parser, after);
+ protected_set_expr_location (cond.value, cond_loc);
+
if (c_parser_next_token_is_not (parser, CPP_QUERY))
return cond;
cond = default_function_array_conversion (cond);
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);
+ cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
skip_evaluation += cond.value == truthvalue_true_node;
}
else
{
cond.value
= c_objc_common_truthvalue_conversion
- (default_conversion (cond.value));
+ (cond_loc, default_conversion (cond.value));
skip_evaluation += cond.value == truthvalue_false_node;
exp1 = c_parser_expression_conv (parser);
skip_evaluation += ((cond.value == truthvalue_true_node)
enum tree_code op;
} 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) \
= default_function_array_conversion (stack[sp - 1].expr); \
stack[sp].expr \
= default_function_array_conversion (stack[sp].expr); \
- stack[sp - 1].expr = parser_build_binary_op (stack[sp].op, \
+ stack[sp - 1].expr = parser_build_binary_op (binary_loc, \
+ stack[sp].op, \
stack[sp - 1].expr, \
stack[sp].expr); \
sp--; \
expression. */
goto out;
}
+ binary_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
while (oprec <= stack[sp].prec)
POP;
stack[sp].expr
= default_function_array_conversion (stack[sp].expr);
stack[sp].expr.value = c_objc_common_truthvalue_conversion
- (default_conversion (stack[sp].expr.value));
+ (binary_loc, default_conversion (stack[sp].expr.value));
skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
break;
case TRUTH_ORIF_EXPR:
stack[sp].expr
= default_function_array_conversion (stack[sp].expr);
stack[sp].expr.value = c_objc_common_truthvalue_conversion
- (default_conversion (stack[sp].expr.value));
+ (binary_loc, default_conversion (stack[sp].expr.value));
skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
break;
default:
{
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 (loc, op.value, "unary *");
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");
+ warning_at (c_parser_peek_token (parser)->location,
+ OPT_Wtraditional,
+ "traditional C rejects the unary plus operator");
+ 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
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);
}
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++;
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)
&& type_name->declarator->u.array.vla_unspec_p)
{
/* C99 6.7.5.2p4 */
- error ("%<[*]%> not allowed in other than a declaration");
+ error_at (expr_loc,
+ "%<[*]%> not allowed in other than a declaration");
}
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 ("%<sizeof%> applied to a bit-field");
+ error_at (expr_loc, "%<sizeof%> applied to a bit-field");
return c_expr_sizeof_expr (expr);
}
}
{
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;
{
/* 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_at (here, "braced-group within expression allowed "
+ "only inside a function");
parser->error = true;
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
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;
}
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 (c_parser_peek_token (parser)->location,
+ c_parser_peek_token (parser)->keyword,
c_parser_peek_token (parser)->value);
expr.original_code = ERROR_MARK;
c_parser_consume_token (parser);
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);
}
}
}
expr.original_code = ERROR_MARK;
break;
}
+ loc = c_parser_peek_token (parser)->location;
e1 = c_parser_expr_no_commas (parser, NULL);
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
c = fold (e1.value);
if (TREE_CODE (c) != INTEGER_CST)
- error ("first argument to %<__builtin_choose_expr%> not"
- " a constant");
+ error_at (loc,
+ "first argument to %<__builtin_choose_expr%> not"
+ " a constant");
expr = integer_zerop (c) ? e3 : e2;
}
break;
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_at (start_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 ("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);
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:
"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. */
return expr;
}
c_parser_consume_token (parser);
- expr.value = build_component_ref (build_indirect_ref (expr.value,
- "->"), ident);
+ expr.value = build_component_ref (build_indirect_ref (loc,
+ expr.value,
+ "->"),
+ ident);
expr.original_code = ERROR_MARK;
break;
case CPP_PLUS_PLUS:
/* Postincrement. */
c_parser_consume_token (parser);
expr = default_function_array_conversion (expr);
- expr.value = build_unary_op (POSTINCREMENT_EXPR, expr.value, 0);
+ expr.value = build_unary_op (loc,
+ POSTINCREMENT_EXPR, expr.value, 0);
expr.original_code = ERROR_MARK;
break;
case CPP_MINUS_MINUS:
/* Postdecrement. */
c_parser_consume_token (parser);
expr = default_function_array_conversion (expr);
- expr.value = build_unary_op (POSTDECREMENT_EXPR, expr.value, 0);
+ expr.value = build_unary_op (loc,
+ POSTDECREMENT_EXPR, expr.value, 0);
expr.original_code = ERROR_MARK;
break;
default:
/* 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;
}
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);
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. */
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))
{
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:
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)
{
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);
}
{
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);
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_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;
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;
else if (!strcmp ("shared", p))
result = PRAGMA_OMP_CLAUSE_SHARED;
break;
+ case 'u':
+ if (!strcmp ("untied", p))
+ result = PRAGMA_OMP_CLAUSE_UNTIED;
+ break;
}
}
/* 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;
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 %<(%>"))
{
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 (OMP_CLAUSE_COLLAPSE);
+ OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
/* OpenMP 2.5:
copyin ( variable-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 %<)%>");
build_int_cst (TREE_TYPE (t), 0));
if (c == boolean_true_node)
{
- warning (0, "%<num_threads%> value must be positive");
+ warning_at (expr_loc, 0,
+ "%<num_threads%> value must be positive");
t = integer_one_node;
}
schedule ( schedule-kind , expression )
schedule-kind:
- static | dynamic | guided | runtime
+ static | dynamic | guided | runtime | auto
*/
static tree
}
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 %<runtime%> does not take "
- "a %<chunk_size%> parameter");
+ error_at (here, "schedule %<runtime%> does not take "
+ "a %<chunk_size%> parameter");
+ else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
+ error_at (here,
+ "schedule %<auto%> does not take "
+ "a %<chunk_size%> parameter");
else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
else
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. */
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";
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;
/* 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_at (here, "%qs is not valid for %qs", c_name, where);
}
}
tree lhs, rhs;
tree stmt;
enum tree_code code;
+ struct c_expr rhs_expr;
c_parser_skip_to_pragma_eol (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);
{
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 ();
}
-/* 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))
{
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;
- c_parser_require (parser, CPP_EQ, "expected %<=%>");
+ /* 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;
+ location_t init_loc;
+
+ decl = c_parser_postfix_expression (parser).value;
+
+ c_parser_require (parser, CPP_EQ, "expected %<=%>");
+ init_loc = c_parser_peek_token (parser)->location;
+
+ init_exp = c_parser_expr_no_commas (parser, NULL);
+ init_exp = default_function_array_conversion (init_exp);
+ init = build_modify_expr (init_loc,
+ decl, NOP_EXPR, init_exp.value);
+ init = c_process_expr_stmt (init);
+
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ }
+ 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;
+ }
- 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 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;
+ cond = c_parser_expression_conv (parser).value;
+ cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
+ 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 (c_parser_expression (parser).value);
+ protected_set_expr_location (incr, incr_loc);
+ }
+ 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));
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_at (loc,
+ "iteration variable %qD should not be firstprivate",
+ OMP_CLAUSE_DECL (*c));
+ *c = OMP_CLAUSE_CHAIN (*c);
+ }
+ else
+ {
+ /* Copy lastprivate (decl) clause to OMP_FOR_CLAUSES,
+ change it to shared (decl) in
+ OMP_PARALLEL_CLAUSES. */
+ tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE);
+ OMP_CLAUSE_DECL (l) = OMP_CLAUSE_DECL (*c);
+ OMP_CLAUSE_CHAIN (l) = clauses;
+ clauses = l;
+ OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
+ }
+ }
+ }
+ OMP_FOR_CLAUSES (stmt) = clauses;
+ }
+ 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:
| (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
"#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);
}
else if (!error_suppress)
{
- error ("expected %<#pragma omp section%> or %<}%>");
+ error_at (loc, "expected %<#pragma omp section%> or %<}%>");
error_suppress = true;
}
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;
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. */
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 ();
}
tree vars, t;
c_parser_consume_pragma (parser);
- vars = c_parser_omp_var_list_parens (parser, 0, NULL);
+ 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))
/* 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 %<threadprivate%> after first use", v);
else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v))
error ("automatic variable %qE cannot be %<threadprivate%>", v);
+ else if (TREE_TYPE (v) == error_mark_node)
+ ;
else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
error ("%<threadprivate%> %qE has incomplete type", v);
else