Skip to content

Commit

Permalink
[clang][Interp] Properly emit call ops to invalid functions
Browse files Browse the repository at this point in the history
Just like everywhere else, we can't just abort compilation because
a function is invalid. We need to emit the Call op and let later
interpretation handle the failure.

This fixes a long standing FIXME comment.
  • Loading branch information
tbaederr committed Feb 15, 2024
1 parent a1155f6 commit 6a8ab12
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 14 deletions.
8 changes: 0 additions & 8 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2835,14 +2835,6 @@ bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
const Function *Func = getFunction(FuncDecl);
if (!Func)
return false;
// If the function is being compiled right now, this is a recursive call.
// In that case, the function can't be valid yet, even though it will be
// later.
// If the function is already fully compiled but not constexpr, it was
// found to be faulty earlier on, so bail out.
if (Func->isFullyCompiled() && !Func->isConstexpr())
return false;

assert(HasRVO == Func->hasRVO());

bool HasQualifier = false;
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,11 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const Function *F) {
if (!DiagDecl->isDefined() && 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())
return false;

S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
<< DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
S.Note(DiagDecl->getLocation(), diag::note_declared_at);
Expand Down
4 changes: 1 addition & 3 deletions clang/test/AST/Interp/cxx20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,13 @@ namespace ConstThis {
// ref-note {{declared const here}}
int a;
public:
constexpr Foo() { // expected-note {{declared here}}
constexpr Foo() {
this->a = 10;
T = 13; // expected-error {{cannot assign to non-static data member 'T' with const-qualified type}} \
// ref-error {{cannot assign to non-static data member 'T' with const-qualified type}}
}
};
constexpr Foo F; // expected-error {{must be initialized by a constant expression}} \
// FIXME: The following note is wrong. \
// expected-note {{undefined constructor 'Foo' cannot be used in a constant expression}} \
// ref-error {{must be initialized by a constant expression}}


Expand Down
5 changes: 2 additions & 3 deletions clang/test/AST/Interp/records.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1232,10 +1232,9 @@ namespace InheritedConstructor {
namespace InvalidCtorInitializer {
struct X {
int Y;
constexpr X() // expected-note {{declared here}}
constexpr X()
: Y(fo_o_()) {} // both-error {{use of undeclared identifier 'fo_o_'}}
};
// no crash on evaluating the constexpr ctor.
constexpr int Z = X().Y; // both-error {{constexpr variable 'Z' must be initialized by a constant expression}} \
// expected-note {{undefined constructor 'X'}}
constexpr int Z = X().Y; // both-error {{constexpr variable 'Z' must be initialized by a constant expression}}
}

0 comments on commit 6a8ab12

Please sign in to comment.