@@ -11656,16 +11656,7 @@ c_finish_omp_declare_simd (tree fndecl,
pc = &OMP_CLAUSE_CHAIN (c);
}
cl = c_finish_omp_clauses (cl);
- tree saved_arguments = DECL_ARGUMENTS (fndecl);
- DECL_ARGUMENTS (fndecl) = parms;
- cl = c_omp_declare_simd_clauses_to_numbers (fndecl, cl);
- DECL_ARGUMENTS (fndecl) = saved_arguments;
- 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;
+ cl = c_omp_declare_simd_clauses_to_numbers (parms, cl);
c = build_tree_list (get_identifier ("omp declare simd"), cl);
TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
DECL_ATTRIBUTES (fndecl) = c;
@@ -5100,9 +5100,8 @@ 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);
+/* Remove redundant "omp declare simd" attributes from fndecl. */
+extern void omp_remove_redundant_declare_simd_attrs (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
@@ -7299,6 +7299,22 @@ check_static_quals (tree decl, cp_cv_qua
decl);
}
+/* Helper function. Replace the temporary this parameter injected
+ during cp_finish_omp_declare_simd with the real this parameter. */
+
+static tree
+declare_simd_adjust_this (tree *tp, int *walk_subtrees, void *data)
+{
+ tree this_parm = (tree) data;
+ if (TREE_CODE (*tp) == PARM_DECL
+ && DECL_NAME (*tp) == this_identifier
+ && *tp != this_parm)
+ *tp = this_parm;
+ else if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
/* CTYPE is class type, or null if non-class.
TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
or METHOD_TYPE.
@@ -7337,8 +7353,7 @@ grokfndecl (tree ctype,
int template_count,
tree in_namespace,
tree* attrlist,
- location_t location,
- vec<tree, va_gc> *omp_declare_simd_clauses)
+ location_t location)
{
tree decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@@ -7627,8 +7642,25 @@ 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);
+ if (flag_openmp)
+ {
+ /* Adjust "omp declare simd" attributes. */
+ tree ods = lookup_attribute ("omp declare simd", *attrlist);
+ if (ods)
+ {
+ tree attr;
+ for (attr = ods; attr;
+ attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr)))
+ {
+ if (TREE_CODE (type) == METHOD_TYPE)
+ walk_tree (&TREE_VALUE (attr), declare_simd_adjust_this,
+ DECL_ARGUMENTS (decl), NULL);
+ TREE_VALUE (attr)
+ = c_omp_declare_simd_clauses_to_numbers (DECL_ARGUMENTS (decl),
+ TREE_VALUE (attr));
+ }
+ }
+ }
/* Caller will do the rest of this. */
if (check < 0)
@@ -10494,8 +10526,7 @@ grokdeclarator (const cp_declarator *dec
inlinep | (2 * constexpr_p),
sfk,
funcdef_flag, template_count, in_namespace,
- attrlist, declarator->id_loc,
- declspecs->omp_declare_simd_clauses);
+ attrlist, declarator->id_loc);
decl = set_virt_specifiers (decl, virt_specifiers);
if (decl == NULL_TREE)
return error_mark_node;
@@ -10708,8 +10739,7 @@ grokdeclarator (const cp_declarator *dec
publicp, inlinep | (2 * constexpr_p), sfk,
funcdef_flag,
template_count, in_namespace, attrlist,
- declarator->id_loc,
- declspecs->omp_declare_simd_clauses);
+ declarator->id_loc);
if (decl == NULL_TREE)
return error_mark_node;
@@ -1227,12 +1227,11 @@ cp_token_cache_new (cp_token *first, cp_
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)
+ if (parser->omp_declare_simd && !parser->omp_declare_simd->error_seen)
{
error ("%<#pragma omp declare simd%> not immediately followed by "
"function declaration or definition");
- parser->omp_declare_simd_clauses = NULL;
+ parser->omp_declare_simd = NULL;
}
}
@@ -1240,14 +1239,13 @@ cp_ensure_no_omp_declare_simd (cp_parser
and put that into "omp declare simd" attribute. */
static inline void
-cp_finish_omp_declare_simd (cp_parser *parser,
- cp_decl_specifier_seq *declspecs, tree fndecl)
+cp_finalize_omp_declare_simd (cp_parser *parser, tree fndecl)
{
- if (__builtin_expect (parser->omp_declare_simd_clauses != NULL, 0))
+ if (__builtin_expect (parser->omp_declare_simd != NULL, 0))
{
if (fndecl == error_mark_node)
{
- parser->omp_declare_simd_clauses = NULL;
+ parser->omp_declare_simd = NULL;
return;
}
if (TREE_CODE (fndecl) != FUNCTION_DECL)
@@ -1256,7 +1254,6 @@ cp_finish_omp_declare_simd (cp_parser *p
return;
}
}
- declspecs->omp_declare_simd_clauses = NULL;
}
/* Decl-specifiers. */
@@ -2066,7 +2063,7 @@ static cp_virt_specifiers cp_parser_virt
static cp_ref_qualifier cp_parser_ref_qualifier_opt
(cp_parser *);
static tree cp_parser_late_return_type_opt
- (cp_parser *, cp_cv_quals);
+ (cp_parser *, cp_declarator *, cp_cv_quals);
static tree cp_parser_declarator_id
(cp_parser *, bool);
static tree cp_parser_type_id
@@ -2100,6 +2097,9 @@ static vec<constructor_elt, va_gc> *cp_p
static bool cp_parser_ctor_initializer_opt_and_function_body
(cp_parser *, bool);
+static tree cp_parser_late_parsing_omp_declare_simd
+ (cp_parser *, tree);
+
/* Classes [gram.class] */
static tree cp_parser_class_name
@@ -16504,12 +16504,10 @@ cp_parser_init_declarator (cp_parser* pa
{
if (parser->in_unbraced_linkage_specification_p)
decl_specifiers->storage_class = sc_extern;
- decl_specifiers->omp_declare_simd_clauses
- = parser->omp_declare_simd_clauses;
decl = start_decl (declarator, decl_specifiers,
range_for_decl_p? SD_INITIALIZED : is_initialized,
attributes, prefix_attributes, &pushed_scope);
- cp_finish_omp_declare_simd (parser, decl_specifiers, decl);
+ cp_finalize_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. */
@@ -16613,14 +16611,12 @@ cp_parser_init_declarator (cp_parser* pa
pop_scope (pushed_scope);
pushed_scope = NULL_TREE;
}
- decl_specifiers->omp_declare_simd_clauses
- = parser->omp_declare_simd_clauses;
decl = grokfield (declarator, decl_specifiers,
initializer, !is_non_constant_init,
/*asmspec=*/NULL_TREE, prefix_attributes);
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
- cp_finish_omp_declare_simd (parser, decl_specifiers, decl);
+ cp_finalize_omp_declare_simd (parser, decl);
}
/* Finish processing the declaration. But, skip member
@@ -16922,7 +16918,9 @@ cp_parser_direct_declarator (cp_parser*
attrs = cp_parser_std_attribute_spec_seq (parser);
late_return = (cp_parser_late_return_type_opt
- (parser, memfn ? cv_quals : -1));
+ (parser, declarator,
+ memfn ? cv_quals : -1));
+
/* Parse the virt-specifier-seq. */
virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
@@ -17648,24 +17646,28 @@ parsing_nsdmi (void)
Returns the type indicated by the type-id.
+ In addition to this this parses any queued up omp declare simd
+ clauses.
+
QUALS is either a bitmask of cv_qualifiers or -1 for a non-member
function. */
static tree
-cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals)
+cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
+ cp_cv_quals quals)
{
cp_token *token;
- tree type;
+ tree type = NULL_TREE;
+ bool declare_simd_p = (parser->omp_declare_simd
+ && declarator
+ && declarator->kind == cdk_id);
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* A late-specified return type is indicated by an initial '->'. */
- if (token->type != CPP_DEREF)
+ if (token->type != CPP_DEREF && !declare_simd_p)
return NULL_TREE;
- /* Consume the ->. */
- cp_lexer_consume_token (parser->lexer);
-
tree save_ccp = current_class_ptr;
tree save_ccr = current_class_ref;
if (quals >= 0)
@@ -17674,7 +17676,18 @@ cp_parser_late_return_type_opt (cp_parse
inject_this_parameter (current_class_type, quals);
}
- type = cp_parser_trailing_type_id (parser);
+ if (token->type == CPP_DEREF)
+ {
+ /* Consume the ->. */
+ cp_lexer_consume_token (parser->lexer);
+
+ type = cp_parser_trailing_type_id (parser);
+ }
+
+ if (declare_simd_p)
+ declarator->std_attributes
+ = cp_parser_late_parsing_omp_declare_simd (parser,
+ declarator->std_attributes);
if (quals >= 0)
{
@@ -20151,14 +20164,12 @@ cp_parser_member_declaration (cp_parser*
if (declarator->kind == cdk_function)
declarator->id_loc = token->location;
/* Create the declaration. */
- decl_specifiers.omp_declare_simd_clauses
- = parser->omp_declare_simd_clauses;
decl = grokfield (declarator, &decl_specifiers,
initializer, /*init_const_expr_p=*/true,
asm_specification, attributes);
}
- cp_finish_omp_declare_simd (parser, &decl_specifiers, decl);
+ cp_finalize_omp_declare_simd (parser, decl);
/* Reset PREFIX_ATTRIBUTES. */
while (attributes && TREE_CHAIN (attributes) != first_attribute)
@@ -22293,8 +22304,6 @@ cp_parser_function_definition_from_speci
bool success_p;
/* Begin the function-definition. */
- decl_specifiers->omp_declare_simd_clauses
- = parser->omp_declare_simd_clauses;
success_p = start_function (decl_specifiers, declarator, attributes);
/* The things we're about to see are not directly qualified by any
@@ -22309,15 +22318,13 @@ cp_parser_function_definition_from_speci
if (success_p)
{
- cp_finish_omp_declare_simd (parser, decl_specifiers,
- current_function_decl);
- parser->omp_declare_simd_clauses = NULL;
+ cp_finalize_omp_declare_simd (parser, current_function_decl);
+ parser->omp_declare_simd = NULL;
}
if (!success_p)
{
/* Skip the entire function. */
- decl_specifiers->omp_declare_simd_clauses = NULL;
cp_parser_skip_to_end_of_block_or_statement (parser);
fn = error_mark_node;
}
@@ -22848,10 +22855,8 @@ cp_parser_save_member_function_body (cp_
tree fn;
/* Create the FUNCTION_DECL. */
- decl_specifiers->omp_declare_simd_clauses
- = parser->omp_declare_simd_clauses;
fn = grokmethod (decl_specifiers, declarator, attributes);
- cp_finish_omp_declare_simd (parser, decl_specifiers, fn);
+ cp_finalize_omp_declare_simd (parser, fn);
/* If something went badly wrong, bail out now. */
if (fn == error_mark_node)
{
@@ -26592,20 +26597,15 @@ cp_parser_omp_var_list_no_open (cp_parse
tree name, decl;
token = cp_lexer_peek_token (parser->lexer);
- if (parser->omp_declare_simd_clauses)
- decl = name = cp_parser_identifier (parser);
- else
- {
- 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)
- 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)
+ 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);
@@ -29686,7 +29686,6 @@ cp_parser_omp_target (cp_parser *parser,
| (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))
@@ -29694,13 +29693,24 @@ 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,
- false);
- parser->omp_declare_simd_clauses->last () = clauses;
+ bool first_p = parser->omp_declare_simd == NULL;
+ cp_omp_declare_simd_data data;
+ if (first_p)
+ {
+ data.error_seen = false;
+ data.fndecl_seen = false;
+ data.tokens = vNULL;
+ parser->omp_declare_simd = &data;
+ }
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+ parser->omp_declare_simd->error_seen = true;
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ struct cp_token_cache *cp
+ = cp_token_cache_new (pragma_tok, cp_lexer_peek_token (parser->lexer));
+ parser->omp_declare_simd->tokens.safe_push (cp);
if (first_p)
{
while (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
@@ -29720,16 +29730,61 @@ cp_parser_omp_declare_simd (cp_parser *p
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)
+ if (parser->omp_declare_simd
+ && !parser->omp_declare_simd->error_seen
+ && !parser->omp_declare_simd->fndecl_seen)
error_at (pragma_tok->location,
"%<#pragma omp declare simd%> not immediately followed by "
"function declaration or definition");
- parser->omp_declare_simd_clauses = NULL;
+ data.tokens.release ();
+ parser->omp_declare_simd = NULL;
}
}
+/* Finalize #pragma omp declare simd clauses after direct declarator has
+ been parsed, and put that into "omp declare simd" attribute. */
+
+static tree
+cp_parser_late_parsing_omp_declare_simd (cp_parser *parser, tree attrs)
+{
+ struct cp_token_cache *ce;
+ cp_omp_declare_simd_data *data = parser->omp_declare_simd;
+ int i;
+
+ if (!data->error_seen && data->fndecl_seen)
+ {
+ error ("%<#pragma omp declare simd%> not immediately followed by "
+ "a single function declaration or definition");
+ data->error_seen = true;
+ return attrs;
+ }
+ if (data->error_seen)
+ return attrs;
+
+ FOR_EACH_VEC_ELT (data->tokens, i, ce)
+ {
+ tree c, cl;
+
+ cp_parser_push_lexer_for_tokens (parser, ce);
+ parser->lexer->in_pragma = true;
+ gcc_assert (cp_lexer_peek_token (parser->lexer)->type == CPP_PRAGMA);
+ cp_token *pragma_tok = cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cl = cp_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
+ "#pragma omp declare simd", pragma_tok);
+ cp_parser_pop_lexer (parser);
+ c = build_tree_list (get_identifier ("omp declare simd"), cl);
+ TREE_CHAIN (c) = attrs;
+ if (processing_template_decl)
+ ATTR_IS_DEPENDENT (c) = 1;
+ attrs = c;
+ }
+
+ data->fndecl_seen = true;
+ return attrs;
+}
+
+
/* OpenMP 4.0:
# pragma omp declare target new-line
declarations and definitions
@@ -8494,8 +8494,9 @@ apply_late_template_attributes (tree *de
complain, in_decl);
c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
clauses = finish_omp_clauses (clauses);
+ tree parms = DECL_ARGUMENTS (*decl_p);
TREE_VALUE (t)
- = c_omp_declare_simd_clauses_to_numbers (*decl_p, clauses);
+ = c_omp_declare_simd_clauses_to_numbers (parms, clauses);
}
/* If the first attribute argument is an identifier, don't
pass it through tsubst. Attributes like mode, format,
@@ -4799,10 +4799,6 @@ typedef struct cp_decl_specifier_seq {
/* If non-NULL, a built-in type that the user attempted to redefine
to some other type. */
tree redefined_builtin_type;
- /* 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. */
- vec<tree, va_gc> *omp_declare_simd_clauses;
/* The storage class specified -- or sc_none if no storage class was
explicitly specified. */
cp_storage_class storage_class;
@@ -5778,7 +5774,6 @@ 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);
@@ -196,6 +196,14 @@ typedef struct GTY (()) cp_parser_contex
} cp_parser_context;
+/* Control structure for #pragma omp declare simd parsing. */
+struct cp_omp_declare_simd_data {
+ bool error_seen; /* Set if error has been reported. */
+ bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
+ vec<cp_token_cache_ptr> tokens;
+};
+
+
/* The cp_parser structure represents the C++ parser. */
typedef struct GTY(()) cp_parser {
@@ -342,14 +350,9 @@ typedef struct GTY(()) cp_parser {
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;
+ /* When parsing #pragma omp declare simd, this is a pointer to a
+ data structure with everything needed for parsing the clauses. */
+ cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd;
} cp_parser;
/* In parser.c */
@@ -5238,90 +5238,6 @@ 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
@@ -4617,7 +4617,7 @@ build_type_attribute_qual_variant (tree
/* Check if "omp declare simd" attribute arguments, CLAUSES1 and CLAUSES2, are
the same. */
-bool
+static bool
omp_declare_simd_clauses_equal (tree clauses1, tree clauses2)
{
tree cl1, cl2;
@@ -4656,6 +4656,35 @@ omp_declare_simd_clauses_equal (tree cla
return true;
}
+/* Remove duplicate "omp declare simd" attributes. */
+
+void
+omp_remove_redundant_declare_simd_attrs (tree fndecl)
+{
+ tree attr, end_attr = NULL_TREE, last_attr = NULL_TREE;
+ for (attr = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (fndecl));
+ attr;
+ attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr)))
+ {
+ tree *pc;
+ for (pc = &TREE_CHAIN (attr); *pc && *pc != end_attr; )
+ {
+ if (is_attribute_p ("omp declare simd", TREE_PURPOSE (*pc)))
+ {
+ last_attr = TREE_CHAIN (*pc);
+ if (omp_declare_simd_clauses_equal (TREE_VALUE (*pc),
+ TREE_VALUE (attr)))
+ {
+ *pc = TREE_CHAIN (*pc);
+ continue;
+ }
+ }
+ pc = &TREE_CHAIN (*pc);
+ }
+ end_attr = last_attr;
+ }
+}
+
/* Compare two attributes for their value identity. Return true if the
attribute values are known to be equal; otherwise return false.
*/
@@ -222,3 +222,22 @@ f33 (int x)
extern int f35 (int a, int *b, int c);
return x;
}
+
+#pragma omp declare simd simdlen (N)
+template <int N>
+int f36 (int);
+
+struct D
+{
+ int d;
+ #pragma omp declare simd simdlen (N) linear (a : sizeof (a) + sizeof (d) + sizeof (this) + sizeof (this->d))
+ template <int N>
+ int f37 (int a);
+ int e;
+};
+
+void
+f38 (D &d)
+{
+ d.f37 <12> (6);
+}
@@ -52,9 +52,16 @@ int t;
#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 inbranch notinbranch // { dg-error "clause is incompatible with" }
+int fn11 (int);
-#pragma omp declare simd simdlen (N) // { dg-error "was not declared in this scope" }
-template <int N>
-int fn12 (int);
+struct D
+{
+ int d;
+ #pragma omp declare simd simdlen (N) linear (a : sizeof (e) + sizeof (this->e)) // { dg-error "was not declared" }
+ template <int N>
+ int fn12 (int a);
+ int e;
+};
+
+// { dg-error "has no member" "" { target *-*-* } 61 }
@@ -895,7 +895,7 @@ c_omp_declare_simd_clause_cmp (const voi
CLAUSES on FNDECL into argument indexes and sort them. */
tree
-c_omp_declare_simd_clauses_to_numbers (tree fndecl, tree clauses)
+c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
{
tree c;
vec<tree> clvec = vNULL;
@@ -909,14 +909,14 @@ c_omp_declare_simd_clauses_to_numbers (t
tree decl = OMP_CLAUSE_DECL (c);
tree arg;
int idx;
- for (arg = DECL_ARGUMENTS (fndecl), idx = 0; arg;
+ for (arg = parms, 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);
+ "%qD is not an function argument", decl);
continue;
}
OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);