-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang][bytecode] Use in Expr::tryEvaluateString
#160118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesFixes #157492 Full diff: https://github.com/llvm/llvm-project/pull/160118.diff 3 Files Affected:
diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp
index cfda6e8ded760..fffdafe4b2e2f 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -236,6 +236,48 @@ bool Context::evaluateCharRange(State &Parent, const Expr *SizeExpr,
return evaluateStringRepr(Parent, SizeExpr, PtrExpr, Result);
}
+bool Context::evaluateString(State &Parent, const Expr *E,
+ std::string &Result) {
+ assert(Stk.empty());
+ Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
+
+ auto PtrRes = C.interpretAsPointer(E, [&](const Pointer &Ptr) {
+ const Descriptor *FieldDesc = Ptr.getFieldDesc();
+ if (!FieldDesc->isPrimitiveArray())
+ return false;
+
+ if (!Ptr.isConst())
+ return false;
+
+ unsigned N = Ptr.getNumElems();
+ if (Ptr.elemSize() == 1 /* bytes */) {
+ const char *Chars = reinterpret_cast<const char *>(Ptr.getRawAddress());
+ unsigned Length = strnlen(Chars, N);
+ Result.assign(Chars, Length);
+ return true;
+ }
+
+ PrimType ElemT = FieldDesc->getPrimType();
+ for (unsigned I = Ptr.getIndex(); I != N; ++I) {
+ INT_TYPE_SWITCH(ElemT, {
+ auto Elem = Ptr.elem<T>(I);
+ if (Elem.isZero())
+ return true;
+ Result.push_back(static_cast<char>(Elem));
+ });
+ }
+ // We didn't find a 0 byte.
+ return false;
+ });
+
+ if (PtrRes.isInvalid()) {
+ C.cleanup();
+ Stk.clear();
+ return false;
+ }
+ return true;
+}
+
bool Context::evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result) {
assert(Stk.empty());
Compiler<EvalEmitter> C(*this, *P, Parent, Stk);
diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h
index 280a31725555f..fadedf83e68ff 100644
--- a/clang/lib/AST/ByteCode/Context.h
+++ b/clang/lib/AST/ByteCode/Context.h
@@ -67,6 +67,10 @@ class Context final {
bool evaluateCharRange(State &Parent, const Expr *SizeExpr,
const Expr *PtrExpr, std::string &Result);
+ /// Evaluate \param E and if it can be evaluated to a sirint literal,
+ /// copy the result into \param Result.
+ bool evaluateString(State &Parent, const Expr *E, std::string &Result);
+
/// Evalute \param E and if it can be evaluated to a string literal,
/// run strlen() on it.
bool evaluateStrlen(State &Parent, const Expr *E, uint64_t &Result);
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 3b9ca82910033..e569263c9ab3c 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -18770,9 +18770,15 @@ std::optional<std::string> Expr::tryEvaluateString(ASTContext &Ctx) const {
uint64_t Result;
std::string StringResult;
+ if (Info.EnableNewConstInterp) {
+ if (!Info.Ctx.getInterpContext().evaluateString(Info, this, StringResult))
+ return std::nullopt;
+ return StringResult;
+ }
+
if (EvaluateBuiltinStrLen(this, Result, Info, &StringResult))
return StringResult;
- return {};
+ return std::nullopt;
}
template <typename T>
|
|
@cor3ntin Are the additional test changes ok? |
cor3ntin
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
clang/test/SemaCXX/verbose-trap.cpp
Outdated
| @@ -45,3 +48,10 @@ void f2() { | |||
| void test() { | |||
| f<constCat3, constMsg3>(nullptr); | |||
| } | |||
|
|
|||
| /// Arguments must be null terminated. | |||
| constexpr char K[] = {'a', 'b'}; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we try a case where the array is null terminated. How about a case where the array has multiple null terminators etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a null-terminated array test case, but I can't check that we really have the right string here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that is ok, we are just making we test both the happy and unhappy path.
527f3b9 to
9766cad
Compare
Fixes #157492