https://github.com/akash-manna-sky created 
https://github.com/llvm/llvm-project/pull/226080

Fixes #140338

The `message` clause accepted any character-typed string, checked with 
`isAnyCharacterType()`, but everything that consumes it assumes a narrow 
string: Sema evaluates it into a `std::string` for the compile-time diagnostic, 
and codegen passes it straight to `__kmpc_error`'s `char *` parameter. When the 
issue was filed this hit the assertion in `StringLiteral::getString()`. Since 
#146405 the assert is gone, but the underlying problem stayed: in C++ a wide 
literal like `message(L"bar")` prints `b<NUL><NUL>` as the error text, and with 
`at(execution)` a `wchar_t` array is emitted as the runtime's `char *` 
argument. C was only spared because `wchar_t` is an integer typedef there, so 
the clause was already rejected.

The clause now only accepts `char` and `char8_t` element types. Wide and 
UTF-16/32 literals get the existing "expected string in 'clause message' - 
ignoring" warning and the directive still fires with its generic message, which 
is what C already did and what GCC does with `<message unknown at compile 
time>`. Doing this at the single point where the clause is built covers the 
diagnostic, both codegen paths, and template instantiation without touching the 
evaluator.

>From 4994e1692a6543667719ac66d4ebe2b8b66c3bd6 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Thu, 24 Sep 2026 14:33:40 +0530
Subject: [PATCH] [clang][OpenMP] Reject non-narrow string literals in the
 message clause

The message clause accepted any character-typed string, but everything
that consumes it assumes a narrow string: Sema evaluates it into a
std::string for the diagnostic, and codegen passes it to the runtime as
a char*. A wide or UTF-16/32 literal asserted in StringLiteral::getString
when the issue was filed, and today prints raw bytes with embedded NULs
or hands a wchar_t array to __kmpc_error.

Only accept char and char8_t element types when building the clause.
Anything else gets the existing "expected string" warning and the
directive falls back to its generic message, matching what C already
did and what GCC does.

Fixes #140338
---
 clang/docs/ReleaseNotes.md          |  1 +
 clang/lib/Sema/SemaOpenMP.cpp       |  9 ++++++--
 clang/test/OpenMP/error_message.c   | 33 +++++++++++++++++++++++++++++
 clang/test/OpenMP/error_message.cpp | 21 ++++++++++++++++++
 4 files changed, 62 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/OpenMP/error_message.c

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index f4a34a37aff52..08bda42c42a6f 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -547,6 +547,7 @@ features cannot lower the translation-unit ABI level;
 - Fixed a crash when an `asm` label names the register for a global variable 
of incomplete type. (#GH219746)
 - Fixed an ICE hat occurred when using `__imag int/float` as lvalue in 
assignment. (#GH119498)
 - Fixed an assertion failure in `-Wsign-compare` when a negated or 
complemented vector of unsigned integers was compared against a signed 
constant. (#GH203575)
+- Fixed an assertion failure and a garbled diagnostic when the `message` 
clause of `#pragma omp error` was given a wide or UTF-16/32 string literal. 
Such literals are now diagnosed and ignored, as they already were in C. 
(#GH140338)
 
 #### Bug Fixes to Compiler Builtins
 
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 2e4d9f2f82f0b..c9aa5a8b50227 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -18369,8 +18369,13 @@ OMPClause *SemaOpenMP::ActOnOpenMPMessageClause(Expr 
*ME,
                                                 SourceLocation EndLoc) {
   assert(ME && "NULL expr in Message clause");
   QualType Type = ME->getType();
-  if ((!Type->isPointerType() && !Type->isArrayType()) ||
-      !Type->getPointeeOrArrayElementType()->isAnyCharacterType()) {
+  // The message is consumed as a narrow string by Sema and the runtime.
+  bool IsNarrowString = false;
+  if (Type->isPointerType() || Type->isArrayType()) {
+    const auto *ElemTy = Type->getPointeeOrArrayElementType();
+    IsNarrowString = ElemTy->isCharType() || ElemTy->isChar8Type();
+  }
+  if (!IsNarrowString) {
     Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
         << getOpenMPClauseNameForDiag(OMPC_message) << 0;
     return nullptr;
diff --git a/clang/test/OpenMP/error_message.c 
b/clang/test/OpenMP/error_message.c
new file mode 100644
index 0000000000000..82c533d54b631
--- /dev/null
+++ b/clang/test/OpenMP/error_message.c
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -ferror-limit 100 %s
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=60 -ferror-limit 100 %s
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -ferror-limit 100 
%s
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=60 -ferror-limit 100 
%s
+
+// GH140338
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-error@+1 {{ERROR}}
+#pragma omp error message(L"")
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-error@+1 {{ERROR}}
+#pragma omp error message(L"bar")
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-warning@+1 {{WARNING}}
+#pragma omp error severity(warning) message(L"bar")
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-error@+1 {{ERROR}}
+#pragma omp error message(1)
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-error@+1 {{ERROR}}
+#pragma omp error message(1.2)
+#pragma omp error message("foo") // expected-error {{foo}}
+#pragma omp error message(u8"foo") // expected-error {{foo}}
+
+int foo(int i, const char *msg) {
+// expected-warning@+2 {{expected string literal in 'clause message' - 
ignoring}}
+// expected-error@+1 {{ERROR}}
+#pragma omp error message(msg)
+// expected-warning@+1 {{expected string in 'clause message' - ignoring}}
+#pragma omp error at(execution) message(L"bar") // no error
+  return i;
+}
diff --git a/clang/test/OpenMP/error_message.cpp 
b/clang/test/OpenMP/error_message.cpp
index e96562eaa023f..d07c4d8b75c58 100644
--- a/clang/test/OpenMP/error_message.cpp
+++ b/clang/test/OpenMP/error_message.cpp
@@ -7,6 +7,24 @@
 // Test outside of an executable context.
 #pragma omp error severity(warning) message("msg") at(compilation) // 
expected-warning {{msg}}
 
+// GH140338
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-error@+1 {{ERROR}}
+#pragma omp error message(L"")
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-error@+1 {{ERROR}}
+#pragma omp error message(L"msg")
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-error@+1 {{ERROR}}
+#pragma omp error message(u"msg")
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-error@+1 {{ERROR}}
+#pragma omp error message(U"msg")
+// expected-warning@+2 {{expected string in 'clause message' - ignoring}}
+// expected-warning@+1 {{WARNING}}
+#pragma omp error severity(warning) message(L"msg")
+#pragma omp error message(u8"msg") // expected-error {{msg}}
+
 template <class T>
 T tmain(T argc) {
   if (argc)
@@ -202,5 +220,8 @@ if (1)
   label2:
 #pragma omp error // expected-error {{'#pragma omp error' cannot be an 
immediate substatement}}
 
+// expected-warning@+1 {{expected string in 'clause message' - ignoring}}
+#pragma omp error at(execution) message(L"msg") // no error
+
   return tmain(argc);// expected-note {{in instantiation of function template 
specialization 'tmain<int>' requested here}}
 }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to