Index: clang/lib/AST/Interp/Interp.cpp =================================================================== --- clang/lib/AST/Interp/Interp.cpp +++ clang/lib/AST/Interp/Interp.cpp @@ -98,6 +98,26 @@ return true; } +static bool CheckConstexpr(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { + if (!S.inConstantContext()) + return true; + + auto *VD = Ptr.getDeclDesc()->asValueDecl(); + if (!VD) + return true; + + if (auto *VarD = dyn_cast(VD)) { + if (VarD->hasLocalStorage() || VarD->isConstexpr()) + return true; + } + + const SourceInfo &Loc = S.Current->getSource(OpPC); + S.FFDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD; + S.Note(VD->getLocation(), diag::note_declared_at); + + return false; +} + static bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK) { if (Ptr.isInitialized()) @@ -294,6 +314,8 @@ return false; if (!CheckExtern(S, OpPC, Ptr)) return false; + if (!CheckConstexpr(S, OpPC, Ptr)) + return false; if (!CheckRange(S, OpPC, Ptr, AK_Read)) return false; if (!CheckInitialized(S, OpPC, Ptr, AK_Read)) Index: clang/test/AST/Interp/records.cpp =================================================================== --- clang/test/AST/Interp/records.cpp +++ clang/test/AST/Interp/records.cpp @@ -29,6 +29,15 @@ static_assert(Ints::getFive() == 5, ""); +// Read of a non-constexpr variable in a constant expression. +BoolPair nonConstBP; // ref-note {{declared here}} \ + // expected-note {{declared here}} +constexpr BoolPair *constBP = &nonConstBP; +static_assert(constBP->first, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{read of non-constexpr variable}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{read of non-constexpr variable}} + constexpr Ints ints; static_assert(ints.a == 20, ""); static_assert(ints.b == 30, "");