Author: Timm Bäder Date: 2024-06-06T19:41:41+02:00 New Revision: ce938fcbde547315af18a47a609c2e09ebfb4cec
URL: https://github.com/llvm/llvm-project/commit/ce938fcbde547315af18a47a609c2e09ebfb4cec DIFF: https://github.com/llvm/llvm-project/commit/ce938fcbde547315af18a47a609c2e09ebfb4cec.diff LOG: [clang][Interp] Diagnose functions without body like undefined ones We only get a "reached end of constexpr function" diagnostic otherwise. Added: Modified: clang/lib/AST/Interp/Interp.cpp clang/test/AST/Interp/cxx23.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 41bbaf83b11c8..49015b1dd63d3 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -538,7 +538,7 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { return false; } - if (!F->isConstexpr()) { + if (!F->isConstexpr() || !F->hasBody()) { const SourceLocation &Loc = S.Current->getLocation(OpPC); if (S.getLangOpts().CPlusPlus11) { const FunctionDecl *DiagDecl = F->getDecl(); @@ -572,9 +572,10 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) { 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()) + // 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) diff --git a/clang/test/AST/Interp/cxx23.cpp b/clang/test/AST/Interp/cxx23.cpp index c91d52c552b12..1efd784abbbe8 100644 --- a/clang/test/AST/Interp/cxx23.cpp +++ b/clang/test/AST/Interp/cxx23.cpp @@ -178,3 +178,25 @@ namespace ExplicitLambdaThis { }; static_assert(f()); } + +namespace std { + struct strong_ordering { + int n; + constexpr operator int() const { return n; } + static const strong_ordering less, equal, greater; + }; + constexpr strong_ordering strong_ordering::less = {-1}; + constexpr strong_ordering strong_ordering::equal = {0}; + constexpr strong_ordering strong_ordering::greater = {1}; +} + +namespace UndefinedThreeWay { + struct A { + friend constexpr std::strong_ordering operator<=>(const A&, const A&) = default; // all-note {{declared here}} + }; + + constexpr std::strong_ordering operator<=>(const A&, const A&) noexcept; + constexpr std::strong_ordering (*test_a_threeway)(const A&, const A&) = &operator<=>; + static_assert(!(*test_a_threeway)(A(), A())); // all-error {{static assertion expression is not an integral constant expression}} \ + // all-note {{undefined function 'operator<=>' cannot be used in a constant expression}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits