Author: Ayush Kumar Gaur
Date: 2026-01-26T17:01:02+01:00
New Revision: a150e8081ac2b4c7c056b0290afb88b9a01d7a1d

URL: 
https://github.com/llvm/llvm-project/commit/a150e8081ac2b4c7c056b0290afb88b9a01d7a1d
DIFF: 
https://github.com/llvm/llvm-project/commit/a150e8081ac2b4c7c056b0290afb88b9a01d7a1d.diff

LOG: [clang][bytecode] Avoid crash in constexpr wcslen on invalid argument… 
(#177891)

### What the problem ?

Fix a clang bytecode constant interpreter crash when evaluating
wcslen("x") in a constant-expression path.

Previously we asserted on wchar element size mismatch and crashed in
assertion builds.

### Why it happened

The expression is already ill-typed (char[2] → const wchar_t*), clang
correctly emits a diagnostic, but later ICE checking tries to fold the
expression and reaches the builtin handler. That path must not crash.

### whats the Fix

Replace the assert(ElemSize == wchar_t size) with a graceful failure
(return false / emit appropriate diagnostic) when element sizes don’t
match, so evaluation stops safely.

### how to Test it

Add a regression test that triggers ICE checking with
-fexperimental-new-constant-interpreter and ensures clang does not crash
(verifies it reports the type error / static_assert failure instead).

Fixes #177844.

<img width="1366" height="768" alt="Screenshot_2026-01-25_22_07_50"
src="https://github.com/user-attachments/assets/488dd0b0-3c17-4f45-b2d0-9339b8fd3409";
/>

where wclen_crash.c is 

`
#include <wchar.h>

static_assert(wcslen("x") == 'x');
int main() {}
`

---------

Co-authored-by: Timm Baeder <[email protected]>

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/InterpBuiltin.cpp
    clang/test/AST/ByteCode/builtin-functions.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index d668fa118d3b9..4cf6898df3692 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -367,8 +367,10 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr 
OpPC,
   unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize();
 
   if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {
-    [[maybe_unused]] const ASTContext &AC = S.getASTContext();
-    assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity());
+    const ASTContext &AC = S.getASTContext();
+    unsigned WCharSize = 
AC.getTypeSizeInChars(AC.getWCharType()).getQuantity();
+    if (ElemSize != WCharSize)
+      return false;
   }
 
   size_t Len = 0;

diff  --git a/clang/test/AST/ByteCode/builtin-functions.cpp 
b/clang/test/AST/ByteCode/builtin-functions.cpp
index 116d6aef8350a..b2f0213cfea05 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -1903,3 +1903,15 @@ namespace NonBlockPointerStore {
   void foo(void) { a *= __builtin_sadd_overflow(1, 2, 0); }
   void foo2(void) { a *= __builtin_addc(1, 2, 0, 0); }
 }
+
+namespace WcslenInvalidArg {
+
+  static_assert(__builtin_wcslen("x") == 'x'); // both-error {{cannot 
initialize a parameter of type 'const wchar_t *' with an lvalue of type 'const 
char[2]'}}
+  static_assert(__builtin_wcslen((const wchar_t *)"x") == 1); // both-error 
{{static assertion expression is not an integral constant expression}} \
+                                                              // both-note 
{{cast that performs the conversions of a reinterpret_cast}}
+  const unsigned char u8s[] = "hi";
+  static_assert(__builtin_wcslen((const wchar_t *)u8s) == 2); // both-error 
{{static assertion expression is not an integral constant expression}} \
+                                                              // both-note 
{{cast that performs the conversions of a reinterpret_cast}}
+  static_assert(__builtin_wcslen(L"x") == 1);
+
+}


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

Reply via email to