Skip to content

Commit 9fae0c6

Browse files
committed
Reapply "[clang][Interp] Fix CheckCallable for undefined-and-not-constexpr fns"
This reverts commit ad7aeb0.
1 parent 92f9f01 commit 9fae0c6

File tree

3 files changed

+64
-44
lines changed

3 files changed

+64
-44
lines changed

clang/lib/AST/Interp/Interp.cpp

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -579,57 +579,62 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
579579
return false;
580580
}
581581

582-
if (!F->isConstexpr() || !F->hasBody()) {
583-
const SourceLocation &Loc = S.Current->getLocation(OpPC);
584-
if (S.getLangOpts().CPlusPlus11) {
585-
const FunctionDecl *DiagDecl = F->getDecl();
582+
if (F->isConstexpr() && F->hasBody() &&
583+
(F->getDecl()->isConstexpr() || F->getDecl()->hasAttr<MSConstexprAttr>()))
584+
return true;
586585

587-
// Invalid decls have been diagnosed before.
588-
if (DiagDecl->isInvalidDecl())
589-
return false;
586+
// Implicitly constexpr.
587+
if (F->isLambdaStaticInvoker())
588+
return true;
590589

591-
// If this function is not constexpr because it is an inherited
592-
// non-constexpr constructor, diagnose that directly.
593-
const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
594-
if (CD && CD->isInheritingConstructor()) {
595-
const auto *Inherited = CD->getInheritedConstructor().getConstructor();
596-
if (!Inherited->isConstexpr())
597-
DiagDecl = CD = Inherited;
598-
}
590+
const SourceLocation &Loc = S.Current->getLocation(OpPC);
591+
if (S.getLangOpts().CPlusPlus11) {
592+
const FunctionDecl *DiagDecl = F->getDecl();
593+
594+
// Invalid decls have been diagnosed before.
595+
if (DiagDecl->isInvalidDecl())
596+
return false;
597+
598+
// If this function is not constexpr because it is an inherited
599+
// non-constexpr constructor, diagnose that directly.
600+
const auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
601+
if (CD && CD->isInheritingConstructor()) {
602+
const auto *Inherited = CD->getInheritedConstructor().getConstructor();
603+
if (!Inherited->isConstexpr())
604+
DiagDecl = CD = Inherited;
605+
}
599606

600-
// FIXME: If DiagDecl is an implicitly-declared special member function
601-
// or an inheriting constructor, we should be much more explicit about why
602-
// it's not constexpr.
603-
if (CD && CD->isInheritingConstructor()) {
604-
S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
607+
// FIXME: If DiagDecl is an implicitly-declared special member function
608+
// or an inheriting constructor, we should be much more explicit about why
609+
// it's not constexpr.
610+
if (CD && CD->isInheritingConstructor()) {
611+
S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
605612
<< CD->getInheritedConstructor().getConstructor()->getParent();
606-
S.Note(DiagDecl->getLocation(), diag::note_declared_at);
607-
} else {
608-
// Don't emit anything if the function isn't defined and we're checking
609-
// for a constant expression. It might be defined at the point we're
610-
// actually calling it.
611-
bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
612-
if (!DiagDecl->isDefined() && !IsExtern &&
613-
S.checkingPotentialConstantExpression())
614-
return false;
613+
S.Note(DiagDecl->getLocation(), diag::note_declared_at);
614+
} else {
615+
// Don't emit anything if the function isn't defined and we're checking
616+
// for a constant expression. It might be defined at the point we're
617+
// actually calling it.
618+
bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
619+
if (!DiagDecl->isDefined() && !IsExtern && DiagDecl->isConstexpr() &&
620+
S.checkingPotentialConstantExpression())
621+
return false;
615622

616-
// If the declaration is defined, declared 'constexpr' _and_ has a body,
617-
// the below diagnostic doesn't add anything useful.
618-
if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
619-
DiagDecl->hasBody())
620-
return false;
623+
// If the declaration is defined, declared 'constexpr' _and_ has a body,
624+
// the below diagnostic doesn't add anything useful.
625+
if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
626+
DiagDecl->hasBody())
627+
return false;
621628

622-
S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
629+
S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
623630
<< DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
624-
S.Note(DiagDecl->getLocation(), diag::note_declared_at);
625-
}
626-
} else {
627-
S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
631+
S.Note(DiagDecl->getLocation(), diag::note_declared_at);
628632
}
629-
return false;
633+
} else {
634+
S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
630635
}
631636

632-
return true;
637+
return false;
633638
}
634639

635640
bool CheckCallDepth(InterpState &S, CodePtr OpPC) {

clang/lib/AST/Interp/Interp.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,14 +2531,14 @@ inline bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
25312531
if (!CheckInvoke(S, OpPC, ThisPtr))
25322532
return false;
25332533
}
2534-
2535-
if (S.checkingPotentialConstantExpression())
2536-
return false;
25372534
}
25382535

25392536
if (!CheckCallable(S, OpPC, Func))
25402537
return false;
25412538

2539+
if (Func->hasThisPointer() && S.checkingPotentialConstantExpression())
2540+
return false;
2541+
25422542
if (!CheckCallDepth(S, OpPC))
25432543
return false;
25442544

clang/test/AST/Interp/cxx2a.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both %s
2+
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=expected,both %s -fexperimental-new-constant-interpreter
3+
4+
template <unsigned N>
5+
struct S {
6+
S() requires (N==1) = default;
7+
S() requires (N==2) {} // both-note {{declared here}}
8+
consteval S() requires (N==3) = default;
9+
};
10+
11+
consteval int aConstevalFunction() { // both-error {{consteval function never produces a constant expression}}
12+
S<2> s4; // both-note {{non-constexpr constructor 'S' cannot be used in a constant expression}}
13+
return 0;
14+
}
15+
/// We're NOT calling the above function. The diagnostics should appear anyway.

0 commit comments

Comments
 (0)