@@ -211,25 +211,26 @@ static void diagnoseNonConstVariable(InterpState &S, CodePtr OpPC,
211211 S.Note (VD->getLocation (), diag::note_declared_at);
212212}
213213
214- static bool CheckTemporary (InterpState &S, CodePtr OpPC, const Pointer &Ptr ,
214+ static bool CheckTemporary (InterpState &S, CodePtr OpPC, const Block *B ,
215215 AccessKinds AK) {
216- if (auto ID = Ptr. getDeclID ()) {
217- if (!Ptr. isStaticTemporary ( ))
216+ if (B-> getDeclID ()) {
217+ if (!(B-> isStatic () && B-> isTemporary () ))
218218 return true ;
219219
220220 const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
221- Ptr. getDeclDesc ()->asExpr ());
221+ B-> getDescriptor ()->asExpr ());
222222 if (!MTE)
223223 return true ;
224224
225225 // FIXME(perf): Since we do this check on every Load from a static
226226 // temporary, it might make sense to cache the value of the
227227 // isUsableInConstantExpressions call.
228- if (!MTE-> isUsableInConstantExpressions (S. getASTContext () ) &&
229- Ptr. block ()-> getEvalID () != S. Ctx . getEvalID ( )) {
228+ if (B-> getEvalID () != S. Ctx . getEvalID ( ) &&
229+ !MTE-> isUsableInConstantExpressions (S. getASTContext () )) {
230230 const SourceInfo &E = S.Current ->getSource (OpPC);
231231 S.FFDiag (E, diag::note_constexpr_access_static_temporary, 1 ) << AK;
232- S.Note (Ptr.getDeclLoc (), diag::note_constexpr_temporary_here);
232+ S.Note (B->getDescriptor ()->getLocation (),
233+ diag::note_constexpr_temporary_here);
233234 return false ;
234235 }
235236 }
@@ -658,17 +659,19 @@ static bool CheckVolatile(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
658659 return false ;
659660}
660661
661- bool CheckInitialized (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
662- AccessKinds AK) {
662+ bool DiagnoseUninitialized (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
663+ AccessKinds AK) {
663664 assert (Ptr.isLive ());
665+ assert (!Ptr.isInitialized ());
666+ return DiagnoseUninitialized (S, OpPC, Ptr.isExtern (), Ptr.getDeclDesc (), AK);
667+ }
664668
665- if (Ptr.isInitialized ())
666- return true ;
667-
668- if (Ptr.isExtern () && S.checkingPotentialConstantExpression ())
669+ bool DiagnoseUninitialized (InterpState &S, CodePtr OpPC, bool Extern,
670+ const Descriptor *Desc, AccessKinds AK) {
671+ if (Extern && S.checkingPotentialConstantExpression ())
669672 return false ;
670673
671- if (const auto *VD = Ptr. getDeclDesc () ->asVarDecl ();
674+ if (const auto *VD = Desc ->asVarDecl ();
672675 VD && (VD->isConstexpr () || VD->hasGlobalStorage ())) {
673676
674677 if (VD == S.EvaluatingDecl &&
@@ -703,9 +706,9 @@ bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
703706 return false ;
704707}
705708
706- static bool CheckLifetime (InterpState &S, CodePtr OpPC, const Pointer &Ptr ,
709+ static bool CheckLifetime (InterpState &S, CodePtr OpPC, Lifetime LT ,
707710 AccessKinds AK) {
708- if (Ptr. getLifetime () == Lifetime::Started)
711+ if (LT == Lifetime::Started)
709712 return true ;
710713
711714 if (!S.checkingPotentialConstantExpression ()) {
@@ -715,11 +718,11 @@ static bool CheckLifetime(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
715718 return false ;
716719}
717720
718- static bool CheckWeak (InterpState &S, CodePtr OpPC, const Pointer &Ptr ) {
719- if (!Ptr. isWeak ())
721+ static bool CheckWeak (InterpState &S, CodePtr OpPC, const Block *B ) {
722+ if (!B-> isWeak ())
720723 return true ;
721724
722- const auto *VD = Ptr. getDeclDesc ()->asVarDecl ();
725+ const auto *VD = B-> getDescriptor ()->asVarDecl ();
723726 assert (VD);
724727 S.FFDiag (S.Current ->getLocation (OpPC), diag::note_constexpr_var_init_weak)
725728 << VD;
@@ -732,32 +735,56 @@ static bool CheckWeak(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
732735// ones removed that are impossible on primitive global values.
733736// For example, since those can't be members of structs, they also can't
734737// be mutable.
735- bool CheckGlobalLoad (InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
736- if (!CheckExtern (S, OpPC, Ptr))
738+ bool CheckGlobalLoad (InterpState &S, CodePtr OpPC, const Block *B) {
739+ const auto &Desc =
740+ *reinterpret_cast <const GlobalInlineDescriptor *>(B->rawData ());
741+ if (!CheckExtern (S, OpPC, Pointer (const_cast <Block *>(B))))
737742 return false ;
738- if (!CheckConstant (S, OpPC, Ptr))
739- return false ;
740- if (!CheckDummy (S, OpPC, Ptr, AK_Read))
743+ if (!CheckConstant (S, OpPC, B->getDescriptor ()))
741744 return false ;
742- if (!CheckInitialized (S, OpPC, Ptr , AK_Read))
745+ if (!CheckDummy (S, OpPC, B , AK_Read))
743746 return false ;
744- if (!CheckTemporary (S, OpPC, Ptr, AK_Read))
747+ if (Desc.InitState != GlobalInitState::Initialized)
748+ return DiagnoseUninitialized (S, OpPC, B->isExtern (), B->getDescriptor (),
749+ AK_Read);
750+ if (!CheckTemporary (S, OpPC, B, AK_Read))
745751 return false ;
746- if (!CheckWeak (S, OpPC, Ptr ))
752+ if (!CheckWeak (S, OpPC, B ))
747753 return false ;
748- if (!CheckVolatile (S, OpPC, Ptr, AK_Read))
754+ if (B->getDescriptor ()->IsVolatile ) {
755+ if (!S.getLangOpts ().CPlusPlus )
756+ return Invalid (S, OpPC);
757+
758+ const ValueDecl *D = B->getDescriptor ()->asValueDecl ();
759+ S.FFDiag (S.Current ->getLocation (OpPC),
760+ diag::note_constexpr_access_volatile_obj, 1 )
761+ << AK_Read << 1 << D;
762+ S.Note (D->getLocation (), diag::note_constexpr_volatile_here) << 1 ;
749763 return false ;
764+ }
750765 return true ;
751766}
752767
753768// Similarly, for local loads.
754- bool CheckLocalLoad (InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
755- if (!CheckLifetime (S, OpPC, Ptr, AK_Read))
756- return false ;
757- if (!CheckInitialized (S, OpPC, Ptr, AK_Read))
758- return false ;
759- if (!CheckVolatile (S, OpPC, Ptr, AK_Read))
769+ bool CheckLocalLoad (InterpState &S, CodePtr OpPC, const Block *B) {
770+ assert (!B->isExtern ());
771+ const auto &Desc = *reinterpret_cast <const InlineDescriptor *>(B->rawData ());
772+ if (!CheckLifetime (S, OpPC, Desc.LifeState , AK_Read))
773+ return false ;
774+ if (!Desc.IsInitialized )
775+ return DiagnoseUninitialized (S, OpPC, /* Extern=*/ false , B->getDescriptor (),
776+ AK_Read);
777+ if (B->getDescriptor ()->IsVolatile ) {
778+ if (!S.getLangOpts ().CPlusPlus )
779+ return Invalid (S, OpPC);
780+
781+ const ValueDecl *D = B->getDescriptor ()->asValueDecl ();
782+ S.FFDiag (S.Current ->getLocation (OpPC),
783+ diag::note_constexpr_access_volatile_obj, 1 )
784+ << AK_Read << 1 << D;
785+ S.Note (D->getLocation (), diag::note_constexpr_volatile_here) << 1 ;
760786 return false ;
787+ }
761788 return true ;
762789}
763790
@@ -769,19 +796,19 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
769796 return false ;
770797 if (!CheckConstant (S, OpPC, Ptr))
771798 return false ;
772- if (!CheckDummy (S, OpPC, Ptr, AK))
799+ if (Ptr. isBlockPointer () && !CheckDummy (S, OpPC, Ptr. block () , AK))
773800 return false ;
774801 if (!CheckRange (S, OpPC, Ptr, AK))
775802 return false ;
776803 if (!CheckActive (S, OpPC, Ptr, AK))
777804 return false ;
778- if (!CheckLifetime (S, OpPC, Ptr, AK))
779- return false ;
780- if (!CheckInitialized (S, OpPC, Ptr, AK))
805+ if (!CheckLifetime (S, OpPC, Ptr.getLifetime (), AK))
781806 return false ;
782- if (!CheckTemporary (S, OpPC, Ptr, AK))
807+ if (!Ptr.isInitialized ())
808+ return DiagnoseUninitialized (S, OpPC, Ptr, AK);
809+ if (Ptr.isBlockPointer () && !CheckTemporary (S, OpPC, Ptr.block (), AK))
783810 return false ;
784- if (!CheckWeak (S, OpPC, Ptr))
811+ if (Ptr. isBlockPointer () && !CheckWeak (S, OpPC, Ptr. block () ))
785812 return false ;
786813 if (!CheckMutable (S, OpPC, Ptr))
787814 return false ;
@@ -798,21 +825,21 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
798825 if (!CheckConstant (S, OpPC, Ptr))
799826 return false ;
800827
801- if (!CheckDummy (S, OpPC, Ptr, AK_Read))
828+ if (Ptr. isBlockPointer () && !CheckDummy (S, OpPC, Ptr. block () , AK_Read))
802829 return false ;
803830 if (!CheckExtern (S, OpPC, Ptr))
804831 return false ;
805832 if (!CheckRange (S, OpPC, Ptr, AK_Read))
806833 return false ;
807834 if (!CheckActive (S, OpPC, Ptr, AK_Read))
808835 return false ;
809- if (!CheckLifetime (S, OpPC, Ptr, AK_Read))
810- return false ;
811- if (!CheckInitialized (S, OpPC, Ptr, AK_Read))
836+ if (!CheckLifetime (S, OpPC, Ptr.getLifetime (), AK_Read))
812837 return false ;
813- if (!CheckTemporary (S, OpPC, Ptr, AK_Read))
838+ if (!Ptr.isInitialized ())
839+ return DiagnoseUninitialized (S, OpPC, Ptr, AK_Read);
840+ if (Ptr.isBlockPointer () && !CheckTemporary (S, OpPC, Ptr.block (), AK_Read))
814841 return false ;
815- if (!CheckWeak (S, OpPC, Ptr))
842+ if (Ptr. isBlockPointer () && !CheckWeak (S, OpPC, Ptr. block () ))
816843 return false ;
817844 if (!CheckMutable (S, OpPC, Ptr))
818845 return false ;
@@ -822,9 +849,9 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
822849bool CheckStore (InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
823850 if (!CheckLive (S, OpPC, Ptr, AK_Assign))
824851 return false ;
825- if (!CheckDummy (S, OpPC, Ptr, AK_Assign))
852+ if (Ptr. isBlockPointer () && !CheckDummy (S, OpPC, Ptr. block () , AK_Assign))
826853 return false ;
827- if (!CheckLifetime (S, OpPC, Ptr, AK_Assign))
854+ if (!CheckLifetime (S, OpPC, Ptr. getLifetime () , AK_Assign))
828855 return false ;
829856 if (!CheckExtern (S, OpPC, Ptr))
830857 return false ;
@@ -1098,12 +1125,11 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
10981125 return diagnoseUnknownDecl (S, OpPC, D);
10991126}
11001127
1101- bool CheckDummy (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
1102- AccessKinds AK) {
1103- if (!Ptr. isDummy ())
1128+ bool CheckDummy (InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
1129+ const Descriptor *Desc = B-> getDescriptor ();
1130+ if (!Desc-> isDummy ())
11041131 return true ;
11051132
1106- const Descriptor *Desc = Ptr.getDeclDesc ();
11071133 const ValueDecl *D = Desc->asValueDecl ();
11081134 if (!D)
11091135 return false ;
@@ -1426,7 +1452,7 @@ static bool checkConstructor(InterpState &S, CodePtr OpPC, const Function *Func,
14261452bool CheckDestructor (InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
14271453 if (!CheckLive (S, OpPC, Ptr, AK_Destroy))
14281454 return false ;
1429- if (!CheckTemporary (S, OpPC, Ptr, AK_Destroy))
1455+ if (!CheckTemporary (S, OpPC, Ptr. block () , AK_Destroy))
14301456 return false ;
14311457 if (!CheckRange (S, OpPC, Ptr, AK_Destroy))
14321458 return false ;
@@ -1749,7 +1775,7 @@ static void startLifetimeRecurse(const Pointer &Ptr) {
17491775
17501776bool StartLifetime (InterpState &S, CodePtr OpPC) {
17511777 const auto &Ptr = S.Stk .peek <Pointer>();
1752- if (!CheckDummy (S, OpPC, Ptr, AK_Destroy))
1778+ if (Ptr. isBlockPointer () && !CheckDummy (S, OpPC, Ptr. block () , AK_Destroy))
17531779 return false ;
17541780 startLifetimeRecurse (Ptr.narrow ());
17551781 return true ;
@@ -1780,7 +1806,7 @@ static void endLifetimeRecurse(const Pointer &Ptr) {
17801806// / Ends the lifetime of the peek'd pointer.
17811807bool EndLifetime (InterpState &S, CodePtr OpPC) {
17821808 const auto &Ptr = S.Stk .peek <Pointer>();
1783- if (!CheckDummy (S, OpPC, Ptr, AK_Destroy))
1809+ if (Ptr. isBlockPointer () && !CheckDummy (S, OpPC, Ptr. block () , AK_Destroy))
17841810 return false ;
17851811 endLifetimeRecurse (Ptr.narrow ());
17861812 return true ;
@@ -1789,7 +1815,7 @@ bool EndLifetime(InterpState &S, CodePtr OpPC) {
17891815// / Ends the lifetime of the pop'd pointer.
17901816bool EndLifetimePop (InterpState &S, CodePtr OpPC) {
17911817 const auto &Ptr = S.Stk .pop <Pointer>();
1792- if (!CheckDummy (S, OpPC, Ptr, AK_Destroy))
1818+ if (Ptr. isBlockPointer () && !CheckDummy (S, OpPC, Ptr. block () , AK_Destroy))
17931819 return false ;
17941820 endLifetimeRecurse (Ptr.narrow ());
17951821 return true ;
@@ -1804,16 +1830,16 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
18041830
18051831 // Similar to CheckStore(), but with the additional CheckTemporary() call and
18061832 // the AccessKinds are different.
1807- if (!CheckTemporary (S, OpPC, Ptr, AK_Construct))
1833+ if (!CheckTemporary (S, OpPC, Ptr. block () , AK_Construct))
18081834 return false ;
18091835 if (!CheckLive (S, OpPC, Ptr, AK_Construct))
18101836 return false ;
1811- if (!CheckDummy (S, OpPC, Ptr, AK_Construct))
1837+ if (!CheckDummy (S, OpPC, Ptr. block () , AK_Construct))
18121838 return false ;
18131839
18141840 // CheckLifetime for this and all base pointers.
18151841 for (Pointer P = Ptr;;) {
1816- if (!CheckLifetime (S, OpPC, P, AK_Construct))
1842+ if (!CheckLifetime (S, OpPC, P. getLifetime () , AK_Construct))
18171843 return false ;
18181844
18191845 if (P.isRoot ())
0 commit comments