diff mbox

[gomp4.5] declare target restrictions and clarifications

Message ID 20151015175604.GH478@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Oct. 15, 2015, 5:56 p.m. UTC
Hi!

This patch implements some new restrictions, clarifications etc.
on the declare target construct.  Committed to gomp-4_5-branch.

2015-10-15  Jakub Jelinek  <jakub@redhat.com>

gcc/c/
	* c-parser.c (c_parser_omp_declare_target): Call c_finish_omp_clauses
	in the parenthesized extended-list syntax case.
	* c-decl.c (c_decl_attributes): Don't diagnose block scope vars inside
	declare target.
	* c-typeck.c (c_finish_omp_clauses): Diagnose the same var or function
	appearing multiple times on the same directive.  Fix up wording for
	the to clause if t is neither a FUNCTION_DECL nor a VAR_DECL.
gcc/cp/
	* parser.c (cp_parser_omp_declare_target): Call finish_omp_clauses
	in the parenthesized extended-list syntax case.  Call
	cp_parser_require_pragma_eol instead of cp_parser_skip_to_pragma_eol.
	(cp_parser_omp_end_declare_target): Call cp_parser_require_pragma_eol
	instead of cp_parser_skip_to_pragma_eol.
	* decl2.c (cplus_decl_attributes): Don't diagnose block scope vars inside
	declare target.
	* semantics.c (finish_omp_clauses): Diagnose the same var or function
	appearing multiple times on the same directive.  Fix up wording for
	the to clause if t is neither a FUNCTION_DECL nor a VAR_DECL,
	use special wording for OVERLOADs and TEMPLATE_ID_EXPR.
gcc/testsuite/
	* c-c++-common/gomp/declare-target-2.c: Add various new tests.  Adjust
	expected diagnostics wording in one case.
	* g++.dg/gomp/declare-target-1.C: New test.
libgomp/
	* testsuite/libgomp.c/target-28.c: New test.
	* testsuite/libgomp.c++/target-13.C: New test.


	Jakub
diff mbox

Patch

--- gcc/c/c-parser.c.jj	2015-10-14 18:04:13.000000000 +0200
+++ gcc/c/c-parser.c	2015-10-15 16:55:36.639169199 +0200
@@ -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
--- gcc/c/c-decl.c.jj	2015-10-14 10:24:55.000000000 +0200
+++ gcc/c/c-decl.c	2015-10-15 19:24:50.809431612 +0200
@@ -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
--- gcc/c/c-typeck.c.jj	2015-10-14 18:04:13.000000000 +0200
+++ gcc/c/c-typeck.c	2015-10-15 18:17:41.991147724 +0200
@@ -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:
--- gcc/cp/parser.c.jj	2015-10-14 18:04:13.000000000 +0200
+++ gcc/cp/parser.c	2015-10-15 17:36:30.206793453 +0200
@@ -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 "
--- gcc/cp/decl2.c.jj	2015-10-14 10:25:31.000000000 +0200
+++ gcc/cp/decl2.c	2015-10-15 19:25:38.678722369 +0200
@@ -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)))
--- gcc/cp/semantics.c.jj	2015-10-14 18:04:13.000000000 +0200
+++ gcc/cp/semantics.c	2015-10-15 18:32:24.482064935 +0200
@@ -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:
--- gcc/testsuite/c-c++-common/gomp/declare-target-2.c.jj	2015-10-14 10:25:30.000000000 +0200
+++ gcc/testsuite/c-c++-common/gomp/declare-target-2.c	2015-10-15 18:07:05.489584542 +0200
@@ -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." } */
--- gcc/testsuite/g++.dg/gomp/declare-target-1.C.jj	2015-10-15 18:09:08.043767545 +0200
+++ gcc/testsuite/g++.dg/gomp/declare-target-1.C	2015-10-15 19:11:29.037310874 +0200
@@ -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)
--- libgomp/testsuite/libgomp.c/target-28.c.jj	2015-10-15 18:56:27.932665314 +0200
+++ libgomp/testsuite/libgomp.c/target-28.c	2015-10-15 19:21:22.756514178 +0200
@@ -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;
+}
--- libgomp/testsuite/libgomp.c++/target-13.C.jj	2015-10-15 19:27:52.179745374 +0200
+++ libgomp/testsuite/libgomp.c++/target-13.C	2015-10-15 19:29:00.188739477 +0200
@@ -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;
+}