Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2499,7 +2499,7 @@ return this->emitGetPtrThisField(Offset, E); } - return false; + return this->emitInvalidDeclRef(E, E); } template Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -174,6 +174,9 @@ bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result, APFloat::opStatus Status); +/// Checks why the given DeclRefExpr is invalid. +bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR); + bool CheckBitcast(InterpState &S, CodePtr OpPC, unsigned IndeterminateBits, bool TargetIsUCharOrByte); @@ -1897,6 +1900,12 @@ return false; } +inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, + const DeclRefExpr *DR) { + assert(DR); + return CheckDeclRef(S, OpPC, DR); +} + template ::T> inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) { std::vector ArrayIndices; Index: clang/lib/AST/Interp/Interp.cpp =================================================================== --- clang/lib/AST/Interp/Interp.cpp +++ clang/lib/AST/Interp/Interp.cpp @@ -541,6 +541,20 @@ return true; } +/// We aleady know the given DeclRefExpr is invalid for some reason, +/// now figure out why and print appropriate diagnostics. +bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) { + const ValueDecl *D = DR->getDecl(); + const SourceInfo &E = S.Current->getSource(OpPC); + + if (isa(D)) { + S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D; + S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange(); + } + + return false; +} + bool CheckBitcast(InterpState &S, CodePtr OpPC, unsigned IndeterminateBits, bool TargetIsUCharOrByte) { Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -54,6 +54,7 @@ def ArgCastKind : ArgType { let Name = "CastKind"; } def ArgCallExpr : ArgType { let Name = "const CallExpr *"; } def ArgOffsetOfExpr : ArgType { let Name = "const OffsetOfExpr *"; } +def ArgDeclRef : ArgType { let Name = "const DeclRefExpr *"; } //===----------------------------------------------------------------------===// // Classes of types instructions operate on. @@ -649,3 +650,7 @@ def InvalidCast : Opcode { let Args = [ArgCastKind]; } + +def InvalidDeclRef : Opcode { + let Args = [ArgDeclRef]; +} Index: clang/test/AST/Interp/functions.cpp =================================================================== --- clang/test/AST/Interp/functions.cpp +++ clang/test/AST/Interp/functions.cpp @@ -1,5 +1,9 @@ // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s +// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -verify %s +// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify %s // RUN: %clang_cc1 -verify=ref %s +// RUN: %clang_cc1 -std=c++14 -verify=ref %s +// RUN: %clang_cc1 -std=c++20 -verify=ref %s constexpr void doNothing() {} constexpr int gimme5() { @@ -300,3 +304,24 @@ } static_assert((foo(),1) == 1, ""); } + +namespace InvalidReclRefs { + void param(bool b) { // ref-note {{declared here}} \ + // expected-note {{declared here}} + static_assert(b, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{function parameter 'b' with unknown value}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{function parameter 'b' with unknown value}} + static_assert(true ? true : b, ""); + } + +#if __cplusplus >= 202002L + consteval void param2(bool b) { // ref-note {{declared here}} \ + // expected-note {{declared here}} + static_assert(b, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{function parameter 'b' with unknown value}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{function parameter 'b' with unknown value}} + } +#endif +}