Skip to content

Commit 4abd830

Browse files
committed
Lookup of fields in anonymous nested structs and unions
Fixes #591 Signed-off-by: Roberto Raggi <[email protected]>
1 parent 3dc6d0e commit 4abd830

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

src/parser/cxx/name_lookup.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,19 @@ auto Lookup::lookupHelper(Scope* scope, const Name* name,
144144
}
145145

146146
if (auto classSymbol = symbol_cast<ClassSymbol>(scope->owner())) {
147+
// iterate over the annonymous nested structs and unions
148+
for (auto member : classSymbol->scope()->symbols()) {
149+
if (member->name()) continue; // skip named members
150+
if (!member->isClass()) continue; // skip non-class members
151+
auto nestedClass = symbol_cast<ClassSymbol>(member);
152+
auto symbol = lookupHelper(nestedClass->scope(), name, cache, accept);
153+
154+
if (symbol) {
155+
// found a match in an anonymous nested class
156+
return symbol;
157+
}
158+
}
159+
147160
for (const auto& base : classSymbol->baseClasses()) {
148161
auto baseClass = symbol_cast<ClassSymbol>(base->symbol());
149162
if (!baseClass) continue;

src/parser/cxx/parser.cc

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7749,12 +7749,6 @@ auto Parser::parse_class_specifier(ClassSpecifierAST*& yyast, DeclSpecs& specs)
77497749
SourceLocation classLoc;
77507750
if (!parse_class_key(classLoc)) return false;
77517751

7752-
auto globalScopeGuard = Binder::ScopeGuard{&binder_};
7753-
7754-
if (is_parsing_c()) {
7755-
setScope(getCurrentNonClassScope());
7756-
}
7757-
77587752
List<AttributeSpecifierAST*>* attributeList = nullptr;
77597753
NestedNameSpecifierAST* nestedNameSpecifier = nullptr;
77607754
UnqualifiedIdAST* unqualifiedId = nullptr;
@@ -7809,6 +7803,15 @@ auto Parser::parse_class_specifier(ClassSpecifierAST*& yyast, DeclSpecs& specs)
78097803

78107804
if (!lookat_class_head()) return false;
78117805

7806+
auto globalScopeGuard = Binder::ScopeGuard{&binder_};
7807+
7808+
if (is_parsing_c()) {
7809+
if (unqualifiedId) {
7810+
// declared named structs in the enclosed non-class scope in C mode
7811+
setScope(getCurrentNonClassScope());
7812+
}
7813+
}
7814+
78127815
auto ast = make_node<ClassSpecifierAST>(pool_);
78137816
yyast = ast;
78147817

src/parser/cxx/type_checker.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,7 @@ auto TypeChecker::Visitor::check_member_access(MemberExpressionAST* ast)
21242124
} else {
21252125
(void)ensure_prvalue(ast->baseExpression);
21262126
objectType = ast->baseExpression->type;
2127+
cv1 = strip_cv(objectType);
21272128
}
21282129

21292130
auto pointerType = type_cast<PointerType>(objectType);

tests/unit_tests/sema/class_02.cc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %cxx -verify -fcheck %s
2+
3+
struct A {
4+
struct {
5+
int x;
6+
};
7+
union {
8+
int y;
9+
struct {
10+
int z;
11+
};
12+
};
13+
};
14+
15+
int main() {
16+
struct A a;
17+
(void)_Generic(a.x, int: 123);
18+
(void)_Generic(a.y, int: 321);
19+
(void)_Generic(a.z, int: 444);
20+
}

0 commit comments

Comments
 (0)