Skip to content

Commit 75d0402

Browse files
committed
Improve handling of elaborated type specifiers
Signed-off-by: Roberto Raggi <[email protected]>
1 parent f33d561 commit 75d0402

File tree

1 file changed

+48
-21
lines changed

1 file changed

+48
-21
lines changed

src/parser/cxx/binder.cc

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,6 @@ void Binder::bind(ElaboratedTypeSpecifierAST* ast, DeclSpecs& declSpecs,
140140
bool isDeclaration) {
141141
const auto _ = ScopeGuard{this};
142142

143-
auto className = get_name(control(), ast->unqualifiedId);
144-
const auto location = ast->unqualifiedId->firstSourceLocation();
145-
146143
if (ast->nestedNameSpecifier) {
147144
auto parent = ast->nestedNameSpecifier->symbol;
148145

@@ -151,32 +148,62 @@ void Binder::bind(ElaboratedTypeSpecifierAST* ast, DeclSpecs& declSpecs,
151148
}
152149
}
153150

154-
ClassSymbol* classSymbol = nullptr;
151+
auto templateId = ast_cast<SimpleTemplateIdAST>(ast->unqualifiedId);
155152

156-
if (scope()->isClassOrNamespaceScope()) {
157-
for (auto candidate : scope()->find(className) | views::classes) {
158-
classSymbol = candidate;
159-
break;
153+
const Identifier* name = nullptr;
154+
if (templateId)
155+
name = templateId->identifier;
156+
else if (auto nameId = ast_cast<NameIdAST>(ast->unqualifiedId))
157+
name = nameId->identifier;
158+
159+
const auto location = ast->unqualifiedId->firstSourceLocation();
160+
161+
if (ast->classKey == TokenKind::T_CLASS ||
162+
ast->classKey == TokenKind::T_STRUCT ||
163+
ast->classKey == TokenKind::T_UNION) {
164+
auto is_class = [](Symbol* symbol) {
165+
if (symbol->isClass()) return true;
166+
return false;
167+
};
168+
169+
auto candidate =
170+
Lookup{scope()}.lookup(ast->nestedNameSpecifier, name, is_class);
171+
172+
auto classSymbol = symbol_cast<ClassSymbol>(candidate);
173+
174+
if (classSymbol) {
175+
// validate the resolved class symbol
176+
177+
if (isDeclaration) {
178+
// if the class is already declared, we need to check if the
179+
if (classSymbol->enclosingScope() != declaringScope()) {
180+
// the class is declared in a different scope
181+
classSymbol = nullptr;
182+
}
183+
}
160184
}
161-
}
162185

163-
if (!classSymbol) {
164-
const auto isUnion = ast->classKey == TokenKind::T_UNION;
165-
classSymbol = control()->newClassSymbol(scope(), location);
186+
if (!classSymbol) {
187+
const auto isUnion = ast->classKey == TokenKind::T_UNION;
188+
classSymbol = control()->newClassSymbol(scope(), location);
166189

167-
classSymbol->setIsUnion(isUnion);
168-
classSymbol->setName(className);
169-
classSymbol->setTemplateParameters(currentTemplateParameters());
170-
classSymbol->setTemplateDeclaration(declSpecs.templateHead);
171-
declaringScope()->addSymbol(classSymbol);
190+
classSymbol->setIsUnion(isUnion);
191+
classSymbol->setName(name);
192+
classSymbol->setTemplateParameters(currentTemplateParameters());
193+
classSymbol->setTemplateDeclaration(declSpecs.templateHead);
194+
declaringScope()->addSymbol(classSymbol);
172195

173-
classSymbol->setDeclaration(ast);
174-
}
196+
classSymbol->setDeclaration(ast);
197+
}
175198

176-
ast->symbol = classSymbol;
199+
ast->symbol = classSymbol;
200+
}
177201

178202
declSpecs.setTypeSpecifier(ast);
179-
declSpecs.setType(ast->symbol->type());
203+
204+
if (ast->symbol) {
205+
declSpecs.setType(ast->symbol->type());
206+
}
180207
}
181208

182209
void Binder::bind(ClassSpecifierAST* ast, DeclSpecs& declSpecs) {

0 commit comments

Comments
 (0)