Author: Timm Baeder Date: 2024-12-09T12:34:25+01:00 New Revision: 00b50c917bf5e5abaded4f314b767b086069d1ee
URL: https://github.com/llvm/llvm-project/commit/00b50c917bf5e5abaded4f314b767b086069d1ee DIFF: https://github.com/llvm/llvm-project/commit/00b50c917bf5e5abaded4f314b767b086069d1ee.diff LOG: [clang][bytecode] Handle __builtin_wcslen (#119187) Handle different char widths in builtin_strlen. 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 24b630d0455e14..2469648d68edb1 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -243,7 +243,7 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, unsigned ID = Func->getBuiltinID(); const Pointer &StrPtr = getParam<Pointer>(Frame, 0); - if (ID == Builtin::BIstrlen) + if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen) diagnoseNonConstexprBuiltin(S, OpPC, ID); if (!CheckArray(S, OpPC, StrPtr)) @@ -256,6 +256,12 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, return false; assert(StrPtr.getFieldDesc()->isPrimitiveArray()); + unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize(); + + if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) { + const ASTContext &AC = S.getASTContext(); + assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity()); + } size_t Len = 0; for (size_t I = StrPtr.getIndex();; ++I, ++Len) { @@ -264,7 +270,20 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, if (!CheckRange(S, OpPC, ElemPtr, AK_Read)) return false; - uint8_t Val = ElemPtr.deref<uint8_t>(); + uint32_t Val; + switch (ElemSize) { + case 1: + Val = ElemPtr.deref<uint8_t>(); + break; + case 2: + Val = ElemPtr.deref<uint16_t>(); + break; + case 4: + Val = ElemPtr.deref<uint32_t>(); + break; + default: + llvm_unreachable("Unsupported char size"); + } if (Val == 0) break; } @@ -1859,6 +1878,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, break; case Builtin::BI__builtin_strlen: case Builtin::BIstrlen: + case Builtin::BI__builtin_wcslen: + case Builtin::BIwcslen: if (!interp__builtin_strlen(S, OpPC, Frame, F, Call)) return false; break; diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp index e2121a54e15768..4c21496d3972c9 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -15,6 +15,10 @@ #error "huh?" #endif +extern "C" { + typedef decltype(sizeof(int)) size_t; + extern size_t wcslen(const wchar_t *p); +} namespace strcmp { constexpr char kFoobar[6] = {'f','o','o','b','a','r'}; @@ -93,6 +97,14 @@ constexpr const char *a = "foo\0quux"; constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator. constexpr int bad = __builtin_strlen(d); // both-error {{constant expression}} \ // both-note {{one-past-the-end}} + + constexpr int wn = __builtin_wcslen(L"hello"); + static_assert(wn == 5); + constexpr int wm = wcslen(L"hello"); // both-error {{constant expression}} \ + // both-note {{non-constexpr function 'wcslen' cannot be used in a constant expression}} + + int arr[3]; // both-note {{here}} + int wk = arr[wcslen(L"hello")]; // both-warning {{array index 5}} } namespace nan { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits