diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index db6d818eef334..e4b48c4e946f1 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2835,14 +2835,6 @@ bool ByteCodeExprGen::VisitCallExpr(const CallExpr *E) { const Function *Func = getFunction(FuncDecl); if (!Func) return false; - // If the function is being compiled right now, this is a recursive call. - // In that case, the function can't be valid yet, even though it will be - // later. - // If the function is already fully compiled but not constexpr, it was - // found to be faulty earlier on, so bail out. - if (Func->isFullyCompiled() && !Func->isConstexpr()) - return false; - assert(HasRVO == Func->hasRVO()); bool HasQualifier = false; diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 2338f88569db8..2a51f18adf02c 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -477,6 +477,11 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { if (!DiagDecl->isDefined() && S.checkingPotentialConstantExpression()) return false; + // If the declaration is defined _and_ declared 'constexpr', the below + // diagnostic doesn't add anything useful. + if (DiagDecl->isDefined() && DiagDecl->isConstexpr()) + return false; + S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1) << DiagDecl->isConstexpr() << (bool)CD << DiagDecl; S.Note(DiagDecl->getLocation(), diag::note_declared_at); diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp index 0af553a77892e..0fc5d977b59f4 100644 --- a/clang/test/AST/Interp/cxx20.cpp +++ b/clang/test/AST/Interp/cxx20.cpp @@ -230,15 +230,13 @@ namespace ConstThis { // ref-note {{declared const here}} int a; public: - constexpr Foo() { // expected-note {{declared here}} + constexpr Foo() { this->a = 10; T = 13; // expected-error {{cannot assign to non-static data member 'T' with const-qualified type}} \ // ref-error {{cannot assign to non-static data member 'T' with const-qualified type}} } }; constexpr Foo F; // expected-error {{must be initialized by a constant expression}} \ - // FIXME: The following note is wrong. \ - // expected-note {{undefined constructor 'Foo' cannot be used in a constant expression}} \ // ref-error {{must be initialized by a constant expression}} diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 93da831f3bda0..62f1f1d6e426c 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1232,10 +1232,9 @@ namespace InheritedConstructor { namespace InvalidCtorInitializer { struct X { int Y; - constexpr X() // expected-note {{declared here}} + constexpr X() : Y(fo_o_()) {} // both-error {{use of undeclared identifier 'fo_o_'}} }; // no crash on evaluating the constexpr ctor. - constexpr int Z = X().Y; // both-error {{constexpr variable 'Z' must be initialized by a constant expression}} \ - // expected-note {{undefined constructor 'X'}} + constexpr int Z = X().Y; // both-error {{constexpr variable 'Z' must be initialized by a constant expression}} }