[clang] 00b50c9 - [clang][bytecode] Handle __builtin_wcslen (#119187)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 9 03:34:29 PST 2024
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 {
More information about the cfe-commits
mailing list