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
