@@ -340,6 +340,10 @@ 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. */
+ vec<tree, va_gc> *omp_declare_simd_clauses;
} cp_parser;
/* In parser.c */
@@ -1169,6 +1169,19 @@ 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)
+ {
+ error ("%<#pragma omp declare simd%> not immediately followed by "
+ "function declaration or definition");
+ parser->omp_declare_simd_clauses = NULL;
+ }
+}
/* Decl-specifiers. */
@@ -2149,7 +2162,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);
@@ -11154,6 +11173,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. */
@@ -15049,6 +15070,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);
@@ -15698,6 +15720,8 @@ cp_parser_asm_definition (cp_parser* par
}
}
+static void cp_finish_omp_declare_simd (cp_parser *, tree);
+
/* Declarators [gram.dcl.decl] */
/* Parse an init-declarator.
@@ -15989,6 +16013,8 @@ cp_parser_init_declarator (cp_parser* pa
&& declarator->id_loc != UNKNOWN_LOCATION
&& DECL_SOURCE_LOCATION (decl) == input_location)
DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
+ if (parser->omp_declare_simd_clauses)
+ cp_finish_omp_declare_simd (parser, decl);
}
else if (scope)
/* Enter the SCOPE. That way unqualified names appearing in the
@@ -16091,6 +16117,8 @@ cp_parser_init_declarator (cp_parser* pa
prefix_attributes);
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
+ if (parser->omp_declare_simd_clauses)
+ cp_finish_omp_declare_simd (parser, decl);
}
/* Finish processing the declaration. But, skip member
@@ -18302,6 +18330,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 +19109,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 +19561,16 @@ 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);
}
+ if (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);
@@ -21697,6 +21730,11 @@ cp_parser_function_definition_from_speci
else
{
timevar_id_t tv;
+ if (parser->omp_declare_simd_clauses)
+ {
+ cp_finish_omp_declare_simd (parser, current_function_decl);
+ parser->omp_declare_simd_clauses = NULL;
+ }
if (DECL_DECLARED_INLINE_P (current_function_decl))
tv = TV_PARSE_INLINE;
else
@@ -22207,6 +22245,12 @@ cp_parser_save_member_function_body (cp_
return error_mark_node;
}
+ if (parser->omp_declare_simd_clauses)
+ {
+ cp_finish_omp_declare_simd (parser, fn);
+ parser->omp_declare_simd_clauses = NULL;
+ }
+
/* Remember it, if there default args to post process. */
cp_parser_save_default_args (parser, fn);
@@ -24544,7 +24588,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);
@@ -25887,20 +25931,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 +27089,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);
}
@@ -28566,6 +28617,166 @@ 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] == NULL
+ || !DECL_P ((*parser->omp_declare_simd_clauses)[0])))
+ error_at (pragma_tok->location,
+ "%<#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 void
+cp_finish_omp_declare_simd (cp_parser *parser, tree fndecl)
+{
+ tree clauses;
+ int i;
+
+ 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;
+ }
+ if ((*parser->omp_declare_simd_clauses)[0]
+ && DECL_P ((*parser->omp_declare_simd_clauses)[0]))
+ {
+ error_at (DECL_SOURCE_LOCATION (fndecl),
+ "%<#pragma omp declare simd%> not immediately followed by "
+ "a single function declaration or definition");
+ parser->omp_declare_simd_clauses = NULL;
+ return;
+ }
+
+ FOR_EACH_VEC_SAFE_ELT (parser->omp_declare_simd_clauses, i, clauses)
+ {
+ tree c, *pc, decl, name;
+ for (pc = &clauses, c = clauses; 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);
+ }
+ clauses = finish_omp_clauses (clauses);
+ }
+
+ vec_safe_truncate (parser->omp_declare_simd_clauses, 1);
+ (*parser->omp_declare_simd_clauses)[0] = fndecl;
+}
+
+/* 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
@@ -28965,6 +29176,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:
@@ -29070,6 +29283,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:
@@ -29081,7 +29298,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;
@@ -0,0 +1,203 @@
+// 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)
+#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a \
+ : 4) simdlen (4)
+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) 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) 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) 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) simdlen (8)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ 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)
+ #pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a : 4) simdlen (4)
+ 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;
+}
@@ -0,0 +1,53 @@
+// 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);