Skip to content

Commit 7627031

Browse files
tbaederrmahesh-attarde
authored andcommitted
[clang][bytecode] Use in Expr::tryEvaluateString (llvm#160118)
Fixes llvm#157492
1 parent de23b89 commit 7627031

File tree

4 files changed

+71
-1
lines changed

4 files changed

+71
-1
lines changed

clang/lib/AST/ByteCode/Context.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,52 @@ bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
237237
return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
238238
}
239239

240+
bool Context::evaluateString(State &Parent, const Expr *E,
241+
std::string &Result) {
242+
assert(Stk.empty());
243+
Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
244+
245+
auto PtrRes = C.interpretAsPointer(E, [&](const Pointer &Ptr) {
246+
const Descriptor *FieldDesc = Ptr.getFieldDesc();
247+
if (!FieldDesc->isPrimitiveArray())
248+
return false;
249+
250+
if (!Ptr.isConst())
251+
return false;
252+
253+
unsigned N = Ptr.getNumElems();
254+
255+
if (Ptr.elemSize() == 1 /* bytes */) {
256+
const char *Chars = reinterpret_cast<const char *>(Ptr.getRawAddress());
257+
unsigned Length = strnlen(Chars, N);
258+
// Wasn't null terminated.
259+
if (N == Length)
260+
return false;
261+
Result.assign(Chars, Length);
262+
return true;
263+
}
264+
265+
PrimType ElemT = FieldDesc->getPrimType();
266+
for (unsigned I = Ptr.getIndex(); I != N; ++I) {
267+
INT_TYPE_SWITCH(ElemT, {
268+
auto Elem = Ptr.elem<T>(I);
269+
if (Elem.isZero())
270+
return true;
271+
Result.push_back(static_cast<char>(Elem));
272+
});
273+
}
274+
// We didn't find a 0 byte.
275+
return false;
276+
});
277+
278+
if (PtrRes.isInvalid()) {
279+
C.cleanup();
280+
Stk.clear();
281+
return false;
282+
}
283+
return true;
284+
}
285+
240286
bool Context::evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result) {
241287
assert(Stk.empty());
242288
Compiler<EvalEmitter> C(*this, *P, Parent, Stk);

clang/lib/AST/ByteCode/Context.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ class Context final {
6767
bool evaluateCharRange(State &Parent, const Expr *SizeExpr,
6868
const Expr *PtrExpr, std::string &Result);
6969

70+
/// Evaluate \param E and if it can be evaluated to a null-terminated string,
71+
/// copy the result into \param Result.
72+
bool evaluateString(State &Parent, const Expr *E, std::string &Result);
73+
7074
/// Evalute \param E and if it can be evaluated to a string literal,
7175
/// run strlen() on it.
7276
bool evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result);

clang/lib/AST/ExprConstant.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18905,9 +18905,15 @@ std::optional<std::string> Expr::tryEvaluateString(ASTContext &Ctx) const {
1890518905
uint64_t Result;
1890618906
std::string StringResult;
1890718907

18908+
if (Info.EnableNewConstInterp) {
18909+
if (!Info.Ctx.getInterpContext().evaluateString(Info, this, StringResult))
18910+
return std::nullopt;
18911+
return StringResult;
18912+
}
18913+
1890818914
if (EvaluateBuiltinStrLen(this, Result, Info, &StringResult))
1890918915
return StringResult;
18910-
return {};
18916+
return std::nullopt;
1891118917
}
1891218918

1891318919
template <typename T>

clang/test/SemaCXX/verbose-trap.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify %s
22
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify %s
33

4+
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fcxx-exceptions -verify %s -fexperimental-new-constant-interpreter
5+
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify %s -fexperimental-new-constant-interpreter
6+
47
#if !__has_builtin(__builtin_verbose_trap)
58
#error
69
#endif
@@ -45,3 +48,14 @@ void f2() {
4548
void test() {
4649
f<constCat3, constMsg3>(nullptr);
4750
}
51+
52+
/// Arguments must be null terminated.
53+
int foo() {
54+
constexpr char K[] = {'a', 'b'};
55+
__builtin_verbose_trap("hehe", K); // expected-error {{argument to __builtin_verbose_trap must be a pointer to a constant string}}
56+
__builtin_verbose_trap(K, "hehe"); //expected-error {{argument to __builtin_verbose_trap must be a pointer to a constant string}}
57+
58+
constexpr char K2[] = {'a', 'b', '\0'};
59+
__builtin_verbose_trap("hehe", K2);
60+
__builtin_verbose_trap(K2, "hehe");
61+
}

0 commit comments

Comments
 (0)