llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> ... if the pointer is also outside its lifetime. In that case, prefer to diagnose it as outside its lifetime. --- Full diff: https://github.com/llvm/llvm-project/pull/209702.diff 4 Files Affected: - (modified) clang/lib/AST/ByteCode/Interp.cpp (+13-11) - (modified) clang/lib/AST/ByteCode/Interp.h (+8-7) - (modified) clang/lib/AST/ByteCode/Pointer.h (+1-17) - (modified) clang/test/AST/ByteCode/cxx2a.cpp (+12) ``````````diff diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 58bbf4aaf5f89..1310500ca871e 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -731,15 +731,16 @@ static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr, return false; } -bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, +bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK) { assert(Ptr.isLive()); assert(!Ptr.isInitialized()); - return DiagnoseUninitialized(S, OpPC, Ptr.isExtern(), Ptr.block(), AK); + return diagnoseUninitialized(S, OpPC, Ptr.isExtern(), Ptr.block(), + Ptr.getLifetime(), AK); } -bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern, - const Block *B, AccessKinds AK) { +bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern, + const Block *B, Lifetime LT, AccessKinds AK) { if (S.checkingPotentialConstantExpression()) { // Extern and static member declarations might be initialized later. if (Extern) @@ -783,7 +784,8 @@ bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern, if (!S.checkingPotentialConstantExpression()) { S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_uninit) - << AK << /*uninitialized=*/true << S.Current->getRange(OpPC); + << AK << /*uninitialized=*/(LT == Lifetime::Started) + << S.Current->getRange(OpPC); noteValueLocation(S, B); } return false; @@ -836,7 +838,7 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B) { if (!CheckConstant(S, OpPC, B->getDescriptor())) return false; if (Desc.InitState != GlobalInitState::Initialized) - return DiagnoseUninitialized(S, OpPC, B->isExtern(), B, AK_Read); + return diagnoseUninitialized(S, OpPC, B->isExtern(), B); if (!CheckTemporary(S, OpPC, B, AK_Read)) return false; if (B->getDescriptor()->IsVolatile) { @@ -858,10 +860,10 @@ bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) { assert(!B->isExtern()); const auto &Desc = *reinterpret_cast<const InlineDescriptor *>(B->rawData()); const Descriptor *BlockDesc = B->getDescriptor(); + if (!Desc.IsInitialized) + return diagnoseUninitialized(S, OpPC, /*Extern=*/false, B, Desc.LifeState); if (!CheckLifetime(S, OpPC, Desc.LifeState, B, AK_Read)) return false; - if (!Desc.IsInitialized) - return DiagnoseUninitialized(S, OpPC, /*Extern=*/false, B, AK_Read); if (BlockDesc->IsVolatile) { if (!S.getLangOpts().CPlusPlus) return Invalid(S, OpPC); @@ -917,7 +919,7 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, if (!CheckActive(S, OpPC, Ptr, AK)) return false; if (!Ptr.isInitialized()) - return DiagnoseUninitialized(S, OpPC, Ptr, AK); + return diagnoseUninitialized(S, OpPC, Ptr, AK); if (!CheckLifetime(S, OpPC, Ptr, AK)) return false; if (!CheckTemporary(S, OpPC, Ptr.block(), AK)) @@ -985,7 +987,7 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { if (!CheckLifetime(S, OpPC, Ptr, AK_Read)) return false; if (!Ptr.isInitialized()) - return DiagnoseUninitialized(S, OpPC, Ptr, AK_Read); + return diagnoseUninitialized(S, OpPC, Ptr, AK_Read); if (!CheckTemporary(S, OpPC, Ptr.block(), AK_Read)) return false; if (!CheckMutable(S, OpPC, Ptr)) @@ -2122,7 +2124,7 @@ bool DynamicCast(InterpState &S, CodePtr OpPC, const Type *DestTypePtr, return false; if (!Ptr.isInitialized()) - return DiagnoseUninitialized(S, OpPC, Ptr, AK_Read); + return diagnoseUninitialized(S, OpPC, Ptr, AK_Read); // Our given pointer, limited by the base that's currently being initialized, // if any. diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 201679017c98b..b676e7ab43750 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -81,10 +81,11 @@ bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc, bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr); -bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, +bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK); -bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern, - const Block *B, AccessKinds AK); +bool diagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern, + const Block *B, Lifetime LT = Lifetime::Started, + AccessKinds AK = AK_Read); /// Checks a direct load of a primitive value from a global or local variable. bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B); @@ -1764,7 +1765,7 @@ bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) { const Block *B = S.P.getGlobal(I); const auto &Desc = B->getBlockDesc<GlobalInlineDescriptor>(); if (Desc.InitState != GlobalInitState::Initialized) - return DiagnoseUninitialized(S, OpPC, B->isExtern(), B, AK_Read); + return diagnoseUninitialized(S, OpPC, B->isExtern(), B); S.Stk.push<T>(B->deref<T>()); return true; @@ -2076,7 +2077,7 @@ inline bool GetRefGlobal(InterpState &S, CodePtr OpPC, uint32_t I) { const auto &Desc = B->getBlockDesc<GlobalInlineDescriptor>(); if (Desc.InitState != GlobalInitState::Initialized) - return DiagnoseUninitialized(S, OpPC, B->isExtern(), B, AK_Read); + return diagnoseUninitialized(S, OpPC, B->isExtern(), B); S.Stk.push<Pointer>(B->deref<Pointer>()); return true; @@ -2693,7 +2694,7 @@ static inline bool IncPtr(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!Ptr.isInitialized()) - return DiagnoseUninitialized(S, OpPC, Ptr, AK_Increment); + return diagnoseUninitialized(S, OpPC, Ptr, AK_Increment); return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr); } @@ -2702,7 +2703,7 @@ static inline bool DecPtr(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!Ptr.isInitialized()) - return DiagnoseUninitialized(S, OpPC, Ptr, AK_Decrement); + return diagnoseUninitialized(S, OpPC, Ptr, AK_Decrement); return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr); } diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index dda5ac61ef126..417c28b46875a 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -957,23 +957,7 @@ class Pointer { Lifetime getLifetime() const { if (!isBlockPointer()) return Lifetime::Started; - if (BS.Base < sizeof(InlineDescriptor)) - return Lifetime::Started; - - if (inArray() && !isArrayRoot()) { - InitMapPtr &IM = getInitMap(); - - if (!IM.hasInitMap()) { - if (IM.allInitialized()) - return Lifetime::Started; - return getArray().getLifetime(); - } - - return IM->isElementAlive(getIndex()) ? Lifetime::Started - : Lifetime::Ended; - } - - return getInlineDesc()->LifeState; + return view().getLifetime(); } /// Start the lifetime of this pointer. This works for pointer with an diff --git a/clang/test/AST/ByteCode/cxx2a.cpp b/clang/test/AST/ByteCode/cxx2a.cpp index 2f2f2b95745b3..e2cf74aa4ec57 100644 --- a/clang/test/AST/ByteCode/cxx2a.cpp +++ b/clang/test/AST/ByteCode/cxx2a.cpp @@ -302,3 +302,15 @@ namespace PseudoDtorOnGlobal { a.m.~T(); // both-note {{cannot modify an object that is visible outside}} } } + +namespace UninitializedAndLifetime { + struct A { int n; }; + constexpr void use_after_destroy() { + A a; // both-note {{declared here}} + a.~A(); + A b = a; // both-note {{in call}} \ + // both-note {{read of object outside its lifetime}} + } + static_assert((use_after_destroy(), true)); // both-error {{not an integral constant expression}} \ + // both-note {{in call}} +} `````````` </details> https://github.com/llvm/llvm-project/pull/209702 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
