[clang-tools-extra] [libcxx] [llvm] [flang] [clang] [compiler-rt] [libc] [C23] Complete support for WG14 N2508 (PR #71398)

via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 6 06:11:20 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-openmp

Author: Aaron Ballman (AaronBallman)

<details>
<summary>Changes</summary>

In Clang 16, we implemented the ability to add a label at the end of a compound statement. These changes complete the implementation by allowing a label to be followed by a declaration in C.

Note, this seems to have fixed an issue with some OpenMP stand-alone directives not being properly diagnosed as per:
https://www.openmp.org/spec-html/5.1/openmpsu19.html#x34-330002.1.3
(The same requirement exists in OpenMP 5.2 as well.)

---

Patch is 26.22 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/71398.diff


17 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+22) 
- (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+6) 
- (modified) clang/include/clang/Parse/Parser.h (+3-6) 
- (modified) clang/lib/Parse/ParseOpenMP.cpp (+2-2) 
- (modified) clang/lib/Parse/ParseStmt.cpp (+21-13) 
- (modified) clang/test/C/C2x/n2508.c (+11) 
- (modified) clang/test/OpenMP/barrier_ast_print.cpp (+16-8) 
- (modified) clang/test/OpenMP/barrier_messages.cpp (+4-4) 
- (modified) clang/test/OpenMP/cancel_messages.cpp (+4-2) 
- (modified) clang/test/OpenMP/cancellation_point_messages.cpp (+4-2) 
- (modified) clang/test/OpenMP/depobj_messages.cpp (+4-4) 
- (modified) clang/test/OpenMP/error_message.cpp (+5-5) 
- (modified) clang/test/OpenMP/flush_messages.cpp (+4-4) 
- (modified) clang/test/OpenMP/scan_messages.cpp (+6-4) 
- (modified) clang/test/OpenMP/taskwait_messages.cpp (+4-4) 
- (modified) clang/test/OpenMP/taskyield_messages.cpp (+4-4) 
- (modified) clang/www/c_status.html (+1-1) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5e19dbea6608486..ae851d754c84831 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -209,6 +209,12 @@ C23 Feature Support
 - Clang now supports ``<stdckdint.h>`` which defines several macros for performing
   checked integer arithmetic. It is also exposed in pre-C23 modes.
 
+- Completed the implementation of
+  `N2508 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf>`_. We
+  previously implemented allowing a label at the end of a compound statement,
+  and now we've implemented allowing a label to be followed by a declaration
+  instead of a statement.
+
 Non-comprehensive list of changes in this release
 -------------------------------------------------
 
@@ -545,6 +551,22 @@ Bug Fixes in This Version
   Fixes (`#67687 <https://github.com/llvm/llvm-project/issues/67687>`_)
 - Fix crash from constexpr evaluator evaluating uninitialized arrays as rvalue.
   Fixes (`#67317 <https://github.com/llvm/llvm-project/issues/67317>`_)
+- Clang now properly diagnoses use of stand-alone OpenMP directives after a
+  label (including ``case`` or ``default`` labels).
+
+  Before:
+
+  .. code-block:: c++
+
+  label:
+  #pragma omp barrier // ok
+
+  After:
+
+  .. code-block:: c++
+
+  label:
+  #pragma omp barrier // error: '#pragma omp barrier' cannot be an immediate substatement
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index de180344fcc5c74..2bc72acc1375143 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -299,6 +299,12 @@ def note_missing_selector_name : Note<
 def note_force_empty_selector_name : Note<
   "or insert whitespace before ':' to use %0 as parameter name "
   "and have an empty entry in the selector">;
+def ext_c_label_followed_by_declaration : ExtWarn<
+  "label followed by a declaration is a C23 extension">,
+  InGroup<C23>;
+def warn_c23_compat_label_followed_by_declaration : Warning<
+  "label followed by a declaration is incompatible with C standards before "
+  "C23">, InGroup<CPre23Compat>, DefaultIgnore;
 def ext_c_label_end_of_compound_statement : ExtWarn<
   "label at end of compound statement is a C23 extension">,
    InGroup<C23>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 30e0352c868637b..22e8c4ceea39cd6 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -410,18 +410,15 @@ class Parser : public CodeCompletionHandler {
 
   /// Flags describing a context in which we're parsing a statement.
   enum class ParsedStmtContext {
-    /// This context permits declarations in language modes where declarations
-    /// are not statements.
-    AllowDeclarationsInC = 0x1,
     /// This context permits standalone OpenMP directives.
-    AllowStandaloneOpenMPDirectives = 0x2,
+    AllowStandaloneOpenMPDirectives = 0x1,
     /// This context is at the top level of a GNU statement expression.
-    InStmtExpr = 0x4,
+    InStmtExpr = 0x2,
 
     /// The context of a regular substatement.
     SubStmt = 0,
     /// The context of a compound-statement.
-    Compound = AllowDeclarationsInC | AllowStandaloneOpenMPDirectives,
+    Compound = AllowStandaloneOpenMPDirectives,
 
     LLVM_MARK_AS_BITMASK_ENUM(InStmtExpr)
   };
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 3e7d8274aeefc52..9b47ec4fbbc51f1 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2670,7 +2670,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
   }
   case OMPD_threadprivate: {
     // FIXME: Should this be permitted in C++?
-    if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
+    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
         ParsedStmtContext()) {
       Diag(Tok, diag::err_omp_immediate_directive)
           << getOpenMPDirectiveName(DKind) << 0;
@@ -2689,7 +2689,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
   }
   case OMPD_allocate: {
     // FIXME: Should this be permitted in C++?
-    if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
+    if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
         ParsedStmtContext()) {
       Diag(Tok, diag::err_omp_immediate_directive)
           << getOpenMPDirectiveName(DKind) << 0;
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 2531147c23196ae..da991c641130921 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -235,10 +235,7 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
     auto IsStmtAttr = [](ParsedAttr &Attr) { return Attr.isStmtAttr(); };
     bool AllAttrsAreStmtAttrs = llvm::all_of(CXX11Attrs, IsStmtAttr) &&
                                 llvm::all_of(GNUAttrs, IsStmtAttr);
-    if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
-         (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
-             ParsedStmtContext()) &&
-        ((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) ||
+    if (((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) ||
          isDeclarationStatement())) {
       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
       DeclGroupPtrTy Decl;
@@ -698,6 +695,19 @@ StmtResult Parser::ParseSEHLeaveStatement() {
   return Actions.ActOnSEHLeaveStmt(LeaveLoc, getCurScope());
 }
 
+static void DiagnoseLabelFollowedByDecl(Parser &P, const Stmt *SubStmt) {
+  // When in C mode (but not Microsoft extensions mode), diagnose use of a
+  // label that is followed by a declaration rather than a statement.
+  if (!P.getLangOpts().CPlusPlus && !P.getLangOpts().MicrosoftExt &&
+      isa<DeclStmt>(SubStmt)) {
+    if (P.getLangOpts().C23)
+      P.Diag(SubStmt->getBeginLoc(),
+             diag::warn_c23_compat_label_followed_by_declaration);
+    else
+      P.Diag(SubStmt->getBeginLoc(), diag::ext_c_label_followed_by_declaration);
+  }
+}
+
 /// ParseLabeledStatement - We have an identifier and a ':' after it.
 ///
 ///       label:
@@ -712,9 +722,7 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
   assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
          "Not an identifier!");
 
-  // The substatement is always a 'statement', not a 'declaration', but is
-  // otherwise in the same context as the labeled-statement.
-  StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
+  StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
 
   Token IdentTok = Tok;  // Save the whole token.
   ConsumeToken();  // eat the identifier.
@@ -763,6 +771,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
   if (SubStmt.isInvalid())
     SubStmt = Actions.ActOnNullStmt(ColonLoc);
 
+  DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
+
   LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
                                               IdentTok.getLocation());
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
@@ -781,9 +791,7 @@ StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
                                       bool MissingCase, ExprResult Expr) {
   assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!");
 
-  // The substatement is always a 'statement', not a 'declaration', but is
-  // otherwise in the same context as the labeled-statement.
-  StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
+  StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
 
   // It is very common for code to contain many case statements recursively
   // nested, as in (but usually without indentation):
@@ -909,6 +917,7 @@ StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
     // Broken sub-stmt shouldn't prevent forming the case statement properly.
     if (SubStmt.isInvalid())
       SubStmt = Actions.ActOnNullStmt(SourceLocation());
+    DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
     Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
   }
 
@@ -924,9 +933,7 @@ StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
 StmtResult Parser::ParseDefaultStatement(ParsedStmtContext StmtCtx) {
   assert(Tok.is(tok::kw_default) && "Not a default stmt!");
 
-  // The substatement is always a 'statement', not a 'declaration', but is
-  // otherwise in the same context as the labeled-statement.
-  StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
+  StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
 
   SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
 
@@ -960,6 +967,7 @@ StmtResult Parser::ParseDefaultStatement(ParsedStmtContext StmtCtx) {
   if (SubStmt.isInvalid())
     SubStmt = Actions.ActOnNullStmt(ColonLoc);
 
+  DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
   return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
                                   SubStmt.get(), getCurScope());
 }
diff --git a/clang/test/C/C2x/n2508.c b/clang/test/C/C2x/n2508.c
index 2dee0b668cb4e8c..b47c1274aab965c 100644
--- a/clang/test/C/C2x/n2508.c
+++ b/clang/test/C/C2x/n2508.c
@@ -21,3 +21,14 @@ void test() {
 final:
 }
 
+void test_labels() {
+label:
+  int i = 0;
+
+  switch (i) {
+  case 1:
+    _Static_assert(true);
+  default:
+    _Static_assert(true);
+  }
+}
diff --git a/clang/test/OpenMP/barrier_ast_print.cpp b/clang/test/OpenMP/barrier_ast_print.cpp
index a8db2172c19289d..9b7398b3d5b4324 100644
--- a/clang/test/OpenMP/barrier_ast_print.cpp
+++ b/clang/test/OpenMP/barrier_ast_print.cpp
@@ -17,13 +17,13 @@ T tmain(T argc) {
   static T a;
 #pragma omp barrier
   switch (argc) {
-  case 0:
+  case 0: {
 #pragma omp barrier
-    break;
-  default:
+  } break;
+  default: {
 #pragma omp barrier
 #pragma omp barrier
-    break;
+  } break;
   }
   return a + argc;
 }
@@ -35,11 +35,15 @@ T tmain(T argc) {
 // CHECK-NEXT: #pragma omp barrier
 // CHECK-NEXT: switch (argc) {
 // CHECK-NEXT: case 0:
+// CHECK-NEXT: {
 // CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: }
 // CHECK-NEXT: break;
 // CHECK-NEXT: default:
+// CHECK-NEXT: {
 // CHECK-NEXT: #pragma omp barrier
 // CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: }
 // CHECK-NEXT: break;
 // CHECK-NEXT: }
 
@@ -49,21 +53,25 @@ int main(int argc, char **argv) {
 #pragma omp barrier
   // CHECK-NEXT: #pragma omp barrier
   switch (argc) {
-  case 0:
+  case 0: {
 #pragma omp barrier
 #pragma omp barrier
-    break;
-  default:
+  } break;
+  default: {
 #pragma omp barrier
-    break;
+  } break;
   }
 // CHECK-NEXT: switch (argc) {
 // CHECK-NEXT: case 0:
+// CHECK-NEXT: {
 // CHECK-NEXT: #pragma omp barrier
 // CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: }
 // CHECK-NEXT: break;
 // CHECK-NEXT: default:
+// CHECK-NEXT: {
 // CHECK-NEXT: #pragma omp barrier
+// CHECK-NEXT: }
 // CHECK-NEXT: break;
 // CHECK-NEXT: }
   return tmain(argc) + tmain(argv[0][0]) + a;
diff --git a/clang/test/OpenMP/barrier_messages.cpp b/clang/test/OpenMP/barrier_messages.cpp
index 589b9c711aaae95..1dda66b9b242592 100644
--- a/clang/test/OpenMP/barrier_messages.cpp
+++ b/clang/test/OpenMP/barrier_messages.cpp
@@ -38,7 +38,7 @@ T tmain(T argc) {
   switch (argc) {
 #pragma omp barrier
   case 1:
-#pragma omp barrier
+#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
     break;
   default: {
 #pragma omp barrier
@@ -50,7 +50,7 @@ T tmain(T argc) {
 #pragma omp barrier
     }
 label:
-#pragma omp barrier
+#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
 label1 : {
 #pragma omp barrier
 }
@@ -92,7 +92,7 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp barrier
   case 1:
-#pragma omp barrier
+#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
     break;
   default: {
 #pragma omp barrier
@@ -104,7 +104,7 @@ int main(int argc, char **argv) {
 #pragma omp barrier
     }
 label:
-#pragma omp barrier
+#pragma omp barrier // expected-error {{'#pragma omp barrier' cannot be an immediate substatement}}
 label1 : {
 #pragma omp barrier
 }
diff --git a/clang/test/OpenMP/cancel_messages.cpp b/clang/test/OpenMP/cancel_messages.cpp
index fd19f1f373ef9b1..0c96beecc04b04e 100644
--- a/clang/test/OpenMP/cancel_messages.cpp
+++ b/clang/test/OpenMP/cancel_messages.cpp
@@ -71,7 +71,8 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp cancel taskgroup // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
   case 1:
-#pragma omp cancel parallel // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancel parallel // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}} \
+                               expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
     break;
   default: {
 #pragma omp cancel sections // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
@@ -83,7 +84,8 @@ int main(int argc, char **argv) {
 #pragma omp cancel taskgroup // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
     }
 label:
-#pragma omp cancel parallel // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancel parallel // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}} \
+                               expected-error {{'#pragma omp cancel' cannot be an immediate substatement}}
 label1 : {
 #pragma omp cancel sections // expected-error {{orphaned 'omp cancel' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
 }
diff --git a/clang/test/OpenMP/cancellation_point_messages.cpp b/clang/test/OpenMP/cancellation_point_messages.cpp
index 268cab2d80a6e40..e928449ff57a980 100644
--- a/clang/test/OpenMP/cancellation_point_messages.cpp
+++ b/clang/test/OpenMP/cancellation_point_messages.cpp
@@ -71,7 +71,8 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp cancellation point taskgroup // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
   case 1:
-#pragma omp cancellation point parallel // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancellation point parallel // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}} \
+                                           expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
     break;
   default: {
 #pragma omp cancellation point sections // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
@@ -83,7 +84,8 @@ int main(int argc, char **argv) {
 #pragma omp cancellation point taskgroup // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
     }
 label:
-#pragma omp cancellation point parallel // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
+#pragma omp cancellation point parallel // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}} \
+                                           expected-error {{'#pragma omp cancellation point' cannot be an immediate substatement}}
 label1 : {
 #pragma omp cancellation point sections // expected-error {{orphaned 'omp cancellation point' directives are prohibited; perhaps you forget to enclose the directive into a region?}}
 }
diff --git a/clang/test/OpenMP/depobj_messages.cpp b/clang/test/OpenMP/depobj_messages.cpp
index 38617e16cab9c9a..9d750f651d81f39 100644
--- a/clang/test/OpenMP/depobj_messages.cpp
+++ b/clang/test/OpenMP/depobj_messages.cpp
@@ -59,7 +59,7 @@ T tmain(T argc) {
   switch (argc) {
 #pragma omp depobj(x) depend(in:s)
   case 1:
-#pragma omp depobj(x) depend(in:s)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
     break;
   default: {
 #pragma omp depobj(x) depend(in:s)
@@ -71,7 +71,7 @@ T tmain(T argc) {
 #pragma omp depobj(x) depend(in:s)
     }
 label:
-#pragma omp depobj(x) depend(in:s)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
 label1 : {
 #pragma omp depobj(x) depend(in:s)
 }
@@ -124,7 +124,7 @@ omp_depend_t x;
   switch (argc) {
 #pragma omp depobj(x) depend(in:s)
   case 1:
-#pragma omp depobj(x) depend(in:s)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
     break;
   default: {
 #pragma omp depobj(x) depend(in:s)
@@ -136,7 +136,7 @@ omp_depend_t x;
 #pragma omp depobj(x) depend(in:s)
     }
 label:
-#pragma omp depobj(x) depend(in:s)
+#pragma omp depobj(x) depend(in:s) // expected-error {{'#pragma omp depobj' cannot be an immediate substatement}}
 label1 : {
 #pragma omp depobj(x) depend(in:s)
 }
diff --git a/clang/test/OpenMP/error_message.cpp b/clang/test/OpenMP/error_message.cpp
index 40f1db40fb63af2..9796a6443c0100f 100644
--- a/clang/test/OpenMP/error_message.cpp
+++ b/clang/test/OpenMP/error_message.cpp
@@ -32,8 +32,8 @@ T tmain(T argc) {
   }
   switch (argc) {
 #pragma omp error // expected-error {{ERROR}}
-  case 1:
-#pragma omp error // expected-error {{ERROR}}
+  case 1: // FIXME: error without 'at execution' is not a stand-alone directive and so this should be accepted.
+#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
     break;
   default: {
 #pragma omp error // expected-error {{ERROR}}
@@ -45,7 +45,7 @@ T tmain(T argc) {
 #pragma omp error // expected-error {{ERROR}}
     }
 label:
-#pragma omp error // expected-error {{ERROR}}
+#pragma omp error // expected-error {{'#pragma omp error' cannot be an immediate substatement}}
 label1 : {
 #pragma omp error // expected-error {{ERROR}}
 }
@@ -168,7 +168,7 @@ int main(int argc, char **argv) {
 // expected-error at +1 {{ERROR}}
 #pragma omp error
   case 1:
-// expected-error at +1 {{ERROR}}
+// expected-error at +1 {{'#pragma omp error' cannot be an immediate substatement}}
 #pragma omp error
     break;
   default: {
@@ -183,7 +183,7 @@ int main(int argc, char **argv) {
 #pragma omp error
     }
 label:
-// expected-error at +1 {{ERROR}}
+// expected-error at +1 {{'#pragma omp error' cannot be an immediate substatement}}
 #pragma omp error
 label1 : {
 // expected-error at +1 {{ERROR}}
diff --git a/clang/test/OpenMP/flush_messages.cpp b/clang/test/OpenMP/flush_messages.cpp
index 1be0fb8d590adc3..ad4830b5bf94f96 100644
--- a/clang/test/OpenMP/flush_messages.cpp
+++ b/clang/test/OpenMP/flush_messages.cpp
@@ -43,7 +43,7 @@ T tmain(T argc) {
   switch (argc) {
 #pragma omp flush
   case 1:
-#pragma omp flush
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
     break;
   default: {
 #pragma omp flush
@@ -55,7 +55,7 @@ T tmain(T argc) {
 #pragma omp flush
     }
 label:
-#pragma omp flush
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
 label1 : {
 #pragma omp flush
 }
@@ -107,7 +107,7 @@ int main(int argc, char **argv) {
   switch (argc) {
 #pragma omp flush
   case 1:
-#pragma omp flush
+#pragma omp flush // expected-error {{'#pragma omp flush' cannot be an immediate substatement}}
     break;
   default: {
 #pragma omp flush
@@ -119,7 +119,7 @@ int main(int argc, char **argv) {
 #pragma omp flush
     }
 l...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/71398


More information about the llvm-commits mailing list