[clang] 6fbd26b - [clang][Interp] Add QualType parameter to Pointer::toRValue
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 5 02:58:20 PDT 2024
Author: Timm Bäder
Date: 2024-07-05T11:58:04+02:00
New Revision: 6fbd26b147ab93da4d0689ea2f6ff73cc9859cb8
URL: https://github.com/llvm/llvm-project/commit/6fbd26b147ab93da4d0689ea2f6ff73cc9859cb8
DIFF: https://github.com/llvm/llvm-project/commit/6fbd26b147ab93da4d0689ea2f6ff73cc9859cb8.diff
LOG: [clang][Interp] Add QualType parameter to Pointer::toRValue
This fixes the crash from #97302, but exposes an underlying problem.
Added:
Modified:
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/EvaluationResult.cpp
clang/lib/AST/Interp/EvaluationResult.h
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/Pointer.cpp
clang/lib/AST/Interp/Pointer.h
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp
index d17151416b44b..5d20a0b8182a9 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -156,7 +156,8 @@ template <> bool EvalEmitter::emitRet<PT_Ptr>(const SourceInfo &Info) {
if (!Ptr.isConst() && Ptr.block()->getEvalID() != Ctx.getEvalID())
return false;
- if (std::optional<APValue> V = Ptr.toRValue(Ctx)) {
+ if (std::optional<APValue> V =
+ Ptr.toRValue(Ctx, EvalResult.getSourceType())) {
EvalResult.setValue(*V);
} else {
return false;
@@ -186,7 +187,8 @@ bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
if (CheckFullyInitialized && !EvalResult.checkFullyInitialized(S, Ptr))
return false;
- if (std::optional<APValue> APV = Ptr.toRValue(S.getCtx())) {
+ if (std::optional<APValue> APV =
+ Ptr.toRValue(S.getCtx(), EvalResult.getSourceType())) {
EvalResult.setValue(*APV);
return true;
}
@@ -257,7 +259,8 @@ void EvalEmitter::updateGlobalTemporaries() {
if (std::optional<PrimType> T = Ctx.classify(E->getType())) {
TYPE_SWITCH(*T, { *Cached = Ptr.deref<T>().toAPValue(); });
} else {
- if (std::optional<APValue> APV = Ptr.toRValue(Ctx))
+ if (std::optional<APValue> APV =
+ Ptr.toRValue(Ctx, Temp->getTemporaryExpr()->getType()))
*Cached = *APV;
}
}
diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp
index a62f3f635e6e0..d0d68f75dd803 100644
--- a/clang/lib/AST/Interp/EvaluationResult.cpp
+++ b/clang/lib/AST/Interp/EvaluationResult.cpp
@@ -43,7 +43,7 @@ std::optional<APValue> EvaluationResult::toRValue() const {
// We have a pointer and want an RValue.
if (const auto *P = std::get_if<Pointer>(&Value))
- return P->toRValue(*Ctx);
+ return P->toRValue(*Ctx, getSourceType());
else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope
return FP->toAPValue();
llvm_unreachable("Unhandled lvalue kind");
diff --git a/clang/lib/AST/Interp/EvaluationResult.h b/clang/lib/AST/Interp/EvaluationResult.h
index ecf2250074cc9..378f1ccdb0af4 100644
--- a/clang/lib/AST/Interp/EvaluationResult.h
+++ b/clang/lib/AST/Interp/EvaluationResult.h
@@ -100,6 +100,15 @@ class EvaluationResult final {
bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const;
+ QualType getSourceType() const {
+ if (const auto *D =
+ dyn_cast_if_present<ValueDecl>(Source.dyn_cast<const Decl *>()))
+ return D->getType();
+ else if (const auto *E = Source.dyn_cast<const Expr *>())
+ return E->getType();
+ return QualType();
+ }
+
/// Dump to stderr.
void dump() const;
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 5d8362b4fa881..12143fbf50808 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1309,7 +1309,8 @@ inline bool InitGlobalTempComp(InterpState &S, CodePtr OpPC,
S.SeenGlobalTemporaries.push_back(
std::make_pair(P.getDeclDesc()->asExpr(), Temp));
- if (std::optional<APValue> APV = P.toRValue(S.getCtx())) {
+ if (std::optional<APValue> APV =
+ P.toRValue(S.getCtx(), Temp->getTemporaryExpr()->getType())) {
*Cached = *APV;
return true;
}
diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp
index d6603f91fb127..157892ea492f6 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -340,7 +340,9 @@ bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) {
A.getFieldDesc()->IsArray;
}
-std::optional<APValue> Pointer::toRValue(const Context &Ctx) const {
+std::optional<APValue> Pointer::toRValue(const Context &Ctx,
+ QualType ResultType) const {
+ assert(!ResultType.isNull());
// Method to recursively traverse composites.
std::function<bool(QualType, const Pointer &, APValue &)> Composite;
Composite = [&Composite, &Ctx](QualType Ty, const Pointer &Ptr, APValue &R) {
@@ -483,13 +485,19 @@ std::optional<APValue> Pointer::toRValue(const Context &Ctx) const {
llvm_unreachable("invalid value to return");
};
- if (isZero())
- return APValue(static_cast<Expr *>(nullptr), CharUnits::Zero(), {}, false,
- true);
-
- if (isDummy() || !isLive())
+ // Invalid to read from.
+ if (isDummy() || !isLive() || isPastEnd())
return std::nullopt;
+ // We can return these as rvalues, but we can't deref() them.
+ if (isZero() || isIntegralPointer())
+ return toAPValue();
+
+ // Just load primitive types.
+ if (std::optional<PrimType> T = Ctx.classify(ResultType)) {
+ TYPE_SWITCH(*T, return this->deref<T>().toAPValue());
+ }
+
// Return the composite type.
APValue Result;
if (!Composite(getType(), *this, Result))
diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 4f277eb7d9e58..fdd921050fd80 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -131,7 +131,8 @@ class Pointer {
}
/// Converts the pointer to an APValue that is an rvalue.
- std::optional<APValue> toRValue(const Context &Ctx) const;
+ std::optional<APValue> toRValue(const Context &Ctx,
+ QualType ResultType) const;
/// Offsets a pointer inside an array.
[[nodiscard]] Pointer atIndex(uint64_t Idx) const {
More information about the cfe-commits
mailing list