Skip to content

Commit

Permalink
fix: Parse of class virt specifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
robertoraggi committed Aug 20, 2023
1 parent 606acd5 commit 97cb51e
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 37 deletions.
11 changes: 7 additions & 4 deletions packages/cxx-frontend/src/AST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2976,19 +2976,22 @@ export class ClassSpecifierAST extends SpecifierAST {
getName(): NameAST | undefined {
return AST.from<NameAST>(cxx.getASTSlot(this.getHandle(), 2), this.parser);
}
getFinalToken(): Token | undefined {
return Token.from(cxx.getASTSlot(this.getHandle(), 3), this.parser);
}
getBaseClause(): BaseClauseAST | undefined {
return AST.from<BaseClauseAST>(cxx.getASTSlot(this.getHandle(), 3), this.parser);
return AST.from<BaseClauseAST>(cxx.getASTSlot(this.getHandle(), 4), this.parser);
}
getLbraceToken(): Token | undefined {
return Token.from(cxx.getASTSlot(this.getHandle(), 4), this.parser);
return Token.from(cxx.getASTSlot(this.getHandle(), 5), this.parser);
}
*getDeclarationList(): Generator<DeclarationAST | undefined> {
for (let it = cxx.getASTSlot(this.getHandle(), 5); it; it = cxx.getListNext(it)) {
for (let it = cxx.getASTSlot(this.getHandle(), 6); it; it = cxx.getListNext(it)) {
yield AST.from<DeclarationAST>(cxx.getListValue(it), this.parser);
}
}
getRbraceToken(): Token | undefined {
return Token.from(cxx.getASTSlot(this.getHandle(), 6), this.parser);
return Token.from(cxx.getASTSlot(this.getHandle(), 7), this.parser);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/frontend/cxx/ast_printer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,10 @@ void ASTPrinter::visit(EnumSpecifierAST* ast) {

void ASTPrinter::visit(ClassSpecifierAST* ast) {
fmt::print(out_, "{}\n", "class-specifier");
++indent_;
fmt::print(out_, "{:{}}", "", indent_ * 2);
fmt::print(out_, "is-final: {}\n", ast->isFinal);
--indent_;
if (ast->attributeList) {
++indent_;
fmt::print(out_, "{:{}}", "", indent_ * 2);
Expand Down
2 changes: 2 additions & 0 deletions src/parser/cxx/ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2576,6 +2576,7 @@ auto ClassSpecifierAST::firstSourceLocation() -> SourceLocation {
if (auto loc = cxx::firstSourceLocation(classLoc)) return loc;
if (auto loc = cxx::firstSourceLocation(attributeList)) return loc;
if (auto loc = cxx::firstSourceLocation(name)) return loc;
if (auto loc = cxx::firstSourceLocation(finalLoc)) return loc;
if (auto loc = cxx::firstSourceLocation(baseClause)) return loc;
if (auto loc = cxx::firstSourceLocation(lbraceLoc)) return loc;
if (auto loc = cxx::firstSourceLocation(declarationList)) return loc;
Expand All @@ -2588,6 +2589,7 @@ auto ClassSpecifierAST::lastSourceLocation() -> SourceLocation {
if (auto loc = cxx::lastSourceLocation(declarationList)) return loc;
if (auto loc = cxx::lastSourceLocation(lbraceLoc)) return loc;
if (auto loc = cxx::lastSourceLocation(baseClause)) return loc;
if (auto loc = cxx::lastSourceLocation(finalLoc)) return loc;
if (auto loc = cxx::lastSourceLocation(name)) return loc;
if (auto loc = cxx::lastSourceLocation(attributeList)) return loc;
if (auto loc = cxx::lastSourceLocation(classLoc)) return loc;
Expand Down
1 change: 1 addition & 0 deletions src/parser/cxx/ast.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,7 @@ table ClassSpecifier /* SpecifierAST */ {
base_clause: BaseClause;
declaration_list: [Declaration];
class_loc: SourceLocation;
final_loc: SourceLocation;
lbrace_loc: SourceLocation;
rbrace_loc: SourceLocation;
}
Expand Down
2 changes: 2 additions & 0 deletions src/parser/cxx/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -2788,10 +2788,12 @@ class ClassSpecifierAST final : public SpecifierAST {
SourceLocation classLoc;
List<AttributeSpecifierAST*>* attributeList = nullptr;
NameAST* name = nullptr;
SourceLocation finalLoc;
BaseClauseAST* baseClause = nullptr;
SourceLocation lbraceLoc;
List<DeclarationAST*>* declarationList = nullptr;
SourceLocation rbraceLoc;
bool isFinal = false;

void accept(ASTVisitor* visitor) override { visitor->visit(this); }

Expand Down
4 changes: 4 additions & 0 deletions src/parser/cxx/ast_cloner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3110,6 +3110,8 @@ void ASTCloner::visit(ClassSpecifierAST* ast) {

copy->name = accept(ast->name);

copy->finalLoc = ast->finalLoc;

copy->baseClause = accept(ast->baseClause);

copy->lbraceLoc = ast->lbraceLoc;
Expand All @@ -3124,6 +3126,8 @@ void ASTCloner::visit(ClassSpecifierAST* ast) {
}

copy->rbraceLoc = ast->rbraceLoc;

copy->isFinal = ast->isFinal;
}

void ASTCloner::visit(TypenameSpecifierAST* ast) {
Expand Down
3 changes: 3 additions & 0 deletions src/parser/cxx/ast_encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4475,6 +4475,8 @@ void ASTEncoder::visit(ClassSpecifierAST* ast) {

const auto [name, nameType] = acceptName(ast->name);

auto finalLoc = encodeSourceLocation(ast->finalLoc);

const auto baseClause = accept(ast->baseClause);

auto lbraceLoc = encodeSourceLocation(ast->lbraceLoc);
Expand All @@ -4500,6 +4502,7 @@ void ASTEncoder::visit(ClassSpecifierAST* ast) {
builder.add_attribute_list_type(attributeListTypesVector);
builder.add_name(name);
builder.add_name_type(static_cast<io::Name>(nameType));
builder.add_final_loc(finalLoc.o);
builder.add_base_clause(baseClause.o);
builder.add_lbrace_loc(lbraceLoc.o);
builder.add_declaration_list(declarationListOffsetsVector);
Expand Down
12 changes: 8 additions & 4 deletions src/parser/cxx/ast_slot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3539,24 +3539,28 @@ void ASTSlot::visit(ClassSpecifierAST* ast) {
slotKind_ = ASTSlotKind::kNode;
break;
case 3:
value_ = ast->finalLoc.index();
slotKind_ = ASTSlotKind::kToken;
break;
case 4:
value_ = reinterpret_cast<std::intptr_t>(ast->baseClause);
slotKind_ = ASTSlotKind::kNode;
break;
case 4:
case 5:
value_ = ast->lbraceLoc.index();
slotKind_ = ASTSlotKind::kToken;
break;
case 5:
case 6:
value_ = reinterpret_cast<std::intptr_t>(ast->declarationList);
slotKind_ = ASTSlotKind::kNodeList;
break;
case 6:
case 7:
value_ = ast->rbraceLoc.index();
slotKind_ = ASTSlotKind::kToken;
break;
} // switch

slotCount_ = 7;
slotCount_ = 8;
}

void ASTSlot::visit(TypenameSpecifierAST* ast) {
Expand Down
56 changes: 33 additions & 23 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,16 +237,11 @@ auto Parser::parse(UnitAST*& ast) -> bool {
return parsed;
}

auto Parser::parse_id(const Identifier* id) -> bool {
SourceLocation identifierLoc;
return parse_id(id, identifierLoc);
}

auto Parser::parse_id(const Identifier* id, SourceLocation& loc) -> bool {
SourceLocation location;
if (!match(TokenKind::T_IDENTIFIER, location)) return false;
if (unit->identifier(location) != id) return false;
loc = location;
loc = {};
if (LA().isNot(TokenKind::T_IDENTIFIER)) return false;
if (unit->identifier(currentLocation()) != id)return false;
loc = consumeToken();
return true;
}

Expand Down Expand Up @@ -336,9 +331,13 @@ auto Parser::parse_module_keyword(SourceLocation& loc) -> bool {
return true;
}

auto Parser::parse_final() -> bool { return parse_id(final_id); }
auto Parser::parse_final(SourceLocation& loc) -> bool {
return parse_id(final_id, loc);
}

auto Parser::parse_override() -> bool { return parse_id(override_id); }
auto Parser::parse_override(SourceLocation& loc) -> bool {
return parse_id(override_id, loc);
}

auto Parser::parse_type_name(NameAST*& yyast) -> bool {
const auto start = currentLocation();
Expand Down Expand Up @@ -468,7 +467,9 @@ auto Parser::parse_module_head() -> bool {

match(TokenKind::T_EXPORT, exportLoc);

const auto is_module = parse_id(module_id);
SourceLocation moduleLoc;

const auto is_module = parse_id(module_id, moduleLoc);

rewind(start);

Expand Down Expand Up @@ -5405,9 +5406,11 @@ auto Parser::parse_expr_or_braced_init_list(ExpressionAST*& yyast) -> bool {
}

auto Parser::parse_virt_specifier_seq() -> bool {
if (!parse_virt_specifier()) return false;
SourceLocation finalLoc;

if (!parse_virt_specifier(finalLoc)) return false;

while (parse_virt_specifier()) {
while (parse_virt_specifier(finalLoc)) {
//
}

Expand Down Expand Up @@ -6624,8 +6627,10 @@ auto Parser::parse_class_specifier(SpecifierAST*& yyast) -> bool {
List<AttributeSpecifierAST*>* attributeList = nullptr;
NameAST* className = nullptr;
BaseClauseAST* baseClause = nullptr;
SourceLocation finalLoc;

if (!parse_class_head(classLoc, attributeList, className, baseClause)) {
if (!parse_class_head(classLoc, attributeList, className, finalLoc,
baseClause)) {
class_specifiers_.emplace(
start,
std::make_tuple(currentLocation(),
Expand All @@ -6651,9 +6656,14 @@ auto Parser::parse_class_specifier(SpecifierAST*& yyast) -> bool {
ast->classLoc = classLoc;
ast->attributeList = attributeList;
ast->name = className;
ast->finalLoc = finalLoc;
ast->baseClause = baseClause;
ast->lbraceLoc = lbraceLoc;

if (finalLoc) {
ast->isFinal = true;
}

if (!match(TokenKind::T_RBRACE, ast->rbraceLoc)) {
if (!parse_class_body(ast->declarationList)) {
parse_error("expected class body");
Expand Down Expand Up @@ -6700,14 +6710,14 @@ auto Parser::parse_class_body(List<DeclarationAST*>*& yyast) -> bool {

auto Parser::parse_class_head(SourceLocation& classLoc,
List<AttributeSpecifierAST*>*& attributeList,
NameAST*& name, BaseClauseAST*& baseClause)
-> bool {
NameAST*& name, SourceLocation& finalLoc,
BaseClauseAST*& baseClause) -> bool {
if (!parse_class_key(classLoc)) return false;

parse_attribute_specifier_seq(attributeList);

if (parse_class_head_name(name)) {
parse_class_virt_specifier();
parse_class_virt_specifier(finalLoc);
}

parse_base_clause(baseClause);
Expand All @@ -6733,8 +6743,8 @@ auto Parser::parse_class_head_name(NameAST*& yyast) -> bool {
return true;
}

auto Parser::parse_class_virt_specifier() -> bool {
if (!parse_final()) return false;
auto Parser::parse_class_virt_specifier(SourceLocation& finalLoc) -> bool {
if (!parse_final(finalLoc)) return false;

return true;
}
Expand Down Expand Up @@ -7028,10 +7038,10 @@ auto Parser::parse_member_declarator(InitDeclaratorAST*& yyast,
return true;
}

auto Parser::parse_virt_specifier() -> bool {
if (parse_final()) return true;
auto Parser::parse_virt_specifier(SourceLocation& loc) -> bool {
if (parse_final(loc)) return true;

if (parse_override()) return true;
if (parse_override(loc)) return true;

return false;
}
Expand Down
12 changes: 6 additions & 6 deletions src/parser/cxx/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ class Parser final {
return true;
}

auto parse_id(const Identifier* id) -> bool;
auto parse_id(const Identifier* id, SourceLocation& loc) -> bool;
auto parse_nospace() -> bool;
auto parse_greater_greater() -> bool;
Expand All @@ -107,8 +106,8 @@ class Parser final {
auto parse_export_keyword(SourceLocation& loc) -> bool;
auto parse_import_keyword(SourceLocation& loc) -> bool;
auto parse_module_keyword(SourceLocation& loc) -> bool;
auto parse_final() -> bool;
auto parse_override() -> bool;
auto parse_final(SourceLocation& loc) -> bool;
auto parse_override(SourceLocation& loc) -> bool;
auto parse_name_id(NameAST*& yyast) -> bool;
auto parse_literal(ExpressionAST*& yyast) -> bool;
auto parse_translation_unit(UnitAST*& yyast) -> bool;
Expand Down Expand Up @@ -383,9 +382,10 @@ class Parser final {
auto parse_class_body(List<DeclarationAST*>*& yyast) -> bool;
auto parse_class_head(SourceLocation& classLoc,
List<AttributeSpecifierAST*>*& attributeList,
NameAST*& name, BaseClauseAST*& baseClause) -> bool;
NameAST*& name, SourceLocation& finalLoc,
BaseClauseAST*& baseClause) -> bool;
auto parse_class_head_name(NameAST*& yyast) -> bool;
auto parse_class_virt_specifier() -> bool;
auto parse_class_virt_specifier(SourceLocation& loc) -> bool;
auto parse_class_key(SourceLocation& classLoc) -> bool;
auto parse_member_specification(DeclarationAST*& yyast) -> bool;
auto parse_member_declaration(DeclarationAST*& yyast) -> bool;
Expand All @@ -395,7 +395,7 @@ class Parser final {
const DeclSpecs& specs) -> bool;
auto parse_member_declarator(InitDeclaratorAST*& yyast,
const DeclSpecs& specs) -> bool;
auto parse_virt_specifier() -> bool;
auto parse_virt_specifier(SourceLocation& loc) -> bool;
auto parse_pure_specifier() -> bool;
auto parse_conversion_function_id(NameAST*& yyast) -> bool;
auto parse_base_clause(BaseClauseAST*& yyast) -> bool;
Expand Down
6 changes: 6 additions & 0 deletions tests/unit_tests/ast/class_definition_01.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,25 @@ class DerivedClass3 : virtual public EmptyClass {};
// CHECK-NEXT: simple-declaration
// CHECK-NEXT: decl-specifier-list
// CHECK-NEXT: class-specifier
// CHECK-NEXT: is-final: false
// CHECK-NEXT: name: simple-name
// CHECK-NEXT: identifier: EmptyClass
// CHECK-NEXT: simple-declaration
// CHECK-NEXT: decl-specifier-list
// CHECK-NEXT: class-specifier
// CHECK-NEXT: is-final: false
// CHECK-NEXT: name: simple-name
// CHECK-NEXT: identifier: OtherEmptyClass
// CHECK-NEXT: simple-declaration
// CHECK-NEXT: decl-specifier-list
// CHECK-NEXT: class-specifier
// CHECK-NEXT: is-final: true
// CHECK-NEXT: name: simple-name
// CHECK-NEXT: identifier: FinalClass
// CHECK-NEXT: simple-declaration
// CHECK-NEXT: decl-specifier-list
// CHECK-NEXT: class-specifier
// CHECK-NEXT: is-final: false
// CHECK-NEXT: name: simple-name
// CHECK-NEXT: identifier: DerivedClass
// CHECK-NEXT: base-clause: base-clause
Expand All @@ -43,6 +47,7 @@ class DerivedClass3 : virtual public EmptyClass {};
// CHECK-NEXT: simple-declaration
// CHECK-NEXT: decl-specifier-list
// CHECK-NEXT: class-specifier
// CHECK-NEXT: is-final: false
// CHECK-NEXT: name: simple-name
// CHECK-NEXT: identifier: DerivedClass2
// CHECK-NEXT: base-clause: base-clause
Expand All @@ -56,6 +61,7 @@ class DerivedClass3 : virtual public EmptyClass {};
// CHECK-NEXT: simple-declaration
// CHECK-NEXT: decl-specifier-list
// CHECK-NEXT: class-specifier
// CHECK-NEXT: is-final: false
// CHECK-NEXT: name: simple-name
// CHECK-NEXT: identifier: DerivedClass3
// CHECK-NEXT: base-clause: base-clause
Expand Down

0 comments on commit 97cb51e

Please sign in to comment.