Loading clang/lib/AST/ByteCode/Compiler.cpp +17 −4 Original line number Diff line number Diff line Loading @@ -5238,8 +5238,9 @@ template <class Emitter> VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, const Expr *Init, bool Toplevel) { QualType VarTy = VD->getType(); // We don't know what to do with these, so just return false. if (VD->getType().isNull()) if (VarTy.isNull()) return false; // This case is EvalEmitter-only. If we won't create any instructions for the Loading Loading @@ -5299,8 +5300,8 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, if (VarT) { unsigned Offset = this->allocateLocalPrimitive( VD, *VarT, VD->getType().isConstQualified(), VD->getType().isVolatileQualified(), ScopeKind::Block); VD, *VarT, VarTy.isConstQualified(), VarTy.isVolatileQualified(), ScopeKind::Block); if (!Init || Init->getType()->isVoidType()) return true; Loading @@ -5315,11 +5316,23 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, } if (!this->visit(Init)) return false; if (VarTy->isReferenceType()) { // [C++26][decl.ref] // The object designated by such a glvalue can be outside its lifetime // Because a null pointer value or a pointer past the end of an object // does not point to an object, a reference in a well-defined program // cannot refer to such things; assert(classifyPrim(VarTy) == PT_Ptr); if (!this->emitCheckRefInit(Init)) return false; } return this->emitSetLocal(*VarT, Offset, VD); } // Local composite variables. if (UnsignedOrNone Offset = this->allocateLocal(VD, VD->getType(), ScopeKind::Block)) { this->allocateLocal(VD, VarTy, ScopeKind::Block)) { if (!Init) return true; Loading clang/lib/AST/ByteCode/Interp.h +5 −0 Original line number Diff line number Diff line Loading @@ -1977,6 +1977,11 @@ inline bool GetRefLocal(InterpState &S, CodePtr OpPC, uint32_t I) { return handleReference(S, OpPC, LocalBlock); } inline bool CheckRefInit(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.peek<Pointer>(); return CheckRange(S, OpPC, Ptr, AK_Read); } inline bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t Index) { if (S.Current->isBottomFrame()) return false; Loading clang/lib/AST/ByteCode/Opcodes.td +3 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,9 @@ def GetPtrLocal : OffsetOpcode { def GetRefLocal : OffsetOpcode { bit HasCustomEval = 1; } def CheckRefInit : Opcode {} // [] -> [Pointer] def GetPtrParam : OffsetOpcode; // [] -> [Pointer] Loading clang/test/AST/ByteCode/cxx14.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -28,3 +28,10 @@ constexpr int foo() { return s.b[0]; } static_assert(foo() == 12, ""); int arr[3]; // both-note {{declared here}} constexpr bool f() { // both-error {{constexpr function never produces a constant expression}} int &r = arr[3]; // both-note {{read of dereferenced one-past-the-end pointer}} \ // both-warning {{array index 3 is past the end of the array}} return true; } Loading
clang/lib/AST/ByteCode/Compiler.cpp +17 −4 Original line number Diff line number Diff line Loading @@ -5238,8 +5238,9 @@ template <class Emitter> VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, const Expr *Init, bool Toplevel) { QualType VarTy = VD->getType(); // We don't know what to do with these, so just return false. if (VD->getType().isNull()) if (VarTy.isNull()) return false; // This case is EvalEmitter-only. If we won't create any instructions for the Loading Loading @@ -5299,8 +5300,8 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, if (VarT) { unsigned Offset = this->allocateLocalPrimitive( VD, *VarT, VD->getType().isConstQualified(), VD->getType().isVolatileQualified(), ScopeKind::Block); VD, *VarT, VarTy.isConstQualified(), VarTy.isVolatileQualified(), ScopeKind::Block); if (!Init || Init->getType()->isVoidType()) return true; Loading @@ -5315,11 +5316,23 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, } if (!this->visit(Init)) return false; if (VarTy->isReferenceType()) { // [C++26][decl.ref] // The object designated by such a glvalue can be outside its lifetime // Because a null pointer value or a pointer past the end of an object // does not point to an object, a reference in a well-defined program // cannot refer to such things; assert(classifyPrim(VarTy) == PT_Ptr); if (!this->emitCheckRefInit(Init)) return false; } return this->emitSetLocal(*VarT, Offset, VD); } // Local composite variables. if (UnsignedOrNone Offset = this->allocateLocal(VD, VD->getType(), ScopeKind::Block)) { this->allocateLocal(VD, VarTy, ScopeKind::Block)) { if (!Init) return true; Loading
clang/lib/AST/ByteCode/Interp.h +5 −0 Original line number Diff line number Diff line Loading @@ -1977,6 +1977,11 @@ inline bool GetRefLocal(InterpState &S, CodePtr OpPC, uint32_t I) { return handleReference(S, OpPC, LocalBlock); } inline bool CheckRefInit(InterpState &S, CodePtr OpPC) { const Pointer &Ptr = S.Stk.peek<Pointer>(); return CheckRange(S, OpPC, Ptr, AK_Read); } inline bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t Index) { if (S.Current->isBottomFrame()) return false; Loading
clang/lib/AST/ByteCode/Opcodes.td +3 −0 Original line number Diff line number Diff line Loading @@ -325,6 +325,9 @@ def GetPtrLocal : OffsetOpcode { def GetRefLocal : OffsetOpcode { bit HasCustomEval = 1; } def CheckRefInit : Opcode {} // [] -> [Pointer] def GetPtrParam : OffsetOpcode; // [] -> [Pointer] Loading
clang/test/AST/ByteCode/cxx14.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -28,3 +28,10 @@ constexpr int foo() { return s.b[0]; } static_assert(foo() == 12, ""); int arr[3]; // both-note {{declared here}} constexpr bool f() { // both-error {{constexpr function never produces a constant expression}} int &r = arr[3]; // both-note {{read of dereferenced one-past-the-end pointer}} \ // both-warning {{array index 3 is past the end of the array}} return true; }