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
