This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] Implement OpenMP TR8 wording for __func__ etc. (PR c++/88203)


Hi!

In GCC 8 and older, we were implementing the OpenMP 3.1 rule that const vars
without mutable members are predetermined shared, but in GCC 9 and later we
follow the unfortunate OpenMP 4.0 change where they need to be listed
explicitly if default(none).  This isn't very conventient for
__func__/__FUNCTION__/__PRETTY_FUNCTION__, which are function-local
predeclared variables and often appear in macros etc., especially when
GCC nor other compilers actually allowed them to be specified in the data
sharing clauses.

In the upcoming OpenMP 5.1/TR8 we state that __func__ and other predeclared
variables are predetermined shared (so they don't have to be specified with
default(none)), but as exception may be specified in shared and firstprivate
clauses (so they can be specified if users want and override or confirm
the default data sharing).  The following patch implements that change.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk,
queued for backport to 9.x.

2019-09-27  Jakub Jelinek  <jakub@redhat.com>

	PR c++/88203
c-family/
	* c-common.h (c_omp_predefined_variable): Declare.
	* c-omp.c (c_omp_predefined_variable): New function.
	(c_omp_predetermined_sharing): Return OMP_CLAUSE_DEFAULT_SHARED
	for predefined variables.
c/
	* c-parser.c (c_parser_predefined_identifier): New function.
	(c_parser_postfix_expression): Use it.
	(c_parser_omp_variable_list): Parse predefined identifiers.
	* c-typeck.c (c_finish_omp_clauses): Allow predefined variables
	in shared and firstprivate clauses, even when they are predetermined
	shared.
cp/
	* parser.c (cp_parser_omp_var_list_no_open): Parse predefined
	variables.
	* semantics.c (finish_omp_clauses): Allow predefined variables in
	shared and firstprivate clauses, even when they are predetermined
	shared.
	* cp-gimplify.c (cxx_omp_predetermined_sharing_1): Return
	OMP_CLAUSE_DEFAULT_SHARED for predefined variables.
testsuite/
	* c-c++-common/gomp/pr88203-1.c: New test.
	* c-c++-common/gomp/pr88203-2.c: New test.
	* c-c++-common/gomp/pr88203-3.c: New test.

--- gcc/c-family/c-common.h.jj	2019-09-27 12:22:53.302891806 +0200
+++ gcc/c-family/c-common.h	2019-09-27 12:57:56.629349468 +0200
@@ -1187,6 +1187,7 @@ extern void c_omp_split_clauses (locatio
 				 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 bool c_omp_predefined_variable (tree);
 extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
 
 /* Return next tree in the chain for chain_next walking of tree nodes.  */
--- gcc/c-family/c-omp.c.jj	2019-09-20 12:24:56.308191050 +0200
+++ gcc/c-family/c-omp.c	2019-09-27 16:27:16.032950885 +0200
@@ -2083,6 +2083,25 @@ c_omp_declare_simd_clauses_to_decls (tre
       }
 }
 
+/* Return true for __func__ and similar function-local predefined
+   variables (which are in OpenMP predetermined shared, allowed in
+   shared/firstprivate clauses).  */
+
+bool
+c_omp_predefined_variable (tree decl)
+{
+  if (VAR_P (decl)
+      && DECL_ARTIFICIAL (decl)
+      && TREE_READONLY (decl)
+      && TREE_STATIC (decl)
+      && DECL_NAME (decl)
+      && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME]
+	  || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME]
+	  || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME]))
+    return true;
+  return false;
+}
+
 /* True if OpenMP sharing attribute of DECL is predetermined.  */
 
 enum omp_clause_default_kind
@@ -2096,5 +2115,8 @@ c_omp_predetermined_sharing (tree decl)
       && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
     return OMP_CLAUSE_DEFAULT_SHARED;
 
+  if (c_omp_predefined_variable (decl))
+    return OMP_CLAUSE_DEFAULT_SHARED;
+
   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
 }
--- gcc/c/c-parser.c.jj	2019-09-20 12:24:56.198192754 +0200
+++ gcc/c/c-parser.c	2019-09-27 16:56:13.233124695 +0200
@@ -8049,6 +8049,41 @@ enum tgmath_parm_kind
     tgmath_fixed, tgmath_real, tgmath_complex
   };
 
+/* Helper function for c_parser_postfix_expression.  Parse predefined
+   identifiers.  */
+
+static struct c_expr
+c_parser_predefined_identifier (c_parser *parser)
+{
+  location_t loc = c_parser_peek_token (parser)->location;
+  switch (c_parser_peek_token (parser)->keyword)
+    {
+    case RID_FUNCTION_NAME:
+      pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
+	       "identifier", "__FUNCTION__");
+      break;
+    case RID_PRETTY_FUNCTION_NAME:
+      pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
+	       "identifier", "__PRETTY_FUNCTION__");
+      break;
+    case RID_C99_FUNCTION_NAME:
+      pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not support "
+		   "%<__func__%> predefined identifier");
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  struct c_expr expr;
+  expr.original_code = ERROR_MARK;
+  expr.original_type = NULL;
+  expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
+			   c_parser_peek_token (parser)->value);
+  set_c_expr_source_range (&expr, loc, loc);
+  c_parser_consume_token (parser);
+  return expr;
+}
+
 /* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
    C11 6.5.1-6.5.2).  Compound literals aren't handled here; callers have to
    call c_parser_postfix_expression_after_paren_type on encountering them.
@@ -8269,31 +8304,9 @@ c_parser_postfix_expression (c_parser *p
       switch (c_parser_peek_token (parser)->keyword)
 	{
 	case RID_FUNCTION_NAME:
-	  pedwarn (loc, OPT_Wpedantic,  "ISO C does not support "
-		   "%<__FUNCTION__%> predefined identifier");
-	  expr.value = fname_decl (loc,
-				   c_parser_peek_token (parser)->keyword,
-				   c_parser_peek_token (parser)->value);
-	  set_c_expr_source_range (&expr, loc, loc);
-	  c_parser_consume_token (parser);
-	  break;
 	case RID_PRETTY_FUNCTION_NAME:
-	  pedwarn (loc, OPT_Wpedantic,  "ISO C does not support "
-		   "%<__PRETTY_FUNCTION__%> predefined identifier");
-	  expr.value = fname_decl (loc,
-				   c_parser_peek_token (parser)->keyword,
-				   c_parser_peek_token (parser)->value);
-	  set_c_expr_source_range (&expr, loc, loc);
-	  c_parser_consume_token (parser);
-	  break;
 	case RID_C99_FUNCTION_NAME:
-	  pedwarn_c90 (loc, OPT_Wpedantic,  "ISO C90 does not support "
-		   "%<__func__%> predefined identifier");
-	  expr.value = fname_decl (loc,
-				   c_parser_peek_token (parser)->keyword,
-				   c_parser_peek_token (parser)->value);
-	  set_c_expr_source_range (&expr, loc, loc);
-	  c_parser_consume_token (parser);
+	  expr = c_parser_predefined_identifier (parser);
 	  break;
 	case RID_VA_ARG:
 	  {
@@ -11997,15 +12010,9 @@ c_parser_omp_variable_list (c_parser *pa
 {
   auto_vec<c_token> tokens;
   unsigned int tokens_avail = 0;
+  bool first = true;
 
-  if (kind != OMP_CLAUSE_DEPEND
-      && (c_parser_next_token_is_not (parser, CPP_NAME)
-	  || c_parser_peek_token (parser)->id_kind != C_ID_ID))
-    c_parser_error (parser, "expected identifier");
-
-  while (kind == OMP_CLAUSE_DEPEND
-	 || (c_parser_next_token_is (parser, CPP_NAME)
-	     && c_parser_peek_token (parser)->id_kind == C_ID_ID))
+  while (1)
     {
       bool array_section_p = false;
       if (kind == OMP_CLAUSE_DEPEND)
@@ -12026,6 +12033,7 @@ c_parser_omp_variable_list (c_parser *pa
 		break;
 
 	      c_parser_consume_token (parser);
+	      first = false;
 	      continue;
 	    }
 
@@ -12076,16 +12084,35 @@ c_parser_omp_variable_list (c_parser *pa
 	  parser->tokens_avail = tokens.length ();
 	}
 
-      tree t = lookup_name (c_parser_peek_token (parser)->value);
+      tree t = NULL_TREE;
 
-      if (t == NULL_TREE)
+      if (c_parser_next_token_is (parser, CPP_NAME)
+	  && c_parser_peek_token (parser)->id_kind == C_ID_ID)
 	{
-	  undeclared_variable (c_parser_peek_token (parser)->location,
-			       c_parser_peek_token (parser)->value);
-	  t = error_mark_node;
-	}
+	  t = lookup_name (c_parser_peek_token (parser)->value);
 
-      c_parser_consume_token (parser);
+	  if (t == NULL_TREE)
+	    {
+	      undeclared_variable (c_parser_peek_token (parser)->location,
+	      c_parser_peek_token (parser)->value);
+	      t = error_mark_node;
+	    }
+
+	  c_parser_consume_token (parser);
+	}
+      else if (c_parser_next_token_is (parser, CPP_KEYWORD)
+	       && (c_parser_peek_token (parser)->keyword == RID_FUNCTION_NAME
+		   || (c_parser_peek_token (parser)->keyword
+		       == RID_PRETTY_FUNCTION_NAME)
+		   || (c_parser_peek_token (parser)->keyword
+		       == RID_C99_FUNCTION_NAME)))
+	t = c_parser_predefined_identifier (parser).value;
+      else
+	{
+	  if (first)
+	    c_parser_error (parser, "expected identifier");
+	  break;
+	}
 
       if (t == error_mark_node)
 	;
@@ -12223,6 +12250,7 @@ c_parser_omp_variable_list (c_parser *pa
 	break;
 
       c_parser_consume_token (parser);
+      first = false;
     }
 
   return list;
--- gcc/c/c-typeck.c.jj	2019-09-27 12:22:53.529888399 +0200
+++ gcc/c/c-typeck.c	2019-09-27 13:20:33.433958093 +0200
@@ -14822,6 +14822,13 @@ c_finish_omp_clauses (tree clauses, enum
 		case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
 		  break;
 		case OMP_CLAUSE_DEFAULT_SHARED:
+		  if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
+		       || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
+		      && c_omp_predefined_variable (t))
+		    /* The __func__ variable and similar function-local
+		       predefined variables may be listed in a shared or
+		       firstprivate clause.  */
+		    break;
 		  share_name = "shared";
 		  break;
 		case OMP_CLAUSE_DEFAULT_PRIVATE:
--- gcc/cp/parser.c.jj	2019-09-26 21:34:26.302847332 +0200
+++ gcc/cp/parser.c	2019-09-27 15:54:55.458954251 +0200
@@ -32736,6 +32736,14 @@ cp_parser_omp_var_list_no_open (cp_parse
 	    decl = TREE_OPERAND (decl, 0);
 	  cp_lexer_consume_token (parser->lexer);
 	}
+      else if (cp_parser_is_keyword (token, RID_FUNCTION_NAME)
+	       || cp_parser_is_keyword (token, RID_PRETTY_FUNCTION_NAME)
+	       || cp_parser_is_keyword (token, RID_C99_FUNCTION_NAME))
+	{
+	  cp_id_kind idk;
+	  decl = cp_parser_primary_expression (parser, false, false, false,
+					       &idk);
+	}
       else
 	{
 	  name = cp_parser_id_expression (parser, /*template_p=*/false,
--- gcc/cp/semantics.c.jj	2019-09-20 12:25:26.070729807 +0200
+++ gcc/cp/semantics.c	2019-09-27 13:21:05.597473200 +0200
@@ -7967,6 +7967,13 @@ finish_omp_clauses (tree clauses, enum c
 	    case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
 	      break;
 	    case OMP_CLAUSE_DEFAULT_SHARED:
+	      if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
+		   || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
+		  && c_omp_predefined_variable (t))
+		/* The __func__ variable and similar function-local predefined
+		   variables may be listed in a shared or firstprivate
+		   clause.  */
+		break;
 	      if (VAR_P (t)
 		  && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
 		  && TREE_STATIC (t)
--- gcc/cp/cp-gimplify.c.jj	2019-08-29 10:22:17.554533572 +0200
+++ gcc/cp/cp-gimplify.c	2019-09-27 13:01:03.078550974 +0200
@@ -2055,6 +2055,9 @@ cxx_omp_predetermined_sharing_1 (tree de
       tree ctx = CP_DECL_CONTEXT (decl);
       if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
 	return OMP_CLAUSE_DEFAULT_SHARED;
+
+      if (c_omp_predefined_variable (decl))
+	return OMP_CLAUSE_DEFAULT_SHARED;
     }
 
   /* this may not be specified in data-sharing clauses, still we need
--- gcc/testsuite/c-c++-common/gomp/pr88203-1.c.jj	2019-09-27 16:30:59.633617735 +0200
+++ gcc/testsuite/c-c++-common/gomp/pr88203-1.c	2019-09-27 16:07:03.997053776 +0200
@@ -0,0 +1,61 @@
+/* PR c++/88203 */
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99" { target c } } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+
+void foo (const char *);
+#pragma omp declare target to (foo)
+
+void
+f1 (void)
+{
+  #pragma omp parallel default(none)
+  foo (__func__);
+}
+
+void
+f2 (void)
+{
+  #pragma omp parallel default(none) shared(__func__)
+  foo (__func__);
+}
+
+void
+f3 (void)
+{
+  #pragma omp parallel default(none) firstprivate(__func__)
+  foo (__func__);
+}
+
+void
+f4 (void)
+{
+  foo (__func__);
+  #pragma omp parallel default(none)
+  foo (__func__);
+}
+
+void
+f5 (void)
+{
+  foo (__func__);
+  #pragma omp parallel default(none) shared(__func__)
+  foo (__func__);
+}
+
+void
+f6 (void)
+{
+  foo (__func__);
+  #pragma omp parallel default(none) firstprivate(__func__)
+  foo (__func__);
+}
+
+void
+f7 (void)
+{
+  #pragma omp target map(to: __func__)
+  foo (__func__);
+  #pragma omp task depend(inout:__func__)
+  foo (__func__);
+}
--- gcc/testsuite/c-c++-common/gomp/pr88203-2.c.jj	2019-09-27 16:31:16.317370301 +0200
+++ gcc/testsuite/c-c++-common/gomp/pr88203-2.c	2019-09-27 16:33:19.533542874 +0200
@@ -0,0 +1,65 @@
+/* PR c++/88203 */
+/* { dg-do compile } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+/* { dg-additional-options "-std=gnu++11" { target c++ } } */
+
+void foo (const char *, const char *);
+#pragma omp declare target to (foo)
+
+void
+f1 (void)
+{
+  #pragma omp parallel default(none)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+}
+
+void
+f2 (void)
+{
+  #pragma omp parallel default(none) shared(__FUNCTION__, __PRETTY_FUNCTION__)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+  #pragma omp parallel default(none) shared(__FUNCTION__) firstprivate(__PRETTY_FUNCTION__)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+}
+
+void
+f3 (void)
+{
+  #pragma omp parallel default(none) firstprivate(__FUNCTION__, __PRETTY_FUNCTION__)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+  #pragma omp parallel default(none) firstprivate(__FUNCTION__), shared(__PRETTY_FUNCTION__)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+}
+
+void
+f4 (void)
+{
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+  #pragma omp parallel default(none)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+}
+
+void
+f5 (void)
+{
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+  #pragma omp parallel default(none) shared(__FUNCTION__, __PRETTY_FUNCTION__)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+}
+
+void
+f6 (void)
+{
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+  #pragma omp parallel default(none) firstprivate(__FUNCTION__, __PRETTY_FUNCTION__)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+}
+
+void
+f7 (void)
+{
+  #pragma omp target map(to: __FUNCTION__, __PRETTY_FUNCTION__)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+  #pragma omp task depend(inout:__FUNCTION__, __PRETTY_FUNCTION__)
+  foo (__FUNCTION__, __PRETTY_FUNCTION__);
+}
--- gcc/testsuite/c-c++-common/gomp/pr88203-3.c.jj	2019-09-27 16:39:59.077617196 +0200
+++ gcc/testsuite/c-c++-common/gomp/pr88203-3.c	2019-09-27 17:32:23.966774256 +0200
@@ -0,0 +1,28 @@
+/* PR c++/88203 */
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99" { target c } } */
+/* { dg-additional-options "-std=c++11" { target c++ } } */
+
+void foo (const char *);
+#pragma omp declare target to (foo)
+
+void
+f1 (void)
+{
+  #pragma omp parallel for lastprivate (__func__)	/* { dg-error "'__func__' is predetermined 'shared' for 'lastprivate'" } */
+  for (int i = 0; i < 2; i++)
+    foo (__func__);
+  #pragma omp parallel private (__func__)		/* { dg-error "'__func__' is predetermined 'shared' for 'private'" } */
+  foo (__func__);
+}
+
+void
+f2 (void)
+{
+  foo (__func__);
+  #pragma omp parallel default(none) private (__func__)		/* { dg-error "'__func__' is predetermined 'shared' for 'private'" } */
+  foo (__func__);
+  #pragma omp parallel for default(none) lastprivate (__func__)	/* { dg-error "'__func__' is predetermined 'shared' for 'lastprivate'" } */
+  for (int i = 0; i < 2; i++)
+    foo (__func__);
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]