@@ -4397,6 +4397,48 @@ build_type_attribute_qual_variant (tree
return ttype;
}
+/* Check if "omp declare simd" attribute arguments, CLAUSES1 and CLAUSES2, are
+ the same. */
+
+bool
+omp_declare_simd_clauses_equal (tree clauses1, tree clauses2)
+{
+ tree cl1, cl2;
+ for (cl1 = clauses1, cl2 = clauses2;
+ cl1 && cl2;
+ cl1 = OMP_CLAUSE_CHAIN (cl1), cl2 = OMP_CLAUSE_CHAIN (cl2))
+ {
+ if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_CODE (cl2))
+ return false;
+ if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_SIMDLEN)
+ {
+ if (simple_cst_equal (OMP_CLAUSE_DECL (cl1),
+ OMP_CLAUSE_DECL (cl2)) != 1)
+ return false;
+ }
+ switch (OMP_CLAUSE_CODE (cl1))
+ {
+ case OMP_CLAUSE_ALIGNED:
+ if (simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (cl1),
+ OMP_CLAUSE_ALIGNED_ALIGNMENT (cl2)) != 1)
+ return false;
+ break;
+ case OMP_CLAUSE_LINEAR:
+ if (simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (cl1),
+ OMP_CLAUSE_LINEAR_STEP (cl2)) != 1)
+ return false;
+ break;
+ case OMP_CLAUSE_SIMDLEN:
+ if (simple_cst_equal (OMP_CLAUSE_SIMDLEN_EXPR (cl1),
+ OMP_CLAUSE_SIMDLEN_EXPR (cl2)) != 1)
+ return false;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
/* Compare two attributes for their value identity. Return true if the
attribute values are known to be equal; otherwise return false.
*/
@@ -4414,6 +4456,13 @@ attribute_value_equal (const_tree attr1,
return (simple_cst_list_equal (TREE_VALUE (attr1),
TREE_VALUE (attr2)) == 1);
+ if (flag_openmp
+ && TREE_VALUE (attr1) && TREE_VALUE (attr2)
+ && TREE_CODE (TREE_VALUE (attr1)) == OMP_CLAUSE
+ && TREE_CODE (TREE_VALUE (attr2)) == OMP_CLAUSE)
+ return omp_declare_simd_clauses_equal (TREE_VALUE (attr1),
+ TREE_VALUE (attr2));
+
return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
}
@@ -5051,6 +5051,10 @@ extern tree build_type_attribute_variant
extern tree build_decl_attribute_variant (tree, tree);
extern tree build_type_attribute_qual_variant (tree, tree, int);
+/* Check if "omp declare simd" attribute arguments, CLAUSES1 and CLAUSES2, are
+ the same. */
+extern bool omp_declare_simd_clauses_equal (tree, tree);
+
/* Return 0 if the attributes for two types are incompatible, 1 if they
are compatible, and 2 if they are nearly compatible (which causes a
warning to be generated). */
@@ -368,6 +368,8 @@ static tree handle_optimize_attribute (t
static tree ignore_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
+static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int,
+ bool *);
static void check_function_nonnull (tree, int, tree *);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -738,6 +740,8 @@ const struct attribute_spec c_common_att
The name contains space to prevent its usage in source code. */
{ "fn spec", 1, 1, false, true, true,
handle_fnspec_attribute, false },
+ { "omp declare simd", 0, -1, true, false, false,
+ handle_omp_declare_simd_attribute, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
@@ -7958,6 +7962,15 @@ handle_fnspec_attribute (tree *node ATTR
return NULL_TREE;
}
+/* Handle an "omp declare simd" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *)
+{
+ return NULL_TREE;
+}
+
/* Handle a "returns_twice" attribute; arguments as in
struct attribute_spec.handler. */
@@ -1042,6 +1042,8 @@ extern void c_finish_omp_taskyield (loca
extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree,
tree, tree, tree);
extern void c_split_parallel_clauses (location_t, tree, tree *, tree *);
+extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree);
+extern void c_omp_declare_simd_clauses_to_decls (tree, tree);
extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
/* Not in c-omp.c; provided by the front end. */
@@ -637,6 +637,100 @@ c_split_parallel_clauses (location_t loc
}
}
+/* qsort callback to compare #pragma omp declare simd clauses. */
+
+static int
+c_omp_declare_simd_clause_cmp (const void *p, const void *q)
+{
+ tree a = *(const tree *) p;
+ tree b = *(const tree *) q;
+ if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
+ {
+ if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
+ return -1;
+ return 1;
+ }
+ if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
+ && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
+ && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
+ {
+ int c = tree_low_cst (OMP_CLAUSE_DECL (a), 0);
+ int d = tree_low_cst (OMP_CLAUSE_DECL (b), 0);
+ if (c < d)
+ return 1;
+ if (c > d)
+ return -1;
+ }
+ return 0;
+}
+
+/* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
+ CLAUSES on FNDECL into argument indexes and sort them. */
+
+tree
+c_omp_declare_simd_clauses_to_numbers (tree fndecl, tree clauses)
+{
+ tree c;
+ vec<tree> clvec = vNULL;
+
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ {
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
+ {
+ tree decl = OMP_CLAUSE_DECL (c);
+ tree arg;
+ int idx;
+ for (arg = DECL_ARGUMENTS (fndecl), idx = 0; arg;
+ arg = TREE_CHAIN (arg), idx++)
+ if (arg == decl)
+ break;
+ if (arg == NULL_TREE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not an argument of %qD", decl, fndecl);
+ continue;
+ }
+ OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
+ }
+ clvec.safe_push (c);
+ }
+ if (!clvec.is_empty ())
+ {
+ unsigned int len = clvec.length (), i;
+ clvec.qsort (c_omp_declare_simd_clause_cmp);
+ clauses = clvec[0];
+ for (i = 0; i < len; i++)
+ OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
+ }
+ clvec.release ();
+ return clauses;
+}
+
+/* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs. */
+
+void
+c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
+{
+ tree c;
+
+ for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
+ && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
+ {
+ int idx = tree_low_cst (OMP_CLAUSE_DECL (c), 0), i;
+ tree arg;
+ for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
+ arg = TREE_CHAIN (arg), i++)
+ if (i == idx)
+ break;
+ gcc_assert (arg);
+ OMP_CLAUSE_DECL (c) = arg;
+ }
+}
+
/* True if OpenMP sharing attribute of DECL is predetermined. */
enum omp_clause_default_kind
@@ -5124,7 +5124,8 @@ extern void warn_misplaced_attr_for_clas
extern tree check_tag_decl (cp_decl_specifier_seq *, bool);
extern tree shadow_tag (cp_decl_specifier_seq *);
extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *, bool);
-extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
+extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *,
+ int, tree, tree, tree *, vec<tree, va_gc> *);
extern void start_decl_1 (tree, bool);
extern bool check_array_initializer (tree, tree, tree);
extern void cp_finish_decl (tree, tree, bool, tree, int);
@@ -5150,12 +5151,14 @@ extern void finish_enum (tree);
extern void build_enumerator (tree, tree, tree, location_t);
extern tree lookup_enumerator (tree, tree);
extern void start_preparsed_function (tree, tree, int);
-extern int start_function (cp_decl_specifier_seq *, const cp_declarator *, tree);
+extern int start_function (cp_decl_specifier_seq *, const cp_declarator *, tree,
+ vec<tree, va_gc> *);
extern tree begin_function_body (void);
extern void finish_function_body (tree);
extern tree outer_curly_brace_block (tree);
extern tree finish_function (int);
-extern tree grokmethod (cp_decl_specifier_seq *, const cp_declarator *, tree);
+extern tree grokmethod (cp_decl_specifier_seq *, const cp_declarator *, tree,
+ vec<tree, va_gc> *);
extern void maybe_register_incomplete_var (tree);
extern void maybe_commonize_var (tree);
extern void complete_vars (tree);
@@ -5204,7 +5207,7 @@ extern tree delete_sanity (tree, tree,
extern tree check_classfn (tree, tree, tree);
extern void check_member_template (tree);
extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
- tree, bool, tree, tree);
+ tree, bool, tree, tree, vec<tree, va_gc> *);
extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
tree, tree);
extern tree cp_reconstruct_complex_type (tree, tree);
@@ -5702,6 +5705,7 @@ extern void simplify_aggr_init_expr (tr
extern void finalize_nrv (tree *, tree, tree);
extern void note_decl_for_pch (tree);
extern tree finish_omp_clauses (tree);
+extern void finish_omp_declare_simd (tree, vec<tree, va_gc> *);
extern void finish_omp_threadprivate (tree);
extern tree begin_omp_structured_block (void);
extern tree finish_omp_structured_block (tree);
@@ -796,7 +796,7 @@ grokfield (const cp_declarator *declarat
cp_decl_specifier_seq *declspecs,
tree init, bool init_const_expr_p,
tree asmspec_tree,
- tree attrlist)
+ tree attrlist, vec<tree, va_gc> *omp_declare_simd_clauses)
{
tree value;
const char *asmspec = 0;
@@ -809,7 +809,8 @@ grokfield (const cp_declarator *declarat
&& TREE_CHAIN (init) == NULL_TREE)
init = NULL_TREE;
- value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist);
+ value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist,
+ omp_declare_simd_clauses);
if (! value || error_operand_p (value))
/* friend or constructor went bad. */
return error_mark_node;
@@ -1019,7 +1020,8 @@ grokbitfield (const cp_declarator *decla
cp_decl_specifier_seq *declspecs, tree width,
tree attrlist)
{
- tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, &attrlist);
+ tree value
+ = grokdeclarator (declarator, declspecs, BITFIELD, 0, &attrlist, NULL);
if (value == error_mark_node)
return NULL_TREE; /* friends went bad. */
@@ -1111,6 +1113,11 @@ is_late_template_attribute (tree attr, t
if (is_attribute_p ("unused", name))
return false;
+ /* #pragma omp declare simd attribute needs to be always finalized. */
+ if (flag_openmp
+ && is_attribute_p ("omp declare simd", name))
+ return true;
+
/* If any of the arguments are dependent expressions, we can't evaluate
the attribute until instantiation time. */
for (arg = args; arg; arg = TREE_CHAIN (arg))
@@ -1296,6 +1303,9 @@ cp_check_const_attributes (tree attribut
for (attr = attributes; attr; attr = TREE_CHAIN (attr))
{
tree arg;
+ if (TREE_VALUE (attr) == NULL_TREE
+ || TREE_CODE (TREE_VALUE (attr)) != TREE_LIST)
+ continue;
for (arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
{
tree expr = TREE_VALUE (arg);
@@ -4368,7 +4368,7 @@ shadow_tag (cp_decl_specifier_seq *decls
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (/*declarator=*/NULL,
- declspecs, NORMAL, 0, NULL);
+ declspecs, NORMAL, 0, NULL, NULL);
finish_anon_union (decl);
}
}
@@ -4389,7 +4389,7 @@ groktypename (cp_decl_specifier_seq *typ
= is_template_arg ? TEMPLATE_TYPE_ARG : TYPENAME;
attrs = type_specifiers->attributes;
type_specifiers->attributes = NULL_TREE;
- type = grokdeclarator (declarator, type_specifiers, context, 0, &attrs);
+ type = grokdeclarator (declarator, type_specifiers, context, 0, &attrs, NULL);
if (attrs && type != error_mark_node)
{
if (CLASS_TYPE_P (type))
@@ -4430,7 +4430,8 @@ start_decl (const cp_declarator *declara
int initialized,
tree attributes,
tree prefix_attributes,
- tree *pushed_scope_p)
+ tree *pushed_scope_p,
+ vec<tree, va_gc> *omp_declare_simd_clauses)
{
tree decl;
tree context;
@@ -4448,7 +4449,7 @@ start_decl (const cp_declarator *declara
attributes = chainon (attributes, prefix_attributes);
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
- &attributes);
+ &attributes, omp_declare_simd_clauses);
deprecated_state = DEPRECATED_NORMAL;
@@ -7323,7 +7324,8 @@ grokfndecl (tree ctype,
int template_count,
tree in_namespace,
tree* attrlist,
- location_t location)
+ location_t location,
+ vec<tree, va_gc> *omp_declare_simd_clauses)
{
tree decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@@ -7594,6 +7596,9 @@ grokfndecl (tree ctype,
if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
TREE_NOTHROW (decl) = 1;
+ if (omp_declare_simd_clauses)
+ finish_omp_declare_simd (decl, omp_declare_simd_clauses);
+
/* Caller will do the rest of this. */
if (check < 0)
return decl;
@@ -8589,7 +8595,8 @@ grokdeclarator (const cp_declarator *dec
cp_decl_specifier_seq *declspecs,
enum decl_context decl_context,
int initialized,
- tree* attrlist)
+ tree* attrlist,
+ vec<tree, va_gc> *omp_declare_simd_clauses)
{
tree type = NULL_TREE;
int longlong = 0;
@@ -10416,7 +10423,8 @@ grokdeclarator (const cp_declarator *dec
inlinep | (2 * constexpr_p),
sfk,
funcdef_flag, template_count, in_namespace,
- attrlist, declarator->id_loc);
+ attrlist, declarator->id_loc,
+ omp_declare_simd_clauses);
decl = set_virt_specifiers (decl, virt_specifiers);
if (decl == NULL_TREE)
return error_mark_node;
@@ -10637,7 +10645,8 @@ grokdeclarator (const cp_declarator *dec
publicp, inlinep | (2 * constexpr_p), sfk,
funcdef_flag,
template_count, in_namespace, attrlist,
- declarator->id_loc);
+ declarator->id_loc,
+ omp_declare_simd_clauses);
if (decl == NULL_TREE)
return error_mark_node;
@@ -13313,11 +13322,12 @@ start_preparsed_function (tree decl1, tr
int
start_function (cp_decl_specifier_seq *declspecs,
const cp_declarator *declarator,
- tree attrs)
+ tree attrs, vec<tree, va_gc> *omp_declare_simd_clauses)
{
tree decl1;
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
+ decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs,
+ omp_declare_simd_clauses);
if (decl1 == error_mark_node)
return 0;
/* If the declarator is not suitable for a function definition,
@@ -13959,10 +13969,11 @@ finish_function (int flags)
tree
grokmethod (cp_decl_specifier_seq *declspecs,
- const cp_declarator *declarator, tree attrlist)
+ const cp_declarator *declarator, tree attrlist,
+ vec<tree, va_gc> *omp_declare_simd_clauses)
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
- &attrlist);
+ &attrlist, omp_declare_simd_clauses);
if (fndecl == error_mark_node)
return error_mark_node;
@@ -34,7 +34,7 @@ enum decl_context
/* We need this in here to get the decl_context definition. */
extern tree grokdeclarator (const cp_declarator *,
cp_decl_specifier_seq *,
- enum decl_context, int, tree*);
+ enum decl_context, int, tree*, vec<tree, va_gc> *);
/* States indicating how grokdeclarator() should handle declspecs marked
with __attribute__((deprecated)). An object declared as
@@ -1169,6 +1169,41 @@ cp_token_cache_new (cp_token *first, cp_
return cache;
}
+/* Diagnose if #pragma omp declare simd isn't followed immediately
+ by function declaration or definition. */
+
+static inline void
+cp_ensure_no_omp_declare_simd (cp_parser *parser)
+{
+ if (parser->omp_declare_simd_clauses
+ && (*parser->omp_declare_simd_clauses)[0] != error_mark_node)
+ {
+ error ("%<#pragma omp declare simd%> not immediately followed by "
+ "function declaration or definition");
+ parser->omp_declare_simd_clauses = NULL;
+ }
+}
+
+/* Finalize #pragma omp declare simd clauses after FNDECL has been parsed,
+ and put that into "omp declare simd" attribute. */
+
+static inline void
+cp_finish_omp_declare_simd (cp_parser *parser, tree fndecl)
+{
+ if (__builtin_expect (parser->omp_declare_simd_clauses != NULL, 0))
+ {
+ if (fndecl == error_mark_node)
+ {
+ parser->omp_declare_simd_clauses = NULL;
+ return;
+ }
+ if (TREE_CODE (fndecl) != FUNCTION_DECL)
+ {
+ cp_ensure_no_omp_declare_simd (parser);
+ return;
+ }
+ }
+}
/* Decl-specifiers. */
@@ -2149,7 +2184,13 @@ static bool cp_parser_function_transacti
static tree cp_parser_transaction_cancel
(cp_parser *);
-enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
+enum pragma_context {
+ pragma_external,
+ pragma_member,
+ pragma_objc_icode,
+ pragma_stmt,
+ pragma_compound
+};
static bool cp_parser_pragma
(cp_parser *, enum pragma_context);
@@ -8126,7 +8167,7 @@ cp_parser_trait_expr (cp_parser* parser,
/* Call grokdeclarator to figure out what type this is. */
type1 = grokdeclarator (NULL, &decl_specs, TYPENAME,
- /*initialized=*/0, /*attrlist=*/NULL);
+ /*initialized=*/0, /*attrlist=*/NULL, NULL);
if (binary)
{
@@ -8143,7 +8184,7 @@ cp_parser_trait_expr (cp_parser* parser,
/* Call grokdeclarator to figure out what type this is. */
type2 = grokdeclarator (NULL, &decl_specs, TYPENAME,
- /*initialized=*/0, /*attrlist=*/NULL);
+ /*initialized=*/0, /*attrlist=*/NULL, NULL);
}
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
@@ -8600,9 +8641,7 @@ cp_parser_lambda_declarator_opt (cp_pars
/*late_return_type=*/NULL_TREE);
declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
- fco = grokmethod (&return_type_specs,
- declarator,
- attributes);
+ fco = grokmethod (&return_type_specs, declarator, attributes, NULL);
if (fco != error_mark_node)
{
DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
@@ -9447,7 +9486,7 @@ cp_parser_condition (cp_parser* parser)
decl = start_decl (declarator, &type_specifiers,
/*initialized_p=*/true,
attributes, /*prefix_attributes=*/NULL_TREE,
- &pushed_scope);
+ &pushed_scope, NULL);
/* Parse the initializer. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
@@ -11154,6 +11193,8 @@ cp_parser_linkage_specification (cp_pars
production. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
+ cp_ensure_no_omp_declare_simd (parser);
+
/* Consume the `{' token. */
cp_lexer_consume_token (parser->lexer);
/* Parse the declarations. */
@@ -11524,7 +11565,7 @@ cp_parser_conversion_type_id (cp_parser*
declarator = cp_parser_conversion_declarator_opt (parser);
type_specified = grokdeclarator (declarator, &type_specifiers, TYPENAME,
- /*initialized=*/0, &attributes);
+ /*initialized=*/0, &attributes, NULL);
if (attributes)
cplus_decl_attributes (&type_specified, attributes, /*flags=*/0);
@@ -12398,7 +12439,7 @@ cp_parser_template_parameter (cp_parser*
parm = grokdeclarator (parameter_declarator->declarator,
¶meter_declarator->decl_specifiers,
TPARM, /*initialized=*/0,
- /*attrlist=*/NULL);
+ /*attrlist=*/NULL, NULL);
if (parm == error_mark_node)
return error_mark_node;
@@ -13449,7 +13490,7 @@ cp_parser_explicit_instantiation (cp_par
" %<constexpr%> specifier");
decl = grokdeclarator (declarator, &decl_specifiers,
- NORMAL, 0, &decl_specifiers.attributes);
+ NORMAL, 0, &decl_specifiers.attributes, NULL);
/* Turn access control back on for names used during
template instantiation. */
pop_deferring_access_checks ();
@@ -14702,7 +14743,7 @@ cp_parser_enum_specifier (cp_parser* par
if (type_specifiers.type != error_mark_node)
{
underlying_type = grokdeclarator (NULL, &type_specifiers, TYPENAME,
- /*initialized=*/0, NULL);
+ /*initialized=*/0, NULL, NULL);
if (underlying_type == error_mark_node)
underlying_type = NULL_TREE;
}
@@ -15049,6 +15090,7 @@ cp_parser_namespace_definition (cp_parse
bool has_visibility;
bool is_inline;
+ cp_ensure_no_omp_declare_simd (parser);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE))
{
maybe_warn_cpp0x (CPP0X_INLINE_NAMESPACES);
@@ -15443,10 +15485,10 @@ cp_parser_alias_declaration (cp_parser*
member_p = at_class_scope_p ();
if (member_p)
decl = grokfield (declarator, &decl_specs, NULL_TREE, false,
- NULL_TREE, attributes);
+ NULL_TREE, attributes, NULL);
else
decl = start_decl (declarator, &decl_specs, 0,
- attributes, NULL_TREE, &pushed_scope);
+ attributes, NULL_TREE, &pushed_scope, NULL);
if (decl == error_mark_node)
return decl;
@@ -15981,7 +16023,8 @@ cp_parser_init_declarator (cp_parser* pa
decl = start_decl (declarator, decl_specifiers,
range_for_decl_p? SD_INITIALIZED : is_initialized,
attributes, prefix_attributes,
- &pushed_scope);
+ &pushed_scope, parser->omp_declare_simd_clauses);
+ cp_finish_omp_declare_simd (parser, decl);
/* Adjust location of decl if declarator->id_loc is more appropriate:
set, and decl wasn't merged with another decl, in which case its
location would be different from input_location, and more accurate. */
@@ -16088,9 +16131,10 @@ cp_parser_init_declarator (cp_parser* pa
decl = grokfield (declarator, decl_specifiers,
initializer, !is_non_constant_init,
/*asmspec=*/NULL_TREE,
- prefix_attributes);
+ prefix_attributes, parser->omp_declare_simd_clauses);
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
+ cp_finish_omp_declare_simd (parser, decl);
}
/* Finish processing the declaration. But, skip member
@@ -17425,7 +17469,7 @@ cp_parser_parameter_declaration_list (cp
¶meter->decl_specifiers,
PARM,
parameter->default_argument != NULL_TREE,
- ¶meter->decl_specifiers.attributes);
+ ¶meter->decl_specifiers.attributes, NULL);
deprecated_state = DEPRECATED_NORMAL;
@@ -18302,6 +18346,8 @@ cp_parser_class_specifier_1 (cp_parser*
return error_mark_node;
}
+ cp_ensure_no_omp_declare_simd (parser);
+
/* Issue an error message if type-definitions are forbidden here. */
cp_parser_check_type_definition (parser);
/* Remember that we are defining one more class. */
@@ -19079,7 +19125,7 @@ cp_parser_member_specification_opt (cp_p
/* Accept #pragmas at class scope. */
if (token->type == CPP_PRAGMA)
{
- cp_parser_pragma (parser, pragma_external);
+ cp_parser_pragma (parser, pragma_member);
break;
}
@@ -19531,13 +19577,15 @@ cp_parser_member_declaration (cp_parser*
else
if (declarator->kind == cdk_function)
declarator->id_loc = token->location;
- /* Create the declaration. */
- decl = grokfield (declarator, &decl_specifiers,
- initializer, /*init_const_expr_p=*/true,
- asm_specification,
- attributes);
+ /* Create the declaration. */
+ decl = grokfield (declarator, &decl_specifiers,
+ initializer, /*init_const_expr_p=*/true,
+ asm_specification,
+ attributes, parser->omp_declare_simd_clauses);
}
+ cp_finish_omp_declare_simd (parser, decl);
+
/* Reset PREFIX_ATTRIBUTES. */
while (attributes && TREE_CHAIN (attributes) != first_attribute)
attributes = TREE_CHAIN (attributes);
@@ -20230,7 +20278,8 @@ cp_parser_exception_declaration (cp_pars
if (!type_specifiers.any_specifiers_p)
return error_mark_node;
- return grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL);
+ return grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1,
+ NULL, NULL);
}
/* Parse a throw-expression.
@@ -21666,7 +21715,8 @@ cp_parser_function_definition_from_speci
bool success_p;
/* Begin the function-definition. */
- success_p = start_function (decl_specifiers, declarator, attributes);
+ success_p = start_function (decl_specifiers, declarator, attributes,
+ parser->omp_declare_simd_clauses);
/* The things we're about to see are not directly qualified by any
template headers we've seen thus far. */
@@ -21678,6 +21728,12 @@ cp_parser_function_definition_from_speci
might be a friend. */
perform_deferred_access_checks (tf_warning_or_error);
+ if (success_p)
+ {
+ cp_finish_omp_declare_simd (parser, current_function_decl);
+ parser->omp_declare_simd_clauses = NULL;
+ }
+
if (!success_p)
{
/* Skip the entire function. */
@@ -22196,7 +22252,9 @@ cp_parser_save_member_function_body (cp_
tree fn;
/* Create the FUNCTION_DECL. */
- fn = grokmethod (decl_specifiers, declarator, attributes);
+ fn = grokmethod (decl_specifiers, declarator, attributes,
+ parser->omp_declare_simd_clauses);
+ cp_finish_omp_declare_simd (parser, fn);
/* If something went badly wrong, bail out now. */
if (fn == error_mark_node)
{
@@ -22698,7 +22756,7 @@ cp_parser_sizeof_operand (cp_parser* par
&decl_specs,
TYPENAME,
/*initialized=*/0,
- /*attrlist=*/NULL);
+ /*attrlist=*/NULL, NULL);
}
}
else if (pack_expansion_p)
@@ -24500,7 +24558,7 @@ cp_parser_objc_method_tail_params_opt (c
parm = grokdeclarator (parmdecl->declarator,
&parmdecl->decl_specifiers,
PARM, /*initialized=*/0,
- /*attrlist=*/NULL);
+ /*attrlist=*/NULL, NULL);
chainon (params, build_tree_list (NULL_TREE, parm));
token = cp_lexer_peek_token (parser->lexer);
@@ -24544,7 +24602,7 @@ cp_parser_objc_interstitial_code (cp_par
cp_parser_linkage_specification (parser);
/* Handle #pragma, if any. */
else if (token->type == CPP_PRAGMA)
- cp_parser_pragma (parser, pragma_external);
+ cp_parser_pragma (parser, pragma_objc_icode);
/* Allow stray semicolons. */
else if (token->type == CPP_SEMICOLON)
cp_lexer_consume_token (parser->lexer);
@@ -24848,7 +24906,7 @@ cp_parser_objc_class_ivars (cp_parser* p
else
decl = grokfield (declarator, &declspecs,
NULL_TREE, /*init_const_expr_p=*/false,
- NULL_TREE, attributes);
+ NULL_TREE, attributes, NULL);
/* Add the instance variable. */
if (decl != error_mark_node && decl != NULL_TREE)
@@ -25182,7 +25240,7 @@ cp_parser_objc_try_catch_finally_stateme
parameter_declaration = grokdeclarator (parm->declarator,
&parm->decl_specifiers,
PARM, /*initialized=*/0,
- /*attrlist=*/NULL);
+ /*attrlist=*/NULL, NULL);
}
if (seen_open_paren)
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
@@ -25392,7 +25450,7 @@ cp_parser_objc_struct_declaration (cp_pa
decl = grokfield (declarator, &declspecs,
NULL_TREE, /*init_const_expr_p=*/false,
- NULL_TREE, attributes);
+ NULL_TREE, attributes, NULL);
if (decl == error_mark_node || decl == NULL_TREE)
return error_mark_node;
@@ -25887,20 +25945,25 @@ cp_parser_omp_var_list_no_open (cp_parse
tree name, decl;
token = cp_lexer_peek_token (parser->lexer);
- name = cp_parser_id_expression (parser, /*template_p=*/false,
- /*check_dependency_p=*/true,
- /*template_p=*/NULL,
- /*declarator_p=*/false,
- /*optional_p=*/false);
- if (name == error_mark_node)
+ if (parser->omp_declare_simd_clauses)
+ decl = name = cp_parser_identifier (parser);
+ else
{
- if (colon)
- parser->colon_corrects_to_scope_p
- = saved_colon_corrects_to_scope_p;
- goto skip_comma;
- }
+ name = cp_parser_id_expression (parser, /*template_p=*/false,
+ /*check_dependency_p=*/true,
+ /*template_p=*/NULL,
+ /*declarator_p=*/false,
+ /*optional_p=*/false);
+ if (name == error_mark_node)
+ {
+ if (colon)
+ parser->colon_corrects_to_scope_p
+ = saved_colon_corrects_to_scope_p;
+ goto skip_comma;
+ }
- decl = cp_parser_lookup_name_simple (parser, name, token->location);
+ decl = cp_parser_lookup_name_simple (parser, name, token->location);
+ }
if (decl == error_mark_node)
cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
token->location);
@@ -27040,6 +27103,8 @@ cp_parser_omp_all_clauses (cp_parser *pa
}
saw_error:
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ if (parser->omp_declare_simd_clauses)
+ return clauses;
return finish_omp_clauses (clauses);
}
@@ -27799,7 +27864,7 @@ cp_parser_omp_for_loop (cp_parser *parse
decl = start_decl (declarator, &type_specifiers,
SD_INITIALIZED, attributes,
/*prefix_attributes=*/NULL_TREE,
- &pushed_scope);
+ &pushed_scope, NULL);
auto_node = type_uses_auto (TREE_TYPE (decl));
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
@@ -28599,6 +28664,91 @@ cp_parser_omp_cancellation_point (cp_par
finish_omp_cancellation_point (clauses);
}
+/* OpenMP 4.0:
+ # pragma omp declare simd declare-simd-clauses[optseq] new-line */
+
+#define OMP_DECLARE_SIMD_CLAUSE_MASK \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
+
+static void
+cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
+ enum pragma_context context)
+{
+ bool first_p = parser->omp_declare_simd_clauses == NULL;
+ vec_safe_push (parser->omp_declare_simd_clauses, NULL_TREE);
+ tree clauses
+ = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
+ "#pragma omp declare simd", pragma_tok);
+ parser->omp_declare_simd_clauses->last () = clauses;
+ if (first_p)
+ {
+ while (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
+ cp_parser_pragma (parser, context);
+ switch (context)
+ {
+ case pragma_external:
+ cp_parser_declaration (parser);
+ break;
+ case pragma_member:
+ cp_parser_member_declaration (parser);
+ break;
+ case pragma_objc_icode:
+ cp_parser_block_declaration (parser, /*statement_p=*/false);
+ break;
+ default:
+ cp_parser_declaration_statement (parser);
+ break;
+ }
+ if (parser->omp_declare_simd_clauses
+ && (*parser->omp_declare_simd_clauses)[0] != error_mark_node
+ && (*parser->omp_declare_simd_clauses)[0] != integer_zero_node)
+ error_at (pragma_tok->location,
+ "%<#pragma omp declare simd%> not immediately followed by "
+ "function declaration or definition");
+ parser->omp_declare_simd_clauses = NULL;
+ }
+}
+
+/* OpenMP 4.0
+ #pragma omp declare simd declare-simd-clauses[optseq] new-line
+ #pragma omp declare reduction (reduction-id : typename-list : expression) \
+ identity-clause[opt] new-line */
+
+static void
+cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
+ enum pragma_context context)
+{
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+
+ if (strcmp (p, "simd") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_omp_declare_simd (parser, pragma_tok,
+ context);
+ return;
+ }
+ cp_ensure_no_omp_declare_simd (parser);
+/* if (strcmp (p, "reduction") == 0)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_omp_declare_reduction (parser, pragma_tok,
+ context);
+ return;
+ } */
+ }
+ cp_parser_error (parser, "expected %<simd%> or %<reduction%>");
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+}
+
/* Main entry point to OpenMP statement pragmas. */
static void
@@ -28998,6 +29148,8 @@ cp_parser_pragma (cp_parser *parser, enu
parser->lexer->in_pragma = true;
id = pragma_tok->pragma_kind;
+ if (id != PRAGMA_OMP_DECLARE_REDUCTION)
+ cp_ensure_no_omp_declare_simd (parser);
switch (id)
{
case PRAGMA_GCC_PCH_PREPROCESS:
@@ -29103,6 +29255,10 @@ cp_parser_pragma (cp_parser *parser, enu
cp_parser_omp_threadprivate (parser, pragma_tok);
return false;
+ case PRAGMA_OMP_DECLARE_REDUCTION:
+ cp_parser_omp_declare (parser, pragma_tok, context);
+ return false;
+
case PRAGMA_OMP_ATOMIC:
case PRAGMA_OMP_CRITICAL:
case PRAGMA_OMP_FOR:
@@ -29114,7 +29270,7 @@ cp_parser_pragma (cp_parser *parser, enu
case PRAGMA_OMP_SINGLE:
case PRAGMA_OMP_TASK:
case PRAGMA_OMP_TASKGROUP:
- if (context == pragma_external)
+ if (context != pragma_stmt && context != pragma_compound)
goto bad_stmt;
cp_parser_omp_construct (parser, pragma_tok);
return true;
@@ -340,6 +340,15 @@ typedef struct GTY(()) cp_parser {
/* The number of template parameter lists that apply directly to the
current declaration. */
unsigned num_template_parameter_lists;
+
+ /* When parsing #pragma omp declare simd, this is a vector of
+ the clauses, each tree is either NULL_TREE, or OMP_CLAUSE
+ with optional chain of other clauses. If error regarding
+ omp declare simd has been reported already, either
+ omp_declare_simd_clauses is set to NULL, or first element set
+ to error_mark_node. If a FUNCTION_DECL has been seen already,
+ first element is set to integer_zero_node. */
+ vec<tree, va_gc> *omp_declare_simd_clauses;
} cp_parser;
/* In parser.c */
@@ -8431,6 +8431,8 @@ can_complete_type_without_circularity (t
return 1;
}
+static tree tsubst_omp_clauses (tree, bool, tree, tsubst_flags_t, tree);
+
/* Apply any attributes which had to be deferred until instantiation
time. DECL_P, ATTRIBUTES and ATTR_FLAGS are as cplus_decl_attributes;
ARGS, COMPLAIN, IN_DECL are as tsubst. */
@@ -8472,15 +8474,28 @@ apply_late_template_attributes (tree *de
{
*p = TREE_CHAIN (t);
TREE_CHAIN (t) = NULL_TREE;
+ if (flag_openmp
+ && is_attribute_p ("omp declare simd",
+ get_attribute_name (t))
+ && TREE_VALUE (t))
+ {
+ tree clauses = TREE_VALUE (t);
+ clauses = tsubst_omp_clauses (clauses, true, args,
+ complain, in_decl);
+ c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
+ clauses = finish_omp_clauses (clauses);
+ TREE_VALUE (t)
+ = c_omp_declare_simd_clauses_to_numbers (*decl_p, clauses);
+ }
/* If the first attribute argument is an identifier, don't
pass it through tsubst. Attributes like mode, format,
cleanup and several target specific attributes expect it
unmodified. */
- if (TREE_VALUE (t)
- && TREE_CODE (TREE_VALUE (t)) == TREE_LIST
- && TREE_VALUE (TREE_VALUE (t))
- && (TREE_CODE (TREE_VALUE (TREE_VALUE (t)))
- == IDENTIFIER_NODE))
+ else if (TREE_VALUE (t)
+ && TREE_CODE (TREE_VALUE (t)) == TREE_LIST
+ && TREE_VALUE (TREE_VALUE (t))
+ && (TREE_CODE (TREE_VALUE (TREE_VALUE (t)))
+ == IDENTIFIER_NODE))
{
tree chain
= tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain,
@@ -12562,8 +12577,8 @@ tsubst_copy (tree t, tree args, tsubst_f
/* Like tsubst_copy, but specifically for OpenMP clauses. */
static tree
-tsubst_omp_clauses (tree clauses, tree args, tsubst_flags_t complain,
- tree in_decl)
+tsubst_omp_clauses (tree clauses, bool declare_simd,
+ tree args, tsubst_flags_t complain, tree in_decl)
{
tree new_clauses = NULL, nc, oc;
@@ -12596,22 +12611,52 @@ tsubst_omp_clauses (tree clauses, tree a
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_FINAL:
+ case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_UNIFORM:
+ case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_DIST_SCHEDULE:
+ case OMP_CLAUSE_NUM_TEAMS:
+ case OMP_CLAUSE_SAFELEN:
+ case OMP_CLAUSE_SIMDLEN:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
break;
+ case OMP_CLAUSE_LINEAR:
+ case OMP_CLAUSE_ALIGNED:
+ OMP_CLAUSE_OPERAND (nc, 0)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_OPERAND (nc, 1)
+ = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
+ in_decl, /*integral_constant_expression_p=*/false);
+ break;
+
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_MERGEABLE:
+ case OMP_CLAUSE_INBRANCH:
+ case OMP_CLAUSE_NOTINBRANCH:
+ case OMP_CLAUSE_PROC_BIND:
+ case OMP_CLAUSE_FOR:
+ case OMP_CLAUSE_PARALLEL:
+ case OMP_CLAUSE_SECTIONS:
+ case OMP_CLAUSE_TASKGROUP:
break;
default:
gcc_unreachable ();
}
}
- return finish_omp_clauses (nreverse (new_clauses));
+ new_clauses = nreverse (new_clauses);
+ if (!declare_simd)
+ new_clauses = finish_omp_clauses (new_clauses);
+ return new_clauses;
}
/* Like tsubst_copy_and_build, but unshare TREE_LIST nodes. */
@@ -13181,7 +13226,7 @@ tsubst_expr (tree t, tree args, tsubst_f
break;
case OMP_PARALLEL:
- tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
+ tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t), false,
args, complain, in_decl);
stmt = begin_omp_parallel ();
RECUR (OMP_PARALLEL_BODY (t));
@@ -13190,7 +13235,7 @@ tsubst_expr (tree t, tree args, tsubst_f
break;
case OMP_TASK:
- tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t),
+ tmp = tsubst_omp_clauses (OMP_TASK_CLAUSES (t), false,
args, complain, in_decl);
stmt = begin_omp_task ();
RECUR (OMP_TASK_BODY (t));
@@ -13206,7 +13251,7 @@ tsubst_expr (tree t, tree args, tsubst_f
tree declv, initv, condv, incrv;
int i;
- clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t),
+ clauses = tsubst_omp_clauses (OMP_FOR_CLAUSES (t), false,
args, complain, in_decl);
declv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
initv = make_tree_vec (TREE_VEC_LENGTH (OMP_FOR_INIT (t)));
@@ -13237,7 +13282,8 @@ tsubst_expr (tree t, tree args, tsubst_f
case OMP_SECTIONS:
case OMP_SINGLE:
- tmp = tsubst_omp_clauses (OMP_CLAUSES (t), args, complain, in_decl);
+ tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false,
+ args, complain, in_decl);
stmt = push_stmt_list ();
RECUR (OMP_BODY (t));
stmt = pop_stmt_list (stmt);
@@ -4028,6 +4028,7 @@ finish_omp_clauses (tree clauses)
bitmap_head aligned_head;
tree c, t, *pc = &clauses;
const char *name;
+ bool branch_seen = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -4426,8 +4427,6 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_UNTIED:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_MERGEABLE:
- case OMP_CLAUSE_INBRANCH:
- case OMP_CLAUSE_NOTINBRANCH:
case OMP_CLAUSE_PARALLEL:
case OMP_CLAUSE_FOR:
case OMP_CLAUSE_SECTIONS:
@@ -4435,6 +4434,17 @@ finish_omp_clauses (tree clauses)
case OMP_CLAUSE_PROC_BIND:
break;
+ case OMP_CLAUSE_INBRANCH:
+ case OMP_CLAUSE_NOTINBRANCH:
+ if (branch_seen)
+ {
+ error ("%<inbranch%> clause is incompatible with "
+ "%<notinbranch%>");
+ remove = true;
+ }
+ branch_seen = true;
+ break;
+
default:
gcc_unreachable ();
}
@@ -4619,6 +4629,90 @@ finish_omp_clauses (tree clauses)
return clauses;
}
+/* Finalize #pragma omp declare simd clauses after FNDECL has been parsed,
+ and put that into "omp declare simd" attribute. */
+
+void
+finish_omp_declare_simd (tree fndecl, vec<tree, va_gc> *clauses)
+{
+ tree cl;
+ int i;
+
+ if (TREE_CODE (fndecl) != FUNCTION_DECL)
+ return;
+ if ((*clauses)[0] == integer_zero_node)
+ {
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "%<#pragma omp declare simd%> not immediately followed by "
+ "a single function declaration or definition");
+ (*clauses)[0] = error_mark_node;
+ return;
+ }
+ if ((*clauses)[0] == error_mark_node)
+ return;
+
+ FOR_EACH_VEC_SAFE_ELT (clauses, i, cl)
+ {
+ tree c, *pc, decl, name;
+ for (pc = &cl, c = cl; c; c = *pc)
+ {
+ bool remove = false;
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_UNIFORM:
+ case OMP_CLAUSE_LINEAR:
+ case OMP_CLAUSE_ALIGNED:
+ case OMP_CLAUSE_REDUCTION:
+ name = OMP_CLAUSE_DECL (c);
+ if (name == error_mark_node)
+ remove = true;
+ else
+ {
+ for (decl = DECL_ARGUMENTS (fndecl); decl;
+ decl = TREE_CHAIN (decl))
+ if (DECL_NAME (decl) == name)
+ break;
+ if (decl == NULL_TREE)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a function parameter", name);
+ remove = true;
+ }
+ else
+ OMP_CLAUSE_DECL (c) = decl;
+ }
+ break;
+ default:
+ break;
+ }
+ if (remove)
+ *pc = OMP_CLAUSE_CHAIN (c);
+ else
+ pc = &OMP_CLAUSE_CHAIN (c);
+ }
+ cl = finish_omp_clauses (cl);
+ cl = c_omp_declare_simd_clauses_to_numbers (fndecl, cl);
+ if (!processing_template_decl)
+ {
+ for (c = lookup_attribute ("omp declare simd",
+ DECL_ATTRIBUTES (fndecl));
+ c; c = lookup_attribute ("omp declare simd",
+ TREE_CHAIN (c)))
+ if (omp_declare_simd_clauses_equal (TREE_VALUE (c), cl))
+ break;
+ if (c)
+ continue;
+ }
+ c = build_tree_list (get_identifier ("omp declare simd"), cl);
+ TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
+ if (processing_template_decl)
+ ATTR_IS_DEPENDENT (c) = 1;
+ DECL_ATTRIBUTES (fndecl) = c;
+ }
+
+ (*clauses)[0] = integer_zero_node;
+}
+
/* For all variables in the tree_list VARS, mark them as thread local. */
void
@@ -0,0 +1,212 @@
+// Test parsing of #pragma omp declare simd
+// { dg-do compile }
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) \
+ linear (c : 4) simdlen (8) notinbranch
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a \
+ : 4) simdlen (4) inbranch
+int f1 (int a, int *b, int c);
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+int f2 (int a, int *b, int c)
+{
+ return a + *b + c;
+}
+
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+template <typename T>
+T f3 (int a, int *b, T c);
+
+template <>
+int f3 (int, int *, int);
+
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) notinbranch simdlen (4)
+template <typename T>
+int f4 (int a, int *b, T c)
+{
+ return a + *b + c;
+}
+
+template <>
+int f4 (int, int *, int);
+
+template <typename T>
+int f5 (int a, int *b, T c);
+
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+template <>
+int f5 (int a, int *b, int c);
+
+template <int N>
+int f6 (int a, int *b, int c);
+
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) inbranch simdlen (4)
+template <>
+int f6<3> (int a, int *b, int c);
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (long long)) linear (c : 4) simdlen (8)
+__extension__
+long long f7 (long long a, long long *b, long long c);
+
+#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) notinbranch simdlen (8)
+extern "C"
+int f8 (int a, int *b, int c);
+
+extern "C"
+{
+ #pragma omp declare simd
+ int f9 (int a, int *b, int c);
+}
+
+namespace N1
+{
+ namespace N2
+ {
+ #pragma omp declare simd simdlen (2) aligned (b : sizeof (long long) * 2)
+ __extension__ long long
+ f10 (long long *b)
+ {
+ return *b;
+ }
+ }
+}
+
+struct A
+{
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ int f11 (int a, int *b, int c);
+
+ #pragma omp declare simd
+ template <int N>
+ int f12 (int a, int *b, int c);
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) notinbranch simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4) inbranch
+ static int f13 (int a, int *b, int c);
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ int f14 (int a, int *b, int c) { return a + *b + c; }
+
+ #pragma omp declare simd
+ template <int N>
+ int f15 (int a, int *b, int c) { return a + *b + c; }
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ static int f16 (int a, int *b, int c) { return a + *b + c; }
+};
+
+template <>
+int A::f12<2> (int, int *, int);
+
+template <>
+int A::f15<2> (int, int *, int);
+
+template <typename T>
+struct B
+{
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8) notinbranch
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4) inbranch
+ int f17 (int a, int *b, int c);
+
+ #pragma omp declare simd
+ template <int N>
+ int f18 (int a, int *b, int c);
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ static int f19 (int a, int *b, int c);
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ int f20 (int a, int *b, int c) { return a + *b + c; }
+
+ #pragma omp declare simd
+ template <int N>
+ int f21 (int a, int *b, int c) { return a + *b + c; }
+
+ #pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ static int f22 (int a, int *b, int c) { return a + *b + c; }
+
+ template <int N>
+ int f23 (int, int *, int);
+
+ template <int N>
+ static int f24 (int, int *, int);
+
+ template <int N>
+ int f25 (int, int *, int);
+
+ template <int N>
+ static int f26 (int, int *, int);
+};
+
+B <int> b;
+
+template <>
+template <>
+int B<int>::f18<0> (int, int *, int);
+
+template <>
+template <>
+int B<int>::f21<9> (int, int *, int);
+
+#pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int)) uniform (a, c)
+template <>
+template <>
+int B<int>::f23<7> (int a, int *b, int c);
+
+#pragma omp declare simd simdlen (4) aligned (b : 8 * sizeof (int)) linear (a, c : 2)
+template <>
+template <>
+int B<int>::f24<-1> (int a, int *b, int c);
+
+#pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int)) uniform (a, c)
+template <>
+template <>
+int B<int>::f25<7> (int a, int *b, int c)
+{
+ return a + *b + c;
+}
+
+#pragma omp declare simd simdlen (4) aligned (b : 8 * sizeof (int)) linear (a, c : 2)
+template <>
+template <>
+int B<int>::f26<-1> (int a, int *b, int c)
+{
+ return a + *b + c;
+}
+
+int
+f27 (int x)
+{
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ extern int f28 (int a, int *b, int c);
+ {
+ x++;
+ #pragma omp declare simd simdlen (4) linear (c)
+ extern int f29 (int a, int *b, int c);
+ }
+ return x;
+}
+
+#pragma omp declare simd simdlen (16)
+int
+f30 (int x)
+{
+ #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int))
+ extern int f31 (int a, int *b, int c);
+ return x;
+}
+
+template <int N>
+struct C
+{
+ #pragma omp declare simd simdlen (N) aligned (a : N * sizeof (int)) linear (c : N) notinbranch
+ int f32 (int a, int *b, int c);
+};
+
+C <2> c;
@@ -0,0 +1,60 @@
+// Test parsing of #pragma omp declare simd
+// { dg-do compile }
+
+#pragma omp declare simd
+int a; // { dg-error "not immediately followed by function declaration or definition" }
+
+#pragma omp declare simd
+int fn1 (int a), fn2 (int a); // { dg-error "not immediately followed by a single function declaration or definition" }
+
+#pragma omp declare simd
+int b, fn3 (int a); // { dg-error "not immediately followed by function declaration or definition" }
+
+#pragma omp declare simd linear (a)
+int fn4 (int a), c; // { dg-error "not immediately followed by function declaration or definition" }
+
+#pragma omp declare simd
+extern "C" // { dg-error "not immediately followed by function declaration or definition" }
+{
+ int fn5 (int a);
+}
+
+#pragma omp declare simd // { dg-error "not immediately followed by function declaration or definition" }
+namespace N1
+{
+ int fn6 (int a);
+}
+
+#pragma omp declare simd simdlen (4)
+struct A
+{ // { dg-error "not immediately followed by function declaration or definition" }
+ int fn7 (int a);
+};
+
+#pragma omp declare simd
+template <typename T>
+struct B
+{ // { dg-error "not immediately followed by function declaration or definition" }
+ int fn8 (int a);
+};
+
+struct C
+{
+#pragma omp declare simd // { dg-error "not immediately followed by function declaration or definition" }
+ public: // { dg-error "expected unqualified-id before" }
+ int fn9 (int a);
+};
+
+int t;
+
+#pragma omp declare simd
+#pragma omp declare simd
+#pragma omp threadprivate(t) // { dg-error "not immediately followed by function declaration or definition" }
+int fn10 (int a);
+
+#pragma omp declare simd inbranch notinbranch
+int fn11 (int); // { dg-error "clause is incompatible with" }
+
+#pragma omp declare simd simdlen (N) // { dg-error "was not declared in this scope" }
+template <int N>
+int fn12 (int);