@@ -738,19 +738,21 @@ static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B) {
738738bool CheckGlobalLoad (InterpState &S, CodePtr OpPC, const Block *B) {
739739 const auto &Desc =
740740 *reinterpret_cast <const GlobalInlineDescriptor *>(B->rawData ());
741- if (!CheckExtern (S, OpPC, Pointer (const_cast <Block *>(B))))
742- return false ;
741+ if (!B->isAccessible ()) {
742+ if (!CheckExtern (S, OpPC, Pointer (const_cast <Block *>(B))))
743+ return false ;
744+ if (!CheckDummy (S, OpPC, B, AK_Read))
745+ return false ;
746+ return CheckWeak (S, OpPC, B);
747+ }
748+
743749 if (!CheckConstant (S, OpPC, B->getDescriptor ()))
744750 return false ;
745- if (!CheckDummy (S, OpPC, B, AK_Read))
746- return false ;
747751 if (Desc.InitState != GlobalInitState::Initialized)
748752 return DiagnoseUninitialized (S, OpPC, B->isExtern (), B->getDescriptor (),
749753 AK_Read);
750754 if (!CheckTemporary (S, OpPC, B, AK_Read))
751755 return false ;
752- if (!CheckWeak (S, OpPC, B))
753- return false ;
754756 if (B->getDescriptor ()->IsVolatile ) {
755757 if (!S.getLangOpts ().CPlusPlus )
756758 return Invalid (S, OpPC);
@@ -790,14 +792,32 @@ bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
790792
791793bool CheckLoad (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
792794 AccessKinds AK) {
793- if (!CheckLive (S, OpPC, Ptr, AK))
794- return false ;
795- if (!CheckExtern (S, OpPC, Ptr))
795+ if (!Ptr.isBlockPointer ()) {
796+ if (Ptr.isZero ()) {
797+ const auto &Src = S.Current ->getSource (OpPC);
798+
799+ if (Ptr.isField ())
800+ S.FFDiag (Src, diag::note_constexpr_null_subobject) << CSK_Field;
801+ else
802+ S.FFDiag (Src, diag::note_constexpr_access_null) << AK;
803+ }
796804 return false ;
805+ }
806+
807+ // Block pointers are the only ones we can actually read from.
808+ if (!Ptr.block ()->isAccessible ()) {
809+ if (!CheckLive (S, OpPC, Ptr, AK))
810+ return false ;
811+ if (!CheckExtern (S, OpPC, Ptr))
812+ return false ;
813+ if (!CheckDummy (S, OpPC, Ptr.block (), AK))
814+ return false ;
815+ if (!CheckWeak (S, OpPC, Ptr.block ()))
816+ return false ;
817+ }
818+
797819 if (!CheckConstant (S, OpPC, Ptr))
798820 return false ;
799- if (Ptr.isBlockPointer () && !CheckDummy (S, OpPC, Ptr.block (), AK))
800- return false ;
801821 if (!CheckRange (S, OpPC, Ptr, AK))
802822 return false ;
803823 if (!CheckActive (S, OpPC, Ptr, AK))
@@ -806,10 +826,9 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
806826 return false ;
807827 if (!Ptr.isInitialized ())
808828 return DiagnoseUninitialized (S, OpPC, Ptr, AK);
809- if (Ptr.isBlockPointer () && !CheckTemporary (S, OpPC, Ptr.block (), AK))
810- return false ;
811- if (Ptr.isBlockPointer () && !CheckWeak (S, OpPC, Ptr.block ()))
829+ if (!CheckTemporary (S, OpPC, Ptr.block (), AK))
812830 return false ;
831+
813832 if (!CheckMutable (S, OpPC, Ptr))
814833 return false ;
815834 if (!CheckVolatile (S, OpPC, Ptr, AK))
@@ -820,35 +839,54 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
820839// / This is not used by any of the opcodes directly. It's used by
821840// / EvalEmitter to do the final lvalue-to-rvalue conversion.
822841bool CheckFinalLoad (InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
823- if (!CheckLive (S, OpPC, Ptr, AK_Read))
842+ if (!Ptr.isBlockPointer ()) {
843+ if (Ptr.isZero ()) {
844+ const auto &Src = S.Current ->getSource (OpPC);
845+
846+ if (Ptr.isField ())
847+ S.FFDiag (Src, diag::note_constexpr_null_subobject) << CSK_Field;
848+ else
849+ S.FFDiag (Src, diag::note_constexpr_access_null) << AK_Read;
850+ }
824851 return false ;
852+ }
853+
854+ assert (Ptr.isBlockPointer ());
855+ if (!Ptr.block ()->isAccessible ()) {
856+ if (!CheckLive (S, OpPC, Ptr, AK_Read))
857+ return false ;
858+ if (!CheckExtern (S, OpPC, Ptr))
859+ return false ;
860+ if (!CheckDummy (S, OpPC, Ptr.block (), AK_Read))
861+ return false ;
862+ return CheckWeak (S, OpPC, Ptr.block ());
863+ }
864+
825865 if (!CheckConstant (S, OpPC, Ptr))
826866 return false ;
827867
828- if (Ptr.isBlockPointer () && !CheckDummy (S, OpPC, Ptr.block (), AK_Read))
829- return false ;
830- if (!CheckExtern (S, OpPC, Ptr))
831- return false ;
832868 if (!CheckActive (S, OpPC, Ptr, AK_Read))
833869 return false ;
834870 if (!CheckLifetime (S, OpPC, Ptr.getLifetime (), AK_Read))
835871 return false ;
836872 if (!Ptr.isInitialized ())
837873 return DiagnoseUninitialized (S, OpPC, Ptr, AK_Read);
838- if (Ptr.isBlockPointer () && !CheckTemporary (S, OpPC, Ptr.block (), AK_Read))
839- return false ;
840- if (Ptr.isBlockPointer () && !CheckWeak (S, OpPC, Ptr.block ()))
874+ if (!CheckTemporary (S, OpPC, Ptr.block (), AK_Read))
841875 return false ;
842876 if (!CheckMutable (S, OpPC, Ptr))
843877 return false ;
844878 return true ;
845879}
846880
847881bool CheckStore (InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
848- if (!CheckLive (S, OpPC, Ptr, AK_Assign))
849- return false ;
850- if (Ptr.isBlockPointer () && !CheckDummy (S, OpPC, Ptr.block (), AK_Assign))
882+ if (!Ptr.isBlockPointer ())
851883 return false ;
884+
885+ if (!Ptr.block ()->isAccessible ()) {
886+ if (!CheckLive (S, OpPC, Ptr, AK_Assign))
887+ return false ;
888+ return CheckDummy (S, OpPC, Ptr.block (), AK_Assign);
889+ }
852890 if (!CheckLifetime (S, OpPC, Ptr.getLifetime (), AK_Assign))
853891 return false ;
854892 if (!CheckExtern (S, OpPC, Ptr))
@@ -1124,11 +1162,10 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
11241162}
11251163
11261164bool CheckDummy (InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
1127- const Descriptor *Desc = B->getDescriptor ();
1128- if (!Desc->isDummy ())
1165+ if (!B->isDummy ())
11291166 return true ;
11301167
1131- const ValueDecl *D = Desc ->asValueDecl ();
1168+ const ValueDecl *D = B-> getDescriptor () ->asValueDecl ();
11321169 if (!D)
11331170 return false ;
11341171
@@ -1835,14 +1872,21 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
18351872 if (Ptr.inUnion () && Ptr.getBase ().getRecord ()->isUnion ())
18361873 Ptr.activate ();
18371874
1875+ if (!Ptr.isBlockPointer ())
1876+ return false ;
1877+
18381878 // Similar to CheckStore(), but with the additional CheckTemporary() call and
18391879 // the AccessKinds are different.
1880+
1881+ if (!Ptr.block ()->isAccessible ()) {
1882+ if (!CheckExtern (S, OpPC, Ptr))
1883+ return false ;
1884+ if (!CheckLive (S, OpPC, Ptr, AK_Construct))
1885+ return false ;
1886+ return CheckDummy (S, OpPC, Ptr.block (), AK_Construct);
1887+ }
18401888 if (!CheckTemporary (S, OpPC, Ptr.block (), AK_Construct))
18411889 return false ;
1842- if (!CheckLive (S, OpPC, Ptr, AK_Construct))
1843- return false ;
1844- if (!CheckDummy (S, OpPC, Ptr.block (), AK_Construct))
1845- return false ;
18461890
18471891 // CheckLifetime for this and all base pointers.
18481892 for (Pointer P = Ptr;;) {
@@ -1853,8 +1897,7 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
18531897 break ;
18541898 P = P.getBase ();
18551899 }
1856- if (!CheckExtern (S, OpPC, Ptr))
1857- return false ;
1900+
18581901 if (!CheckRange (S, OpPC, Ptr, AK_Construct))
18591902 return false ;
18601903 if (!CheckGlobal (S, OpPC, Ptr))
0 commit comments