Skip to content

Commit 00b50c9

Browse files
authored
[clang][bytecode] Handle __builtin_wcslen (#119187)
Handle different char widths in builtin_strlen.
1 parent bbd99d9 commit 00b50c9

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
243243
unsigned ID = Func->getBuiltinID();
244244
const Pointer &StrPtr = getParam<Pointer>(Frame, 0);
245245

246-
if (ID == Builtin::BIstrlen)
246+
if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)
247247
diagnoseNonConstexprBuiltin(S, OpPC, ID);
248248

249249
if (!CheckArray(S, OpPC, StrPtr))
@@ -256,6 +256,12 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
256256
return false;
257257

258258
assert(StrPtr.getFieldDesc()->isPrimitiveArray());
259+
unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize();
260+
261+
if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {
262+
const ASTContext &AC = S.getASTContext();
263+
assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity());
264+
}
259265

260266
size_t Len = 0;
261267
for (size_t I = StrPtr.getIndex();; ++I, ++Len) {
@@ -264,7 +270,20 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
264270
if (!CheckRange(S, OpPC, ElemPtr, AK_Read))
265271
return false;
266272

267-
uint8_t Val = ElemPtr.deref<uint8_t>();
273+
uint32_t Val;
274+
switch (ElemSize) {
275+
case 1:
276+
Val = ElemPtr.deref<uint8_t>();
277+
break;
278+
case 2:
279+
Val = ElemPtr.deref<uint16_t>();
280+
break;
281+
case 4:
282+
Val = ElemPtr.deref<uint32_t>();
283+
break;
284+
default:
285+
llvm_unreachable("Unsupported char size");
286+
}
268287
if (Val == 0)
269288
break;
270289
}
@@ -1859,6 +1878,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
18591878
break;
18601879
case Builtin::BI__builtin_strlen:
18611880
case Builtin::BIstrlen:
1881+
case Builtin::BI__builtin_wcslen:
1882+
case Builtin::BIwcslen:
18621883
if (!interp__builtin_strlen(S, OpPC, Frame, F, Call))
18631884
return false;
18641885
break;

clang/test/AST/ByteCode/builtin-functions.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
#error "huh?"
1616
#endif
1717

18+
extern "C" {
19+
typedef decltype(sizeof(int)) size_t;
20+
extern size_t wcslen(const wchar_t *p);
21+
}
1822

1923
namespace strcmp {
2024
constexpr char kFoobar[6] = {'f','o','o','b','a','r'};
@@ -93,6 +97,14 @@ constexpr const char *a = "foo\0quux";
9397
constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator.
9498
constexpr int bad = __builtin_strlen(d); // both-error {{constant expression}} \
9599
// both-note {{one-past-the-end}}
100+
101+
constexpr int wn = __builtin_wcslen(L"hello");
102+
static_assert(wn == 5);
103+
constexpr int wm = wcslen(L"hello"); // both-error {{constant expression}} \
104+
// both-note {{non-constexpr function 'wcslen' cannot be used in a constant expression}}
105+
106+
int arr[3]; // both-note {{here}}
107+
int wk = arr[wcslen(L"hello")]; // both-warning {{array index 5}}
96108
}
97109

98110
namespace nan {

0 commit comments

Comments
 (0)