summaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r--gcc/c/c-parser.c1504
1 files changed, 928 insertions, 576 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index c9eb8ddbae..988369e419 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1,5 +1,5 @@
/* Parser for C and Objective-C.
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2017 Free Software Foundation, Inc.
Parser actions based on the old Bison parser; structure somewhat
influenced by and fragments based on the C++ parser.
@@ -52,12 +52,19 @@ along with GCC; see the file COPYING3. If not see
#include "c-lang.h"
#include "c-family/c-objc.h"
#include "plugin.h"
-#include "omp-low.h"
+#include "omp-general.h"
+#include "omp-offload.h"
#include "builtins.h"
#include "gomp-constants.h"
#include "c-family/c-indentation.h"
#include "gimple-expr.h"
#include "context.h"
+#include "gcc-rich-location.h"
+#include "c-parser.h"
+#include "gimple-parser.h"
+#include "read-rtl-function.h"
+#include "run-rtl-passes.h"
+#include "intl.h"
/* We need to walk over decls with incomplete struct/union/enum types
after parsing the whole translation unit.
@@ -66,7 +73,7 @@ along with GCC; see the file COPYING3. If not see
In c_parser_translation_unit(), we iterate over incomplete_record_decls
and report error if any of the decls are still incomplete. */
-vec<tree> incomplete_record_decls = vNULL;
+vec<tree> incomplete_record_decls;
void
set_c_expr_source_range (c_expr *expr,
@@ -149,61 +156,6 @@ c_parse_init (void)
}
}
-/* The C lexer intermediates between the lexer in cpplib and c-lex.c
- and the C parser. Unlike the C++ lexer, the parser structure
- stores the lexer information instead of using a separate structure.
- Identifiers are separated into ordinary identifiers, type names,
- keywords and some other Objective-C types of identifiers, and some
- look-ahead is maintained.
-
- ??? It might be a good idea to lex the whole file up front (as for
- C++). It would then be possible to share more of the C and C++
- lexer code, if desired. */
-
-/* More information about the type of a CPP_NAME token. */
-enum c_id_kind {
- /* An ordinary identifier. */
- C_ID_ID,
- /* An identifier declared as a typedef name. */
- C_ID_TYPENAME,
- /* An identifier declared as an Objective-C class name. */
- C_ID_CLASSNAME,
- /* An address space identifier. */
- C_ID_ADDRSPACE,
- /* Not an identifier. */
- C_ID_NONE
-};
-
-/* A single C token after string literal concatenation and conversion
- of preprocessing tokens to tokens. */
-struct GTY (()) c_token {
- /* The kind of token. */
- ENUM_BITFIELD (cpp_ttype) type : 8;
- /* If this token is a CPP_NAME, this value indicates whether also
- declared as some kind of type. Otherwise, it is C_ID_NONE. */
- ENUM_BITFIELD (c_id_kind) id_kind : 8;
- /* If this token is a keyword, this value indicates which keyword.
- Otherwise, this value is RID_MAX. */
- ENUM_BITFIELD (rid) keyword : 8;
- /* If this token is a CPP_PRAGMA, this indicates the pragma that
- was seen. Otherwise it is PRAGMA_NONE. */
- ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
- /* The location at which this token was found. */
- location_t location;
- /* The value associated with this token, if any. */
- tree value;
-
- source_range get_range () const
- {
- return get_range_from_loc (line_table, location);
- }
-
- location_t get_finish () const
- {
- return get_range ().m_finish;
- }
-};
-
/* A parser structure recording information about the state and
context of parsing. Includes lexer information with up to two
tokens of look-ahead; more are not needed for C. */
@@ -256,6 +208,30 @@ struct GTY(()) c_parser {
vec <c_token, va_gc> *cilk_simd_fn_tokens;
};
+/* Return a pointer to the Nth token in PARSERs tokens_buf. */
+
+c_token *
+c_parser_tokens_buf (c_parser *parser, unsigned n)
+{
+ return &parser->tokens_buf[n];
+}
+
+/* Return the error state of PARSER. */
+
+bool
+c_parser_error (c_parser *parser)
+{
+ return parser->error;
+}
+
+/* Set the error state of PARSER to ERR. */
+
+void
+c_parser_set_error (c_parser *parser, bool err)
+{
+ parser->error = err;
+}
+
/* The actual parser and external interface. ??? Does this need to be
garbage-collected? */
@@ -269,7 +245,8 @@ 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,
+ &token->flags,
(parser->lex_untranslated_string
? C_LEX_STRING_NO_TRANSLATE : 0));
token->id_kind = C_ID_NONE;
@@ -300,6 +277,9 @@ c_lex_one_token (c_parser *parser, c_token *token)
else if (rid_code >= RID_FIRST_ADDR_SPACE
&& rid_code <= RID_LAST_ADDR_SPACE)
{
+ addr_space_t as;
+ as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE);
+ targetm.addr_space.diagnose_usage (as, token->location);
token->id_kind = C_ID_ADDRSPACE;
token->keyword = rid_code;
break;
@@ -447,7 +427,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
/* Return a pointer to the next token from PARSER, reading it in if
necessary. */
-static inline c_token *
+c_token *
c_parser_peek_token (c_parser *parser)
{
if (parser->tokens_avail == 0)
@@ -458,37 +438,10 @@ c_parser_peek_token (c_parser *parser)
return &parser->tokens[0];
}
-/* Return true if the next token from PARSER has the indicated
- TYPE. */
-
-static inline bool
-c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
-{
- return c_parser_peek_token (parser)->type == type;
-}
-
-/* Return true if the next token from PARSER does not have the
- indicated TYPE. */
-
-static inline bool
-c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
-{
- return !c_parser_next_token_is (parser, type);
-}
-
-/* Return true if the next token from PARSER is the indicated
- KEYWORD. */
-
-static inline bool
-c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
-{
- return c_parser_peek_token (parser)->keyword == keyword;
-}
-
/* Return a pointer to the next-but-one token from PARSER, reading it
in if necessary. The next token is already read in. */
-static c_token *
+c_token *
c_parser_peek_2nd_token (c_parser *parser)
{
if (parser->tokens_avail >= 2)
@@ -504,7 +457,7 @@ c_parser_peek_2nd_token (c_parser *parser)
/* Return a pointer to the Nth token from PARSER, reading it
in if necessary. The N-1th token is already read in. */
-static c_token *
+c_token *
c_parser_peek_nth_token (c_parser *parser, unsigned int n)
{
/* N is 1-based, not zero-based. */
@@ -518,9 +471,52 @@ c_parser_peek_nth_token (c_parser *parser, unsigned int n)
return &parser->tokens[n - 1];
}
+bool
+c_keyword_starts_typename (enum rid keyword)
+{
+ switch (keyword)
+ {
+ case RID_UNSIGNED:
+ case RID_LONG:
+ case RID_SHORT:
+ case RID_SIGNED:
+ case RID_COMPLEX:
+ case RID_INT:
+ case RID_CHAR:
+ case RID_FLOAT:
+ case RID_DOUBLE:
+ case RID_VOID:
+ case RID_DFLOAT32:
+ case RID_DFLOAT64:
+ case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
+ case RID_BOOL:
+ case RID_ENUM:
+ case RID_STRUCT:
+ case RID_UNION:
+ case RID_TYPEOF:
+ case RID_CONST:
+ case RID_ATOMIC:
+ case RID_VOLATILE:
+ case RID_RESTRICT:
+ case RID_ATTRIBUTE:
+ case RID_FRACT:
+ case RID_ACCUM:
+ case RID_SAT:
+ case RID_AUTO_TYPE:
+ return true;
+ default:
+ if (keyword >= RID_FIRST_INT_N
+ && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+ && int_n_enabled_p[keyword - RID_FIRST_INT_N])
+ return true;
+ return false;
+ }
+}
+
/* Return true if TOKEN can start a type name,
false otherwise. */
-static bool
+bool
c_token_starts_typename (c_token *token)
{
switch (token->type)
@@ -541,43 +537,7 @@ c_token_starts_typename (c_token *token)
gcc_unreachable ();
}
case CPP_KEYWORD:
- switch (token->keyword)
- {
- case RID_UNSIGNED:
- case RID_LONG:
- case RID_SHORT:
- case RID_SIGNED:
- case RID_COMPLEX:
- case RID_INT:
- case RID_CHAR:
- case RID_FLOAT:
- case RID_DOUBLE:
- case RID_VOID:
- case RID_DFLOAT32:
- case RID_DFLOAT64:
- case RID_DFLOAT128:
- case RID_BOOL:
- case RID_ENUM:
- case RID_STRUCT:
- case RID_UNION:
- case RID_TYPEOF:
- case RID_CONST:
- case RID_ATOMIC:
- case RID_VOLATILE:
- case RID_RESTRICT:
- case RID_ATTRIBUTE:
- case RID_FRACT:
- case RID_ACCUM:
- case RID_SAT:
- case RID_AUTO_TYPE:
- return true;
- default:
- if (token->keyword >= RID_FIRST_INT_N
- && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
- && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
- return true;
- return false;
- }
+ return c_keyword_starts_typename (token->keyword);
case CPP_LESS:
if (c_dialect_objc ())
return true;
@@ -587,18 +547,6 @@ c_token_starts_typename (c_token *token)
}
}
-enum c_lookahead_kind {
- /* Always treat unknown identifiers as typenames. */
- cla_prefer_type,
-
- /* Could be parsing a nonabstract declarator. Only treat an identifier
- as a typename if followed by another identifier or a star. */
- cla_nonabstract_decl,
-
- /* Never treat identifiers as typenames. */
- cla_prefer_id
-};
-
/* Return true if the next token from PARSER can start a type name,
false otherwise. LA specifies how to do lookahead in order to
detect unknown type names. If unsure, pick CLA_PREFER_ID. */
@@ -717,6 +665,7 @@ c_token_starts_declspecs (c_token *token)
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_ENUM:
case RID_STRUCT:
@@ -764,7 +713,7 @@ c_token_starts_declaration (c_token *token)
/* Return true if the next token from PARSER can start declaration
specifiers, false otherwise. */
-static inline bool
+bool
c_parser_next_token_starts_declspecs (c_parser *parser)
{
c_token *token = c_parser_peek_token (parser);
@@ -786,7 +735,7 @@ c_parser_next_token_starts_declspecs (c_parser *parser)
/* Return true if the next tokens from PARSER can start declaration
specifiers or a static assertion, false otherwise. */
-static inline bool
+bool
c_parser_next_tokens_start_declaration (c_parser *parser)
{
c_token *token = c_parser_peek_token (parser);
@@ -814,7 +763,7 @@ c_parser_next_tokens_start_declaration (c_parser *parser)
/* Consume the next token from PARSER. */
-static void
+void
c_parser_consume_token (c_parser *parser)
{
gcc_assert (parser->tokens_avail >= 1);
@@ -907,7 +856,7 @@ c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
this way is not i18n-friendly and some other approach should be
used. */
-static void
+void
c_parser_error (c_parser *parser, const char *gmsgid)
{
c_token *token = c_parser_peek_token (parser);
@@ -950,7 +899,7 @@ c_parser_error (c_parser *parser, const char *gmsgid)
been produced and no message will be produced this time. Returns
true if found, false otherwise. */
-static bool
+bool
c_parser_require (c_parser *parser,
enum cpp_ttype type,
const char *msgid)
@@ -993,7 +942,7 @@ c_parser_require_keyword (c_parser *parser,
already been produced and no message will be produced this
time. */
-static void
+void
c_parser_skip_until_found (c_parser *parser,
enum cpp_ttype type,
const char *msgid)
@@ -1228,58 +1177,27 @@ restore_extension_diagnostics (int flags)
warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
}
-/* Possibly kinds of declarator to parse. */
-enum c_dtr_syn {
- /* A normal declarator with an identifier. */
- C_DTR_NORMAL,
- /* An abstract declarator (maybe empty). */
- C_DTR_ABSTRACT,
- /* A parameter declarator: may be either, but after a type name does
- not redeclare a typedef name as an identifier if it can
- alternatively be interpreted as a typedef name; see DR#009,
- applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
- following DR#249. For example, given a typedef T, "int T" and
- "int *T" are valid parameter declarations redeclaring T, while
- "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
- abstract declarators rather than involving redundant parentheses;
- the same applies with attributes inside the parentheses before
- "T". */
- C_DTR_PARM
-};
-
-/* The binary operation precedence levels, where 0 is a dummy lowest level
- used for the bottom of the stack. */
-enum c_parser_prec {
- PREC_NONE,
- PREC_LOGOR,
- PREC_LOGAND,
- PREC_BITOR,
- PREC_BITXOR,
- PREC_BITAND,
- PREC_EQ,
- PREC_REL,
- PREC_SHIFT,
- PREC_ADD,
- PREC_MULT,
- NUM_PRECS
+/* Helper data structure for parsing #pragma acc routine. */
+struct oacc_routine_data {
+ bool error_seen; /* Set if error has been reported. */
+ bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
+ tree clauses;
+ location_t loc;
};
static void c_parser_external_declaration (c_parser *);
static void c_parser_asm_definition (c_parser *);
static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
bool, bool, tree *, vec<c_token>,
- tree = NULL_TREE);
+ struct oacc_routine_data * = NULL,
+ bool * = NULL);
static void c_parser_static_assert_declaration_no_semi (c_parser *);
static void c_parser_static_assert_declaration (c_parser *);
-static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
- bool, bool, bool, enum c_lookahead_kind);
static struct c_typespec c_parser_enum_specifier (c_parser *);
static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
static tree c_parser_struct_declaration (c_parser *);
static struct c_typespec c_parser_typeof_specifier (c_parser *);
static tree c_parser_alignas_specifier (c_parser *);
-static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
- bool *);
static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
c_dtr_syn, bool *);
static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
@@ -1291,7 +1209,6 @@ static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
static struct c_parm *c_parser_parameter_declaration (c_parser *, tree);
static tree c_parser_simple_asm_expr (c_parser *);
static tree c_parser_attributes (c_parser *);
-static struct c_type_name *c_parser_type_name (c_parser *);
static struct c_expr c_parser_initializer (c_parser *);
static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
struct obstack *);
@@ -1305,7 +1222,7 @@ static void c_parser_statement (c_parser *, bool *);
static void c_parser_statement_after_labels (c_parser *, bool *,
vec<tree> * = NULL);
static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
-static void c_parser_switch_statement (c_parser *);
+static void c_parser_switch_statement (c_parser *, bool *);
static void c_parser_while_statement (c_parser *, bool, bool *);
static void c_parser_do_statement (c_parser *, bool);
static void c_parser_for_statement (c_parser *, bool, bool *);
@@ -1351,16 +1268,16 @@ static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
static void c_parser_omp_taskwait (c_parser *);
static void c_parser_omp_taskyield (c_parser *);
static void c_parser_omp_cancel (c_parser *);
-static void c_parser_omp_cancellation_point (c_parser *);
enum pragma_context { pragma_external, pragma_struct, pragma_param,
pragma_stmt, pragma_compound };
static bool c_parser_pragma (c_parser *, enum pragma_context, bool *);
+static void c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
static void c_parser_omp_end_declare_target (c_parser *);
static void c_parser_omp_declare (c_parser *, enum pragma_context);
static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
-static void c_parser_oacc_routine (c_parser *parser, enum pragma_context);
+static void c_parser_oacc_routine (c_parser *, enum pragma_context);
/* These Objective-C parser functions are only ever called when
compiling Objective-C. */
@@ -1397,7 +1314,9 @@ static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
static void c_parser_cilk_grainsize (c_parser *, bool *);
-/* Parse a translation unit (C90 6.7, C99 6.9).
+static void c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass);
+
+/* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9).
translation-unit:
external-declarations
@@ -1440,7 +1359,7 @@ c_parser_translation_unit (c_parser *parser)
error ("storage size of %q+D isn%'t known", decl);
}
-/* Parse an external declaration (C90 6.7, C99 6.9).
+/* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9).
external-declaration:
function-definition
@@ -1539,6 +1458,7 @@ c_parser_external_declaration (c_parser *parser)
}
/* Else fall through, and yield a syntax error trying to parse
as a declaration or function definition. */
+ /* FALLTHRU */
default:
decl_or_fndef:
/* A declaration or a function definition (or, in Objective-C,
@@ -1552,11 +1472,11 @@ c_parser_external_declaration (c_parser *parser)
}
static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token>);
-static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
+static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
- 6.7, 6.9.1). If FNDEF_OK is true, a function definition is
- accepted; otherwise (old-style parameter declarations) only other
+ 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition
+ is accepted; otherwise (old-style parameter declarations) only other
declarations are accepted. If STATIC_ASSERT_OK is true, a static
assertion is accepted; otherwise (old-style parameter declarations)
it is not. If NESTED is true, we are inside a function or parsing
@@ -1570,6 +1490,8 @@ static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
attributes; otherwise they may not.
OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
declaration when parsing an Objective-C foreach statement.
+ FALLTHRU_ATTR_P is used to signal whether this function parsed
+ "__attribute__((fallthrough));".
declaration:
declaration-specifiers init-declarator-list[opt] ;
@@ -1597,6 +1519,8 @@ static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
declaration-specifiers declarator declaration-list[opt]
compound-statement
+ attribute ;
+
Objective-C:
attributes objc-class-definition
attributes objc-category-definition
@@ -1623,7 +1547,17 @@ static void c_finish_oacc_routine (c_parser *, tree, tree, bool, bool, bool);
OpenMP:
declaration:
- threadprivate-directive */
+ threadprivate-directive
+
+ GIMPLE:
+
+ gimple-function-definition:
+ declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator
+ declaration-list[opt] compound-statement
+
+ rtl-function-definition:
+ declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator
+ declaration-list[opt] compound-statement */
static void
c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
@@ -1631,7 +1565,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
bool nested, bool start_attr_ok,
tree *objc_foreach_object_declaration,
vec<c_token> omp_declare_simd_clauses,
- tree oacc_routine_clauses)
+ struct oacc_routine_data *oacc_routine_data,
+ bool *fallthru_attr_p)
{
struct c_declspecs *specs;
tree prefix_attrs;
@@ -1655,15 +1590,50 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
&& (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
{
tree name = c_parser_peek_token (parser)->value;
- error_at (here, "unknown type name %qE", name);
- /* Give a hint to the user. This is not C++ with its implicit
- typedef. */
+
+ /* Issue a warning about NAME being an unknown type name, perhaps
+ with some kind of hint.
+ If the user forgot a "struct" etc, suggest inserting
+ it. Otherwise, attempt to look for misspellings. */
+ gcc_rich_location richloc (here);
if (tag_exists_p (RECORD_TYPE, name))
- inform (here, "use %<struct%> keyword to refer to the type");
+ {
+ /* This is not C++ with its implicit typedef. */
+ richloc.add_fixit_insert_before ("struct ");
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE;"
+ " use %<struct%> keyword to refer to the type",
+ name);
+ }
else if (tag_exists_p (UNION_TYPE, name))
- inform (here, "use %<union%> keyword to refer to the type");
+ {
+ richloc.add_fixit_insert_before ("union ");
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE;"
+ " use %<union%> keyword to refer to the type",
+ name);
+ }
else if (tag_exists_p (ENUMERAL_TYPE, name))
- inform (here, "use %<enum%> keyword to refer to the type");
+ {
+ richloc.add_fixit_insert_before ("enum ");
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE;"
+ " use %<enum%> keyword to refer to the type",
+ name);
+ }
+ else
+ {
+ const char *hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME);
+ if (hint)
+ {
+ richloc.add_fixit_replace (hint);
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE; did you mean %qs?",
+ name, hint);
+ }
+ else
+ error_at (here, "unknown type name %qE", name);
+ }
/* Parse declspecs normally to get a correct pointer type, but avoid
a further "fails to be a type name" error. Refuse nested functions
@@ -1687,12 +1657,22 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
+
finish_declspecs (specs);
bool auto_type_p = specs->typespec_word == cts_auto_type;
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{
if (auto_type_p)
error_at (here, "%<__auto_type%> in empty declaration");
+ else if (specs->typespec_kind == ctsk_none
+ && attribute_fallthrough_p (specs->attrs))
+ {
+ if (fallthru_attr_p != NULL)
+ *fallthru_attr_p = true;
+ tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
+ void_type_node, 0);
+ add_stmt (fn);
+ }
else if (empty_ok)
shadow_tag (specs);
else
@@ -1701,9 +1681,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
pedwarn (here, 0, "empty declaration");
}
c_parser_consume_token (parser);
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, NULL_TREE,
- oacc_routine_clauses, false, true, false);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
return;
}
@@ -1796,17 +1775,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
break;
}
}
-
+ else if (attribute_fallthrough_p (specs->attrs))
+ warning_at (here, OPT_Wattributes,
+ "%<fallthrough%> attribute not followed by %<;%>");
+
pending_xref_error ();
prefix_attrs = specs->attrs;
all_prefix_attrs = prefix_attrs;
specs->attrs = NULL_TREE;
- for (bool first = true;; first = false)
+ while (true)
{
struct c_declarator *declarator;
bool dummy = false;
timevar_id_t tv;
- tree fnbody;
+ tree fnbody = NULL_TREE;
/* Declaring either one or more declarators (in which case we
should diagnose if there were no declaration specifiers) or a
function definition (in which case the diagnostic for
@@ -1820,10 +1802,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
omp_declare_simd_clauses);
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, NULL_TREE,
- oacc_routine_clauses,
- false, first, false);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
c_parser_skip_to_end_of_block_or_statement (parser);
return;
}
@@ -1876,9 +1856,16 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
c_parser_consume_token (parser);
if (auto_type_p)
{
- start_init (NULL_TREE, asm_name, global_bindings_p ());
init_loc = c_parser_peek_token (parser)->location;
+ rich_location richloc (line_table, init_loc);
+ start_init (NULL_TREE, asm_name, global_bindings_p (), &richloc);
+ /* A parameter is initialized, which is invalid. Don't
+ attempt to instrument the initializer. */
+ int flag_sanitize_save = flag_sanitize;
+ if (nested && !empty_ok)
+ flag_sanitize = 0;
init = c_parser_expr_no_commas (parser, NULL);
+ flag_sanitize = flag_sanitize_save;
if (TREE_CODE (init.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
error_at (here,
@@ -1933,14 +1920,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, d, NULL_TREE,
omp_declare_simd_clauses);
- start_init (d, asm_name, global_bindings_p ());
init_loc = c_parser_peek_token (parser)->location;
+ rich_location richloc (line_table, init_loc);
+ start_init (d, asm_name, global_bindings_p (), &richloc);
+ /* A parameter is initialized, which is invalid. Don't
+ attempt to instrument the initializer. */
+ int flag_sanitize_save = flag_sanitize;
+ if (TREE_CODE (d) == PARM_DECL)
+ flag_sanitize = 0;
init = c_parser_initializer (parser);
+ flag_sanitize = flag_sanitize_save;
finish_init ();
}
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, d, oacc_routine_clauses,
- false, first, false);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, d, false);
if (d != error_mark_node)
{
maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
@@ -1984,9 +1977,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
if (parms)
temp_pop_parm_decls ();
}
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, d, oacc_routine_clauses,
- false, first, false);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, d, false);
if (d)
finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
NULL_TREE, asm_name);
@@ -2074,7 +2066,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
tv = TV_PARSE_INLINE;
else
tv = TV_PARSE_FUNC;
- timevar_push (tv);
+ auto_timevar at (g_timer, tv);
/* Parse old-style parameter declarations. ??? Attributes are
not allowed to start declaration specifiers here because of a
@@ -2097,14 +2089,44 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
|| !vec_safe_is_empty (parser->cilk_simd_fn_tokens))
c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
omp_declare_simd_clauses);
- if (oacc_routine_clauses)
- c_finish_oacc_routine (parser, current_function_decl,
- oacc_routine_clauses, false, first, true);
+ if (oacc_routine_data)
+ c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
= c_parser_peek_token (parser)->location;
- fnbody = c_parser_compound_statement (parser);
- if (flag_cilkplus && contains_array_notation_expr (fnbody))
- fnbody = expand_array_notation_exprs (fnbody);
+
+ /* If the definition was marked with __GIMPLE then parse the
+ function body as GIMPLE. */
+ if (specs->gimple_p)
+ {
+ cfun->pass_startwith = specs->gimple_or_rtl_pass;
+ bool saved = in_late_binary_op;
+ in_late_binary_op = true;
+ c_parser_parse_gimple_body (parser);
+ in_late_binary_op = saved;
+ }
+ /* Similarly, if it was marked with __RTL, use the RTL parser now,
+ consuming the function body. */
+ else if (specs->rtl_p)
+ {
+ c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
+
+ /* Normally, store_parm_decls sets next_is_function_body,
+ anticipating a function body. We need a push_scope/pop_scope
+ pair to flush out this state, or subsequent function parsing
+ will go wrong. */
+ push_scope ();
+ pop_scope ();
+
+ finish_function ();
+ return;
+ }
+ else
+ {
+ fnbody = c_parser_compound_statement (parser);
+ if (flag_cilkplus && contains_array_notation_expr (fnbody))
+ fnbody = expand_array_notation_exprs (fnbody);
+ }
+ tree fndecl = current_function_decl;
if (nested)
{
tree decl = current_function_decl;
@@ -2120,11 +2142,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
}
else
{
- add_stmt (fnbody);
+ if (fnbody)
+ add_stmt (fnbody);
finish_function ();
}
+ /* Get rid of the empty stmt list for GIMPLE. */
+ if (specs->gimple_p)
+ DECL_SAVED_TREE (fndecl) = NULL_TREE;
- timevar_pop (tv);
break;
}
}
@@ -2237,7 +2262,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
}
/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
- 6.7), adding them to SPECS (which may already include some).
+ 6.7, C11 6.7), adding them to SPECS (which may already include some).
Storage class specifiers are accepted iff SCSPEC_OK; type
specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
accepted iff ALIGNSPEC_OK; attributes are accepted at the start
@@ -2254,7 +2279,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
handled as storage class specifiers, as is __thread. Alignment
specifiers are from C11.
- C90 6.5.1, C99 6.7.1:
+ C90 6.5.1, C99 6.7.1, C11 6.7.1:
storage-class-specifier:
typedef
extern
@@ -2265,14 +2290,14 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
(_Thread_local is new in C11.)
- C99 6.7.4:
+ C99 6.7.4, C11 6.7.4:
function-specifier:
inline
_Noreturn
(_Noreturn is new in C11.)
- C90 6.5.2, C99 6.7.2:
+ C90 6.5.2, C99 6.7.2, C11 6.7.2:
type-specifier:
void
char
@@ -2294,7 +2319,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
(_Bool and _Complex are new in C99.)
(atomic-type-specifier is new in C11.)
- C90 6.5.3, C99 6.7.3:
+ C90 6.5.3, C99 6.7.3, C11 6.7.3:
type-qualifier:
const
@@ -2345,7 +2370,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
objc-protocol-refs
*/
-static void
+void
c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
bool scspec_ok, bool typespec_ok, bool start_attr_ok,
bool alignspec_ok, bool auto_type_ok,
@@ -2488,6 +2513,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_FRACT:
case RID_ACCUM:
@@ -2549,10 +2575,6 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
and objc_types_are_equivalent may also need updates. */
if (c_dialect_objc ())
sorry ("%<_Atomic%> in Objective-C");
- /* C parser handling of OpenMP constructs needs checking for
- correct lvalue-to-rvalue conversions. */
- if (flag_openmp)
- sorry ("%<_Atomic%> with OpenMP");
if (flag_isoc99)
pedwarn_c99 (loc, OPT_Wpedantic,
"ISO C99 does not support the %<_Atomic%> qualifier");
@@ -2613,6 +2635,20 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
align = c_parser_alignas_specifier (parser);
declspecs_add_alignas (loc, specs, align);
break;
+ case RID_GIMPLE:
+ if (! flag_gimple)
+ error_at (loc, "%<__GIMPLE%> only valid with -fgimple");
+ c_parser_consume_token (parser);
+ specs->gimple_p = true;
+ specs->locations[cdw_gimple] = loc;
+ specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser);
+ break;
+ case RID_RTL:
+ c_parser_consume_token (parser);
+ specs->rtl_p = true;
+ specs->locations[cdw_rtl] = loc;
+ specs->gimple_or_rtl_pass = c_parser_gimple_or_rtl_pass_list (parser);
+ break;
default:
goto out;
}
@@ -2620,7 +2656,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
out: ;
}
-/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2).
+/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2).
enum-specifier:
enum attributes[opt] identifier[opt] { enumerator-list } attributes[opt]
@@ -2658,7 +2694,6 @@ c_parser_enum_specifier (c_parser *parser)
location_t enum_loc;
location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
- enum_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
attrs = c_parser_attributes (parser);
enum_loc = c_parser_peek_token (parser)->location;
@@ -2784,7 +2819,7 @@ c_parser_enum_specifier (c_parser *parser)
return ret;
}
-/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1).
+/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1).
struct-or-union-specifier:
struct-or-union attributes[opt] identifier[opt]
@@ -2979,8 +3014,8 @@ c_parser_struct_or_union_specifier (c_parser *parser)
return ret;
}
-/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1), *without*
- the trailing semicolon.
+/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1),
+ *without* the trailing semicolon.
struct-declaration:
specifier-qualifier-list struct-declarator-list
@@ -3265,13 +3300,13 @@ c_parser_alignas_specifier (c_parser * parser)
}
/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
- 6.5.5, C99 6.7.5, 6.7.6). If TYPE_SEEN_P then a typedef name may
- be redeclared; otherwise it may not. KIND indicates which kind of
- declarator is wanted. Returns a valid declarator except in the
- case of a syntax error in which case NULL is returned. *SEEN_ID is
- set to true if an identifier being declared is seen; this is used
- to diagnose bad forms of abstract array declarators and to
- determine whether an identifier list is syntactically permitted.
+ 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then
+ a typedef name may be redeclared; otherwise it may not. KIND
+ indicates which kind of declarator is wanted. Returns a valid
+ declarator except in the case of a syntax error in which case NULL is
+ returned. *SEEN_ID is set to true if an identifier being declared is
+ seen; this is used to diagnose bad forms of abstract array declarators
+ and to determine whether an identifier list is syntactically permitted.
declarator:
pointer[opt] direct-declarator
@@ -3347,7 +3382,7 @@ c_parser_alignas_specifier (c_parser * parser)
This function also accepts an omitted abstract declarator as being
an abstract declarator, although not part of the formal syntax. */
-static struct c_declarator *
+struct c_declarator *
c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
bool *seen_id)
{
@@ -3430,6 +3465,7 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
&& c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
{
struct c_declarator *inner = build_id_declarator (NULL_TREE);
+ inner->id_loc = c_parser_peek_token (parser)->location;
return c_parser_direct_declarator_inner (parser, *seen_id, inner);
}
@@ -3631,7 +3667,8 @@ c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs)
&& c_parser_peek_2nd_token (parser)->type != CPP_NAME
&& c_parser_peek_2nd_token (parser)->type != CPP_MULT
&& c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
- && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE)
+ && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE
+ && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD)
{
tree list = NULL_TREE, *nextp = &list;
while (c_parser_next_token_is (parser, CPP_NAME)
@@ -3806,7 +3843,18 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
c_parser_set_source_position_from_token (token);
if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
{
- error_at (token->location, "unknown type name %qE", token->value);
+ const char *hint = lookup_name_fuzzy (token->value,
+ FUZZY_LOOKUP_TYPENAME);
+ if (hint)
+ {
+ gcc_rich_location richloc (token->location);
+ richloc.add_fixit_replace (hint);
+ error_at_rich_loc (&richloc,
+ "unknown type name %qE; did you mean %qs?",
+ token->value, hint);
+ }
+ else
+ error_at (token->location, "unknown type name %qE", token->value);
parser->error = true;
}
/* ??? In some Objective-C cases '...' isn't applicable so there
@@ -3948,6 +3996,7 @@ c_parser_attribute_any_word (c_parser *parser)
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_FRACT:
case RID_ACCUM:
@@ -4223,13 +4272,13 @@ c_parser_attributes (c_parser *parser)
return attrs;
}
-/* Parse a type name (C90 6.5.5, C99 6.7.6).
+/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7).
type-name:
specifier-qualifier-list abstract-declarator[opt]
*/
-static struct c_type_name *
+struct c_type_name *
c_parser_type_name (c_parser *parser)
{
struct c_declspecs *specs = build_null_declspecs ();
@@ -4259,7 +4308,7 @@ c_parser_type_name (c_parser *parser)
return ret;
}
-/* Parse an initializer (C90 6.5.7, C99 6.7.8).
+/* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9).
initializer:
assignment-expression
@@ -4319,6 +4368,11 @@ c_parser_initializer (c_parser *parser)
}
}
+/* The location of the last comma within the current initializer list,
+ or UNKNOWN_LOCATION if not within one. */
+
+location_t last_init_list_comma;
+
/* Parse a braced initializer list. TYPE is the type specified for a
compound literal, and NULL_TREE for other initializers and for
nested braced lists. NESTED_P is true for nested braced lists,
@@ -4356,7 +4410,10 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
if (parser->error)
break;
if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
+ {
+ last_init_list_comma = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ }
else
break;
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
@@ -4370,13 +4427,13 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
- pop_init_level (brace_loc, 0, &braced_init_obstack);
+ pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma);
obstack_free (&braced_init_obstack, NULL);
return ret;
}
location_t close_loc = next_tok->location;
c_parser_consume_token (parser);
- ret = pop_init_level (brace_loc, 0, &braced_init_obstack);
+ ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
obstack_free (&braced_init_obstack, NULL);
set_c_expr_source_range (&ret, brace_loc, close_loc);
return ret;
@@ -4396,6 +4453,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
/* Old-style structure member designator. */
set_init_label (c_parser_peek_token (parser)->location,
c_parser_peek_token (parser)->value,
+ c_parser_peek_token (parser)->location,
braced_init_obstack);
/* Use the colon as the error location. */
pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
@@ -4425,6 +4483,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
if (c_parser_next_token_is (parser, CPP_NAME))
{
set_init_label (des_loc, c_parser_peek_token (parser)->value,
+ c_parser_peek_token (parser)->location,
braced_init_obstack);
c_parser_consume_token (parser);
}
@@ -4611,7 +4670,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
}
/* Parse a compound statement (possibly a function body) (C90 6.6.2,
- C99 6.8.2).
+ C99 6.8.2, C11 6.8.2).
compound-statement:
{ block-item-list[opt] }
@@ -4778,12 +4837,14 @@ c_parser_compound_statement_nostart (c_parser *parser)
{
last_label = false;
mark_valid_location_for_stdc_pragma (false);
+ bool fallthru_attr_p = false;
c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, vNULL);
- if (last_stmt)
+ true, NULL, vNULL, NULL,
+ &fallthru_attr_p);
+ if (last_stmt && !fallthru_attr_p)
pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
"ISO C90 forbids mixed declarations and code");
- last_stmt = false;
+ last_stmt = fallthru_attr_p;
}
else if (!last_label
&& c_parser_next_token_is_keyword (parser, RID_EXTENSION))
@@ -4879,7 +4940,7 @@ c_parser_all_labels (c_parser *parser)
c_parser_label (parser);
}
-/* Parse a label (C90 6.6.1, C99 6.8.1).
+/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
label:
identifier : attributes[opt]
@@ -4900,6 +4961,11 @@ c_parser_label (c_parser *parser)
{
location_t loc1 = c_parser_peek_token (parser)->location;
tree label = NULL_TREE;
+
+ /* Remember whether this case or a user-defined label is allowed to fall
+ through to. */
+ bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
+
if (c_parser_next_token_is_keyword (parser, RID_CASE))
{
tree exp1, exp2;
@@ -4946,6 +5012,33 @@ c_parser_label (c_parser *parser)
}
if (label)
{
+ if (TREE_CODE (label) == LABEL_EXPR)
+ FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
+ else
+ FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
+
+ /* Allow '__attribute__((fallthrough));'. */
+ if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ tree attrs = c_parser_attributes (parser);
+ if (attribute_fallthrough_p (attrs))
+ {
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ tree fn = build_call_expr_internal_loc (loc,
+ IFN_FALLTHROUGH,
+ void_type_node, 0);
+ add_stmt (fn);
+ }
+ else
+ warning_at (loc, OPT_Wattributes, "%<fallthrough%> attribute "
+ "not followed by %<;%>");
+ }
+ else if (attrs != NULL_TREE)
+ warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>"
+ " can be applied to a null statement");
+ }
if (c_parser_next_tokens_start_declaration (parser))
{
error_at (c_parser_peek_token (parser)->location,
@@ -4960,7 +5053,7 @@ c_parser_label (c_parser *parser)
}
}
-/* Parse a statement (C90 6.6, C99 6.8).
+/* Parse a statement (C90 6.6, C99 6.8, C11 6.8).
statement:
labeled-statement
@@ -4999,6 +5092,9 @@ c_parser_label (c_parser *parser)
jump-statement:
goto * expression ;
+ expression-statement:
+ attributes ;
+
Objective-C:
statement:
@@ -5138,7 +5234,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_if_statement (parser, if_p, chain);
break;
case RID_SWITCH:
- c_parser_switch_statement (parser);
+ c_parser_switch_statement (parser, if_p);
break;
case RID_WHILE:
c_parser_while_statement (parser, false, if_p);
@@ -5260,6 +5356,31 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
gcc_assert (c_dialect_objc ());
c_parser_objc_synchronized_statement (parser);
break;
+ case RID_ATTRIBUTE:
+ {
+ /* Allow '__attribute__((fallthrough));'. */
+ tree attrs = c_parser_attributes (parser);
+ if (attribute_fallthrough_p (attrs))
+ {
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ tree fn = build_call_expr_internal_loc (loc,
+ IFN_FALLTHROUGH,
+ void_type_node, 0);
+ add_stmt (fn);
+ /* Eat the ';'. */
+ c_parser_consume_token (parser);
+ }
+ else
+ warning_at (loc, OPT_Wattributes,
+ "%<fallthrough%> attribute not followed "
+ "by %<;%>");
+ }
+ else if (attrs != NULL_TREE)
+ warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>"
+ " can be applied to a null statement");
+ break;
+ }
default:
goto expr_stmt;
}
@@ -5425,7 +5546,44 @@ c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
return c_end_compound_stmt (body_loc, block, flag_isoc99);
}
-/* Parse an if statement (C90 6.6.4, C99 6.8.4).
+/* We might need to reclassify any previously-lexed identifier, e.g.
+ when we've left a for loop with an if-statement without else in the
+ body - we might have used a wrong scope for the token. See PR67784. */
+
+static void
+c_parser_maybe_reclassify_token (c_parser *parser)
+{
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_token *token = c_parser_peek_token (parser);
+
+ if (token->id_kind != C_ID_CLASSNAME)
+ {
+ tree decl = lookup_name (token->value);
+
+ token->id_kind = C_ID_ID;
+ if (decl)
+ {
+ if (TREE_CODE (decl) == TYPE_DECL)
+ token->id_kind = C_ID_TYPENAME;
+ }
+ else if (c_dialect_objc ())
+ {
+ tree objc_interface_decl = objc_is_class_name (token->value);
+ /* Objective-C class names are in the same namespace as
+ variables and typedefs, and hence are shadowed by local
+ declarations. */
+ if (objc_interface_decl)
+ {
+ token->value = objc_interface_decl;
+ token->id_kind = C_ID_CLASSNAME;
+ }
+ }
+ }
+ }
+}
+
+/* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
if-statement:
if ( expression ) statement
@@ -5505,7 +5663,7 @@ c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
/* Diagnose an ambiguous else if if-then-else is nested inside
if-then. */
if (nested_if)
- warning_at (loc, OPT_Wparentheses,
+ warning_at (loc, OPT_Wdangling_else,
"suggest explicit braces to avoid ambiguous %<else%>");
if (warn_duplicated_cond)
@@ -5523,16 +5681,17 @@ c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
if (flag_cilkplus && contains_array_notation_expr (if_stmt))
if_stmt = fix_conditional_array_notations (if_stmt);
add_stmt (if_stmt);
+ c_parser_maybe_reclassify_token (parser);
}
-/* Parse a switch statement (C90 6.6.4, C99 6.8.4).
+/* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
switch-statement:
switch (expression) statement
*/
static void
-c_parser_switch_statement (c_parser *parser)
+c_parser_switch_statement (c_parser *parser, bool *if_p)
{
struct c_expr ce;
tree block, expr, body, save_break;
@@ -5563,11 +5722,12 @@ c_parser_switch_statement (c_parser *parser)
{
switch_cond_loc = UNKNOWN_LOCATION;
expr = error_mark_node;
+ ce.original_type = error_mark_node;
}
c_start_case (switch_loc, switch_cond_loc, expr, explicit_cast_p);
save_break = c_break_label;
c_break_label = NULL_TREE;
- body = c_parser_c99_block_statement (parser, NULL/*if??*/);
+ body = c_parser_c99_block_statement (parser, if_p);
c_finish_case (body, ce.original_type);
if (c_break_label)
{
@@ -5578,9 +5738,10 @@ c_parser_switch_statement (c_parser *parser)
}
c_break_label = save_break;
add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
+ c_parser_maybe_reclassify_token (parser);
}
-/* Parse a while statement (C90 6.6.5, C99 6.8.5).
+/* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
while-statement:
while (expression) statement
@@ -5620,6 +5781,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p)
body = c_parser_c99_block_statement (parser, if_p);
c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
+ c_parser_maybe_reclassify_token (parser);
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -5629,7 +5791,7 @@ c_parser_while_statement (c_parser *parser, bool ivdep, bool *if_p)
c_cont_label = save_cont;
}
-/* Parse a do statement (C90 6.6.5, C99 6.8.5).
+/* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
do-statement:
do statement while ( expression ) ;
@@ -5673,7 +5835,7 @@ c_parser_do_statement (c_parser *parser, bool ivdep)
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
-/* Parse a for statement (C90 6.6.5, C99 6.8.5).
+/* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
for-statement:
for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
@@ -5916,38 +6078,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, bool *if_p)
else
c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
-
- /* We might need to reclassify any previously-lexed identifier, e.g.
- when we've left a for loop with an if-statement without else in the
- body - we might have used a wrong scope for the token. See PR67784. */
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_token *token = c_parser_peek_token (parser);
-
- if (token->id_kind != C_ID_CLASSNAME)
- {
- tree decl = lookup_name (token->value);
-
- token->id_kind = C_ID_ID;
- if (decl)
- {
- if (TREE_CODE (decl) == TYPE_DECL)
- token->id_kind = C_ID_TYPENAME;
- }
- else if (c_dialect_objc ())
- {
- tree objc_interface_decl = objc_is_class_name (token->value);
- /* Objective-C class names are in the same namespace as
- variables and typedefs, and hence are shadowed by local
- declarations. */
- if (objc_interface_decl)
- {
- token->value = objc_interface_decl;
- token->id_kind = C_ID_CLASSNAME;
- }
- }
- }
- }
+ c_parser_maybe_reclassify_token (parser);
token_indent_info next_tinfo
= get_token_indent_info (c_parser_peek_token (parser));
@@ -6040,8 +6171,8 @@ c_parser_asm_statement (c_parser *parser)
{
if (!c_parser_require (parser, CPP_COLON,
is_goto
- ? "expected %<:%>"
- : "expected %<:%> or %<)%>"))
+ ? G_("expected %<:%>")
+ : G_("expected %<:%> or %<)%>")))
goto error_close_paren;
/* Once past any colon, we're no longer a simple asm. */
@@ -6230,9 +6361,9 @@ c_parser_asm_goto_operands (c_parser *parser)
}
/* Parse an expression other than a compound expression; that is, an
- assignment expression (C90 6.3.16, C99 6.5.16). If AFTER is not
- NULL then it is an Objective-C message expression which is the
- primary-expression starting the expression as an initializer.
+ assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If
+ AFTER is not NULL then it is an Objective-C message expression which
+ is the primary-expression starting the expression as an initializer.
assignment-expression:
conditional-expression
@@ -6313,8 +6444,8 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
return ret;
}
-/* Parse a conditional expression (C90 6.3.15, C99 6.5.15). If AFTER
- is not NULL then it is an Objective-C message expression which is
+/* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If
+ AFTER is not NULL then it is an Objective-C message expression which is
the primary-expression starting the expression as an initializer.
conditional-expression:
@@ -6352,14 +6483,17 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
tree eptype = NULL_TREE;
middle_loc = c_parser_peek_token (parser)->location;
- pedwarn (middle_loc, OPT_Wpedantic,
+ pedwarn (middle_loc, OPT_Wpedantic,
"ISO C forbids omitting the middle term of a ?: expression");
- warn_for_omitted_condop (middle_loc, cond.value);
if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
{
eptype = TREE_TYPE (cond.value);
cond.value = TREE_OPERAND (cond.value, 0);
}
+ tree e = cond.value;
+ while (TREE_CODE (e) == COMPOUND_EXPR)
+ e = TREE_OPERAND (e, 1);
+ warn_for_omitted_condop (middle_loc, e);
/* Make sure first operand is calculated only once. */
exp1.value = c_save_expr (default_conversion (cond.value));
if (eptype)
@@ -6424,9 +6558,9 @@ c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
}
/* Parse a binary expression; that is, a logical-OR-expression (C90
- 6.3.5-6.3.14, C99 6.5.5-6.5.14). If AFTER is not NULL then it is
- an Objective-C message expression which is the primary-expression
- starting the expression as an initializer.
+ 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not
+ NULL then it is an Objective-C message expression which is the
+ primary-expression starting the expression as an initializer.
OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
when it should be the unfolded lhs. In a valid OpenMP source,
@@ -6698,8 +6832,8 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
#undef POP
}
-/* Parse a cast expression (C90 6.3.4, C99 6.5.4). If AFTER is not
- NULL then it is an Objective-C message expression which is the
+/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
+ is not NULL then it is an Objective-C message expression which is the
primary-expression starting the expression as an initializer.
cast-expression:
@@ -6759,7 +6893,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
return c_parser_unary_expression (parser);
}
-/* Parse an unary expression (C90 6.3.3, C99 6.5.3).
+/* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
unary-expression:
postfix-expression
@@ -7079,9 +7213,10 @@ c_parser_alignof_expression (c_parser *parser)
mark_exp_read (expr.value);
c_inhibit_evaluation_warnings--;
in_alignof--;
- pedwarn (start_loc,
- OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
- alignof_spelling);
+ if (is_c11_alignof)
+ pedwarn (start_loc,
+ OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
+ alignof_spelling);
ret.value = c_alignof_expr (start_loc, expr.value);
ret.original_code = ERROR_MARK;
ret.original_type = NULL;
@@ -7176,7 +7311,6 @@ struct c_generic_association
static struct c_expr
c_parser_generic_selection (c_parser *parser)
{
- vec<c_generic_association> associations = vNULL;
struct c_expr selector, error_expr;
tree selector_type;
struct c_generic_association matched_assoc;
@@ -7233,6 +7367,7 @@ c_parser_generic_selection (c_parser *parser)
return error_expr;
}
+ auto_vec<c_generic_association> associations;
while (1)
{
struct c_generic_association assoc, *iter;
@@ -7253,13 +7388,13 @@ c_parser_generic_selection (c_parser *parser)
if (type_name == NULL)
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error_exit;
+ return error_expr;
}
assoc.type = groktypename (type_name, NULL, NULL);
if (assoc.type == error_mark_node)
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error_exit;
+ return error_expr;
}
if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
@@ -7278,14 +7413,14 @@ c_parser_generic_selection (c_parser *parser)
if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error_exit;
+ return error_expr;
}
assoc.expression = c_parser_expr_no_commas (parser, NULL);
if (assoc.expression.value == error_mark_node)
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error_exit;
+ return error_expr;
}
for (ix = 0; associations.iterate (ix, &iter); ++ix)
@@ -7328,7 +7463,7 @@ c_parser_generic_selection (c_parser *parser)
else
{
error_at (assoc.type_location,
- "%<_Generic> selector matches multiple associations");
+ "%<_Generic%> selector matches multiple associations");
inform (matched_assoc.type_location,
"other match is here");
}
@@ -7341,8 +7476,6 @@ c_parser_generic_selection (c_parser *parser)
c_parser_consume_token (parser);
}
- associations.release ();
-
if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
@@ -7358,13 +7491,10 @@ c_parser_generic_selection (c_parser *parser)
}
return matched_assoc.expression;
-
- error_exit:
- associations.release ();
- return error_expr;
}
-/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).
+/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
+ C11 6.5.1-6.5.2).
postfix-expression:
primary-expression
@@ -7452,6 +7582,9 @@ c_parser_postfix_expression (c_parser *parser)
case CPP_CHAR32:
case CPP_WCHAR:
expr.value = c_parser_peek_token (parser)->value;
+ /* For the purpose of warning when a pointer is compared with
+ a zero character constant. */
+ expr.original_type = char_type_node;
set_c_expr_source_range (&expr, tok_range);
c_parser_consume_token (parser);
break;
@@ -7698,8 +7831,9 @@ c_parser_postfix_expression (c_parser *parser)
accept sub structure and sub array references. */
if (c_parser_next_token_is (parser, CPP_NAME))
{
+ c_token *comp_tok = c_parser_peek_token (parser);
offsetof_ref = build_component_ref
- (loc, offsetof_ref, c_parser_peek_token (parser)->value);
+ (loc, offsetof_ref, comp_tok->value, comp_tok->location);
c_parser_consume_token (parser);
while (c_parser_next_token_is (parser, CPP_DOT)
|| c_parser_next_token_is (parser,
@@ -7725,9 +7859,10 @@ c_parser_postfix_expression (c_parser *parser)
c_parser_error (parser, "expected identifier");
break;
}
+ c_token *comp_tok = c_parser_peek_token (parser);
offsetof_ref = build_component_ref
- (loc, offsetof_ref,
- c_parser_peek_token (parser)->value);
+ (loc, offsetof_ref, comp_tok->value,
+ comp_tok->location);
c_parser_consume_token (parser);
}
else
@@ -8105,6 +8240,7 @@ c_parser_postfix_expression (c_parser *parser)
break;
}
/* Else fall through to report error. */
+ /* FALLTHRU */
default:
c_parser_error (parser, "expected expression");
expr.set_error ();
@@ -8137,7 +8273,8 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
tree type_expr = NULL_TREE;
bool type_expr_const = true;
check_compound_literal_type (type_loc, type_name);
- start_init (NULL_TREE, NULL, 0);
+ rich_location richloc (line_table, type_loc);
+ start_init (NULL_TREE, NULL, 0, &richloc);
type = groktypename (type_name, &type_expr, &type_expr_const);
start_loc = c_parser_peek_token (parser)->location;
if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
@@ -8166,7 +8303,9 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
set_c_expr_source_range (&expr, init.src_range);
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
- if (type != error_mark_node && type_expr)
+ if (type != error_mark_node
+ && expr.value != error_mark_node
+ && type_expr)
{
if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
{
@@ -8204,7 +8343,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
{
struct c_expr orig_expr;
tree ident, idx;
- location_t sizeof_arg_loc[3];
+ location_t sizeof_arg_loc[3], comp_loc;
tree sizeof_arg[3];
unsigned int literal_zero_mask;
unsigned int i;
@@ -8282,18 +8421,15 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.value, exprlist,
sizeof_arg,
sizeof_ptr_memacc_comptypes);
- if (warn_memset_transposed_args
- && TREE_CODE (expr.value) == FUNCTION_DECL
+ if (TREE_CODE (expr.value) == FUNCTION_DECL
&& DECL_BUILT_IN_CLASS (expr.value) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (expr.value) == BUILT_IN_MEMSET
- && vec_safe_length (exprlist) == 3
- && integer_zerop ((*exprlist)[2])
- && (literal_zero_mask & (1 << 2)) != 0
- && (!integer_zerop ((*exprlist)[1])
- || (literal_zero_mask & (1 << 1)) == 0))
- warning_at (expr_loc, OPT_Wmemset_transposed_args,
- "%<memset%> used with constant zero length parameter; "
- "this could be due to transposed parameters");
+ && vec_safe_length (exprlist) == 3)
+ {
+ tree arg0 = (*exprlist)[0];
+ tree arg2 = (*exprlist)[2];
+ warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
+ }
start = expr.get_start ();
finish = parser->tokens_buf[0].get_finish ();
@@ -8321,7 +8457,11 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
c_parser_consume_token (parser);
expr = default_function_array_conversion (expr_loc, expr);
if (c_parser_next_token_is (parser, CPP_NAME))
- ident = c_parser_peek_token (parser)->value;
+ {
+ c_token *comp_tok = c_parser_peek_token (parser);
+ ident = comp_tok->value;
+ comp_loc = comp_tok->location;
+ }
else
{
c_parser_error (parser, "expected identifier");
@@ -8333,7 +8473,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
start = expr.get_start ();
finish = c_parser_peek_token (parser)->get_finish ();
c_parser_consume_token (parser);
- expr.value = build_component_ref (op_loc, expr.value, ident);
+ expr.value = build_component_ref (op_loc, expr.value, ident,
+ comp_loc);
set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) != COMPONENT_REF)
@@ -8353,7 +8494,11 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
c_parser_consume_token (parser);
expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
if (c_parser_next_token_is (parser, CPP_NAME))
- ident = c_parser_peek_token (parser)->value;
+ {
+ c_token *comp_tok = c_parser_peek_token (parser);
+ ident = comp_tok->value;
+ comp_loc = comp_tok->location;
+ }
else
{
c_parser_error (parser, "expected identifier");
@@ -8369,7 +8514,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
build_indirect_ref (op_loc,
expr.value,
RO_ARROW),
- ident);
+ ident, comp_loc);
set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
if (TREE_CODE (expr.value) != COMPONENT_REF)
@@ -8396,8 +8541,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
else
{
expr = default_function_array_read_conversion (expr_loc, expr);
- expr.value = build_unary_op (op_loc,
- POSTINCREMENT_EXPR, expr.value, 0);
+ expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
+ expr.value, false);
}
set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
@@ -8415,8 +8560,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
else
{
expr = default_function_array_read_conversion (expr_loc, expr);
- expr.value = build_unary_op (op_loc,
- POSTDECREMENT_EXPR, expr.value, 0);
+ expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
+ expr.value, false);
}
set_c_expr_source_range (&expr, start, finish);
expr.original_code = ERROR_MARK;
@@ -8428,7 +8573,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
}
}
-/* Parse an expression (C90 6.3.17, C99 6.5.17).
+/* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
expression:
assignment-expression
@@ -9559,6 +9704,7 @@ c_parser_objc_selector (c_parser *parser)
case RID_CHAR:
case RID_FLOAT:
case RID_DOUBLE:
+ CASE_RID_FLOATN_NX:
case RID_VOID:
case RID_BOOL:
case RID_ATOMIC:
@@ -10023,6 +10169,7 @@ static bool
c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
{
unsigned int id;
+ const char *construct = NULL;
id = c_parser_peek_token (parser)->pragma_kind;
gcc_assert (id != PRAGMA_NONE);
@@ -10034,24 +10181,48 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
return false;
case PRAGMA_OACC_ENTER_DATA:
+ if (context != pragma_compound)
+ {
+ construct = "acc enter data";
+ in_compound:
+ if (context == pragma_stmt)
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "%<#pragma %s%> may only be used in compound "
+ "statements", construct);
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+ }
+ goto bad_stmt;
+ }
c_parser_oacc_enter_exit_data (parser, true);
return false;
case PRAGMA_OACC_EXIT_DATA:
+ if (context != pragma_compound)
+ {
+ construct = "acc exit data";
+ goto in_compound;
+ }
c_parser_oacc_enter_exit_data (parser, false);
return false;
case PRAGMA_OACC_ROUTINE:
+ if (context != pragma_external)
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "%<#pragma acc routine%> must be at file scope");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+ }
c_parser_oacc_routine (parser, context);
return false;
case PRAGMA_OACC_UPDATE:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma acc update%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "acc update";
+ goto in_compound;
}
c_parser_oacc_update (parser);
return false;
@@ -10059,10 +10230,8 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_BARRIER:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp barrier%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "omp barrier";
+ goto in_compound;
}
c_parser_omp_barrier (parser);
return false;
@@ -10070,10 +10239,8 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_FLUSH:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp flush%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "omp flush";
+ goto in_compound;
}
c_parser_omp_flush (parser);
return false;
@@ -10081,10 +10248,8 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
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;
+ construct = "omp taskwait";
+ goto in_compound;
}
c_parser_omp_taskwait (parser);
return false;
@@ -10092,10 +10257,8 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_TASKYIELD:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp taskyield%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "omp taskyield";
+ goto in_compound;
}
c_parser_omp_taskyield (parser);
return false;
@@ -10103,23 +10266,14 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_CANCEL:
if (context != pragma_compound)
{
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp cancel%> may only be "
- "used in compound statements");
- goto bad_stmt;
+ construct = "omp cancel";
+ goto in_compound;
}
c_parser_omp_cancel (parser);
return false;
case PRAGMA_OMP_CANCELLATION_POINT:
- if (context != pragma_compound)
- {
- if (context == pragma_stmt)
- c_parser_error (parser, "%<#pragma omp cancellation point%> may "
- "only be used in compound statements");
- goto bad_stmt;
- }
- c_parser_omp_cancellation_point (parser);
+ c_parser_omp_cancellation_point (parser, context);
return false;
case PRAGMA_OMP_THREADPRIVATE:
@@ -10140,7 +10294,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
- case PRAGMA_OMP_DECLARE_REDUCTION:
+ case PRAGMA_OMP_DECLARE:
c_parser_omp_declare (parser, context);
return false;
@@ -10194,6 +10348,14 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
c_parser_cilk_grainsize (parser, if_p);
return false;
+ case PRAGMA_OACC_WAIT:
+ if (context != pragma_compound)
+ {
+ construct = "acc wait";
+ goto in_compound;
+ }
+ /* FALL THROUGH. */
+
default:
if (id < PRAGMA_FIRST_EXTERNAL)
{
@@ -10617,9 +10779,12 @@ c_parser_omp_variable_list (c_parser *parser,
t = error_mark_node;
break;
}
- tree ident = c_parser_peek_token (parser)->value;
+
+ c_token *comp_tok = c_parser_peek_token (parser);
+ tree ident = comp_tok->value;
+ location_t comp_loc = comp_tok->location;
c_parser_consume_token (parser);
- t = build_component_ref (op_loc, t, ident);
+ t = build_component_ref (op_loc, t, ident, comp_loc);
}
/* FALLTHROUGH */
case OMP_CLAUSE_DEPEND:
@@ -10631,8 +10796,12 @@ c_parser_omp_variable_list (c_parser *parser,
c_parser_consume_token (parser);
if (!c_parser_next_token_is (parser, CPP_COLON))
{
- low_bound = c_parser_expression (parser).value;
- mark_exp_read (low_bound);
+ location_t expr_loc
+ = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr,
+ false, true);
+ low_bound = expr.value;
}
if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
length = integer_one_node;
@@ -10647,8 +10816,12 @@ c_parser_omp_variable_list (c_parser *parser,
}
if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
{
- length = c_parser_expression (parser).value;
- mark_exp_read (length);
+ location_t expr_loc
+ = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr,
+ false, true);
+ length = expr.value;
}
}
/* Look for the closing `]'. */
@@ -10833,6 +11006,7 @@ c_parser_omp_clause_collapse (c_parser *parser, tree list)
location_t loc;
check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
+ check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
@@ -11170,8 +11344,9 @@ c_parser_omp_clause_num_gangs (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;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11214,8 +11389,9 @@ 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;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11258,8 +11434,9 @@ c_parser_omp_clause_num_tasks (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;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11302,8 +11479,9 @@ c_parser_omp_clause_grainsize (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;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11346,8 +11524,9 @@ c_parser_omp_clause_priority (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;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11390,8 +11569,10 @@ c_parser_omp_clause_hint (c_parser *parser, tree list)
location_t hint_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- tree c, t = c_parser_expression (parser).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11494,8 +11675,9 @@ c_parser_omp_clause_num_workers (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;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -11616,11 +11798,12 @@ c_parser_oacc_shape_clause (c_parser *parser, omp_clause_code kind,
}
location_t expr_loc = c_parser_peek_token (parser)->location;
- tree expr = c_parser_expr_no_commas (parser, NULL).value;
+ c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
+ cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
+ tree expr = cexpr.value;
if (expr == error_mark_node)
goto cleanup_error;
- mark_exp_read (expr);
expr = c_fully_fold (expr, false, NULL);
/* Attempt to statically determine when the number isn't a
@@ -11637,7 +11820,7 @@ c_parser_oacc_shape_clause (c_parser *parser, omp_clause_code kind,
if (c == boolean_true_node)
{
warning_at (loc, 0,
- "%<%s%> value must be positive", str);
+ "%qs value must be positive", str);
expr = integer_one_node;
}
@@ -11734,10 +11917,11 @@ static tree
c_parser_oacc_clause_tile (c_parser *parser, tree list)
{
tree c, expr = error_mark_node;
- location_t loc, expr_loc;
+ location_t loc;
tree tile = NULL_TREE;
check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
+ 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 %<(%>"))
@@ -11745,17 +11929,22 @@ c_parser_oacc_clause_tile (c_parser *parser, tree list)
do
{
+ if (tile && !c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
+ return list;
+
if (c_parser_next_token_is (parser, CPP_MULT)
&& (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
|| c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
{
c_parser_consume_token (parser);
- expr = integer_minus_one_node;
+ expr = integer_zero_node;
}
else
{
- expr_loc = c_parser_peek_token (parser)->location;
- expr = c_parser_expr_no_commas (parser, NULL).value;
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
+ cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
+ expr = cexpr.value;
if (expr == error_mark_node)
{
@@ -11764,29 +11953,19 @@ c_parser_oacc_clause_tile (c_parser *parser, tree list)
return list;
}
- if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
- {
- c_parser_error (parser, "%<tile%> value must be integral");
- return list;
- }
-
- mark_exp_read (expr);
expr = c_fully_fold (expr, false, NULL);
- /* Attempt to statically determine when expr isn't positive. */
- c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
- build_int_cst (TREE_TYPE (expr), 0));
- protected_set_expr_location (c, expr_loc);
- if (c == boolean_true_node)
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
+ || !tree_fits_shwi_p (expr)
+ || tree_to_shwi (expr) <= 0)
{
- warning_at (expr_loc, 0,"%<tile%> value must be positive");
- expr = integer_one_node;
+ error_at (expr_loc, "%<tile%> argument needs positive"
+ " integral constant");
+ expr = integer_zero_node;
}
}
tile = tree_cons (NULL_TREE, expr, tile);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
}
while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN));
@@ -11937,7 +12116,7 @@ c_parser_omp_clause_reduction (c_parser *parser, tree list)
default:
c_parser_error (parser,
"expected %<+%>, %<*%>, %<-%>, %<&%>, "
- "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or %<max%>");
+ "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
return list;
}
@@ -12093,8 +12272,9 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
c_parser_consume_token (parser);
here = c_parser_peek_token (parser)->location;
- t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (here, expr, false, true);
+ t = expr.value;
t = c_fully_fold (t, false, NULL);
if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
@@ -12105,7 +12285,20 @@ c_parser_omp_clause_schedule (c_parser *parser, tree list)
"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;
+ {
+ /* Attempt to statically determine when the number isn't
+ positive. */
+ tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
+ build_int_cst (TREE_TYPE (t), 0));
+ protected_set_expr_location (s, loc);
+ if (s == boolean_true_node)
+ {
+ warning_at (loc, 0,
+ "chunk size value must be positive");
+ t = integer_one_node;
+ }
+ OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
+ }
else
c_parser_error (parser, "expected integer expression");
@@ -12166,8 +12359,9 @@ c_parser_omp_clause_vector_length (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;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -12269,8 +12463,9 @@ c_parser_omp_clause_num_teams (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;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -12312,8 +12507,9 @@ c_parser_omp_clause_thread_limit (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;
- mark_exp_read (t);
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -12365,8 +12561,10 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list)
if (c_parser_next_token_is (parser, CPP_COLON))
{
c_parser_consume_token (parser);
- tree alignment = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (alignment);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree alignment = expr.value;
alignment = c_fully_fold (alignment, false, NULL);
if (TREE_CODE (alignment) != INTEGER_CST
|| !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
@@ -12428,8 +12626,10 @@ c_parser_omp_clause_linear (c_parser *parser, tree list, bool is_cilk_simd_fn)
if (c_parser_next_token_is (parser, CPP_COLON))
{
c_parser_consume_token (parser);
- step = c_parser_expression (parser).value;
- mark_exp_read (step);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expression (parser);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ step = expr.value;
step = c_fully_fold (step, false, NULL);
if (is_cilk_simd_fn && TREE_CODE (step) == PARM_DECL)
{
@@ -12469,8 +12669,10 @@ c_parser_omp_clause_safelen (c_parser *parser, tree list)
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return list;
- t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ t = expr.value;
t = c_fully_fold (t, false, NULL);
if (TREE_CODE (t) != INTEGER_CST
|| !INTEGRAL_TYPE_P (TREE_TYPE (t))
@@ -12505,8 +12707,10 @@ c_parser_omp_clause_simdlen (c_parser *parser, tree list)
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return list;
- t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ t = expr.value;
t = c_fully_fold (t, false, NULL);
if (TREE_CODE (t) != INTEGER_CST
|| !INTEGRAL_TYPE_P (TREE_TYPE (t))
@@ -12821,8 +13025,10 @@ c_parser_omp_clause_device (c_parser *parser, tree list)
location_t clause_loc = c_parser_peek_token (parser)->location;
if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- tree c, t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
@@ -12870,8 +13076,10 @@ c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
{
c_parser_consume_token (parser);
- t = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (t);
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ t = expr.value;
t = c_fully_fold (t, false, NULL);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
}
@@ -13160,7 +13368,7 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
c_parser_skip_to_pragma_eol (parser);
if (finish_p)
- return c_finish_omp_clauses (clauses, false);
+ return c_finish_omp_clauses (clauses, C_ORT_ACC);
return clauses;
}
@@ -13445,8 +13653,8 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
if (finish_p)
{
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
- return c_finish_omp_clauses (clauses, true, true);
- return c_finish_omp_clauses (clauses, true);
+ return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
+ return c_finish_omp_clauses (clauses, C_ORT_OMP);
}
return clauses;
@@ -13480,7 +13688,7 @@ c_parser_oacc_cache (location_t loc, c_parser *parser)
tree stmt, clauses;
clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE__CACHE_, NULL);
- clauses = c_finish_omp_clauses (clauses, false);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
c_parser_skip_to_pragma_eol (parser);
@@ -13579,24 +13787,20 @@ c_parser_oacc_declare (c_parser *parser)
switch (OMP_CLAUSE_MAP_KIND (t))
{
+ case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_FORCE_ALLOC:
case GOMP_MAP_FORCE_TO:
case GOMP_MAP_FORCE_DEVICEPTR:
case GOMP_MAP_DEVICE_RESIDENT:
break;
- case GOMP_MAP_POINTER:
- /* Generated by c_finish_omp_clauses from array sections;
- avoid spurious diagnostics. */
- break;
-
case GOMP_MAP_LINK:
if (!global_bindings_p ()
&& (TREE_STATIC (decl)
|| !DECL_EXTERNAL (decl)))
{
error_at (loc,
- "%qD must be a global variable in"
+ "%qD must be a global variable in "
"%<#pragma acc declare link%>",
decl);
error = true;
@@ -13714,28 +13918,25 @@ c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
{
location_t loc = c_parser_peek_token (parser)->location;
tree clauses, stmt;
+ const char *p = "";
c_parser_consume_pragma (parser);
- if (!c_parser_next_token_is (parser, CPP_NAME))
+ if (c_parser_next_token_is (parser, CPP_NAME))
{
- c_parser_error (parser, enter
- ? "expected %<data%> in %<#pragma acc enter data%>"
- : "expected %<data%> in %<#pragma acc exit data%>");
- c_parser_skip_to_pragma_eol (parser);
- return;
+ p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
}
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
if (strcmp (p, "data") != 0)
{
- c_parser_error (parser, "invalid pragma");
+ error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
+ enter ? "enter" : "exit");
+ parser->error = true;
c_parser_skip_to_pragma_eol (parser);
return;
}
- c_parser_consume_token (parser);
-
if (enter)
clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
"#pragma acc enter data");
@@ -13743,11 +13944,10 @@ c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
"#pragma acc exit data");
- if (find_omp_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
+ if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
{
- error_at (loc, enter
- ? "%<#pragma acc enter data%> has no data movement clause"
- : "%<#pragma acc exit data%> has no data movement clause");
+ error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
+ enter ? "enter" : "exit");
return;
}
@@ -13816,9 +14016,9 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
{
clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
if (*cclauses)
- *cclauses = c_finish_omp_clauses (*cclauses, false);
+ *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC);
if (clauses)
- clauses = c_finish_omp_clauses (clauses, false);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
}
tree block = c_begin_compound_stmt (true);
@@ -13944,95 +14144,154 @@ c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
static void
c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
{
- tree decl = NULL_TREE;
- /* Create a dummy claue, to record location. */
- tree c_head = build_omp_clause (c_parser_peek_token (parser)->location,
- OMP_CLAUSE_SEQ);
-
- if (context != pragma_external)
- c_parser_error (parser, "%<#pragma acc routine%> not at file scope");
+ gcc_checking_assert (context == pragma_external);
+
+ oacc_routine_data data;
+ data.error_seen = false;
+ data.fndecl_seen = false;
+ data.clauses = NULL_TREE;
+ data.loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
- /* Scan for optional '( name )'. */
- if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
+ /* Look for optional '( name )'. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
- c_parser_consume_token (parser);
+ c_parser_consume_token (parser); /* '(' */
- c_token *token = c_parser_peek_token (parser);
-
- if (token->type == CPP_NAME && (token->id_kind == C_ID_ID
- || token->id_kind == C_ID_TYPENAME))
+ tree decl = NULL_TREE;
+ c_token *name_token = c_parser_peek_token (parser);
+ location_t name_loc = name_token->location;
+ if (name_token->type == CPP_NAME
+ && (name_token->id_kind == C_ID_ID
+ || name_token->id_kind == C_ID_TYPENAME))
{
- decl = lookup_name (token->value);
+ decl = lookup_name (name_token->value);
if (!decl)
- {
- error_at (token->location, "%qE has not been declared",
- token->value);
- decl = error_mark_node;
- }
+ error_at (name_loc,
+ "%qE has not been declared", name_token->value);
+ c_parser_consume_token (parser);
}
else
c_parser_error (parser, "expected function name");
- if (token->type != CPP_CLOSE_PAREN)
- c_parser_consume_token (parser);
+ if (!decl
+ || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ {
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+
+ data.clauses
+ = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+ "#pragma acc routine");
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_at (name_loc, "%qD does not refer to a function", decl);
+ return;
+ }
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
+ c_finish_oacc_routine (&data, decl, false);
}
+ else /* No optional '( name )'. */
+ {
+ data.clauses
+ = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
+ "#pragma acc routine");
- /* Build a chain of clauses. */
- parser->in_pragma = true;
- tree clauses = c_parser_oacc_all_clauses
- (parser, OACC_ROUTINE_CLAUSE_MASK, "#pragma acc routine");
+ /* Emit a helpful diagnostic if there's another pragma following this
+ one. Also don't allow a static assertion declaration, as in the
+ following we'll just parse a *single* "declaration or function
+ definition", and the static assertion counts an one. */
+ if (c_parser_next_token_is (parser, CPP_PRAGMA)
+ || c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
+ {
+ error_at (data.loc,
+ "%<#pragma acc routine%> not immediately followed by"
+ " function declaration or definition");
+ /* ..., and then just keep going. */
+ return;
+ }
- /* Force clauses to be non-null, by attaching context to it. */
- clauses = tree_cons (c_head, clauses, NULL_TREE);
-
- if (decl)
- c_finish_oacc_routine (parser, decl, clauses, true, true, false);
- else if (c_parser_peek_token (parser)->type == CPP_PRAGMA)
- /* This will emit an error. */
- c_finish_oacc_routine (parser, NULL_TREE, clauses, false, true, false);
- else
- c_parser_declaration_or_fndef (parser, true, false, false, false,
- true, NULL, vNULL, clauses);
+ /* We only have to consider the pragma_external case here. */
+ if (c_parser_next_token_is (parser, CPP_KEYWORD)
+ && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
+ {
+ int ext = disable_extension_diagnostics ();
+ do
+ c_parser_consume_token (parser);
+ while (c_parser_next_token_is (parser, CPP_KEYWORD)
+ && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+ NULL, vNULL, &data);
+ restore_extension_diagnostics (ext);
+ }
+ else
+ c_parser_declaration_or_fndef (parser, true, true, true, false, true,
+ NULL, vNULL, &data);
+ }
}
-/* Finalize an OpenACC routine pragma, applying it to FNDECL. CLAUSES
- are the parsed clauses. IS_DEFN is true if we're applying it to
- the definition (so expect FNDEF to look somewhat defined. */
+/* Finalize an OpenACC routine pragma, applying it to FNDECL.
+ IS_DEFN is true if we're applying it to the definition. */
static void
-c_finish_oacc_routine (c_parser *ARG_UNUSED (parser), tree fndecl,
- tree clauses, bool named, bool first, bool is_defn)
+c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
+ bool is_defn)
{
- location_t loc = OMP_CLAUSE_LOCATION (TREE_PURPOSE (clauses));
+ /* Keep going if we're in error reporting mode. */
+ if (data->error_seen
+ || fndecl == error_mark_node)
+ return;
- if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL || !first)
+ if (data->fndecl_seen)
{
- if (fndecl != error_mark_node)
- error_at (loc, "%<#pragma acc routine%> %s",
- named ? "does not refer to a function"
- : "not followed by single function");
+ error_at (data->loc,
+ "%<#pragma acc routine%> not immediately followed by"
+ " a single function declaration or definition");
+ data->error_seen = true;
+ return;
+ }
+ if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
+ {
+ error_at (data->loc,
+ "%<#pragma acc routine%> not immediately followed by"
+ " function declaration or definition");
+ data->error_seen = true;
return;
}
- if (get_oacc_fn_attrib (fndecl))
- error_at (loc, "%<#pragma acc routine%> already applied to %D", fndecl);
+ if (oacc_get_fn_attrib (fndecl))
+ {
+ error_at (data->loc,
+ "%<#pragma acc routine%> already applied to %qD", fndecl);
+ data->error_seen = true;
+ return;
+ }
if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
- error_at (loc, "%<#pragma acc routine%> must be applied before %s",
- TREE_USED (fndecl) ? "use" : "definition");
+ {
+ error_at (data->loc,
+ TREE_USED (fndecl)
+ ? G_("%<#pragma acc routine%> must be applied before use")
+ : G_("%<#pragma acc routine%> must be applied before "
+ "definition"));
+ data->error_seen = true;
+ return;
+ }
- /* Process for function attrib */
- tree dims = build_oacc_routine_dims (TREE_VALUE (clauses));
- replace_oacc_fn_attrib (fndecl, dims);
+ /* Process the routine's dimension clauses. */
+ tree dims = oacc_build_routine_dims (data->clauses);
+ oacc_replace_fn_attrib (fndecl, dims);
- /* Also attach as a declare. */
+ /* Add an "omp declare target" attribute. */
DECL_ATTRIBUTES (fndecl)
= tree_cons (get_identifier ("omp declare target"),
- clauses, DECL_ATTRIBUTES (fndecl));
+ NULL_TREE, DECL_ATTRIBUTES (fndecl));
+
+ /* Remember that we've used this "#pragma acc routine". */
+ data->fndecl_seen = true;
}
/* OpenACC 2.0:
@@ -14056,7 +14315,7 @@ c_parser_oacc_update (c_parser *parser)
tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
"#pragma acc update");
- if (find_omp_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
+ if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
{
error_at (loc,
"%<#pragma acc update%> must contain at least one "
@@ -14630,11 +14889,17 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
bool fail = false, open_brace_parsed = false;
int i, collapse = 1, ordered = 0, count, nbraces = 0;
location_t for_loc;
+ bool tiling = false;
vec<tree, va_gc> *for_block = make_tree_vector ();
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
+ else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
+ {
+ tiling = true;
+ collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
+ }
else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
&& OMP_CLAUSE_ORDERED_EXPR (cl))
{
@@ -14664,7 +14929,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
pc = &OMP_CLAUSE_CHAIN (*pc);
}
- gcc_assert (collapse >= 1 && ordered >= 0);
+ gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
count = ordered ? ordered : collapse;
declv = make_tree_vec (count);
@@ -14992,7 +15257,7 @@ omp_split_clauses (location_t loc, enum tree_code code,
c_omp_split_clauses (loc, code, mask, clauses, cclauses);
for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
if (cclauses[i])
- cclauses[i] = c_finish_omp_clauses (cclauses[i], true);
+ cclauses[i] = c_finish_omp_clauses (cclauses[i], C_ORT_OMP);
}
/* OpenMP 4.0:
@@ -15027,7 +15292,7 @@ c_parser_omp_simd (location_t loc, c_parser *parser,
{
omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
- tree c = find_omp_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
+ tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
OMP_CLAUSE_ORDERED);
if (c && OMP_CLAUSE_ORDERED_EXPR (c))
{
@@ -15180,7 +15445,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
if (context != pragma_stmt && context != pragma_compound)
{
c_parser_error (parser, "expected declaration specifiers");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ c_parser_skip_to_pragma_eol (parser, false);
return false;
}
@@ -15193,7 +15458,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
if (context == pragma_stmt)
{
error_at (loc,
- "%<#pragma omp ordered%> with %<depend> clause may "
+ "%<#pragma omp ordered%> with %<depend%> clause may "
"only be used in compound statements");
c_parser_skip_to_pragma_eol (parser, false);
return false;
@@ -15577,7 +15842,7 @@ c_parser_omp_cancel (c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
static void
-c_parser_omp_cancellation_point (c_parser *parser)
+c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
{
location_t loc = c_parser_peek_token (parser)->location;
tree clauses;
@@ -15600,6 +15865,18 @@ c_parser_omp_cancellation_point (c_parser *parser)
return;
}
+ if (context != pragma_compound)
+ {
+ if (context == pragma_stmt)
+ error_at (loc,
+ "%<#pragma %s%> may only be used in compound statements",
+ "omp cancellation point");
+ else
+ c_parser_error (parser, "expected declaration specifiers");
+ c_parser_skip_to_pragma_eol (parser, false);
+ return;
+ }
+
clauses
= c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
"#pragma omp cancellation point");
@@ -15850,9 +16127,8 @@ c_parser_omp_target_update (location_t loc, c_parser *parser,
{
if (context == pragma_stmt)
{
- error_at (loc,
- "%<#pragma omp target update%> may only be "
- "used in compound statements");
+ error_at (loc, "%<#pragma %s%> may only be used in compound statements",
+ "omp target update");
c_parser_skip_to_pragma_eol (parser, false);
return false;
}
@@ -15860,8 +16136,8 @@ c_parser_omp_target_update (location_t loc, c_parser *parser,
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
"#pragma omp target update");
- if (find_omp_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
- && find_omp_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
+ if (omp_find_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
+ && omp_find_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
{
error_at (loc,
"%<#pragma omp target update%> must contain at least one "
@@ -15910,9 +16186,8 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
if (context == pragma_stmt)
{
- error_at (loc,
- "%<#pragma omp target enter data%> may only be "
- "used in compound statements");
+ error_at (loc, "%<#pragma %s%> may only be used in compound statements",
+ "omp target enter data");
c_parser_skip_to_pragma_eol (parser, false);
return NULL_TREE;
}
@@ -15995,9 +16270,8 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
if (context == pragma_stmt)
{
- error_at (loc,
- "%<#pragma omp target exit data%> may only be "
- "used in compound statements");
+ error_at (loc, "%<#pragma %s%> may only be used in compound statements",
+ "omp target exit data");
c_parser_skip_to_pragma_eol (parser, false);
return NULL_TREE;
}
@@ -16025,7 +16299,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
map_seen |= 1;
error_at (OMP_CLAUSE_LOCATION (*pc),
"%<#pragma omp target exit data%> with map-type other "
- "than %<from%>, %<release> or %<delete%> on %<map%>"
+ "than %<from%>, %<release%> or %<delete%> on %<map%>"
" clause");
*pc = OMP_CLAUSE_CHAIN (*pc);
continue;
@@ -16212,6 +16486,11 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
return c_parser_omp_target_update (loc, parser, context);
}
}
+ if (!flag_openmp) /* flag_openmp_simd */
+ {
+ c_parser_skip_to_pragma_eol (parser, false);
+ return false;
+ }
stmt = make_node (OMP_TARGET);
TREE_TYPE (stmt) = void_type_node;
@@ -16271,14 +16550,13 @@ check_clauses:
static void
c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
{
- vec<c_token> clauses = vNULL;
+ auto_vec<c_token> clauses;
while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
{
c_token *token = c_parser_peek_token (parser);
if (token->type == CPP_EOF)
{
c_parser_skip_to_pragma_eol (parser);
- clauses.release ();
return;
}
clauses.safe_push (*token);
@@ -16290,7 +16568,7 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
while (c_parser_next_token_is (parser, CPP_PRAGMA))
{
if (c_parser_peek_token (parser)->pragma_kind
- != PRAGMA_OMP_DECLARE_REDUCTION
+ != PRAGMA_OMP_DECLARE
|| c_parser_peek_2nd_token (parser)->type != CPP_NAME
|| strcmp (IDENTIFIER_POINTER
(c_parser_peek_2nd_token (parser)->value),
@@ -16300,7 +16578,6 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
"%<#pragma omp declare simd%> must be followed by "
"function declaration or definition or another "
"%<#pragma omp declare simd%>");
- clauses.release ();
return;
}
c_parser_consume_pragma (parser);
@@ -16310,7 +16587,6 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
if (token->type == CPP_EOF)
{
c_parser_skip_to_pragma_eol (parser);
- clauses.release ();
return;
}
clauses.safe_push (*token);
@@ -16382,7 +16658,6 @@ c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
default:
gcc_unreachable ();
}
- clauses.release ();
}
/* Finalize #pragma omp declare simd clauses after FNDECL has been parsed,
@@ -16525,7 +16800,7 @@ c_parser_omp_declare_target (c_parser *parser)
{
clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO_DECLARE,
clauses);
- clauses = c_finish_omp_clauses (clauses, true);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
c_parser_skip_to_pragma_eol (parser);
}
else
@@ -16560,8 +16835,11 @@ c_parser_omp_declare_target (c_parser *parser)
}
if (!at1)
{
- symtab_node *node = symtab_node::get (t);
DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
+ if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
+ continue;
+
+ symtab_node *node = symtab_node::get (t);
if (node != NULL)
{
node->offloadable = 1;
@@ -16684,7 +16962,7 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
default:
c_parser_error (parser,
"expected %<+%>, %<*%>, %<-%>, %<&%>, "
- "%<^%>, %<|%>, %<&&%>, %<||%>, %<min%> or identifier");
+ "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
goto fail;
}
@@ -16716,6 +16994,9 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
|| TREE_CODE (type) == ARRAY_TYPE)
error_at (loc, "function or array type in "
"%<#pragma omp declare reduction%>");
+ else if (TYPE_ATOMIC (type))
+ error_at (loc, "%<_Atomic%> qualified type in "
+ "%<#pragma omp declare reduction%>");
else if (TYPE_QUALS_NO_ADDR_SPACE (type))
error_at (loc, "const, volatile or restrict qualified type in "
"%<#pragma omp declare reduction%>");
@@ -16893,8 +17174,9 @@ c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
else
{
tree st = push_stmt_list ();
- start_init (omp_priv, NULL_TREE, 0);
location_t loc = c_parser_peek_token (parser)->location;
+ rich_location richloc (line_table, loc);
+ start_init (omp_priv, NULL_TREE, 0, &richloc);
struct c_expr init = c_parser_initializer (parser);
finish_init ();
finish_decl (omp_priv, loc, init.value,
@@ -17494,7 +17776,7 @@ c_parser_cilk_all_clauses (c_parser *parser)
saw_error:
c_parser_skip_to_pragma_eol (parser);
- return c_finish_cilk_clauses (clauses);
+ return c_finish_omp_clauses (clauses, C_ORT_CILK);
}
/* This function helps parse the grainsize pragma for a _Cilk_for statement.
@@ -17576,7 +17858,7 @@ c_parser_cilk_for (c_parser *parser, tree grain, bool *if_p)
tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE);
OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR;
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain;
- clauses = c_finish_omp_clauses (clauses, false);
+ clauses = c_finish_omp_clauses (clauses, C_ORT_CILK);
tree block = c_begin_compound_stmt (true);
tree sb = push_stmt_list ();
@@ -17642,7 +17924,7 @@ c_parser_cilk_for (c_parser *parser, tree grain, bool *if_p)
OMP_CLAUSE_OPERAND (c, 0)
= cilk_for_number_of_iterations (omp_for);
OMP_CLAUSE_CHAIN (c) = clauses;
- OMP_PARALLEL_CLAUSES (omp_par) = c_finish_omp_clauses (c, true);
+ OMP_PARALLEL_CLAUSES (omp_par) = c_finish_omp_clauses (c, C_ORT_CILK);
add_stmt (omp_par);
}
@@ -18034,4 +18316,74 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
return value_tree;
}
+/* Parse the body of a function declaration marked with "__RTL".
+
+ The RTL parser works on the level of characters read from a
+ FILE *, whereas c_parser works at the level of tokens.
+ Square this circle by consuming all of the tokens up to and
+ including the closing brace, recording the start/end of the RTL
+ fragment, and reopening the file and re-reading the relevant
+ lines within the RTL parser.
+
+ This requires the opening and closing braces of the C function
+ to be on separate lines from the RTL they wrap.
+
+ Take ownership of START_WITH_PASS, if non-NULL. */
+
+void
+c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
+{
+ if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ {
+ free (start_with_pass);
+ return;
+ }
+
+ location_t start_loc = c_parser_peek_token (parser)->location;
+
+ /* Consume all tokens, up to the closing brace, handling
+ matching pairs of braces in the rtl dump. */
+ int num_open_braces = 1;
+ while (1)
+ {
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_OPEN_BRACE:
+ num_open_braces++;
+ break;
+ case CPP_CLOSE_BRACE:
+ if (--num_open_braces == 0)
+ goto found_closing_brace;
+ break;
+ case CPP_EOF:
+ error_at (start_loc, "no closing brace");
+ free (start_with_pass);
+ return;
+ default:
+ break;
+ }
+ c_parser_consume_token (parser);
+ }
+
+ found_closing_brace:
+ /* At the closing brace; record its location. */
+ location_t end_loc = c_parser_peek_token (parser)->location;
+
+ /* Consume the closing brace. */
+ c_parser_consume_token (parser);
+
+ /* Invoke the RTL parser. */
+ if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
+ {
+ free (start_with_pass);
+ return;
+ }
+
+ /* If a pass name was provided for START_WITH_PASS, run the backend
+ accordingly now, on the cfun created above, transferring
+ ownership of START_WITH_PASS. */
+ if (start_with_pass)
+ run_rtl_passes (start_with_pass);
+}
+
#include "gt-c-c-parser.h"