[clang] 9fae0c6 - Reapply "[clang][Interp] Fix CheckCallable for undefined-and-not-constexpr fns"
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 18 07:16:30 PDT 2024
Author: Timm Bäder
Date: 2024-07-18T16:15:59+02:00
New Revision: 9fae0c6f9c05915a5daac5b368258a40e1fab237
URL: https://github.com/llvm/llvm-project/commit/9fae0c6f9c05915a5daac5b368258a40e1fab237
DIFF: https://github.com/llvm/llvm-project/commit/9fae0c6f9c05915a5daac5b368258a40e1fab237.diff
LOG: Reapply "[clang][Interp] Fix CheckCallable for undefined-and-not-constexpr fns"
This reverts commit ad7aeb0ff58ebd29f68adb85c64e8010639e2a76.
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..e6e9298982887 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -579,57 +579,62 @@ 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() || F->getDecl()->hasAttr<MSConstexprAttr>()))
+ 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.
More information about the cfe-commits
mailing list