diff options
author | keinflue <keinflue@posteo.de> | 2025-08-15 18:43:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-15 09:43:29 -0700 |
commit | af96ed6bf6e6a1ba0cbb36cb3925dd44f41c301e (patch) | |
tree | 251d7fcec66f92b357b47056bd33bdfafea28e42 /clang/lib/Sema/SemaDecl.cpp | |
parent | 2c20a9bfb3ce7a22b040b4a2694f19beeb616cd0 (diff) | |
download | llvm-af96ed6bf6e6a1ba0cbb36cb3925dd44f41c301e.zip llvm-af96ed6bf6e6a1ba0cbb36cb3925dd44f41c301e.tar.gz llvm-af96ed6bf6e6a1ba0cbb36cb3925dd44f41c301e.tar.bz2 |
[clang] Inject IndirectFieldDecl even if name conflicts. (#153140)
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
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 76 |
1 files changed, 41 insertions, 35 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6581d4c..5001e08 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5503,48 +5503,54 @@ InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, DeclContext *Owner, if ((isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) && cast<NamedDecl>(D)->getDeclName()) { ValueDecl *VD = cast<ValueDecl>(D); - if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(), - VD->getLocation(), AnonRecord->isUnion(), - SC)) { - // C++ [class.union]p2: - // The names of the members of an anonymous union shall be - // distinct from the names of any other entity in the - // scope in which the anonymous union is declared. + // C++ [class.union]p2: + // The names of the members of an anonymous union shall be + // distinct from the names of any other entity in the + // scope in which the anonymous union is declared. + + bool FieldInvalid = CheckAnonMemberRedeclaration( + SemaRef, S, Owner, VD->getDeclName(), VD->getLocation(), + AnonRecord->isUnion(), SC); + if (FieldInvalid) 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); - assert(Chaining.size() >= 2); - NamedDecl **NamedChain = - new (SemaRef.Context)NamedDecl*[Chaining.size()]; - for (unsigned i = 0; i < Chaining.size(); i++) - NamedChain[i] = Chaining[i]; + // Inject the IndirectFieldDecl even if invalid, because later + // diagnostics may depend on it being present, see findDefaultInitializer. + + // 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); - IndirectFieldDecl *IndirectField = IndirectFieldDecl::Create( - SemaRef.Context, Owner, VD->getLocation(), VD->getIdentifier(), - VD->getType(), {NamedChain, Chaining.size()}); + assert(Chaining.size() >= 2); + NamedDecl **NamedChain = + new (SemaRef.Context) NamedDecl *[Chaining.size()]; + for (unsigned i = 0; i < Chaining.size(); i++) + NamedChain[i] = Chaining[i]; - for (const auto *Attr : VD->attrs()) - IndirectField->addAttr(Attr->clone(SemaRef.Context)); + IndirectFieldDecl *IndirectField = IndirectFieldDecl::Create( + SemaRef.Context, Owner, VD->getLocation(), VD->getIdentifier(), + VD->getType(), {NamedChain, Chaining.size()}); - IndirectField->setAccess(AS); - IndirectField->setImplicit(); - SemaRef.PushOnScopeChains(IndirectField, S); + for (const auto *Attr : VD->attrs()) + IndirectField->addAttr(Attr->clone(SemaRef.Context)); - // That includes picking up the appropriate access specifier. - if (AS != AS_none) IndirectField->setAccess(AS); + IndirectField->setAccess(AS); + IndirectField->setImplicit(); + IndirectField->setInvalidDecl(FieldInvalid); + SemaRef.PushOnScopeChains(IndirectField, S); - Chaining.resize(OldChainingSize); - } + // That includes picking up the appropriate access specifier. + if (AS != AS_none) + IndirectField->setAccess(AS); + + Chaining.resize(OldChainingSize); } } |