diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 7b10957ad02a0b7ee8af2e86be62965bbb944a6d..9334ed5df3365c06dbdee560e353001258f9b9c9 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,11 @@
+2019-09-27  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/88203
+	* 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.
+
 2019-09-27  Richard Sandiford  <richard.sandiford@arm.com>
 
 	* c-common.h (build_function_call_vec): Take the original
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index c1554f3c3af2083a0bfff4323b14ccb097d1f9f2..1e13aaa16fc26922b3732f8f0523d78cad8d1e6d 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1187,6 +1187,7 @@ extern void c_omp_split_clauses (location_t, enum tree_code, omp_clause_mask,
 				 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.  */
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index 10f7c4ed0c3ec6297e3749bf9756dc278da99704..0048289b6915d9778dfb968c4e79c5b218b8c85c 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -2083,6 +2083,25 @@ c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
       }
 }
 
+/* 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;
 }
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 718e5b8b8509ae5fcea958cfd71ebb0c1c0c78ac..fa0bbc83a1eb6d9fbbdb41defa88693d178b2e3d 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,13 @@
+2019-09-27  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/88203
+	* 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.
+
 2019-09-27  Richard Sandiford  <richard.sandiford@arm.com>
 
 	* c-typeck.c (build_function_call_vec): Take the original function
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 6070502deb51c4c16e9ca37001ff51407f7759e2..c8afab2bc2ea4d549cb842156fb64a517a67fdda 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -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 *parser)
       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 *parser,
 {
   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 *parser,
 		break;
 
 	      c_parser_consume_token (parser);
+	      first = false;
 	      continue;
 	    }
 
@@ -12076,16 +12084,35 @@ c_parser_omp_variable_list (c_parser *parser,
 	  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 *parser,
 	break;
 
       c_parser_consume_token (parser);
+      first = false;
     }
 
   return list;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index cc13fdc84c879df59815c18cedfaef5685e413f4..c7339509bd1c0411d55827d06f03d51eda184d55 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -14822,6 +14822,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 		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:
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 20f543ea716792fb20dbf6241cc0acaf18bdf740..8ea2a84f24f3ae54d587d28742ecd10e7396e30f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,14 @@
+2019-09-27  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/88203
+	* 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.
+
 2019-09-27  Jason Merrill  <jason@redhat.com>
 
 	* constexpr.c (cxx_fold_indirect_ref): Use similar_type_p.
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 49fa47ac3af80b54cd3d95897715a3b1aaf6cfa8..8bda7361bc40f745b0f02d61f3c67ea968c943b1 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2055,6 +2055,9 @@ cxx_omp_predetermined_sharing_1 (tree decl)
       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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 44082f7a05fb45eb9c72e6022eeaa4d7b1015bd6..018a03d4965655333012e762aba69870535256e3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -32736,6 +32736,14 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 	    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,
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 756324876249f253f35a8143f0a9fa36a6efba7b..5a8c4d237e0d7905e65d29680ae56bea0b8caf02 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7967,6 +7967,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 	    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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9aee20c994ae9050163d8e797b34f01473bf371e..163e38d5b6c534ac3e9fcfec3db2d4b71fde5908 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
 2019-09-27  Jakub Jelinek  <jakub@redhat.com>
 
+	PR c++/88203
+	* 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.
+
 	PR middle-end/91920
 	* c-c++-common/gomp/pr91920.c: New test.
 
diff --git a/gcc/testsuite/c-c++-common/gomp/pr88203-1.c b/gcc/testsuite/c-c++-common/gomp/pr88203-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..54a686487c98001a469db5bb9cedd933348b1441
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr88203-1.c
@@ -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__);
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr88203-2.c b/gcc/testsuite/c-c++-common/gomp/pr88203-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..90c4a720774aff18e9f3864501d54abb8947d576
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr88203-2.c
@@ -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__);
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/pr88203-3.c b/gcc/testsuite/c-c++-common/gomp/pr88203-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..6a9585d3281720367cf54055a61320b698539f12
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/pr88203-3.c
@@ -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__);
+}