@@ -15531,6 +15531,7 @@ c_parser_omp_declare_target (c_parser *p
{
clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO_DECLARE,
clauses);
+ clauses = c_finish_omp_clauses (clauses, true);
c_parser_skip_to_pragma_eol (parser);
}
else
@@ -4417,13 +4417,7 @@ c_decl_attributes (tree *node, tree attr
|| TREE_CODE (*node) == FUNCTION_DECL))
{
if (VAR_P (*node)
- && ((DECL_CONTEXT (*node)
- && TREE_CODE (DECL_CONTEXT (*node)) == FUNCTION_DECL)
- || (current_function_decl && !DECL_EXTERNAL (*node))))
- error ("%q+D in block scope inside of declare target directive",
- *node);
- else if (VAR_P (*node)
- && !lang_hooks.types.omp_mappable_type (TREE_TYPE (*node)))
+ && !lang_hooks.types.omp_mappable_type (TREE_TYPE (*node)))
error ("%q+D in declare target directive does not have mappable type",
*node);
else
@@ -12837,17 +12837,22 @@ c_finish_omp_clauses (tree clauses, bool
break;
case OMP_CLAUSE_TO_DECLARE:
- t = OMP_CLAUSE_DECL (c);
- if (TREE_CODE (t) == FUNCTION_DECL)
- break;
- /* FALLTHRU */
case OMP_CLAUSE_LINK:
t = OMP_CLAUSE_DECL (c);
- if (!VAR_P (t))
+ if (TREE_CODE (t) == FUNCTION_DECL
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO_DECLARE)
+ ;
+ else if (!VAR_P (t))
{
- error_at (OMP_CLAUSE_LOCATION (c),
- "%qE is not a variable in clause %qs", t,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO_DECLARE)
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is neither a variable nor a function name in "
+ "clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
else if (DECL_THREAD_LOCAL_P (t))
@@ -12864,6 +12869,17 @@ c_finish_omp_clauses (tree clauses, bool
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ if (remove)
+ break;
+ if (bitmap_bit_p (&generic_head, DECL_UID (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE appears more than once on the same "
+ "%<declare target%> directive", t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&generic_head, DECL_UID (t));
break;
case OMP_CLAUSE_UNIFORM:
@@ -34673,11 +34673,12 @@ cp_parser_omp_declare_target (cp_parser
{
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_TO_DECLARE,
clauses);
- cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ clauses = finish_omp_clauses (clauses, true);
+ cp_parser_require_pragma_eol (parser, pragma_tok);
}
else
{
- cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ cp_parser_require_pragma_eol (parser, pragma_tok);
scope_chain->omp_declare_target_attribute++;
return;
}
@@ -34744,7 +34745,7 @@ cp_parser_omp_end_declare_target (cp_par
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
return;
}
- cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ cp_parser_require_pragma_eol (parser, pragma_tok);
if (!scope_chain->omp_declare_target_attribute)
error_at (pragma_tok->location,
"%<#pragma omp end declare target%> without corresponding "
@@ -1454,11 +1454,6 @@ cplus_decl_attributes (tree *decl, tree
&& DECL_CLASS_SCOPE_P (*decl))
error ("%q+D static data member inside of declare target directive",
*decl);
- else if (VAR_P (*decl)
- && (DECL_FUNCTION_SCOPE_P (*decl)
- || (current_function_decl && !DECL_EXTERNAL (*decl))))
- error ("%q+D in block scope inside of declare target directive",
- *decl);
else if (!processing_template_decl
&& VAR_P (*decl)
&& !cp_omp_mappable_type (TREE_TYPE (*decl)))
@@ -6521,17 +6521,33 @@ finish_omp_clauses (tree clauses, bool a
break;
case OMP_CLAUSE_TO_DECLARE:
- t = OMP_CLAUSE_DECL (c);
- if (TREE_CODE (t) == FUNCTION_DECL)
- break;
- /* FALLTHRU */
case OMP_CLAUSE_LINK:
t = OMP_CLAUSE_DECL (c);
- if (!VAR_P (t))
+ if (TREE_CODE (t) == FUNCTION_DECL
+ && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO_DECLARE)
+ ;
+ else if (!VAR_P (t))
{
- error_at (OMP_CLAUSE_LOCATION (c),
- "%qE is not a variable in clause %qs", t,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO_DECLARE)
+ {
+ if (TREE_CODE (t) == OVERLOAD && OVL_CHAIN (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "overloaded function name %qE in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else if (TREE_CODE (t) == TEMPLATE_ID_EXPR)
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "template %qE in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is neither a variable nor a function name "
+ "in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ }
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
else if (DECL_THREAD_LOCAL_P (t))
@@ -6548,6 +6564,17 @@ finish_omp_clauses (tree clauses, bool a
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
remove = true;
}
+ if (remove)
+ break;
+ if (bitmap_bit_p (&generic_head, DECL_UID (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE appears more than once on the same "
+ "%<declare target%> directive", t);
+ remove = true;
+ }
+ else
+ bitmap_set_bit (&generic_head, DECL_UID (t));
break;
case OMP_CLAUSE_UNIFORM:
@@ -6,7 +6,7 @@ extern int a;
#pragma omp declare target to (a) /* { dg-error "with clauses in between" } */
#pragma omp end declare target
int b;
-#pragma omp declare target to (b) link (b) /* { dg-error "specified both in declare target" } */
+#pragma omp declare target to (b) link (b) /* { dg-error "appears more than once on the same .declare target. directive" } */
int c;
#pragma omp declare target (c)
#pragma omp declare target link (c) /* { dg-error "specified both in declare target" } */
@@ -25,3 +25,21 @@ int g, h;
#pragma omp declare target link (h) /* { dg-error "is threadprivate variable in" } */
int j[10];
#pragma omp declare target to (j[0:4]) /* { dg-error "expected" } */
+int k, l;
+#pragma omp declare target
+int m;
+#pragma omp end declare target
+#pragma omp declare target to (k)
+#pragma omp declare target (k)
+#pragma omp declare target to (k, m) link (l)
+#pragma omp declare target link (l)
+int n, o, s, t;
+#pragma omp declare target to (n) to (n) /* { dg-error "appears more than once on the same .declare target. directive" } */
+#pragma omp declare target link (o, o) /* { dg-error "appears more than once on the same .declare target. directive" } */
+#pragma omp declare target (s, t, s) /* { dg-error "appears more than once on the same .declare target. directive" } */
+int p, q, r;
+#pragma omp declare target (p) to (q) /* { dg-error "expected end of line before .to." } */
+#pragma omp declare target to (p) (q) link (r) /* { dg-error "expected .#pragma omp. clause before" } */
+#pragma omp declare target link (r) (p) /* { dg-error "expected .#pragma omp. clause before" } */
+#pragma omp declare target
+#pragma omp end declare target to (p) /* { dg-error "expected end of line before .to." } */
@@ -0,0 +1,37 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+#pragma omp declare target
+void f1 (int);
+void f1 (double);
+template <typename T>
+void f2 (T);
+template<> void f2<int> (int);
+#pragma omp end declare target
+void f3 (int);
+void f4 (int);
+void f4 (short);
+template <typename T>
+void f5 (T);
+#pragma omp declare target (f3)
+#pragma omp declare target to (f4) // { dg-error "overloaded function name .f4. in clause .to." }
+#pragma omp declare target to (f5<int>) // { dg-error "template .f5<int>. in clause .to." }
+template <int N>
+void f6 (int)
+{
+ static int s;
+ #pragma omp declare target (s)
+}
+namespace N
+{
+ namespace M
+ {
+ void f7 (int);
+ }
+ void f8 (long);
+}
+void f9 (short);
+int v;
+#pragma omp declare target (N::M::f7)
+#pragma omp declare target to (::N::f8)
+#pragma omp declare target to (::f9) to (::v)
@@ -0,0 +1,33 @@
+extern void abort (void);
+
+#pragma omp declare target
+int
+foo (void)
+{
+ static int s;
+ return ++s;
+}
+#pragma omp end declare target
+
+int
+bar (void)
+{
+ static int s;
+ #pragma omp declare target to (s)
+ return ++s;
+}
+#pragma omp declare target (bar)
+
+int
+main ()
+{
+ int r;
+ #pragma omp target map(from:r)
+ {
+ r = (foo () == 1) + (bar () == 1);
+ r += (foo () == 2) + (bar () == 2);
+ }
+ if (r != 4)
+ abort ();
+ return 0;
+}
@@ -0,0 +1,33 @@
+extern "C" void abort (void);
+
+#pragma omp declare target
+int
+foo (void)
+{
+ static int s;
+ return ++s;
+}
+#pragma omp end declare target
+
+int
+bar (void)
+{
+ static int s;
+ #pragma omp declare target to (s)
+ return ++s;
+}
+#pragma omp declare target (bar)
+
+int
+main ()
+{
+ int r;
+ #pragma omp target map(from:r)
+ {
+ r = (foo () == 1) + (bar () == 1);
+ r += (foo () == 2) + (bar () == 2);
+ }
+ if (r != 4)
+ abort ();
+ return 0;
+}