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
