Skip to content

Commit 041080c

Browse files
committed
[AST] Fix a crash on invalid constexpr Ctorinitializer when building RecoveryExpr.
Summary: crash stack: ``` lang: workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:13704: bool EvaluateInPlace(clang::APValue &, (anonymous namespace)::EvalInfo &, const (anonymous namespace)::LValue &, const clang::Expr *, bool): Assertion `!E->isValueDependent()' failed. #8 EvaluateInPlace(clang::APValue&, (anonymous namespace)::EvalInfo&, (anonymous namespace)::LValue const&, clang::Expr const*, bool) workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:0:0 #9 HandleConstructorCall(clang::Expr const*, (anonymous namespace)::LValue const&, clang::APValue*, clang::CXXConstructorDecl const*, (anonymous namespace)::EvalInfo&, clang::APValue&) workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:5779:57 #10 HandleConstructorCall(clang::Expr const*, (anonymous namespace)::LValue const&, llvm::ArrayRef<clang::Expr const*>, clang::CXXConstructorDecl const*, (anonymous namespace)::EvalInfo&, clang::APValue&) workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:5819:10 #11 clang::Expr::isPotentialConstantExpr(clang::FunctionDecl const*, llvm::SmallVectorImpl<std::pair<clang::SourceLocation, clang::PartialDiagnostic> >&) workspace/llvm-project/clang/lib/AST/ExprConstant.cpp:14746:5 #12 CheckConstexprFunctionBody(clang::Sema&, clang::FunctionDecl const*, clang::Stmt*, clang::Sema::CheckConstexprKind) workspace/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp:2306:7 #13 clang::Sema::CheckConstexprFunctionDefinition(clang::FunctionDecl const*, clang::Sema::CheckConstexprKind) workspace/llvm-project/clang/lib/Sema/SemaDeclCXX.cpp:1766:0 #14 clang::Sema::ActOnFinishFunctionBody(clang::Decl*, clang::Stmt*, bool) workspace/llvm-project/clang/lib/Sema/SemaDecl.cpp:14357:9 #15 clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) workspace/llvm-project/clang/lib/Parse/ParseStmt.cpp:2213:18 ``` Reviewers: sammccall Reviewed By: sammccall Subscribers: rsmith, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D77041
1 parent 448b777 commit 041080c

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

clang/lib/AST/ExprConstant.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -4976,6 +4976,13 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
49764976
return false;
49774977
}
49784978

4979+
if (const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(Definition)) {
4980+
for (const auto *InitExpr : CtorDecl->inits()) {
4981+
if (InitExpr->getInit() && InitExpr->getInit()->containsErrors())
4982+
return false;
4983+
}
4984+
}
4985+
49794986
// Can we evaluate this function call?
49804987
if (Definition && Definition->isConstexpr() && Body)
49814988
return true;
@@ -14709,6 +14716,15 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
1470914716
if (FD->isDependentContext())
1471014717
return true;
1471114718

14719+
// Bail out if a constexpr constructor has an initializer that contains an
14720+
// error. We deliberately don't produce a diagnostic, as we have produced a
14721+
// relevant diagnostic when parsing the error initializer.
14722+
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(FD)) {
14723+
for (const auto *InitExpr : Ctor->inits()) {
14724+
if (InitExpr->getInit() && InitExpr->getInit()->containsErrors())
14725+
return false;
14726+
}
14727+
}
1471214728
Expr::EvalStatus Status;
1471314729
Status.Diag = &Diags;
1471414730

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -frecovery-ast -verify %s
2+
3+
struct X {
4+
int Y;
5+
constexpr X() // expected-error {{constexpr constructor never produces}}
6+
: Y(foo()) {} // expected-error {{use of undeclared identifier 'foo'}}
7+
};
8+
// no crash on evaluating the constexpr ctor.
9+
constexpr int Z = X().Y; // expected-error {{constexpr variable 'Z' must be initialized by a constant expression}}
10+
11+
struct X2 {
12+
int Y = foo(); // expected-error {{use of undeclared identifier 'foo'}} \
13+
// expected-note {{subexpression not valid in a constant expression}}
14+
constexpr X2() {} // expected-error {{constexpr constructor never produces a constant expression}}
15+
};
16+
17+
struct CycleDelegate {
18+
int Y;
19+
CycleDelegate(int)
20+
: Y(foo()) {} // expected-error {{use of undeclared identifier 'foo'}}
21+
// no bogus "delegation cycle" diagnostic
22+
CycleDelegate(float) : CycleDelegate(1) {}
23+
};

0 commit comments

Comments
 (0)