https://gcc.gnu.org/g:be2ead6d3eb315b4c1e20c34044f20ff47589b81

commit be2ead6d3eb315b4c1e20c34044f20ff47589b81
Author: Tobias Burnus <tbur...@baylibre.com>
Date:   Mon Jan 27 12:41:53 2025 +0100

    C++: reject OpenMP directives in constexpr functions
    
    gcc/cp/ChangeLog:
    
            * parser.cc (cp_parser_omp_construct, cp_parser_pragma): Reject
            OpenMP expressions in constexpr functions.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/gomp/pr108607.C: Update dg-error.
            * g++.dg/gomp/pr79664.C: Update dg-error.
            * g++.dg/gomp/omp-constexpr.C: New test.
    
    (cherry picked from commit 46dd8acffe8264c5586cf5dc489157ea254dc152)

Diff:
---
 gcc/cp/ChangeLog.omp                      |  8 ++++++
 gcc/cp/parser.cc                          | 24 ++++++++++++++++-
 gcc/testsuite/ChangeLog.omp               |  9 +++++++
 gcc/testsuite/g++.dg/gomp/omp-constexpr.C | 45 +++++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/gomp/pr108607.C      | 16 +++++------
 gcc/testsuite/g++.dg/gomp/pr79664.C       | 38 +++++++++++++-------------
 6 files changed, 112 insertions(+), 28 deletions(-)

diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp
index 0ea0b84c51a6..ae6628104f34 100644
--- a/gcc/cp/ChangeLog.omp
+++ b/gcc/cp/ChangeLog.omp
@@ -1,3 +1,11 @@
+2025-01-27  Tobias Burnus  <tbur...@baylibre.com>
+
+       Backported from master:
+       2024-12-13  Tobias Burnus  <tbur...@baylibre.com>
+
+       * parser.cc (cp_parser_omp_construct, cp_parser_pragma): Reject
+       OpenMP expressions in constexpr functions.
+
 2025-01-27  Tobias Burnus  <tbur...@baylibre.com>
 
        Backported from master:
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 042a5a460e3a..2a47b967e7e5 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -52949,7 +52949,18 @@ cp_parser_omp_construct (cp_parser *parser, cp_token 
*pragma_tok, bool *if_p)
   char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
   omp_clause_mask mask (0);
 
-  switch (cp_parser_pragma_kind (pragma_tok))
+  unsigned int id = cp_parser_pragma_kind (pragma_tok);
+  if (current_function_decl
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && id >= PRAGMA_OMP__START_
+      && id <= PRAGMA_OMP__LAST_)
+    {
+      error_at (cp_lexer_peek_token (parser->lexer)->location,
+               "OpenMP directives may not appear in %<constexpr%> functions");
+      cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+      return;
+    }
+  switch (id)
     {
     case PRAGMA_OACC_ATOMIC:
       cp_parser_omp_atomic (parser, pragma_tok, true);
@@ -53474,6 +53485,17 @@ cp_parser_pragma (cp_parser *parser, enum 
pragma_context context, bool *if_p)
       cp_parser_skip_to_pragma_eol (parser, pragma_tok);
       return false;
     }
+  if (current_function_decl
+      && DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && id >= PRAGMA_OMP__START_
+      && id <= PRAGMA_OMP__LAST_)
+    {
+      error_at (cp_lexer_peek_token (parser->lexer)->location,
+               "OpenMP directives may not appear in %<constexpr%> functions");
+      cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+      return false;
+    }
+
   if (id != PRAGMA_OMP_DECLARE && id != PRAGMA_OACC_ROUTINE)
     cp_ensure_no_omp_declare_simd (parser);
   switch (id)
diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp
index 35da06819a3e..7dd9def7327a 100644
--- a/gcc/testsuite/ChangeLog.omp
+++ b/gcc/testsuite/ChangeLog.omp
@@ -1,3 +1,12 @@
+2025-01-27  Tobias Burnus  <tbur...@baylibre.com>
+
+       Backported from master:
+       2024-12-13  Tobias Burnus  <tbur...@baylibre.com>
+
+       * g++.dg/gomp/pr108607.C: Update dg-error.
+       * g++.dg/gomp/pr79664.C: Update dg-error.
+       * g++.dg/gomp/omp-constexpr.C: New test.
+
 2025-01-27  Tobias Burnus  <tbur...@baylibre.com>
 
        Backported from master:
diff --git a/gcc/testsuite/g++.dg/gomp/omp-constexpr.C 
b/gcc/testsuite/g++.dg/gomp/omp-constexpr.C
new file mode 100644
index 000000000000..0d984d8609b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/omp-constexpr.C
@@ -0,0 +1,45 @@
+// { dg-do compile { target c++11 } }
+
+constexpr int
+f ()
+{
+  int a = 42;
+  #pragma omp parallel for simd  /* { dg-error "OpenMP directives may not 
appear in 'constexpr' functions" }  */
+  for (int i=0; i < 10; i++)
+    a += i;
+  return a;
+} // { dg-error "not a return-statement" "" { target c++11_down } }
+
+constexpr int
+g ()
+{
+  int a = 42;
+  [[omp::sequence(omp::directive(parallel),omp::directive(for))]]  /* { 
dg-error "OpenMP directives may not appear in 'constexpr' functions" }  */
+  for (int i=0; i < 10; i++)
+    a += i;
+  return a;
+} // { dg-error "not a return-statement" "" { target c++11_down } }
+
+constexpr int
+h ()
+{
+  int a = 42;
+  #pragma omp allocate(a) align(128)  /* { dg-error "OpenMP directives may not 
appear in 'constexpr' functions" }  */
+  return a;
+} // { dg-error "not a return-statement" "" { target c++11_down } }
+
+constexpr int
+i ()
+{
+  int a [[omp::decl(allocate, align(128))]] = 42;  /* { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }  */
+  return a;
+} // { dg-error "not a return-statement" "" { target c++11_down } }
+
+
+
+int main() {
+  static constexpr int a = f ();  // { dg-error "called in a constant 
expression" "" { target c++11_down } }
+  static constexpr int b = g ();  // { dg-error "called in a constant 
expression" "" { target c++11_down } }
+  static constexpr int c = h ();  // { dg-error "called in a constant 
expression" "" { target c++11_down } }
+  static constexpr int d = i ();  // { dg-error "called in a constant 
expression" "" { target c++11_down } }
+}
diff --git a/gcc/testsuite/g++.dg/gomp/pr108607.C 
b/gcc/testsuite/g++.dg/gomp/pr108607.C
index 9e5137b63deb..d09f49dcc770 100644
--- a/gcc/testsuite/g++.dg/gomp/pr108607.C
+++ b/gcc/testsuite/g++.dg/gomp/pr108607.C
@@ -9,10 +9,10 @@ bar (int x)
 }
 
 constexpr int
-foo (int x)                    // { dg-message "declared here" "" { target 
c++20_down } }
-{                              // { dg-message "is not usable as a 'constexpr' 
function because" "" { target c++23 } .-1 }
-  #pragma omp scope            // { dg-warning "is not a constant expression" 
"" { target c++20_down } }
-  x = bar (x);                 // { dg-error "is not a constant expression" "" 
{ target c++23 } .-1 }
+foo (int x)
+{
+  #pragma omp scope            // { dg-error "OpenMP directives may not appear 
in 'constexpr' functions" }
+  x = bar (x);
   return x;
 }
 
@@ -24,15 +24,15 @@ baz (int x)
     case 42:
       return 0;
     case 2:
-      #pragma omp scope                // { dg-error "statement is not a 
constant expression" }
+      #pragma omp scope                // { dg-error "OpenMP directives may 
not appear in 'constexpr' functions" }
       x = bar (x);
       return x;
     case 3:
-      #pragma omp parallel     // { dg-error "statement is not a constant 
expression" }
+      #pragma omp parallel     // { dg-error "OpenMP directives may not appear 
in 'constexpr' functions" }
       x = bar (x);
       return x;
     case 4:
-      #pragma omp task         // { dg-error "statement is not a constant 
expression" }
+      #pragma omp task         // { dg-error "OpenMP directives may not appear 
in 'constexpr' functions" }
       x = bar (x);
       return x;
     default:
@@ -40,7 +40,7 @@ baz (int x)
     }
 }
 
-constexpr int a = foo (1);     // { dg-error "called in a constant expression" 
}
+constexpr int a = foo (1);
 constexpr int b = baz (42);
 constexpr int c = baz (2);
 constexpr int d = baz (3);
diff --git a/gcc/testsuite/g++.dg/gomp/pr79664.C 
b/gcc/testsuite/g++.dg/gomp/pr79664.C
index f4c30c0b3f49..fb0469407643 100644
--- a/gcc/testsuite/g++.dg/gomp/pr79664.C
+++ b/gcc/testsuite/g++.dg/gomp/pr79664.C
@@ -6,7 +6,7 @@ constexpr int
 f1 ()
 {
   int i = 0;
-#pragma omp parallel for                       // { dg-error "is not a 
constant expression" }
+#pragma omp parallel for                       // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   for (i = 0; i < 10; ++i)
     ;
   return 0;
@@ -16,7 +16,7 @@ constexpr int
 f2 ()
 {
   int i = 0;
-#pragma omp parallel                           // { dg-error "is not a 
constant expression" }
+#pragma omp parallel                           // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 5;
   return 0;
 }
@@ -25,7 +25,7 @@ constexpr int
 f3 ()
 {
   int i = 0;
-#pragma omp task                               // { dg-error "is not a 
constant expression" }
+#pragma omp task                               // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 5;
   return 0;
 }
@@ -34,7 +34,7 @@ constexpr int
 f4 ()
 {
   int i = 0;
-#pragma omp for                                        // { dg-error "is not a 
constant expression" }
+#pragma omp for                                        // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   for (i = 0; i < 10; ++i)
     ;
   return 0;
@@ -44,7 +44,7 @@ constexpr int
 f5 ()
 {
   int i = 0;
-#pragma omp taskloop                           // { dg-error "is not a 
constant expression" }
+#pragma omp taskloop                           // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   for (i = 0; i < 10; ++i)
     ;
   return 0;
@@ -54,7 +54,7 @@ constexpr int
 f6 ()
 {
   int i = 0;
-#pragma omp target teams                       // { dg-error "is not a 
constant expression" }
+#pragma omp target teams                       // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 5;
   return 0;
 }
@@ -63,7 +63,7 @@ constexpr int
 f7 ()
 {
   int i = 0;
-#pragma omp target data map(tofrom:i)          // { dg-error "is not a 
constant expression" }
+#pragma omp target data map(tofrom:i)          // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 5;
   return 0;
 }
@@ -72,7 +72,7 @@ constexpr int
 f8 ()
 {
   int i = 0;
-#pragma omp target                             // { dg-error "is not a 
constant expression" }
+#pragma omp target                             // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 5;
   return 0;
 }
@@ -81,9 +81,9 @@ constexpr int
 f9 ()
 {
   int i = 0;
-#pragma omp sections                           // { dg-error "is not a 
constant expression" }
+#pragma omp sections                           // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   {
-#pragma omp section
+#pragma omp section                            // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
     i = 5;
   }
   return 0;
@@ -93,7 +93,7 @@ constexpr int
 f10 ()
 {
   int i = 0;
-#pragma omp ordered                            // { dg-error "is not a 
constant expression" }
+#pragma omp ordered                            // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 1;
   return 0;
 }
@@ -102,7 +102,7 @@ constexpr int
 f11 ()
 {
   int i = 0;
-#pragma omp critical                           // { dg-error "is not a 
constant expression" }
+#pragma omp critical                           // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 1;
   return 0;
 }
@@ -111,7 +111,7 @@ constexpr int
 f12 ()
 {
   int i = 0;
-#pragma omp single                             // { dg-error "is not a 
constant expression" }
+#pragma omp single                             // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 1;
   return 0;
 }
@@ -120,7 +120,7 @@ constexpr int
 f13 ()
 {
   int i = 0;
-#pragma omp master                             // { dg-error "is not a 
constant expression" }
+#pragma omp master                             // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 1;
   return 0;
 }
@@ -129,7 +129,7 @@ constexpr int
 f14 ()
 {
   int i = 0;
-#pragma omp taskgroup                          // { dg-error "is not a 
constant expression" }
+#pragma omp taskgroup                          // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 1;
   return 0;
 }
@@ -138,7 +138,7 @@ constexpr int
 f15 ()
 {
   int i = 0;
-#pragma omp target update to(i)                        // { dg-error "is not a 
constant expression" }
+#pragma omp target update to(i)                        // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   i = 1;
   return 0;
 }
@@ -147,7 +147,7 @@ constexpr int
 f16 ()
 {
   int i = 0;
-#pragma omp target update to(i)                        // { dg-error "is not a 
constant expression" }
+#pragma omp target update to(i)                        // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   return 0;
 }
 
@@ -155,7 +155,7 @@ constexpr int
 f17 ()
 {
   int i = 0;
-#pragma omp target enter data map(to:i)                // { dg-error "is not a 
constant expression" }
+#pragma omp target enter data map(to:i)                // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   return 0;
 }
 
@@ -163,6 +163,6 @@ constexpr int
 f18 ()
 {
   int i = 0;
-#pragma omp target exit data map(from:i)       // { dg-error "is not a 
constant expression" }
+#pragma omp target exit data map(from:i)       // { dg-error "OpenMP 
directives may not appear in 'constexpr' functions" }
   return 0;
 }

Reply via email to