[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