[clang] [clang] Inject IndirectFieldDecl even if name conflicts. (PR #153140)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 11 22:52:37 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (keinflue)
<details>
<summary>Changes</summary>
This modifies InjectAnonymousStructOrUnionMembers to inject an IndirectFieldDecl and mark it invalid even if its name conflicts with another name in the scope.
This resolves a crash on a further diagnostic diag::err_multiple_mem_union_initialization which via findDefaultInitializer relies on these declarations being present.
Fixes #<!-- -->149985
---
Full diff: https://github.com/llvm/llvm-project/pull/153140.diff
4 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+2)
- (modified) clang/lib/Sema/SemaDecl.cpp (+32-28)
- (modified) clang/test/CXX/class/class.mem/p13.cpp (+1-1)
- (modified) clang/test/CXX/class/class.union/class.union.anon/p4.cpp (+10)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0e9fcaa5fac6a..00b21471f3731 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -184,6 +184,8 @@ Bug Fixes to C++ Support
(``[[assume(expr)]]``) creates temporary objects.
- Fix the dynamic_cast to final class optimization to correctly handle
casts that are guaranteed to fail (#GH137518).
+- Fix a crash if errors "member of anonymous [...] redeclares" and
+ "intializing multiple members of union" coincide (#GH149985).
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index b5eb825eb52cc..052e026fa3ee3 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -5463,40 +5463,44 @@ InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, DeclContext *Owner,
// distinct from the names of any other entity in the
// scope in which the anonymous union is declared.
Invalid = true;
- } else {
- // C++ [class.union]p2:
- // For the purpose of name lookup, after the anonymous union
- // definition, the members of the anonymous union are
- // considered to have been defined in the scope in which the
- // anonymous union is declared.
- unsigned OldChainingSize = Chaining.size();
- if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD))
- Chaining.append(IF->chain_begin(), IF->chain_end());
- else
- Chaining.push_back(VD);
+ }
+ // Inject the IndirectFieldDecl even if invalid, because later
+ // diagnostics may depend on it being present.
+
+ // C++ [class.union]p2:
+ // For the purpose of name lookup, after the anonymous union
+ // definition, the members of the anonymous union are
+ // considered to have been defined in the scope in which the
+ // anonymous union is declared.
+ unsigned OldChainingSize = Chaining.size();
+ if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD))
+ Chaining.append(IF->chain_begin(), IF->chain_end());
+ else
+ Chaining.push_back(VD);
- assert(Chaining.size() >= 2);
- NamedDecl **NamedChain =
- new (SemaRef.Context)NamedDecl*[Chaining.size()];
- for (unsigned i = 0; i < Chaining.size(); i++)
- NamedChain[i] = Chaining[i];
+ assert(Chaining.size() >= 2);
+ NamedDecl **NamedChain =
+ new (SemaRef.Context) NamedDecl *[Chaining.size()];
+ for (unsigned i = 0; i < Chaining.size(); i++)
+ NamedChain[i] = Chaining[i];
- IndirectFieldDecl *IndirectField = IndirectFieldDecl::Create(
- SemaRef.Context, Owner, VD->getLocation(), VD->getIdentifier(),
- VD->getType(), {NamedChain, Chaining.size()});
+ IndirectFieldDecl *IndirectField = IndirectFieldDecl::Create(
+ SemaRef.Context, Owner, VD->getLocation(), VD->getIdentifier(),
+ VD->getType(), {NamedChain, Chaining.size()});
- for (const auto *Attr : VD->attrs())
- IndirectField->addAttr(Attr->clone(SemaRef.Context));
+ for (const auto *Attr : VD->attrs())
+ IndirectField->addAttr(Attr->clone(SemaRef.Context));
- IndirectField->setAccess(AS);
- IndirectField->setImplicit();
- SemaRef.PushOnScopeChains(IndirectField, S);
+ IndirectField->setAccess(AS);
+ IndirectField->setImplicit();
+ IndirectField->setInvalidDecl(Invalid);
+ SemaRef.PushOnScopeChains(IndirectField, S);
- // That includes picking up the appropriate access specifier.
- if (AS != AS_none) IndirectField->setAccess(AS);
+ // That includes picking up the appropriate access specifier.
+ if (AS != AS_none)
+ IndirectField->setAccess(AS);
- Chaining.resize(OldChainingSize);
- }
+ Chaining.resize(OldChainingSize);
}
}
diff --git a/clang/test/CXX/class/class.mem/p13.cpp b/clang/test/CXX/class/class.mem/p13.cpp
index d947586c41940..4dc959cd0beb8 100644
--- a/clang/test/CXX/class/class.mem/p13.cpp
+++ b/clang/test/CXX/class/class.mem/p13.cpp
@@ -63,7 +63,7 @@ struct X4 { // expected-note{{previous}}
int X;
union {
float Y;
- unsigned X4; // expected-error{{redeclares 'X4'}}
+ unsigned X4; // expected-error{{redeclares 'X4'}} expected-error {{'X4' has the same name as its class}}
};
};
};
diff --git a/clang/test/CXX/class/class.union/class.union.anon/p4.cpp b/clang/test/CXX/class/class.union/class.union.anon/p4.cpp
index a12ec38503fa8..710636d2235db 100644
--- a/clang/test/CXX/class/class.union/class.union.anon/p4.cpp
+++ b/clang/test/CXX/class/class.union/class.union.anon/p4.cpp
@@ -8,3 +8,13 @@ union U {
int y = 1; // expected-error {{initializing multiple members of union}}
};
};
+
+namespace GH149985 {
+ union U {
+ int x; // expected-note {{previous declaration is here}}
+ union {
+ int x = {}; // expected-error {{member of anonymous union redeclares}} expected-note {{previous initialization is here}}
+ };
+ int y = {}; // expected-error {{initializing multiple members of union}}
+ };
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/153140
More information about the cfe-commits
mailing list