mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 19:06:44 +00:00
[clang] Fix a crash issue that caused by handling of fields with initializers in nested anonymous unions (#113049)
Fixes: https://github.com/llvm/llvm-project/issues/112560 This PR create an RecoveryExpr for invalid in-class-initializer. --------- Signed-off-by: yronglin <yronglin777@gmail.com>
This commit is contained in:
parent
cb4433b677
commit
740861d69c
@ -5314,7 +5314,7 @@ public:
|
||||
/// is complete.
|
||||
void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
|
||||
SourceLocation EqualLoc,
|
||||
Expr *Init);
|
||||
ExprResult Init);
|
||||
|
||||
/// Handle a C++ member initializer using parentheses syntax.
|
||||
MemInitResult
|
||||
|
@ -722,8 +722,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
|
||||
ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false,
|
||||
EqualLoc);
|
||||
|
||||
Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc,
|
||||
Init.get());
|
||||
Actions.ActOnFinishCXXInClassMemberInitializer(MI.Field, EqualLoc, Init);
|
||||
|
||||
// The next token should be our artificial terminating EOF token.
|
||||
if (Tok.isNot(tok::eof)) {
|
||||
|
@ -4074,24 +4074,28 @@ ExprResult Sema::ConvertMemberDefaultInitExpression(FieldDecl *FD,
|
||||
|
||||
void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
|
||||
SourceLocation InitLoc,
|
||||
Expr *InitExpr) {
|
||||
ExprResult InitExpr) {
|
||||
// Pop the notional constructor scope we created earlier.
|
||||
PopFunctionScopeInfo(nullptr, D);
|
||||
|
||||
FieldDecl *FD = dyn_cast<FieldDecl>(D);
|
||||
assert((isa<MSPropertyDecl>(D) || FD->getInClassInitStyle() != ICIS_NoInit) &&
|
||||
"must set init style when field is created");
|
||||
|
||||
if (!InitExpr) {
|
||||
// Microsoft C++'s property declaration cannot have a default member
|
||||
// initializer.
|
||||
if (isa<MSPropertyDecl>(D)) {
|
||||
D->setInvalidDecl();
|
||||
if (FD)
|
||||
FD->removeInClassInitializer();
|
||||
return;
|
||||
}
|
||||
|
||||
if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) {
|
||||
FieldDecl *FD = dyn_cast<FieldDecl>(D);
|
||||
assert((FD && FD->getInClassInitStyle() != ICIS_NoInit) &&
|
||||
"must set init style when field is created");
|
||||
|
||||
if (!InitExpr.isUsable() ||
|
||||
DiagnoseUnexpandedParameterPack(InitExpr.get(), UPPC_Initializer)) {
|
||||
FD->setInvalidDecl();
|
||||
FD->removeInClassInitializer();
|
||||
ExprResult RecoveryInit =
|
||||
CreateRecoveryExpr(InitLoc, InitLoc, {}, FD->getType());
|
||||
if (RecoveryInit.isUsable())
|
||||
FD->setInClassInitializer(RecoveryInit.get());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -5587,10 +5587,6 @@ static FieldDecl *FindFieldDeclInstantiationPattern(const ASTContext &Ctx,
|
||||
ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
|
||||
assert(Field->hasInClassInitializer());
|
||||
|
||||
// If we might have already tried and failed to instantiate, don't try again.
|
||||
if (Field->isInvalidDecl())
|
||||
return ExprError();
|
||||
|
||||
CXXThisScopeRAII This(*this, Field->getParent(), Qualifiers());
|
||||
|
||||
auto *ParentRD = cast<CXXRecordDecl>(Field->getParent());
|
||||
|
@ -745,6 +745,7 @@ void InitListChecker::FillInEmptyInitForField(unsigned Init, FieldDecl *Field,
|
||||
if (Field->hasInClassInitializer()) {
|
||||
if (VerifyOnly)
|
||||
return;
|
||||
|
||||
ExprResult DIE;
|
||||
{
|
||||
// Enter a default initializer rebuild context, then we can support
|
||||
|
@ -480,3 +480,37 @@ void RecoveryForStmtCond() {
|
||||
// CHECK-NEXT: `-CompoundStmt {{.*}}
|
||||
for (int i = 0; i < invalid; ++i) {}
|
||||
}
|
||||
|
||||
// Fix crash issue https://github.com/llvm/llvm-project/issues/112560.
|
||||
// Make sure clang compiles the following code without crashing:
|
||||
|
||||
// CHECK:NamespaceDecl {{.*}} GH112560
|
||||
// CHECK-NEXT: |-CXXRecordDecl {{.*}} referenced union U definition
|
||||
// CHECK-NEXT: | |-DefinitionData {{.*}}
|
||||
// CHECK-NEXT: | | |-DefaultConstructor {{.*}}
|
||||
// CHECK-NEXT: | | |-CopyConstructor {{.*}}
|
||||
// CHECK-NEXT: | | |-MoveConstructor {{.*}}
|
||||
// CHECK-NEXT: | | |-CopyAssignment {{.*}}
|
||||
// CHECK-NEXT: | | |-MoveAssignment {{.*}}
|
||||
// CHECK-NEXT: | | `-Destructor {{.*}}
|
||||
// CHECK-NEXT: | |-CXXRecordDecl {{.*}} implicit union U
|
||||
// CHECK-NEXT: | `-FieldDecl {{.*}} invalid f 'int'
|
||||
// CHECK-NEXT: | `-RecoveryExpr {{.*}} 'int' contains-errors
|
||||
// DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors
|
||||
namespace GH112560 {
|
||||
union U {
|
||||
int f = ;
|
||||
};
|
||||
|
||||
// CHECK: FunctionDecl {{.*}} foo 'void ()'
|
||||
// CHECK-NEXT: `-CompoundStmt {{.*}}
|
||||
// CHECK-NEXT: `-DeclStmt {{.*}}
|
||||
// CHECK-NEXT: `-VarDecl {{.*}} g 'U':'GH112560::U' listinit
|
||||
// CHECK-NEXT: `-InitListExpr {{.*}} 'U':'GH112560::U' contains-errors field Field {{.*}} 'f' 'int'
|
||||
// CHECK-NEXT: `-CXXDefaultInitExpr {{.*}} 'int' contains-errors has rewritten init
|
||||
// CHECK-NEXT: `-RecoveryExpr {{.*}} 'int' contains-errors
|
||||
// DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors
|
||||
void foo() {
|
||||
U g{};
|
||||
}
|
||||
} // namespace GH112560
|
||||
|
@ -115,3 +115,14 @@ namespace nested_union {
|
||||
// of Test3, or we should exclude f(Test3) as a candidate.
|
||||
static_assert(f({1}) == 2, ""); // expected-error {{call to 'f' is ambiguous}}
|
||||
}
|
||||
|
||||
// Fix crash issue https://github.com/llvm/llvm-project/issues/112560.
|
||||
// Make sure clang compiles the following code without crashing:
|
||||
namespace GH112560 {
|
||||
union U {
|
||||
int f = ; // expected-error {{expected expression}}
|
||||
};
|
||||
void foo() {
|
||||
U g{};
|
||||
}
|
||||
} // namespace GH112560
|
||||
|
Loading…
x
Reference in New Issue
Block a user