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 { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits