Skip to content

Commit ad55392

Browse files
committed
Move binding of class symbols out of the parser
1 parent 2e70dd0 commit ad55392

File tree

4 files changed

+140
-131
lines changed

4 files changed

+140
-131
lines changed

src/parser/cxx/binder.cc

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,124 @@ void Binder::bind(EnumSpecifierAST* ast, const DeclSpecs& underlyingTypeSpecs) {
131131
}
132132
}
133133

134+
void Binder::bind(ElaboratedTypeSpecifierAST* ast, DeclSpecs& declSpecs) {
135+
auto className = get_name(control(), ast->unqualifiedId);
136+
const auto location = ast->unqualifiedId->firstSourceLocation();
137+
138+
const auto _ = ScopeGuard{this};
139+
140+
if (ast->nestedNameSpecifier) {
141+
auto parent = ast->nestedNameSpecifier->symbol;
142+
143+
if (parent && parent->isClassOrNamespace()) {
144+
setScope(static_cast<ScopedSymbol*>(parent));
145+
}
146+
}
147+
148+
ClassSymbol* classSymbol = nullptr;
149+
150+
if (scope()->isClassOrNamespaceScope()) {
151+
for (auto candidate : scope()->find(className) | views::classes) {
152+
classSymbol = candidate;
153+
break;
154+
}
155+
}
156+
157+
if (!classSymbol) {
158+
const auto isUnion = ast->classKey == TokenKind::T_UNION;
159+
classSymbol = control()->newClassSymbol(scope(), location);
160+
161+
classSymbol->setIsUnion(isUnion);
162+
classSymbol->setName(className);
163+
classSymbol->setTemplateParameters(currentTemplateParameters());
164+
declaringScope()->addSymbol(classSymbol);
165+
}
166+
167+
ast->symbol = classSymbol;
168+
169+
declSpecs.type = ast->symbol->type();
170+
}
171+
172+
void Binder::bind(ClassSpecifierAST* ast, DeclSpecs& specs) {
173+
auto templateParameters = currentTemplateParameters();
174+
175+
if (ast->nestedNameSpecifier) {
176+
auto parent = ast->nestedNameSpecifier->symbol;
177+
178+
if (parent && parent->isClassOrNamespace()) {
179+
setScope(static_cast<ScopedSymbol*>(parent));
180+
}
181+
}
182+
183+
auto className = get_name(control(), ast->unqualifiedId);
184+
auto templateId = ast_cast<SimpleTemplateIdAST>(ast->unqualifiedId);
185+
186+
auto location = ast->classLoc;
187+
if (templateId) {
188+
location = templateId->identifierLoc;
189+
} else if (ast->unqualifiedId) {
190+
location = ast->unqualifiedId->firstSourceLocation();
191+
}
192+
193+
ClassSymbol* primaryTemplate = nullptr;
194+
195+
if (templateId && scope()->isTemplateParametersScope()) {
196+
for (auto candidate : declaringScope()->find(className) | views::classes) {
197+
primaryTemplate = candidate;
198+
break;
199+
}
200+
201+
if (!primaryTemplate) {
202+
error(location, std::format("specialization of undeclared template '{}'",
203+
templateId->identifier->name()));
204+
}
205+
}
206+
207+
ClassSymbol* classSymbol = nullptr;
208+
209+
if (className) {
210+
for (auto candidate : declaringScope()->find(className) | views::classes) {
211+
classSymbol = candidate;
212+
break;
213+
}
214+
}
215+
216+
if (classSymbol && classSymbol->isComplete()) {
217+
classSymbol = nullptr;
218+
}
219+
220+
if (!classSymbol) {
221+
const auto isUnion = ast->classKey == TokenKind::T_UNION;
222+
classSymbol = control()->newClassSymbol(scope(), location);
223+
classSymbol->setIsUnion(isUnion);
224+
classSymbol->setName(className);
225+
classSymbol->setTemplateParameters(templateParameters);
226+
227+
if (!primaryTemplate) {
228+
declaringScope()->addSymbol(classSymbol);
229+
} else {
230+
std::vector<TemplateArgument> arguments;
231+
// TODO: parse template arguments
232+
primaryTemplate->addSpecialization(arguments, classSymbol);
233+
}
234+
}
235+
236+
classSymbol->setFinal(ast->isFinal);
237+
238+
ast->symbol = classSymbol;
239+
}
240+
241+
void Binder::complete(ClassSpecifierAST* ast) {
242+
if (!inTemplate()) {
243+
auto status = ast->symbol->buildClassLayout(control());
244+
if (!status.has_value()) {
245+
error(ast->symbol->location(), status.error());
246+
}
247+
}
248+
249+
ast->symbol->setComplete(true);
250+
}
251+
134252
void Binder::bind(ParameterDeclarationAST* ast, const Decl& decl,
135253
bool inTemplateParameters) {
136254
ast->type = getDeclaratorType(unit_, ast->declarator, decl.specs.getType());

src/parser/cxx/binder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ class Binder {
8787

8888
void bind(EnumSpecifierAST* ast, const DeclSpecs& underlyingTypeSpec);
8989

90+
void bind(ElaboratedTypeSpecifierAST* ast, DeclSpecs& declSpecs);
91+
92+
void bind(ClassSpecifierAST* ast, DeclSpecs& declSpecs);
93+
94+
void complete(ClassSpecifierAST* ast);
95+
9096
void bind(EnumeratorAST* ast, const Type* type,
9197
std::optional<ConstValue> value);
9298

src/parser/cxx/parser.cc

Lines changed: 15 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -5363,39 +5363,7 @@ auto Parser::parse_elaborated_type_specifier(
53635363
className = nameId->identifier;
53645364
}
53655365

5366-
const auto location = ast->unqualifiedId->firstSourceLocation();
5367-
5368-
const auto _ = Binder::ScopeGuard{&binder_};
5369-
5370-
if (ast->nestedNameSpecifier) {
5371-
auto parent = ast->nestedNameSpecifier->symbol;
5372-
5373-
if (parent && parent->isClassOrNamespace()) {
5374-
setScope(static_cast<ScopedSymbol*>(parent));
5375-
}
5376-
}
5377-
5378-
ClassSymbol* classSymbol = nullptr;
5379-
5380-
if (scope()->isClassOrNamespaceScope()) {
5381-
for (auto candidate : scope()->find(className) | views::classes) {
5382-
classSymbol = candidate;
5383-
break;
5384-
}
5385-
}
5386-
5387-
if (!classSymbol) {
5388-
const auto isUnion = classKey == TokenKind::T_UNION;
5389-
classSymbol = control_->newClassSymbol(scope(), location);
5390-
5391-
classSymbol->setIsUnion(isUnion);
5392-
classSymbol->setName(className);
5393-
classSymbol->setTemplateParameters(binder_.currentTemplateParameters());
5394-
binder_.declaringScope()->addSymbol(classSymbol);
5395-
}
5396-
5397-
ast->symbol = classSymbol;
5398-
specs.type = classSymbol->type();
5366+
binder_.bind(ast, specs);
53995367

54005368
return true;
54015369
}
@@ -6014,51 +5982,35 @@ auto Parser::parse_parameter_declaration_clause(
60145982

60155983
auto _ = Binder::ScopeGuard{&binder_};
60165984

6017-
bool parsed = false;
6018-
6019-
SourceLocation ellipsisLoc;
6020-
FunctionParametersSymbol* functionParametersSymbol = nullptr;
6021-
6022-
if (match(TokenKind::T_DOT_DOT_DOT, ellipsisLoc)) {
6023-
parsed = true;
5985+
auto ast = make_node<ParameterDeclarationClauseAST>(pool_);
5986+
ast->functionParametersSymbol =
5987+
control_->newFunctionParametersSymbol(scope(), {});
60245988

6025-
auto ast = make_node<ParameterDeclarationClauseAST>(pool_);
5989+
if (match(TokenKind::T_DOT_DOT_DOT, ast->ellipsisLoc)) {
60265990
yyast = ast;
60275991

6028-
ast->ellipsisLoc = ellipsisLoc;
60295992
ast->isVariadic = true;
6030-
ast->functionParametersSymbol =
6031-
control_->newFunctionParametersSymbol(scope(), {});
6032-
} else if (List<ParameterDeclarationAST*>* parameterDeclarationList = nullptr;
6033-
parse_parameter_declaration_list(parameterDeclarationList,
6034-
functionParametersSymbol)) {
6035-
parsed = true;
6036-
6037-
auto ast = make_node<ParameterDeclarationClauseAST>(pool_);
5993+
} else if (parse_parameter_declaration_list(ast)) {
60385994
yyast = ast;
6039-
ast->parameterDeclarationList = parameterDeclarationList;
5995+
60405996
match(TokenKind::T_COMMA, ast->commaLoc);
60415997
ast->isVariadic = match(TokenKind::T_DOT_DOT_DOT, ast->ellipsisLoc);
6042-
ast->functionParametersSymbol = functionParametersSymbol;
6043-
} else {
6044-
parsed = false;
60455998
}
60465999

6000+
const auto parsed = yyast != nullptr;
6001+
60476002
parameter_declaration_clauses_.set(start, currentLocation(), yyast, parsed);
60486003

60496004
return parsed;
60506005
}
60516006

60526007
auto Parser::parse_parameter_declaration_list(
6053-
List<ParameterDeclarationAST*>*& yyast,
6054-
FunctionParametersSymbol*& functionParametersSymbol) -> bool {
6055-
auto it = &yyast;
6008+
ParameterDeclarationClauseAST* ast) -> bool {
6009+
auto it = &ast->parameterDeclarationList;
60566010

60576011
auto _ = Binder::ScopeGuard{&binder_};
60586012

6059-
functionParametersSymbol = control_->newFunctionParametersSymbol(scope(), {});
6060-
6061-
setScope(functionParametersSymbol);
6013+
setScope(ast->functionParametersSymbol);
60626014

60636015
ParameterDeclarationAST* declaration = nullptr;
60646016

@@ -7794,72 +7746,13 @@ auto Parser::parse_class_specifier(
77947746
ast->isFinal = true;
77957747
}
77967748

7797-
auto _ = Binder::ScopeGuard{&binder_};
7798-
77997749
if (scope()->isTemplateParametersScope()) {
78007750
mark_maybe_template_name(unqualifiedId);
78017751
}
78027752

7803-
auto templateParameters = binder_.currentTemplateParameters();
7804-
7805-
if (nestedNameSpecifier) {
7806-
auto parent = nestedNameSpecifier->symbol;
7753+
binder_.bind(ast, specs);
78077754

7808-
if (parent && parent->isClassOrNamespace()) {
7809-
setScope(static_cast<ScopedSymbol*>(parent));
7810-
}
7811-
}
7812-
7813-
ClassSymbol* primaryTemplate = nullptr;
7814-
7815-
if (templateId && scope()->isTemplateParametersScope()) {
7816-
for (auto candidate :
7817-
binder_.declaringScope()->find(className) | views::classes) {
7818-
primaryTemplate = candidate;
7819-
break;
7820-
}
7821-
7822-
if (!primaryTemplate && config_.checkTypes) {
7823-
parse_error(location,
7824-
std::format("specialization of undeclared template '{}'",
7825-
className->name()));
7826-
}
7827-
}
7828-
7829-
ClassSymbol* classSymbol = nullptr;
7830-
7831-
if (className) {
7832-
for (auto candidate :
7833-
binder_.declaringScope()->find(className) | views::classes) {
7834-
classSymbol = candidate;
7835-
break;
7836-
}
7837-
}
7838-
7839-
if (classSymbol && classSymbol->isComplete()) {
7840-
classSymbol = nullptr;
7841-
}
7842-
7843-
if (!classSymbol) {
7844-
classSymbol = control_->newClassSymbol(scope(), location);
7845-
classSymbol->setIsUnion(isUnion);
7846-
classSymbol->setName(className);
7847-
classSymbol->setTemplateParameters(templateParameters);
7848-
7849-
if (!primaryTemplate) {
7850-
binder_.declaringScope()->addSymbol(classSymbol);
7851-
} else {
7852-
std::vector<TemplateArgument> arguments;
7853-
// TODO: parse template arguments
7854-
primaryTemplate->addSpecialization(arguments, classSymbol);
7855-
}
7856-
}
7857-
7858-
if (finalLoc) {
7859-
classSymbol->setFinal(true);
7860-
}
7861-
7862-
ast->symbol = classSymbol;
7755+
auto _ = Binder::ScopeGuard{&binder_};
78637756

78647757
setScope(ast->symbol);
78657758

@@ -7874,14 +7767,7 @@ auto Parser::parse_class_specifier(
78747767
expect(TokenKind::T_RBRACE, ast->rbraceLoc);
78757768
}
78767769

7877-
if (!binder_.inTemplate()) {
7878-
auto status = classSymbol->buildClassLayout(control_);
7879-
if (!status.has_value() && config_.checkTypes) {
7880-
parse_error(classSymbol->location(), status.error());
7881-
}
7882-
}
7883-
7884-
classSymbol->setComplete(true);
7770+
binder_.complete(ast);
78857771

78867772
return true;
78877773
}

src/parser/cxx/parser.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -540,8 +540,7 @@ class Parser final {
540540
[[nodiscard]] auto parse_parameter_declaration_clause(
541541
ParameterDeclarationClauseAST*& yyast) -> bool;
542542
[[nodiscard]] auto parse_parameter_declaration_list(
543-
List<ParameterDeclarationAST*>*& yyast,
544-
FunctionParametersSymbol*& functionParametersSymbol) -> bool;
543+
ParameterDeclarationClauseAST* ast) -> bool;
545544
[[nodiscard]] auto parse_parameter_declaration(
546545
ParameterDeclarationAST*& yyast, bool templParam) -> bool;
547546
[[nodiscard]] auto parse_initializer(ExpressionAST*& yyast,

0 commit comments

Comments
 (0)