aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorkeinflue <keinflue@posteo.de>2025-08-15 18:43:29 +0200
committerGitHub <noreply@github.com>2025-08-15 09:43:29 -0700
commitaf96ed6bf6e6a1ba0cbb36cb3925dd44f41c301e (patch)
tree251d7fcec66f92b357b47056bd33bdfafea28e42 /clang/lib/Sema/SemaDecl.cpp
parent2c20a9bfb3ce7a22b040b4a2694f19beeb616cd0 (diff)
downloadllvm-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.cpp76
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);
}
}