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 &mu; }
+  Mutex* getMu2(const char16_t* s) { return &mu; }
+  Mutex* getMu3(const char32_t* s) { return &mu; }
+
+  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

Reply via email to