This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG23c39f9a9e14: [clang][Interp] Diagnose unknown parameter values (authored by tbaeder).
Changed prior to commit: https://reviews.llvm.org/D156509?vs=545193&id=556845#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D156509/new/ https://reviews.llvm.org/D156509 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/Interp.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td clang/test/AST/Interp/c.c clang/test/AST/Interp/functions.cpp clang/test/AST/Interp/literals.cpp
Index: clang/test/AST/Interp/literals.cpp =================================================================== --- clang/test/AST/Interp/literals.cpp +++ clang/test/AST/Interp/literals.cpp @@ -1088,3 +1088,31 @@ int array[(intptr_t)(char*)0]; // ref-warning {{variable length array folded to constant array}} \ // expected-warning {{variable length array folded to constant array}} } + +namespace InvalidDeclRefs { + bool b00; // ref-note {{declared here}} \ + // expected-note {{declared here}} + static_assert(b00, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{read of non-const variable}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{read of non-const variable}} + + float b01; // ref-note {{declared here}} \ + // expected-note {{declared here}} + static_assert(b01, ""); // 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}} + + extern const int b02; // ref-note {{declared here}} \ + // expected-note {{declared here}} + static_assert(b02, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{initializer of 'b02' is unknown}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{initializer of 'b02' is unknown}} + + /// FIXME: This should also be diagnosed in the new interpreter. + int b03 = 3; // ref-note {{declared here}} + static_assert(b03, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{read of non-const variable}} +} 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() { @@ -307,3 +311,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 +} Index: clang/test/AST/Interp/c.c =================================================================== --- clang/test/AST/Interp/c.c +++ clang/test/AST/Interp/c.c @@ -3,8 +3,6 @@ // RUN: %clang_cc1 -verify=ref -std=c11 %s // RUN: %clang_cc1 -pedantic -verify=pedantic-ref -std=c11 %s -/// expected-no-diagnostics - _Static_assert(1, ""); _Static_assert(0 != 1, ""); _Static_assert(1.0 == 1.0, ""); // pedantic-ref-warning {{not an integer constant expression}} \ @@ -26,3 +24,15 @@ _Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \ // pedantic-expected-warning {{not an integer constant expression}} +const int c; // ref-note {{declared here}} \ + // pedantic-ref-note {{declared here}} \ + // expected-note {{declared here}} \ + // pedantic-expected-note {{declared here}} +_Static_assert(c == 0, ""); // ref-error {{not an integral constant expression}} \ + // ref-note {{initializer of 'c' is unknown}} \ + // pedantic-ref-error {{not an integral constant expression}} \ + // pedantic-ref-note {{initializer of 'c' is unknown}} \ + // expected-error {{not an integral constant expression}} \ + // expected-note {{initializer of 'c' is unknown}} \ + // pedantic-expected-error {{not an integral constant expression}} \ + // pedantic-expected-note {{initializer of 'c' is unknown}} 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. @@ -632,3 +633,7 @@ def InvalidCast : Opcode { let Args = [ArgCastKind]; } + +def InvalidDeclRef : Opcode { + let Args = [ArgDeclRef]; +} Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -175,6 +175,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); + /// Interpreter entry point. bool Interpret(InterpState &S, APValue &Result); @@ -1854,6 +1857,12 @@ return false; } +inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, + const DeclRefExpr *DR) { + assert(DR); + return CheckDeclRef(S, OpPC, DR); +} + template <PrimType Name, class T = typename PrimConv<Name>::T> inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) { llvm::SmallVector<int64_t> ArrayIndices; Index: clang/lib/AST/Interp/Interp.cpp =================================================================== --- clang/lib/AST/Interp/Interp.cpp +++ clang/lib/AST/Interp/Interp.cpp @@ -542,6 +542,38 @@ 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<ParmVarDecl>(D)) { + S.FFDiag(E, diag::note_constexpr_function_param_value_unknown) << D; + S.Note(D->getLocation(), diag::note_declared_at) << D->getSourceRange(); + } else if (const auto *VD = dyn_cast<VarDecl>(D)) { + if (!VD->getType().isConstQualified()) { + S.FFDiag(E, + VD->getType()->isIntegralOrEnumerationType() + ? diag::note_constexpr_ltor_non_const_int + : diag::note_constexpr_ltor_non_constexpr, + 1) + << VD; + S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange(); + return false; + } + + // const, but no initializer. + if (!VD->getAnyInitializer()) { + S.FFDiag(E, diag::note_constexpr_var_init_unknown, 1) << VD; + S.Note(VD->getLocation(), diag::note_declared_at) << VD->getSourceRange(); + return false; + } + } + + return false; +} + bool Interpret(InterpState &S, APValue &Result) { // The current stack frame when we started Interpret(). // This is being used by the ops to determine wheter Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2492,7 +2492,8 @@ return this->VisitDeclRefExpr(E); } } - return false; + + return this->emitInvalidDeclRef(E, E); } template <class Emitter>
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits