[clang][Interp] Fix calling static operators

They don't have an instance pointer anywhere but get one passed
via their CallExpr.
This commit is contained in:
Timm Bäder 2024-02-19 08:54:36 +01:00
parent 4b9c089381
commit 0b34d7e9e2
3 changed files with 44 additions and 6 deletions

View File

@ -1716,6 +1716,9 @@ bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {
template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
if (DiscardResult)
return true;
assert(Initializing);
const Record *R = P.getOrCreateRecord(E->getLambdaClass());
@ -2824,6 +2827,20 @@ bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
}
}
auto Args = E->arguments();
// Calling a static operator will still
// pass the instance, but we don't need it.
// Discard it here.
if (isa<CXXOperatorCallExpr>(E)) {
if (const auto *MD =
dyn_cast_if_present<CXXMethodDecl>(E->getDirectCallee());
MD && MD->isStatic()) {
if (!this->discard(E->getArg(0)))
return false;
Args = drop_begin(Args, 1);
}
}
// Add the (optional, implicit) This pointer.
if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) {
if (!this->visit(MC->getImplicitObjectArgument()))
@ -2831,7 +2848,7 @@ bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
}
// Put arguments on the stack.
for (const auto *Arg : E->arguments()) {
for (const auto *Arg : Args) {
if (!this->visit(Arg))
return false;
}

View File

@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20 %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref23 %s
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref20,all %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref23,all %s
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23,all %s -fexperimental-new-constant-interpreter
/// FIXME: The new interpreter is missing all the 'control flows through...' diagnostics.
@ -123,3 +123,24 @@ namespace StaticLambdas {
}
static_assert(capture_constexpr());
}
namespace StaticOperators {
auto lstatic = []() static { return 3; }; // ref20-warning {{C++23 extension}} \
// expected20-warning {{C++23 extension}}
static_assert(lstatic() == 3, "");
constexpr int (*f2)(void) = lstatic;
static_assert(f2() == 3);
struct S1 {
constexpr S1() { // all-error {{never produces a constant expression}}
throw; // all-note 2{{not valid in a constant expression}}
}
static constexpr int operator()() { return 3; } // ref20-warning {{C++23 extension}} \
// expected20-warning {{C++23 extension}}
};
static_assert(S1{}() == 3, ""); // all-error {{not an integral constant expression}} \
// all-note {{in call to}}
}

View File

@ -1,5 +1,5 @@
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter
namespace ns1 {
auto lstatic = []() static { return 3; };