Skip to content

Commit 882fd4e

Browse files
committed
Recovery from the invalid in-class-initializer
Signed-off-by: yronglin <[email protected]>
1 parent de4a9d5 commit 882fd4e

File tree

5 files changed

+39
-13
lines changed

5 files changed

+39
-13
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5287,7 +5287,7 @@ class Sema final : public SemaBase {
52875287
/// is complete.
52885288
void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
52895289
SourceLocation EqualLoc,
5290-
Expr *Init);
5290+
ExprResult Init);
52915291

52925292
/// Handle a C++ member initializer using parentheses syntax.
52935293
MemInitResult

clang/lib/Parse/ParseCXXInlineMethods.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
722722
ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
723723
EqualLoc);
724724

725-
Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc,
726-
Init.get());
725+
Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc, Init);
727726

728727
// The next token should be our artificial terminating EOF token.
729728
if (Tok.isNot(tok::eof)) {

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4080,24 +4080,28 @@ ExprResult Sema::ConvertMemberDefaultInitExpression(FieldDecl *FD,
40804080

40814081
void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
40824082
SourceLocation InitLoc,
4083-
Expr *InitExpr) {
4083+
ExprResult InitExpr) {
40844084
// Pop the notional constructor scope we created earlier.
40854085
PopFunctionScopeInfo(nullptr, D);
40864086

4087-
FieldDecl *FD = dyn_cast<FieldDecl>(D);
4088-
assert((isa<MSPropertyDecl>(D) || FD->getInClassInitStyle() != ICIS_NoInit) &&
4089-
"must set init style when field is created");
4090-
4091-
if (!InitExpr) {
4087+
// Microsoft C++'s property declaration cannot have a default member
4088+
// initializer.
4089+
if (isa<MSPropertyDecl>(D)) {
40924090
D->setInvalidDecl();
4093-
if (FD)
4094-
FD->removeInClassInitializer();
40954091
return;
40964092
}
40974093

4098-
if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) {
4094+
FieldDecl *FD = dyn_cast<FieldDecl>(D);
4095+
assert((FD && FD->getInClassInitStyle() != ICIS_NoInit) &&
4096+
"must set init style when field is created");
4097+
4098+
if (!InitExpr.isUsable() ||
4099+
DiagnoseUnexpandedParameterPack(InitExpr.get(), UPPC_Initializer)) {
40994100
FD->setInvalidDecl();
4100-
FD->removeInClassInitializer();
4101+
ExprResult RecoveryInit =
4102+
CreateRecoveryExpr(InitLoc, InitLoc, {}, FD->getType());
4103+
if (RecoveryInit.isUsable())
4104+
FD->setInClassInitializer(RecoveryInit.get());
41014105
return;
41024106
}
41034107

clang/lib/Sema/SemaInit.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,18 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
750750
if (Field->hasInClassInitializer()) {
751751
if (VerifyOnly)
752752
return;
753+
754+
// We do not want to aggressively set the hadError flag and cutoff
755+
// parsing. Try to recover when in-class-initializer is a RecoveryExpr.
756+
if (isa_and_nonnull<RecoveryExpr>(Field->getInClassInitializer())) {
757+
if (Init < NumInits)
758+
ILE->setInit(Init, Field->getInClassInitializer());
759+
else
760+
ILE->updateInit(SemaRef.Context, Init,
761+
Field->getInClassInitializer());
762+
return;
763+
}
764+
753765
ExprResult DIE;
754766
{
755767
// Enter a default initializer rebuild context, then we can support

clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,14 @@ namespace nested_union {
115115
// of Test3, or we should exclude f(Test3) as a candidate.
116116
static_assert(f({1}) == 2, ""); // expected-error {{call to 'f' is ambiguous}}
117117
}
118+
119+
// Fix crash issue https://github.com/llvm/llvm-project/issues/112560.
120+
// Make sure clang compiles the following code without crashing:
121+
namespace GH112560 {
122+
union U {
123+
int f = ; // expected-error {{expected expression}}
124+
};
125+
void foo() {
126+
U g{};
127+
}
128+
} // namespace GH112560

0 commit comments

Comments
 (0)