Skip to content

Commit ce938fc

Browse files
committed
[clang][Interp] Diagnose functions without body like undefined ones
We only get a "reached end of constexpr function" diagnostic otherwise.
1 parent 04acf11 commit ce938fc

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

clang/lib/AST/Interp/Interp.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
538538
return false;
539539
}
540540

541-
if (!F->isConstexpr()) {
541+
if (!F->isConstexpr() || !F->hasBody()) {
542542
const SourceLocation &Loc = S.Current->getLocation(OpPC);
543543
if (S.getLangOpts().CPlusPlus11) {
544544
const FunctionDecl *DiagDecl = F->getDecl();
@@ -572,9 +572,10 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
572572
S.checkingPotentialConstantExpression())
573573
return false;
574574

575-
// If the declaration is defined _and_ declared 'constexpr', the below
576-
// diagnostic doesn't add anything useful.
577-
if (DiagDecl->isDefined() && DiagDecl->isConstexpr())
575+
// If the declaration is defined, declared 'constexpr' _and_ has a body,
576+
// the below diagnostic doesn't add anything useful.
577+
if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
578+
DiagDecl->hasBody())
578579
return false;
579580

580581
S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)

clang/test/AST/Interp/cxx23.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,25 @@ namespace ExplicitLambdaThis {
178178
};
179179
static_assert(f());
180180
}
181+
182+
namespace std {
183+
struct strong_ordering {
184+
int n;
185+
constexpr operator int() const { return n; }
186+
static const strong_ordering less, equal, greater;
187+
};
188+
constexpr strong_ordering strong_ordering::less = {-1};
189+
constexpr strong_ordering strong_ordering::equal = {0};
190+
constexpr strong_ordering strong_ordering::greater = {1};
191+
}
192+
193+
namespace UndefinedThreeWay {
194+
struct A {
195+
friend constexpr std::strong_ordering operator<=>(const A&, const A&) = default; // all-note {{declared here}}
196+
};
197+
198+
constexpr std::strong_ordering operator<=>(const A&, const A&) noexcept;
199+
constexpr std::strong_ordering (*test_a_threeway)(const A&, const A&) = &operator<=>;
200+
static_assert(!(*test_a_threeway)(A(), A())); // all-error {{static assertion expression is not an integral constant expression}} \
201+
// all-note {{undefined function 'operator<=>' cannot be used in a constant expression}}
202+
}

0 commit comments

Comments
 (0)