@@ -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