[clang] 740861d - [clang] Fix a crash issue that caused by handling of fields with initializers in nested anonymous unions (#113049)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 10 04:56:56 PST 2024
Author: yronglin
Date: 2024-12-10T20:56:52+08:00
New Revision: 740861d69c2d2988ed69bc264df73bc5ae9d9e49
URL: https://github.com/llvm/llvm-project/commit/740861d69c2d2988ed69bc264df73bc5ae9d9e49
DIFF: https://github.com/llvm/llvm-project/commit/740861d69c2d2988ed69bc264df73bc5ae9d9e49.diff
LOG: [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 at gmail.com>
Added:
Modified:
clang/include/clang/Sema/Sema.h
clang/lib/Parse/ParseCXXInlineMethods.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaInit.cpp
clang/test/AST/ast-dump-recovery.cpp
clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b8684d11460eda..ae07ed8478f2a8 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5314,7 +5314,7 @@ class Sema final : public SemaBase {
/// is complete.
void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
SourceLocation EqualLoc,
- Expr *Init);
+ ExprResult Init);
/// Handle a C++ member initializer using parentheses syntax.
MemInitResult
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index 2ec66fe95708e1..6c01af55ef3c46 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -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)) {
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index f7a0b3c059ec91..b2c5bb235c119c 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -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;
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 1524622408a18a..20bf6f7f6f28ff 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -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());
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 7c03a12e812809..5909457b04e663 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -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
diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp
index 43884622240269..b59fa3778192f9 100644
--- a/clang/test/AST/ast-dump-recovery.cpp
+++ b/clang/test/AST/ast-dump-recovery.cpp
@@ -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
diff --git a/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp
index 03a6800898d18f..8360b8fd7d8ee2 100644
--- a/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp
+++ b/clang/test/SemaCXX/cxx1y-initializer-aggregates.cpp
@@ -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
More information about the cfe-commits
mailing list