[clang] [clang][OpenMP] Reject non-narrow string literals in the message clause (PR #226080)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 24 04:47:31 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Akash Manna (akash-manna-sky)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/226080.diff
5 Files Affected:
- (modified) clang/docs/ReleaseNotes.md (+1)
- (modified) clang/lib/Sema/SemaOpenMP.cpp (+7-2)
- (added) clang/test/OpenMP/error_message.c (+33)
- (modified) clang/test/OpenMP/error_message.cpp (+21)
- (modified) clang/test/OpenMP/parallel_message_messages.cpp (+1-1)
``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index f4a34a37aff52..48222a212c8af 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -529,6 +529,7 @@ features cannot lower the translation-unit ABI level;
- Fixed a constraint comparison bug in partial ordering. (#GH182671)
- Fixed a rejected-valid case that used an explicit object parameter in an out-of-line definition of a nested class member. (#GH136472)
- Fixed an assertion on omp taskloop transparent (#GH197162)
+- 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)
- Fixed a bug where `__func__`, `__PRETTY_FUNCTION__` and `__FUNCTION__` were not resolving to the proper function when inside a lambda return type (#GH211811)
- Fixed USR generation for declarations whose signature mentions a class-type
non-type template parameter. (#GH212351)
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 at +2 {{expected string in 'clause message' - ignoring}}
+// expected-error at +1 {{ERROR}}
+#pragma omp error message(L"")
+// expected-warning at +2 {{expected string in 'clause message' - ignoring}}
+// expected-error at +1 {{ERROR}}
+#pragma omp error message(L"bar")
+// expected-warning at +2 {{expected string in 'clause message' - ignoring}}
+// expected-warning at +1 {{WARNING}}
+#pragma omp error severity(warning) message(L"bar")
+// expected-warning at +2 {{expected string in 'clause message' - ignoring}}
+// expected-error at +1 {{ERROR}}
+#pragma omp error message(1)
+// expected-warning at +2 {{expected string in 'clause message' - ignoring}}
+// expected-error at +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 at +2 {{expected string literal in 'clause message' - ignoring}}
+// expected-error at +1 {{ERROR}}
+#pragma omp error message(msg)
+// expected-warning at +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 at +2 {{expected string in 'clause message' - ignoring}}
+// expected-error at +1 {{ERROR}}
+#pragma omp error message(L"")
+// expected-warning at +2 {{expected string in 'clause message' - ignoring}}
+// expected-error at +1 {{ERROR}}
+#pragma omp error message(L"msg")
+// expected-warning at +2 {{expected string in 'clause message' - ignoring}}
+// expected-error at +1 {{ERROR}}
+#pragma omp error message(u"msg")
+// expected-warning at +2 {{expected string in 'clause message' - ignoring}}
+// expected-error at +1 {{ERROR}}
+#pragma omp error message(U"msg")
+// expected-warning at +2 {{expected string in 'clause message' - ignoring}}
+// expected-warning at +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 at +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}}
}
diff --git a/clang/test/OpenMP/parallel_message_messages.cpp b/clang/test/OpenMP/parallel_message_messages.cpp
index ea8fa23ef5e53..1ec9a37a1b7fa 100644
--- a/clang/test/OpenMP/parallel_message_messages.cpp
+++ b/clang/test/OpenMP/parallel_message_messages.cpp
@@ -62,7 +62,7 @@ T tmain(T argc, S **argv) {
#pragma omp parallel message("hello" " world")
// Message clause with wide string literal
- #pragma omp parallel message(L"wide string")
+ #pragma omp parallel message(L"wide string") // expected-warning {{expected string in 'clause message' - ignoring}}
// Message clause with UTF-8 string literal
#pragma omp parallel message(u8"utf8 string")
``````````
</details>
https://github.com/llvm/llvm-project/pull/226080
More information about the cfe-commits
mailing list