Timm =?utf-8?q?Bäder?= <[email protected]>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/[email protected]>


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

Similar to https://github.com/llvm/llvm-project/pull/220917, but for 
expressions.


The first commit is the one from 
https://github.com/llvm/llvm-project/pull/220917.

---

Patch is 63.75 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/221218.diff


21 Files Affected:

- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+10-22) 
- (modified) clang/lib/AST/ByteCode/DeclOrExpr.h (+7) 
- (modified) clang/lib/AST/ByteCode/Disasm.cpp (+1-5) 
- (modified) clang/lib/AST/ByteCode/EvaluationResult.cpp (+2-2) 
- (modified) clang/lib/AST/ByteCode/Interp.cpp (+138-47) 
- (modified) clang/lib/AST/ByteCode/Interp.h (+91-43) 
- (modified) clang/lib/AST/ByteCode/InterpBlock.cpp (+1-10) 
- (modified) clang/lib/AST/ByteCode/InterpBlock.h (+4-10) 
- (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+38-15) 
- (modified) clang/lib/AST/ByteCode/InterpBuiltinObjectSize.cpp (+2-2) 
- (modified) clang/lib/AST/ByteCode/InterpHelpers.h (+5-1) 
- (modified) clang/lib/AST/ByteCode/MemberPointer.h (+2) 
- (modified) clang/lib/AST/ByteCode/Opcodes.td (+8-4) 
- (modified) clang/lib/AST/ByteCode/Pointer.cpp (+92-21) 
- (modified) clang/lib/AST/ByteCode/Pointer.h (+44-23) 
- (modified) clang/lib/AST/ByteCode/Program.cpp (-63) 
- (modified) clang/lib/AST/ByteCode/Program.h (-6) 
- (modified) clang/test/AST/ByteCode/records.cpp (+6) 
- (modified) clang/test/CodeGen/pr4349.c (+2-1) 
- (modified) clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp (+1) 
- (modified) clang/unittests/AST/ByteCode/toAPValue.cpp (-2) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 03f9478a6e4e0..d2feac9c03b30 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -7936,12 +7936,18 @@ bool Compiler<Emitter>::VisitUnaryOperator(const 
UnaryOperator *E) {
     // check), so that e.g. '&*(int *)0' is not rejected.
     if (!Ctx.getLangOpts().CPlusPlus) {
       const Expr *Sub = SubExpr->IgnoreParens();
+
       if (const auto *Deref = dyn_cast<UnaryOperator>(Sub);
-          Deref && Deref->getOpcode() == UO_Deref)
-        return this->delegate(Deref->getSubExpr());
+          Deref && Deref->getOpcode() == UO_Deref) {
+        if (DiscardResult)
+          return this->discard(Deref->getSubExpr());
+        return this->visit(Deref->getSubExpr()) && this->emitAddrOf(E);
+      }
     }
     // We should already have a pointer when we get here.
-    return this->delegate(SubExpr);
+    if (DiscardResult)
+      return this->discard(SubExpr);
+    return this->delegate(SubExpr) && this->emitAddrOf(E);
   case UO_Deref: // *x
     if (DiscardResult)
       return this->discard(SubExpr);
@@ -8729,25 +8735,7 @@ bool Compiler<Emitter>::emitDestructionPop(const 
Descriptor *Desc,
 template <class Emitter>
 bool Compiler<Emitter>::emitDummyPtr(DeclOrExpr D, const Expr *E, bool CU) {
   assert(!DiscardResult && "Should've been checked before");
-
-  if (ToLValue) {
-    if (const auto *VD = D.asValueDecl())
-      return this->emitGetOpaquePtr(VD, CU, E);
-  }
-
-  unsigned DummyID = P.getOrCreateDummy(D, CU);
-  if (!this->emitGetPtrGlobal(DummyID, E))
-    return false;
-  if (E->getType()->isVoidType())
-    return true;
-
-  // Convert the dummy pointer to another pointer type if we have to.
-  if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
-    if (isPtrType(PT))
-      return this->emitDecayPtr(PT_Ptr, PT, E);
-    return false;
-  }
-  return true;
+  return this->emitGetOpaquePtr(D, CU, E);
 }
 
 template <class Emitter>
diff --git a/clang/lib/AST/ByteCode/DeclOrExpr.h 
b/clang/lib/AST/ByteCode/DeclOrExpr.h
index e170b52c6e51d..b844c5644a233 100644
--- a/clang/lib/AST/ByteCode/DeclOrExpr.h
+++ b/clang/lib/AST/ByteCode/DeclOrExpr.h
@@ -28,6 +28,7 @@ struct DeclOrExpr {
   bool isExpr() const { return isa_and_nonnull<const Expr *>(V); }
   bool isDecl() const { return isa_and_nonnull<const Decl *>(V); }
   bool isValueDecl() const { return isa_and_nonnull<ValueDecl>(asDecl()); }
+  bool isVarDecl() const { return isa_and_nonnull<VarDecl>(asDecl()); }
 
   const Expr *asExpr() const { return V.dyn_cast<const Expr *>(); }
   const Decl *asDecl() const { return V.dyn_cast<const Decl *>(); }
@@ -49,6 +50,12 @@ struct DeclOrExpr {
       return VD->getType();
     return asExpr()->getType();
   }
+
+  SourceLocation getLocation() const {
+    if (const auto *VD = asValueDecl())
+      return VD->getLocation();
+    return asExpr()->getExprLoc();
+  }
 };
 static_assert(sizeof(DeclOrExpr) == sizeof(void *));
 
diff --git a/clang/lib/AST/ByteCode/Disasm.cpp 
b/clang/lib/AST/ByteCode/Disasm.cpp
index 03187529541d8..c319591b1fee9 100644
--- a/clang/lib/AST/ByteCode/Disasm.cpp
+++ b/clang/lib/AST/ByteCode/Disasm.cpp
@@ -345,7 +345,6 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) 
const {
     // All the maps.
     Bytes += GlobalIndices.getMemorySize();
     Bytes += Records.getMemorySize();
-    Bytes += DummyVariables.getMemorySize();
 
     // All Records.
     for (const Record *R : Records.values()) {
@@ -372,8 +371,6 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) 
const {
                         : TerminalColor{llvm::raw_ostream::RED, false});
       OS << (GP.isInitialized() ? "initialized " : "uninitialized ");
     }
-    if (GP.block()->isDummy())
-      OS << "dummy ";
     Desc->dump(OS);
 
     if (GP.isInitialized() && Desc->IsTemporary) {
@@ -402,7 +399,7 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) 
const {
     }
 
     OS << "\n";
-    if (GP.isInitialized() && Desc->isPrimitive() && !G->block()->isDummy()) {
+    if (GP.isInitialized() && Desc->isPrimitive()) {
       OS << "   ";
       {
         ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_CYAN, false});
@@ -634,7 +631,6 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) 
const {
   OS << "  Extern: " << isExtern() << "\n";
   OS << "  Initialized: " << IsInitialized << "\n";
   OS << "  Weak: " << isWeak() << "\n";
-  OS << "  Dummy: " << isDummy() << '\n';
   OS << "  Dynamic: " << isDynamic() << "\n";
   OS << "  Metadata: " << MDSize << '\n';
 }
diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp 
b/clang/lib/AST/ByteCode/EvaluationResult.cpp
index bc939c9a5c8fc..5d232c5414e04 100644
--- a/clang/lib/AST/ByteCode/EvaluationResult.cpp
+++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp
@@ -179,8 +179,8 @@ static void collectBlocks(PtrView Ptr,
            P.isDereferencable() && !P.isUnknownSizeArray() && 
!P.isOnePastEnd();
   };
 
-  if (!Ptr.isLive() || Ptr.isZero() || Ptr.isDummy() ||
-      Ptr.isUnknownSizeArray() || Ptr.isOnePastEnd())
+  if (!Ptr.isLive() || Ptr.isZero() || Ptr.isUnknownSizeArray() ||
+      Ptr.isOnePastEnd())
     return;
 
   Blocks.insert(Ptr.Pointee);
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index a41cc1f5a564b..1c4d0862f8a49 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -97,6 +97,23 @@ static void noteValueLocation(InterpState &S, const Block 
*B) {
     S.Note(Desc->getLocation(), diag::note_declared_at);
 }
 
+static void noteValueLocation(InterpState &S, const Pointer &Ptr) {
+  if (Ptr.isBlockPointer()) {
+    const Block *B = Ptr.block();
+    const Descriptor *Desc = B->getDescriptor();
+    if (B->isDynamic())
+      S.Note(Desc->getLocation(), diag::note_constexpr_dynamic_alloc_here);
+    else if (B->isTemporary())
+      S.Note(Desc->getLocation(), diag::note_constexpr_temporary_here);
+    else
+      S.Note(Desc->getLocation(), diag::note_declared_at);
+    return;
+  }
+
+  if (Ptr.isOpaquePointer())
+    S.Note(Ptr.asOpaquePointer().Base.getLocation(), diag::note_declared_at);
+}
+
 static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
                                      const ValueDecl *VD,
                                      AccessKinds AK = AK_Read);
@@ -219,6 +236,13 @@ static bool CheckTemporary(InterpState &S, CodePtr OpPC, 
const Block *B,
   return true;
 }
 
+static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+                           AccessKinds AK) {
+  if (!Ptr.isBlockPointer())
+    return true;
+  return CheckTemporary(S, OpPC, Ptr.block(), AK);
+}
+
 static bool CheckGlobal(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
   if (auto ID = Ptr.getDeclID()) {
     if (!Ptr.isStatic())
@@ -291,8 +315,6 @@ void cleanupAfterFunctionCall(InterpState &S, const 
Function *Func) {
 }
 
 bool isConstexprUnknown(const Block *B) {
-  if (B->isDummy())
-    return isa_and_nonnull<ParmVarDecl>(B->getDescriptor()->asValueDecl());
   return B->getDescriptor()->IsConstexprUnknown;
 }
 
@@ -452,7 +474,7 @@ bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer 
&Ptr,
     } else if (!S.checkingPotentialConstantExpression()) {
       S.FFDiag(Src, diag::note_constexpr_access_uninit)
           << AK << /*uninitialized=*/false << S.Current->getRange(OpPC);
-      noteValueLocation(S, Ptr.block());
+      noteValueLocation(S, Ptr);
     }
 
     return false;
@@ -819,8 +841,6 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const 
Block *B) {
   if (!B->isAccessible()) {
     if (!CheckExtern(S, OpPC, Pointer(const_cast<Block *>(B))))
       return false;
-    if (!CheckDummy(S, OpPC, B, AK_Read))
-      return false;
     return CheckWeak(S, OpPC, B);
   }
 
@@ -889,15 +909,13 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const 
Pointer &Ptr,
   }
   // Block and string pointers are the only ones we can actually read from.
   if (!Ptr.isReadablePointerType())
-    return false;
+    return CheckDummy(S, OpPC, Ptr, AK);
 
   if (Ptr.isBlockPointer() && !Ptr.block()->isAccessible()) {
     if (!CheckLive(S, OpPC, Ptr, AK))
       return false;
     if (!CheckExtern(S, OpPC, Ptr))
       return false;
-    if (!CheckDummy(S, OpPC, Ptr.block(), AK))
-      return false;
     return CheckWeak(S, OpPC, Ptr.block());
   }
 
@@ -956,15 +974,13 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const 
Pointer &Ptr,
 bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
   assert(!Ptr.isZero());
   if (!Ptr.isReadablePointerType())
-    return false;
+    return CheckDummy(S, OpPC, Ptr, AK_Read);
 
   if (Ptr.isBlockPointer() && !Ptr.block()->isAccessible()) {
     if (!CheckLive(S, OpPC, Ptr, AK_Read))
       return false;
     if (!CheckExtern(S, OpPC, Ptr))
       return false;
-    if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))
-      return false;
     return CheckWeak(S, OpPC, Ptr.block());
   }
 
@@ -988,15 +1004,19 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const 
Pointer &Ptr) {
 
 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                 bool WillBeActivated) {
-  if (!Ptr.isBlockPointer() || Ptr.isZero())
+  if (Ptr.isZero())
+    return false;
+
+  if (Ptr.isOpaquePointer())
+    return CheckDummy(S, OpPC, Ptr, AK_Assign);
+
+  if (!Ptr.isBlockPointer())
     return false;
 
   if (!Ptr.block()->isAccessible()) {
     if (!CheckLive(S, OpPC, Ptr, AK_Assign))
       return false;
-    if (!CheckExtern(S, OpPC, Ptr))
-      return false;
-    return CheckDummy(S, OpPC, Ptr.block(), AK_Assign);
+    return CheckExtern(S, OpPC, Ptr);
   }
   if (!WillBeActivated && !CheckLifetime(S, OpPC, Ptr, AK_Assign))
     return false;
@@ -1035,6 +1055,8 @@ bool CheckInit(InterpState &S, CodePtr OpPC, const 
Pointer &Ptr) {
     return false;
   if (!CheckRange(S, OpPC, Ptr, AK_Assign))
     return false;
+  if (!Ptr.isBlockPointer())
+    return false;
   return true;
 }
 
@@ -1255,6 +1277,8 @@ bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,
 
 bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
                        const Pointer &Ptr) {
+  if (!Ptr.isBlockPointer() && !Ptr.isOpaquePointer())
+    return false;
   // Regular new type(...) call.
   if (isa_and_nonnull<CXXNewExpr>(Source))
     return true;
@@ -1271,7 +1295,7 @@ bool CheckDeleteSource(InterpState &S, CodePtr OpPC, 
const Expr *Source,
   const SourceInfo &Loc = S.Current->getSource(OpPC);
   S.FFDiag(Loc, diag::note_constexpr_delete_not_heap_alloc)
       << Ptr.toDiagnosticString(S.getASTContext());
-  noteValueLocation(S, Ptr.block());
+  noteValueLocation(S, Ptr);
   return false;
 }
 
@@ -1297,21 +1321,20 @@ bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const 
DeclRefExpr *DR,
   return CheckDeclRef(S, OpPC, DR);
 }
 
-bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
-  if (!B->isDummy())
+bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+                AccessKinds AK) {
+  if (!Ptr.isDummy())
     return true;
 
-  const ValueDecl *D = B->getDescriptor()->asValueDecl();
+  const VarDecl *D = Ptr.getRootVarDecl();
   if (!D)
     return false;
 
   if (AK == AK_Read || AK == AK_Increment || AK == AK_Decrement)
     return diagnoseUnknownDecl(S, OpPC, D, AK);
 
-  if (AK == AK_Destroy || S.getLangOpts().CPlusPlus14) {
-    const SourceInfo &E = S.Current->getSource(OpPC);
-    S.FFDiag(E, diag::note_constexpr_modify_global);
-  }
+  if (AK == AK_Destroy || S.getLangOpts().CPlusPlus14)
+    S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_modify_global);
   return false;
 }
 
@@ -1421,7 +1444,7 @@ bool Free(InterpState &S, CodePtr OpPC, bool 
DeleteIsArrayForm,
       return true;
 
     if (!Ptr.isBlockPointer())
-      return false;
+      return CheckDeleteSource(S, OpPC, nullptr, Ptr);
 
     // Remove base casts.
     QualType InitialType = Ptr.getType();
@@ -1803,7 +1826,7 @@ static bool diagnoseOutOfLifetimeDestroy(InterpState &S, 
CodePtr OpPC,
 bool checkDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
   if (!CheckLive(S, OpPC, Ptr, AK_Destroy))
     return false;
-  if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Destroy))
+  if (!CheckTemporary(S, OpPC, Ptr, AK_Destroy))
     return false;
   if (!CheckRange(S, OpPC, Ptr, AK_Destroy))
     return false;
@@ -1819,7 +1842,7 @@ bool checkDestructor(InterpState &S, CodePtr OpPC, const 
Pointer &Ptr) {
     return true;
 
   // Can't call a dtor on a global variable.
-  if (Ptr.block()->isStatic()) {
+  if (Ptr.isOpaquePointer() || Ptr.block()->isStatic()) {
     const SourceInfo &E = S.Current->getSource(OpPC);
     S.FFDiag(E, diag::note_constexpr_modify_global);
     return false;
@@ -2048,9 +2071,22 @@ bool Call(InterpState &S, CodePtr OpPC, const Function 
*Func,
   return true;
 }
 
-static bool getDynamicDecl(InterpState &S, CodePtr OpPC, PtrView TypePtr,
+static bool getDynamicDecl(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                            const CXXRecordDecl *&DynamicDecl) {
 
+  auto diagUnknownDynamicType = [&](const Pointer &P) -> bool {
+    APValue V = P.toAPValue(S.getASTContext());
+    QualType TT = S.getASTContext().getLValueReferenceType(P.getType());
+    S.FFDiag(S.Current->getSource(OpPC),
+             diag::note_constexpr_polymorphic_unknown_dynamic_type)
+        << AK_MemberCall << V.getAsString(S.getASTContext(), TT);
+    return false;
+  };
+
+  if (!Ptr.isBlockPointer())
+    return diagUnknownDynamicType(Ptr);
+
+  PtrView TypePtr = Ptr.view();
   if (S.InitializingPtrs.empty()) {
     TypePtr = TypePtr.stripBaseCasts();
   } else {
@@ -2082,14 +2118,8 @@ static bool getDynamicDecl(InterpState &S, CodePtr OpPC, 
PtrView TypePtr,
   QualType DynamicType = TypePtr.getType();
   if (TypePtr.Pointee->isStatic() || TypePtr.isConst()) {
     if (const VarDecl *VD = Pointer(TypePtr).getRootVarDecl();
-        VD && !VD->isConstexpr()) {
-      const Expr *E = S.Current->getExpr(OpPC);
-      APValue V = Pointer(TypePtr).toAPValue(S.getASTContext());
-      QualType TT = S.getASTContext().getLValueReferenceType(DynamicType);
-      S.FFDiag(E, diag::note_constexpr_polymorphic_unknown_dynamic_type)
-          << AK_MemberCall << V.getAsString(S.getASTContext(), TT);
-      return false;
-    }
+        VD && !VD->isConstexpr())
+      return diagUnknownDynamicType(Pointer(TypePtr));
   }
 
   if (DynamicType->isPointerType() || DynamicType->isReferenceType()) {
@@ -2154,7 +2184,7 @@ bool DynamicCast(InterpState &S, CodePtr OpPC, const Type 
*DestTypePtr,
   const auto &Ptr = S.Stk.pop<Pointer>();
   QualType TargetType = QualType(DestTypePtr, 0);
 
-  if (Ptr.isConstexprUnknown()) {
+  if (Ptr.isConstexprUnknown() || Ptr.isOpaquePointer()) {
     QualType T = Ptr.getType();
     const Expr *E = S.Current->getExpr(OpPC);
     APValue V = Ptr.toAPValue(S.getASTContext());
@@ -2323,13 +2353,13 @@ bool CallVirt(InterpState &S, CodePtr OpPC, const 
Function *Func,
   size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
   Pointer &ThisPtr = S.Stk.peek<Pointer>(ThisOffset);
 
-  if (!ThisPtr.isBlockPointer())
+  if (!ThisPtr.isBlockPointer() && !ThisPtr.isOpaquePointer())
     return false;
 
   const FunctionDecl *Callee = Func->getDecl();
 
   const CXXRecordDecl *DynamicDecl = nullptr;
-  if (!getDynamicDecl(S, OpPC, ThisPtr.view(), DynamicDecl))
+  if (!getDynamicDecl(S, OpPC, ThisPtr, DynamicDecl))
     return false;
   assert(DynamicDecl);
 
@@ -2556,7 +2586,7 @@ static void setLifeStateRecurse(PtrView Ptr, Lifetime L) {
 /// Ends the lifetime of the peek'd pointer.
 bool EndLifetime(InterpState &S, CodePtr OpPC) {
   const auto &Ptr = S.Stk.peek<Pointer>();
-  if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
+  if (!CheckDummy(S, OpPC, Ptr, AK_Destroy))
     return false;
 
   setLifeStateRecurse(Ptr.view().narrow(), Lifetime::Ended);
@@ -2574,7 +2604,7 @@ bool PseudoDtor(InterpState &S, CodePtr OpPC) {
 
 bool MarkDestroyed(InterpState &S, CodePtr OpPC) {
   const auto &Ptr = S.Stk.peek<Pointer>();
-  if (Ptr.isBlockPointer() && !CheckDummy(S, OpPC, Ptr.block(), AK_Destroy))
+  if (!CheckDummy(S, OpPC, Ptr, AK_Destroy))
     return false;
 
   setLifeStateRecurse(Ptr.view().narrow(), Lifetime::Destroyed);
@@ -2603,7 +2633,7 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, 
const Expr *E,
   }
 
   if (!Ptr.isBlockPointer())
-    return false;
+    return CheckDummy(S, OpPC, Ptr, AK_Construct);
 
   if (!CheckRange(S, OpPC, Ptr, AK_Construct))
     return false;
@@ -2617,9 +2647,9 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, 
const Expr *E,
       return false;
     if (!CheckLive(S, OpPC, Ptr, AK_Construct))
       return false;
-    return CheckDummy(S, OpPC, Ptr.block(), AK_Construct);
+    return CheckDummy(S, OpPC, Ptr, AK_Construct);
   }
-  if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Construct))
+  if (!CheckTemporary(S, OpPC, Ptr, AK_Construct))
     return false;
 
   // CheckLifetime for this and all base pointers.
@@ -2765,10 +2795,10 @@ bool CheckPointerToIntegralCast(InterpState &S, CodePtr 
OpPC,
   if (Ptr.isIntegralPointer())
     return true;
 
-  if (Ptr.isDummy()) {
+  if (Ptr.isOpaquePointer()) {
     if (!CheckIntegralAddressCast(S, OpPC, BitWidth))
       return false;
-    return Ptr.getIndex() == 0;
+    return Ptr.isRoot();
   }
 
   if (!Ptr.isZero()) {
@@ -2854,7 +2884,7 @@ bool GetTypeid(InterpState &S, const Type *TypePtr, const 
Type *TypeInfoType) {
 bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType) {
   const auto &P = S.Stk.pop<Pointer>();
 
-  if (!P.isBlockPointer())
+  if (!P.isBlockPointer() && !P.isOpaquePointer())
     return false;
 
   if (P.isConstexprUnknown()) {
@@ -2868,7 +2898,12 @@ bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const 
Type *TypeInfoType) {
   }
 
   // Pick the most-derived type.
-  CanQualType T = P.stripBaseCasts().getType()->getCanonicalTypeUnqualified();
+  CanQualType T;
+  if (P.isBlockPointer())
+    T = P.stripBaseCasts().getType()->getCanonicalTypeUnqualified();
+  else
+    T = P.getType()->getCanonicalTypeUnqualified();
+
   // ... unless we're currently constructing this object.
   // FIXME: We have a similar check to this in more places.
   if (S.Current->getFunction()) {
@@ -2971,6 +3006,17 @@ static void copyPrimitiveMemory(InterpState &S, PtrView 
Ptr, PrimType T) {
     auto *NewPath = new (S.P) const CXXRecordDecl *[PathLength];
     std::copy_n(Val.path(), PathLength, NewPath);
     Val.takePath(NewPath);
+  } else if (T == PT_Ptr) {
+    auto &Val = Ptr.deref<Pointer>();
+    if (Val.isOpaquePointer() && Val.asOpaquePointer().PathLength != 0) {
+      const OpaquePointer &OP = Val.asOpaquePointer();
+      auto *NewPath = new (S.P) PointerPathEntry[OP.PathLength];
+      std::memcpy(NewPath, OP.Path, OP.PathLength * sizeof(PointerPathEntry));
+      Val = Pointer(OP.withPath(NewPath, OP.PathLength,
+                                OP.getFieldType().getTypePtr(),
+                                OP.isOnePastEnd()),
+                    Val.getByteOffset());
+    }
   }
 }
 
@@ -2983,6 +3029,17 @@ static void copyPrimitiveMemory(InterpState &S, PtrView 
Ptr) {
     auto *NewPath = new (S.P) const CXXRecordDecl *[PathLength];
     std::copy_n(Val.path(), PathLength, NewPath);
     Val.takePath(NewPath);
+  } else if constexpr (std::is_same_v<T, Pointer>) {
+    auto &Val = Ptr.deref<Pointer>();
+    if (Val.isOpaquePointer() && Val.asOpaquePointer().PathLength != 0) {
+      const OpaquePointer &OP = Val.asOpaquePointer();
+      auto *NewPath = new (S.P) PointerPathEntry[OP.PathLength];
+      std::memcpy(NewPath, OP.Path, OP.PathLength * sizeof(PointerPathEntry));
+      Val = Pointer(OP.withPath(NewPath, OP.PathLength,
+                                OP.getFieldType().getTypePtr(),
+                                OP.isOnePastEnd()),
+                    Val.getByteOffset());
+    }
   } else {
     auto &Val = Ptr.deref<T>();
     if (!Val.singleWord()) {
@@ -3042,6 +3099,8 @@ static void finishGlobalRecurse(InterpState &S, PtrView 
Ptr) {
 
 bool FinishInitGlobal(InterpState &S) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
+  if (!Ptr.isBlockPointer())
+    return true;
 
   finishGlobalRecurse(S, Ptr.view());
   if (Ptr.canBeInitialized()) {
@@ -3404,6 +3463,38 @@ std::o...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/221218
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to