Author: Timm Bäder Date: 2024-07-18T15:22:02+02:00 New Revision: d00b35534d068510025d22e5bd9c4fdac45757fb
URL: https://github.com/llvm/llvm-project/commit/d00b35534d068510025d22e5bd9c4fdac45757fb DIFF: https://github.com/llvm/llvm-project/commit/d00b35534d068510025d22e5bd9c4fdac45757fb.diff LOG: [clang][Interp] Fix CheckCallable for undefined-and-not-constexpr fns Added: clang/test/AST/Interp/cxx2a.cpp Modified: clang/lib/AST/Interp/Interp.cpp clang/lib/AST/Interp/Interp.h Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 2be9b5360d055..be47f72e65a29 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -579,57 +579,61 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { return false; } - if (!F->isConstexpr() || !F->hasBody()) { - const SourceLocation &Loc = S.Current->getLocation(OpPC); - if (S.getLangOpts().CPlusPlus11) { - const FunctionDecl *DiagDecl = F->getDecl(); + if (F->isConstexpr() && F->hasBody() && F->getDecl()->isConstexpr()) + return true; - // Invalid decls have been diagnosed before. - if (DiagDecl->isInvalidDecl()) - return false; + // Implicitly constexpr. + if (F->isLambdaStaticInvoker()) + return true; - // If this function is not constexpr because it is an inherited - // non-constexpr constructor, diagnose that directly. - const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl); - if (CD && CD->isInheritingConstructor()) { - const auto *Inherited = CD->getInheritedConstructor().getConstructor(); - if (!Inherited->isConstexpr()) - DiagDecl = CD = Inherited; - } + const SourceLocation &Loc = S.Current->getLocation(OpPC); + if (S.getLangOpts().CPlusPlus11) { + const FunctionDecl *DiagDecl = F->getDecl(); + + // Invalid decls have been diagnosed before. + if (DiagDecl->isInvalidDecl()) + return false; + + // If this function is not constexpr because it is an inherited + // non-constexpr constructor, diagnose that directly. + const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl); + if (CD && CD->isInheritingConstructor()) { + const auto *Inherited = CD->getInheritedConstructor().getConstructor(); + if (!Inherited->isConstexpr()) + DiagDecl = CD = Inherited; + } - // FIXME: If DiagDecl is an implicitly-declared special member function - // or an inheriting constructor, we should be much more explicit about why - // it's not constexpr. - if (CD && CD->isInheritingConstructor()) { - S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1) + // FIXME: If DiagDecl is an implicitly-declared special member function + // or an inheriting constructor, we should be much more explicit about why + // it's not constexpr. + if (CD && CD->isInheritingConstructor()) { + S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1) << CD->getInheritedConstructor().getConstructor()->getParent(); - S.Note(DiagDecl->getLocation(), diag::note_declared_at); - } else { - // Don't emit anything if the function isn't defined and we're checking - // for a constant expression. It might be defined at the point we're - // actually calling it. - bool IsExtern = DiagDecl->getStorageClass() == SC_Extern; - if (!DiagDecl->isDefined() && !IsExtern && - S.checkingPotentialConstantExpression()) - return false; + S.Note(DiagDecl->getLocation(), diag::note_declared_at); + } else { + // Don't emit anything if the function isn't defined and we're checking + // for a constant expression. It might be defined at the point we're + // actually calling it. + bool IsExtern = DiagDecl->getStorageClass() == SC_Extern; + if (!DiagDecl->isDefined() && !IsExtern && DiagDecl->isConstexpr() && + S.checkingPotentialConstantExpression()) + return false; - // If the declaration is defined, declared 'constexpr' _and_ has a body, - // the below diagnostic doesn't add anything useful. - if (DiagDecl->isDefined() && DiagDecl->isConstexpr() && - DiagDecl->hasBody()) - return false; + // If the declaration is defined, declared 'constexpr' _and_ has a body, + // the below diagnostic doesn't add anything useful. + if (DiagDecl->isDefined() && DiagDecl->isConstexpr() && + DiagDecl->hasBody()) + return false; - S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1) + S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1) << DiagDecl->isConstexpr() << (bool)CD << DiagDecl; - S.Note(DiagDecl->getLocation(), diag::note_declared_at); - } - } else { - S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr); + S.Note(DiagDecl->getLocation(), diag::note_declared_at); } - return false; + } else { + S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr); } - return true; + return false; } bool CheckCallDepth(InterpState &S, CodePtr OpPC) { diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 17b3157cb40a9..2e159012f5ffd 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -2531,14 +2531,14 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func, if (!CheckInvoke(S, OpPC, ThisPtr)) return false; } - - if (S.checkingPotentialConstantExpression()) - return false; } if (!CheckCallable(S, OpPC, Func)) return false; + if (Func->hasThisPointer() && S.checkingPotentialConstantExpression()) + return false; + if (!CheckCallDepth(S, OpPC)) return false; diff --git a/clang/test/AST/Interp/cxx2a.cpp b/clang/test/AST/Interp/cxx2a.cpp new file mode 100644 index 0000000000000..27d1aa1a27f75 --- /dev/null +++ b/clang/test/AST/Interp/cxx2a.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both %s +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=expected,both %s -fexperimental-new-constant-interpreter + +template <unsigned N> +struct S { + S() requires (N==1) = default; + S() requires (N==2) {} // both-note {{declared here}} + consteval S() requires (N==3) = default; +}; + +consteval int aConstevalFunction() { // both-error {{consteval function never produces a constant expression}} + S<2> s4; // both-note {{non-constexpr constructor 'S' cannot be used in a constant expression}} + return 0; +} +/// We're NOT calling the above function. The diagnostics should appear anyway. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits