@@ -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,15 +839,32 @@ 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 (!CheckRange (S, OpPC, Ptr, AK_Read))
833
869
return false ;
834
870
if (!CheckActive (S, OpPC, Ptr, AK_Read))
@@ -837,20 +873,22 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
837
873
return false ;
838
874
if (!Ptr.isInitialized ())
839
875
return DiagnoseUninitialized (S, OpPC, Ptr, AK_Read);
840
- if (Ptr.isBlockPointer () && !CheckTemporary (S, OpPC, Ptr.block (), AK_Read))
841
- return false ;
842
- if (Ptr.isBlockPointer () && !CheckWeak (S, OpPC, Ptr.block ()))
876
+ if (!CheckTemporary (S, OpPC, Ptr.block (), AK_Read))
843
877
return false ;
844
878
if (!CheckMutable (S, OpPC, Ptr))
845
879
return false ;
846
880
return true ;
847
881
}
848
882
849
883
bool CheckStore (InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
850
- if (!CheckLive (S, OpPC, Ptr, AK_Assign))
851
- return false ;
852
- if (Ptr.isBlockPointer () && !CheckDummy (S, OpPC, Ptr.block (), AK_Assign))
884
+ if (!Ptr.isBlockPointer ())
853
885
return false ;
886
+
887
+ if (!Ptr.block ()->isAccessible ()) {
888
+ if (!CheckLive (S, OpPC, Ptr, AK_Assign))
889
+ return false ;
890
+ return CheckDummy (S, OpPC, Ptr.block (), AK_Assign);
891
+ }
854
892
if (!CheckLifetime (S, OpPC, Ptr.getLifetime (), AK_Assign))
855
893
return false ;
856
894
if (!CheckExtern (S, OpPC, Ptr))
@@ -1126,11 +1164,10 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
1126
1164
}
1127
1165
1128
1166
bool CheckDummy (InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK) {
1129
- const Descriptor *Desc = B->getDescriptor ();
1130
- if (!Desc->isDummy ())
1167
+ if (!B->isDummy ())
1131
1168
return true ;
1132
1169
1133
- const ValueDecl *D = Desc ->asValueDecl ();
1170
+ const ValueDecl *D = B-> getDescriptor () ->asValueDecl ();
1134
1171
if (!D)
1135
1172
return false ;
1136
1173
@@ -1837,14 +1874,21 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
1837
1874
if (Ptr.inUnion () && Ptr.getBase ().getRecord ()->isUnion ())
1838
1875
Ptr.activate ();
1839
1876
1877
+ if (!Ptr.isBlockPointer ())
1878
+ return false ;
1879
+
1840
1880
// Similar to CheckStore(), but with the additional CheckTemporary() call and
1841
1881
// the AccessKinds are different.
1882
+
1883
+ if (!Ptr.block ()->isAccessible ()) {
1884
+ if (!CheckExtern (S, OpPC, Ptr))
1885
+ return false ;
1886
+ if (!CheckLive (S, OpPC, Ptr, AK_Construct))
1887
+ return false ;
1888
+ return CheckDummy (S, OpPC, Ptr.block (), AK_Construct);
1889
+ }
1842
1890
if (!CheckTemporary (S, OpPC, Ptr.block (), AK_Construct))
1843
1891
return false ;
1844
- if (!CheckLive (S, OpPC, Ptr, AK_Construct))
1845
- return false ;
1846
- if (!CheckDummy (S, OpPC, Ptr.block (), AK_Construct))
1847
- return false ;
1848
1892
1849
1893
// CheckLifetime for this and all base pointers.
1850
1894
for (Pointer P = Ptr;;) {
@@ -1855,8 +1899,7 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
1855
1899
break ;
1856
1900
P = P.getBase ();
1857
1901
}
1858
- if (!CheckExtern (S, OpPC, Ptr))
1859
- return false ;
1902
+
1860
1903
if (!CheckRange (S, OpPC, Ptr, AK_Construct))
1861
1904
return false ;
1862
1905
if (!CheckGlobal (S, OpPC, Ptr))
0 commit comments