[06/12] OpenMP/C++: Force location wrapper on 'omp allocate' directive clauses

Message ID 20260505151030.1749548-7-waffl3x@baylibre.com
State New
Headers
Series OpenMP/C++: 'allocate' directive |

Commit Message

Waffl3x May 5, 2026, 3:01 p.m. UTC
  Some nodes, such as template parameters, don't get wrapped by
maybe_wrap_with_location. We rely on location wrappers for diagnostics of
clause exprs in finish_omp_allocate, the easiest solution is to force a
wrapper by replicating the the mechanisms of maybe_wrap_with_location in
cp_parser_omp_allocate.

Unfortuntely, tsubst_expr uses maybe_wrap_with_location to rewrap location
wrappers, stripping wrappers that we previously forced. This patch solves
that by handling wrappers explicitly in tsubst_expr's OMP_ALLOCATE case.

This is kind of a kludge, if this is deemed to be a good solution we should
possibly split it out into its own function (force_wrap_with_location?) and
change tsubst_expr to use that for rewrapping. This would be trivial to do,
but belongs in a different patch.

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_omp_allocate): Force a location wrapper.
	* pt.cc (tsubst_stmt): Rewrap location wrappers after tsubst_expr.

gcc/testsuite/ChangeLog:

	* g++.dg/gomp/allocate-10.C: Remove xfails.
	* g++.dg/gomp/allocate-14.C: Likewise.
	* g++.dg/gomp/allocate-17.C: Likewise.

Signed-off-by: Waffl3x <waffl3x@baylibre.com>
---
 gcc/cp/parser.cc                        | 26 +++++++++++++++--
 gcc/cp/pt.cc                            | 24 ++++++++++++----
 gcc/testsuite/g++.dg/gomp/allocate-10.C | 12 +++-----
 gcc/testsuite/g++.dg/gomp/allocate-14.C | 37 +++++++++++--------------
 gcc/testsuite/g++.dg/gomp/allocate-17.C | 23 +++++++--------
 5 files changed, 73 insertions(+), 49 deletions(-)
  

Patch

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 924e52da6ea..412a71c439c 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -47373,13 +47373,35 @@  cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok)
     } while (true);
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
+  /* Some codes, such as template parameters, don't get wrapped by
+     maybe_wrap_with_location despite not being able to carry a location.
+     We need a location to issue good diagnostics in finish_omp_allocate.  */
+  auto maybe_force_wrap_with_location = [] (cp_expr expr_with_loc) -> tree
+    {
+      tree expr = expr_with_loc.get_value ();
+      if (!expr || error_operand_p (expr))
+	return expr;
+      /* In most situations, expr will already have been wrapped.  */
+      if (CAN_HAVE_LOCATION_P (expr))
+	return expr;
+
+      location_t expr_loc = expr_with_loc.get_location ();
+      /* Copied from tree.cc:maybe_wrap_with_location.  */
+      const tree_code code
+	= (((CONSTANT_CLASS_P (expr) && TREE_CODE (expr) != STRING_CST)
+	    || (TREE_CODE (expr) == CONST_DECL && !TREE_STATIC (expr)))
+	   ? NON_LVALUE_EXPR : VIEW_CONVERT_EXPR);
+      tree wrapper = build1_loc (expr_loc, code, TREE_TYPE (expr), expr);
+      EXPR_LOCATION_WRAPPER_P (wrapper) = 1;
+      return wrapper;
+    };
   /* We can still diagnose some things about allocator/alignment even if nl
      is NULL_TREE.  */
 
   finish_omp_allocate (pragma_tok->location,
 		       nl,
-		       allocator,
-		       alignment,
+		       maybe_force_wrap_with_location (allocator),
+		       maybe_force_wrap_with_location (alignment),
 		       directive_ctx);
 }
 
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index aa41a46e007..d27f3c1118f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -20469,11 +20469,25 @@  tsubst_stmt (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case OMP_ALLOCATE:
       {
 	gcc_assert (flag_openmp);
-
-	tree alloc
-	  = tsubst_expr (OMP_ALLOCATE_ALLOCATOR (t), args, complain, in_decl);
-	tree align
-	  = tsubst_expr (OMP_ALLOCATE_ALIGN (t), args, complain, in_decl);
+	/* We force a location wrapper in some cases that don't get wrapped by
+	   maybe_wrap_with_location, tsubst_expr doesn't rewrap them in those
+	   cases so we have to do it.  */
+	auto subst_and_rewrap = [&] (const tree expr)
+	  {
+	    if (!expr || expr == error_mark_node)
+	      return expr;
+	    tree ret = tsubst_expr (tree_strip_any_location_wrapper (expr),
+				    args, complain, in_decl);
+	    if (location_wrapper_p (expr) && !CAN_HAVE_LOCATION_P (ret))
+	      {
+		ret = build1_loc (EXPR_LOCATION (expr), TREE_CODE (expr),
+				  TREE_TYPE (ret), ret);
+		EXPR_LOCATION_WRAPPER_P (ret) = 1;
+	      }
+	    return ret;
+	  };
+	tree alloc = subst_and_rewrap (OMP_ALLOCATE_ALLOCATOR (t));
+	tree align = subst_and_rewrap (OMP_ALLOCATE_ALIGN (t));
 	tree vars = copy_list (OMP_ALLOCATE_VARS (t));
 	for (tree node = vars; node != NULL_TREE; node = TREE_CHAIN (node))
 	  {
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-10.C b/gcc/testsuite/g++.dg/gomp/allocate-10.C
index e0f3bcc1780..27f739df6a5 100644
--- a/gcc/testsuite/g++.dg/gomp/allocate-10.C
+++ b/gcc/testsuite/g++.dg/gomp/allocate-10.C
@@ -34,7 +34,7 @@  void auto_nttp_allocator_static_0()
   static int a;
   #pragma omp allocate(a) allocator(Alloc)
   /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-1 } */
-  /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } .-2 } */
+  /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-2 } */
 }
 
 template<auto Alloc>
@@ -49,7 +49,7 @@  void auto_nttp_allocator_static_2()
 {
   static int a;
   #pragma omp allocate(a) allocator(Alloc)
-  /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } .-1 } */
+  /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-1 } */
 }
 
 template<auto Alloc>
@@ -76,8 +76,6 @@  void instantiate_auto_nttp_allocator_static()
 
 #undef DEFINITELY_NOT_PREDEFINED
 
-/* { dg-bogus "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } 0 } */
-
 /* Invalid align clause */
 
 template<auto Align>
@@ -91,7 +89,7 @@  template<auto Align>
 void auto_nttp_align_0()
 {
   int a;
-  #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */
+  #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } } */
 }
 
 template<auto Align>
@@ -99,7 +97,7 @@  void auto_nttp_align_1()
 {
   int a;
   #pragma omp allocate(a) align(Align)
-  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */
+  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */
   /* { dg-error {could not convert 'nullptr' from 'std::nullptr_t' to '(?:long )?unsigned int'} "" { target *-*-* } .-2 } */
 }
 
@@ -111,5 +109,3 @@  void instantiate_auto_nttp_align()
   auto_nttp_align_1<32>(); /* { dg-bogus "required from here" } */
   auto_nttp_align_1<nullptr>(); /* { dg-message "required from here" } */
 }
-
-/* { dg-bogus "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } 0 } */
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-14.C b/gcc/testsuite/g++.dg/gomp/allocate-14.C
index d40288d957d..a622adc34d9 100644
--- a/gcc/testsuite/g++.dg/gomp/allocate-14.C
+++ b/gcc/testsuite/g++.dg/gomp/allocate-14.C
@@ -121,9 +121,9 @@  void nttp_allocator_static()
 {
   static int a; /* { dg-note "'a' declared here" } */
   #pragma omp allocate(a) allocator(Alloc)
-  /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } .-1 } */
+  /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-1 } */
   /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */
-  /* { dg-note "expression evaluates to '1024'" "" { xfail *-*-* } .-3 }*/
+  /* { dg-note "expression evaluates to '1024'" "" { target *-*-* } .-3 }*/
 }
 
 template<omp_allocator_handle_t Alloc>
@@ -145,9 +145,9 @@  void nttp_dependent_type_allocator_static_0()
 {
   static int a; /* { dg-note "'a' declared here" } */
   #pragma omp allocate(a) allocator(Alloc)
-  /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } .-1 } */
+  /* { dg-error "'allocator' clause requires a constant predefined allocator" "" { target *-*-* } .-1 } */
   /* { dg-note "because one or more variables with static storage duration appear in the 'allocate' directive" "" { target *-*-* } .-2 } */
-  /* { dg-note "expression evaluates to '1024'" "" { xfail *-*-* } .-3 }*/
+  /* { dg-note "expression evaluates to '1024'" "" { target *-*-* } .-3 }*/
 }
 
 template<typename AllocT, AllocT Alloc>
@@ -266,7 +266,7 @@  template<int Align>
 void nttp_align()
 {
   int a;
-  #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */
+  #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" } */
 }
 
 template<int Align>
@@ -289,7 +289,7 @@  template<typename AlignT, AlignT Align>
 void nttp_dependent_type_align_0()
 {
   int a;
-  #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */
+  #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" } */
 }
 
 template<typename AlignT, AlignT Align>
@@ -420,7 +420,7 @@  void all_dependent_2()
   int b = 42;
   Var a = b;
   #pragma omp allocate(a) allocator(Alloc) align(Align)
-  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */
+  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */
 }
 
 template<typename Var,
@@ -444,7 +444,7 @@  void all_dependent_4()
   Var a = b; /* { dg-note "'a' declared here" } */
   #pragma omp allocate(a) allocator(Alloc) align(Align)
   /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */
-  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */
+  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-2 } */
 }
 
 template<typename Var,
@@ -456,7 +456,7 @@  void all_dependent_5()
   Var a = b;
   #pragma omp allocate(a) allocator(Alloc) align(Align)
   /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-1 } */
-  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */
+  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-2 } */
 }
 
 template<typename Var,
@@ -469,7 +469,7 @@  void all_dependent_6()
   #pragma omp allocate(a) allocator(Alloc) align(Align)
   /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */
   /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-2 } */
-  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-3 } */
+  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-3 } */
 }
 
 void instantiate_all_dependent()
@@ -603,7 +603,7 @@  template<int Align>
 void templ_no_vars_dep_align_invalid()
 {
   #pragma omp allocate() align(Align) /* { dg-error "expected unqualified-id before '\\\)' token" } */
-  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */
+  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */
 }
 template void templ_no_vars_dep_align_invalid<42>();
 
@@ -876,7 +876,7 @@  template<int Align>
 void templ_invalid_vars_param_dependent_align_invalid(int p) /* { dg-note "parameter 'p' declared here" } */
 {
   #pragma omp allocate(p) align(Align) /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" } */
-  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */
+  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */
 }
 template void templ_invalid_vars_param_dependent_align_invalid<42>(int);
 
@@ -908,7 +908,7 @@  void templ_invalid_vars_out_of_scope_dependent_align_invalid()
   int a; /* { dg-note "declared here" } */
   {
     #pragma omp allocate(a) align(Align) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */
-    /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */
+    /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */
   }
 }
 template void templ_invalid_vars_out_of_scope_dependent_align_invalid<42>();
@@ -944,7 +944,7 @@  void templ_invalid_vars_out_of_scope_and_param_dependent_align_invalid(int p) /*
   {
     #pragma omp allocate(a, p) align(Align) /* { dg-error "'allocate' directive must be in the same scope as 'a'" } */
     /* { dg-error "function parameter 'p' may not appear as list item in an 'allocate' directive" "" { target *-*-* } .-1 } */
-    /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */
+    /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-2 } */
   }
 }
 template void templ_invalid_vars_out_of_scope_and_param_dependent_align_invalid<42>(int);
@@ -1001,7 +1001,7 @@  void multiple_uses_dep_directive_before_invalid_align()
 {
   int a;
   #pragma omp allocate(a) align(Align) /* { dg-note "'a' previously appeared here" } */
-  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */
+  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */
   #pragma omp allocate(a) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */
 }
 template void multiple_uses_dep_directive_before_invalid_align<42>();
@@ -1032,11 +1032,6 @@  void multiple_uses_dep_directive_after_invalid_align()
   int a;
   #pragma omp allocate(a) /* { dg-note "'a' previously appeared here" } */
   #pragma omp allocate(a) align(Align) /* { dg-error "'a' already appeared as list item in an 'allocate' directive" } */
-  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */
+  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */
 }
 template void multiple_uses_dep_directive_after_invalid_align<42>();
-
-/* These are fixed by the later location wrapping patch.  */
-/* { dg-bogus "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } 0 } */
-/* { dg-bogus "'allocator' clause requires a constant predefined allocator" "" { xfail *-*-* } 0 } */
-/* { dg-bogus "expression evaluates to '1024'" "" { xfail *-*-* } 0 } */
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-17.C b/gcc/testsuite/g++.dg/gomp/allocate-17.C
index e265ecdd1e7..93777d611ea 100644
--- a/gcc/testsuite/g++.dg/gomp/allocate-17.C
+++ b/gcc/testsuite/g++.dg/gomp/allocate-17.C
@@ -31,7 +31,7 @@  auto lambda_0_bad_align()
 	  int b = 42;
 	  decltype(p3) a = b;
 	  #pragma omp allocate(a) align(Align) allocator(p2)
-	  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */
+	  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */
 	  return a;
 	};
       };
@@ -87,7 +87,7 @@  auto lambda_0_all()
 	  decltype(p3) a = b; /* { dg-message "'a' declared here" } */
 	  #pragma omp allocate(a) align(Align) allocator(p2)
 	  /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */
-	  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */
+	  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-2 } */
 	  /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-3 } */
 	  return a;
 	};
@@ -212,18 +212,18 @@  auto lambda_1_bad_align()
 {
   return [](auto p0){
     int a = 42;
-    #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */
+    #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" } */
     return [](auto p1){
       int a = 42;
-      #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */
+      #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" } */
       return [](auto p2){
 	int a = 42;
-	#pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */
+	#pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" } */
 	return [p2](auto p3){
 	  int b = 42;
 	  decltype(p3) a = b;
 	  #pragma omp allocate(a) align(Align) allocator(p2)
-	  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-1 } */
+	  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-1 } */
 	  return a;
 	};
       };
@@ -284,19 +284,19 @@  auto lambda_1_all()
 {
   return [](auto p0){
     int a = 42;
-    #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */
+    #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" } */
     return [](auto p1){
       int a = 42;
-      #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */
+      #pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" } */
       return [](auto p2){
 	int a = 42;
-	#pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } } */
+	#pragma omp allocate(a) align(Align) /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" } */
 	return [p2](auto p3){
 	  int b = 42;
 	  decltype(p3) a = b; /* { dg-message "'a' declared here" } */
 	  #pragma omp allocate(a) align(Align) allocator(p2)
 	  /* { dg-error "variables with reference type may not appear in an 'allocate' directive" "" { target *-*-* } .-1 } */
-	  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } .-2 } */
+	  /* { dg-error "'align' clause argument needs to be positive constant power of two integer expression" "" { target *-*-* } .-2 } */
 	  /* { dg-error "invalid conversion from 'int' to 'omp_allocator_handle_t'" "" { target *-*-* } .-3 } */
 	  return a;
 	};
@@ -555,6 +555,3 @@  void instantiate_lambdas_2()
     auto c3 = c2.operator()<int&>(a); /* { dg-message "required from here" } */
   }
 }
-
-/* This is fixed by the later location wrapping patch.  */
-/* { dg-bogus "'align' clause argument needs to be positive constant power of two integer expression" "" { xfail *-*-* } 0 } */