@@ -738,19 +738,21 @@ static bool CheckWeak(InterpState &S, CodePtr OpPC, const Block *B) {
738
738
bool CheckGlobalLoad (InterpState &S, CodePtr OpPC, const Block *B) {
739
739
const auto &Desc =
740
740
*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
+
743
749
if (!CheckConstant (S, OpPC, B->getDescriptor ()))
744
750
return false ;
745
- if (!CheckDummy (S, OpPC, B, AK_Read))
746
- return false ;
747
751
if (Desc.InitState != GlobalInitState::Initialized)
748
752
return DiagnoseUninitialized (S, OpPC, B->isExtern (), B->getDescriptor (),
749
753
AK_Read);
750
754
if (!CheckTemporary (S, OpPC, B, AK_Read))
751
755
return false ;
752
- if (!CheckWeak (S, OpPC, B))
753
- return false ;
754
756
if (B->getDescriptor ()->IsVolatile ) {
755
757
if (!S.getLangOpts ().CPlusPlus )
756
758
return Invalid (S, OpPC);
@@ -790,14 +792,32 @@ bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) {
790
792
791
793
bool CheckLoad (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
792
794
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
+ }
796
804
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
+
797
819
if (!CheckConstant (S, OpPC, Ptr))
798
820
return false ;
799
- if (Ptr.isBlockPointer () && !CheckDummy (S, OpPC, Ptr.block (), AK))
800
- return false ;
801
821
if (!CheckRange (S, OpPC, Ptr, AK))
802
822
return false ;
803
823
if (!CheckActive (S, OpPC, Ptr, AK))
@@ -806,10 +826,9 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
806
826
return false ;
807
827
if (!Ptr.isInitialized ())
808
828
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))
812
830
return false ;
831
+
813
832
if (!CheckMutable (S, OpPC, Ptr))
814
833
return false ;
815
834
if (!CheckVolatile (S, OpPC, Ptr, AK))
@@ -820,35 +839,54 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
820
839
// / This is not used by any of the opcodes directly. It's used by
821
840
// / EvalEmitter to do the final lvalue-to-rvalue conversion.
822
841
bool 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
+ }
824
851
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
+
825
865
if (!CheckConstant (S, OpPC, Ptr))
826
866
return false ;
827
867
828
- if (Ptr.isBlockPointer () && !CheckDummy (S, OpPC, Ptr.block (), AK_Read))
829
- return false ;
830
- if (!CheckExtern (S, OpPC, Ptr))
831
- return false ;
832
868
if (!CheckActive (S, OpPC, Ptr, AK_Read))
833
869
return false ;
834
870
if (!CheckLifetime (S, OpPC, Ptr.getLifetime (), AK_Read))
835
871
return false ;
836
872
if (!Ptr.isInitialized ())
837
873
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))
841
875
return false ;
842
876
if (!CheckMutable (S, OpPC, Ptr))
843
877
return false ;
844
878
return true ;
845
879
}
846
880
847
881
bool 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 ())
851
883
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
+ }
852
890
if (!CheckLifetime (S, OpPC, Ptr.getLifetime (), AK_Assign))
853
891
return false ;
854
892
if (!CheckExtern (S, OpPC, Ptr))
@@ -1124,11 +1162,10 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
1124
1162
}
1125
1163
1126
1164
bool CheckDummy (InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
1127
- const Descriptor *Desc = B->getDescriptor ();
1128
- if (!Desc->isDummy ())
1165
+ if (!B->isDummy ())
1129
1166
return true ;
1130
1167
1131
- const ValueDecl *D = Desc ->asValueDecl ();
1168
+ const ValueDecl *D = B-> getDescriptor () ->asValueDecl ();
1132
1169
if (!D)
1133
1170
return false ;
1134
1171
@@ -1835,14 +1872,21 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
1835
1872
if (Ptr.inUnion () && Ptr.getBase ().getRecord ()->isUnion ())
1836
1873
Ptr.activate ();
1837
1874
1875
+ if (!Ptr.isBlockPointer ())
1876
+ return false ;
1877
+
1838
1878
// Similar to CheckStore(), but with the additional CheckTemporary() call and
1839
1879
// 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
+ }
1840
1888
if (!CheckTemporary (S, OpPC, Ptr.block (), AK_Construct))
1841
1889
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 ;
1846
1890
1847
1891
// CheckLifetime for this and all base pointers.
1848
1892
for (Pointer P = Ptr;;) {
@@ -1853,8 +1897,7 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
1853
1897
break ;
1854
1898
P = P.getBase ();
1855
1899
}
1856
- if (!CheckExtern (S, OpPC, Ptr))
1857
- return false ;
1900
+
1858
1901
if (!CheckRange (S, OpPC, Ptr, AK_Construct))
1859
1902
return false ;
1860
1903
if (!CheckGlobal (S, OpPC, Ptr))
0 commit comments