https://github.com/melver created https://github.com/llvm/llvm-project/pull/180349
The SExprBuilder was previously using StringLiteral::getString() to extract the value of string literals. This method asserts that the string is a narrow string (char width == 1): ``` clang/include/clang/AST/Expr.h:1872: StringRef clang::StringLiteral::getString() const: Assertion `(isUnevaluated() || getCharByteWidth() == 1) && "This function is used in places that assume strings use char"' failed. [...] #9 0x0000556247fcfe3e clang::threadSafety::SExprBuilder::translate(clang::Stmt const*, clang::threadSafety::SExprBuilder::CallingContext*) [...] ``` This fails when using wide string literals as in the new test case added. Switch to using StringLiteral::getBytes(), which provides the raw byte representation of the string. This is sufficient to compare expressions for identity. Fixes: https://github.com/llvm/llvm-project/pull/148551 >From 063fe8558cf1fc4e5fa115a3282592a6db986f76 Mon Sep 17 00:00:00 2001 From: Marco Elver <[email protected]> Date: Sat, 7 Feb 2026 12:24:30 +0100 Subject: [PATCH] Thread Safety Analysis: Fix crash with wide string literals The SExprBuilder was previously using StringLiteral::getString() to extract the value of string literals. This method asserts that the string is a narrow string (char width == 1): ``` clang/include/clang/AST/Expr.h:1872: StringRef clang::StringLiteral::getString() const: Assertion `(isUnevaluated() || getCharByteWidth() == 1) && "This function is used in places that assume strings use char"' failed. [...] #9 0x0000556247fcfe3e clang::threadSafety::SExprBuilder::translate(clang::Stmt const*, clang::threadSafety::SExprBuilder::CallingContext*) [...] ``` This fails when using wide string literals as in the new test case added. Switch to using StringLiteral::getBytes(), which provides the raw byte representation of the string. This is sufficient to compare expressions for identity. Fixes: https://github.com/llvm/llvm-project/pull/148551 --- clang/lib/Analysis/ThreadSafetyCommon.cpp | 4 +-- .../SemaCXX/warn-thread-safety-analysis.cpp | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp index 8180265cc5ed0..b43a986521f99 100644 --- a/clang/lib/Analysis/ThreadSafetyCommon.cpp +++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp @@ -356,10 +356,10 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) { llvm_unreachable("Invalid integer type"); } case Stmt::StringLiteralClass: - return new (Arena) til::LiteralT(cast<StringLiteral>(S)->getString()); + return new (Arena) til::LiteralT(cast<StringLiteral>(S)->getBytes()); case Stmt::ObjCStringLiteralClass: return new (Arena) - til::LiteralT(cast<ObjCStringLiteral>(S)->getString()->getString()); + til::LiteralT(cast<ObjCStringLiteral>(S)->getString()->getBytes()); case Stmt::DeclStmtClass: return translateDeclStmt(cast<DeclStmt>(S), Ctx); diff --git a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp index e57299e93aa48..30d18517c9a19 100644 --- a/clang/test/SemaCXX/warn-thread-safety-analysis.cpp +++ b/clang/test/SemaCXX/warn-thread-safety-analysis.cpp @@ -7770,3 +7770,39 @@ void testLoopConditionalReassignment(Foo *f1, Foo *f2, bool cond) { ptr->mu.Unlock(); // expected-warning{{releasing mutex 'ptr->mu' that was not held}} } // expected-warning{{mutex 'f1->mu' is still held at the end of function}} } // namespace CapabilityAliases + +namespace WideStringLiteral { + +class Foo { + public: + Mutex mu; + Mutex* getMu(const wchar_t* s) { return μ } + Mutex* getMu2(const char16_t* s) { return μ } + Mutex* getMu3(const char32_t* s) { return μ } + + int a GUARDED_BY(getMu(L"abc")); + int b GUARDED_BY(getMu2(u"abc")); + int c GUARDED_BY(getMu3(U"abc")); +}; + +Foo g_foo; + +void test() { + g_foo.getMu(L"abc")->Lock(); + g_foo.a = 0; + g_foo.getMu(L"abc")->Unlock(); +} + +void test2() { + g_foo.getMu2(u"abc")->Lock(); + g_foo.b = 0; + g_foo.getMu2(u"abc")->Unlock(); +} + +void test3() { + g_foo.getMu3(U"abc")->Lock(); + g_foo.c = 0; + g_foo.getMu3(U"abc")->Unlock(); +} + +} // namespace WideStringLiteral _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
