From e046792d013b2ce27d7abf71522e171946080369 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Sun, 13 Jul 2025 14:51:12 +0200 Subject: [PATCH 1/2] Parse C _Atomic qualifier and type qualifiers in array declarators --- packages/cxx-frontend/src/AST.ts | 56 +++++++- packages/cxx-frontend/src/ASTKind.ts | 1 + packages/cxx-frontend/src/ASTSlot.ts | 35 ++--- packages/cxx-frontend/src/ASTVisitor.ts | 12 ++ .../cxx-frontend/src/RecursiveASTVisitor.ts | 11 ++ src/mlir/cxx/mlir/codegen.cc | 7 + src/parser/cxx/ast.cc | 13 ++ src/parser/cxx/ast.fbs | 6 + src/parser/cxx/ast.h | 19 +++ src/parser/cxx/ast_fwd.h | 1 + src/parser/cxx/ast_interpreter.cc | 7 + src/parser/cxx/ast_kind.h | 1 + src/parser/cxx/ast_pretty_printer.cc | 13 ++ src/parser/cxx/ast_printer.cc | 13 ++ src/parser/cxx/ast_printer.h | 1 + src/parser/cxx/ast_rewriter.cc | 21 +++ src/parser/cxx/ast_slot.cc | 122 ++++++++++-------- src/parser/cxx/ast_slot.h | 1 + src/parser/cxx/ast_visitor.cc | 5 + src/parser/cxx/ast_visitor.h | 1 + src/parser/cxx/decl_specs.cc | 5 + src/parser/cxx/decl_specs.h | 1 + src/parser/cxx/flatbuffers/ast_decoder.cc | 21 +++ src/parser/cxx/flatbuffers/ast_encoder.cc | 24 ++++ src/parser/cxx/parser.cc | 41 +++++- src/parser/cxx/parser.h | 2 + src/parser/cxx/private/ast_decoder.h | 2 + src/parser/cxx/private/ast_encoder.h | 1 + 28 files changed, 371 insertions(+), 72 deletions(-) diff --git a/packages/cxx-frontend/src/AST.ts b/packages/cxx-frontend/src/AST.ts index 9a96517c..8960a0ff 100644 --- a/packages/cxx-frontend/src/AST.ts +++ b/packages/cxx-frontend/src/AST.ts @@ -9698,6 +9698,31 @@ export class VolatileQualifierAST extends SpecifierAST { } } +/** + * AtomicQualifierAST node. + */ +export class AtomicQualifierAST extends SpecifierAST { + /** + * Traverse this node using the given visitor. + * @param visitor the visitor. + * @param context the context. + * @returns the result of the visit. + */ + accept( + visitor: ASTVisitor, + context: Context, + ): Result { + return visitor.visitAtomicQualifier(this, context); + } + + /** + * Returns the location of the atomic token in this node + */ + getAtomicToken(): Token | undefined { + return Token.from(cxx.getASTSlot(this.getHandle(), 0), this.parser); + } +} + /** * RestrictQualifierAST node. */ @@ -10728,12 +10753,38 @@ export class ArrayDeclaratorChunkAST extends DeclaratorChunkAST { return Token.from(cxx.getASTSlot(this.getHandle(), 0), this.parser); } + /** + * Returns the typeQualifierList of this node + */ + getTypeQualifierList(): Iterable { + let it = cxx.getASTSlot(this.getHandle(), 0); + let value: SpecifierAST | undefined; + let done = false; + const p = this.parser; + function advance() { + done = it === 0; + if (done) return; + const ast = cxx.getListValue(it); + value = AST.from(ast, p); + it = cxx.getListNext(it); + } + function next() { + advance(); + return { done, value }; + } + return { + [Symbol.iterator]() { + return { next }; + }, + }; + } + /** * Returns the expression of this node */ getExpression(): ExpressionAST | undefined { return AST.from( - cxx.getASTSlot(this.getHandle(), 1), + cxx.getASTSlot(this.getHandle(), 2), this.parser, ); } @@ -10742,7 +10793,7 @@ export class ArrayDeclaratorChunkAST extends DeclaratorChunkAST { * Returns the location of the rbracket token in this node */ getRbracketToken(): Token | undefined { - return Token.from(cxx.getASTSlot(this.getHandle(), 2), this.parser); + return Token.from(cxx.getASTSlot(this.getHandle(), 3), this.parser); } /** @@ -13144,6 +13195,7 @@ const AST_CONSTRUCTORS: Array< PlaceholderTypeSpecifierAST, ConstQualifierAST, VolatileQualifierAST, + AtomicQualifierAST, RestrictQualifierAST, EnumSpecifierAST, ClassSpecifierAST, diff --git a/packages/cxx-frontend/src/ASTKind.ts b/packages/cxx-frontend/src/ASTKind.ts index 743ba81d..6de2d24b 100644 --- a/packages/cxx-frontend/src/ASTKind.ts +++ b/packages/cxx-frontend/src/ASTKind.ts @@ -208,6 +208,7 @@ export enum ASTKind { PlaceholderTypeSpecifier, ConstQualifier, VolatileQualifier, + AtomicQualifier, RestrictQualifier, EnumSpecifier, ClassSpecifier, diff --git a/packages/cxx-frontend/src/ASTSlot.ts b/packages/cxx-frontend/src/ASTSlot.ts index 22984c6e..46650475 100644 --- a/packages/cxx-frontend/src/ASTSlot.ts +++ b/packages/cxx-frontend/src/ASTSlot.ts @@ -234,21 +234,22 @@ export enum ASTSlot { typeId = 212, typeIdList = 213, typeLoc = 214, - typeSpecifier = 215, - typeSpecifierList = 216, - typeTraitLoc = 217, - typedefLoc = 218, - typeidLoc = 219, - typenameLoc = 220, - underlyingTypeLoc = 221, - unqualifiedId = 222, - usingDeclaratorList = 223, - usingLoc = 224, - vaArgLoc = 225, - virtualLoc = 226, - virtualOrAccessLoc = 227, - voidLoc = 228, - volatileLoc = 229, - whileLoc = 230, - yieldLoc = 231, + typeQualifierList = 215, + typeSpecifier = 216, + typeSpecifierList = 217, + typeTraitLoc = 218, + typedefLoc = 219, + typeidLoc = 220, + typenameLoc = 221, + underlyingTypeLoc = 222, + unqualifiedId = 223, + usingDeclaratorList = 224, + usingLoc = 225, + vaArgLoc = 226, + virtualLoc = 227, + virtualOrAccessLoc = 228, + voidLoc = 229, + volatileLoc = 230, + whileLoc = 231, + yieldLoc = 232, } diff --git a/packages/cxx-frontend/src/ASTVisitor.ts b/packages/cxx-frontend/src/ASTVisitor.ts index b35b23cd..6936ac8d 100644 --- a/packages/cxx-frontend/src/ASTVisitor.ts +++ b/packages/cxx-frontend/src/ASTVisitor.ts @@ -2077,6 +2077,18 @@ export abstract class ASTVisitor { context: Context, ): Result; + /** + * Visit AtomicQualifier node. + * + * @param node The node to visit. + * @param context The context. + * @returns The result of the visit. + */ + abstract visitAtomicQualifier( + node: ast.AtomicQualifierAST, + context: Context, + ): Result; + /** * Visit RestrictQualifier node. * diff --git a/packages/cxx-frontend/src/RecursiveASTVisitor.ts b/packages/cxx-frontend/src/RecursiveASTVisitor.ts index f81ee529..fd04e423 100644 --- a/packages/cxx-frontend/src/RecursiveASTVisitor.ts +++ b/packages/cxx-frontend/src/RecursiveASTVisitor.ts @@ -2234,6 +2234,14 @@ export class RecursiveASTVisitor extends ASTVisitor { context: Context, ): void {} + /** + * Visit a AtomicQualifier node. + * + * @param node The node to visit. + * @param context The context. + */ + visitAtomicQualifier(node: ast.AtomicQualifierAST, context: Context): void {} + /** * Visit a RestrictQualifier node. * @@ -2440,6 +2448,9 @@ export class RecursiveASTVisitor extends ASTVisitor { node: ast.ArrayDeclaratorChunkAST, context: Context, ): void { + for (const element of node.getTypeQualifierList()) { + this.accept(element, context); + } this.accept(node.getExpression(), context); for (const element of node.getAttributeList()) { this.accept(element, context); diff --git a/src/mlir/cxx/mlir/codegen.cc b/src/mlir/cxx/mlir/codegen.cc index ebc27142..22c18549 100644 --- a/src/mlir/cxx/mlir/codegen.cc +++ b/src/mlir/cxx/mlir/codegen.cc @@ -397,6 +397,8 @@ struct Codegen::SpecifierVisitor { [[nodiscard]] auto operator()(RestrictQualifierAST* ast) -> SpecifierResult; + [[nodiscard]] auto operator()(AtomicQualifierAST* ast) -> SpecifierResult; + [[nodiscard]] auto operator()(EnumSpecifierAST* ast) -> SpecifierResult; [[nodiscard]] auto operator()(ClassSpecifierAST* ast) -> SpecifierResult; @@ -2417,6 +2419,11 @@ auto Codegen::SpecifierVisitor::operator()(RestrictQualifierAST* ast) return {}; } +auto Codegen::SpecifierVisitor::operator()(AtomicQualifierAST* ast) + -> SpecifierResult { + return {}; +} + auto Codegen::SpecifierVisitor::operator()(EnumSpecifierAST* ast) -> SpecifierResult { for (auto node : ListView{ast->attributeList}) { diff --git a/src/parser/cxx/ast.cc b/src/parser/cxx/ast.cc index 274475c7..e8a6e2c2 100644 --- a/src/parser/cxx/ast.cc +++ b/src/parser/cxx/ast.cc @@ -2616,6 +2616,16 @@ auto VolatileQualifierAST::lastSourceLocation() -> SourceLocation { return {}; } +auto AtomicQualifierAST::firstSourceLocation() -> SourceLocation { + if (auto loc = cxx::firstSourceLocation(atomicLoc)) return loc; + return {}; +} + +auto AtomicQualifierAST::lastSourceLocation() -> SourceLocation { + if (auto loc = cxx::lastSourceLocation(atomicLoc)) return loc; + return {}; +} + auto RestrictQualifierAST::firstSourceLocation() -> SourceLocation { if (auto loc = cxx::firstSourceLocation(restrictLoc)) return loc; return {}; @@ -2838,6 +2848,7 @@ auto FunctionDeclaratorChunkAST::lastSourceLocation() -> SourceLocation { auto ArrayDeclaratorChunkAST::firstSourceLocation() -> SourceLocation { if (auto loc = cxx::firstSourceLocation(lbracketLoc)) return loc; + if (auto loc = cxx::firstSourceLocation(typeQualifierList)) return loc; if (auto loc = cxx::firstSourceLocation(expression)) return loc; if (auto loc = cxx::firstSourceLocation(rbracketLoc)) return loc; if (auto loc = cxx::firstSourceLocation(attributeList)) return loc; @@ -2848,6 +2859,7 @@ auto ArrayDeclaratorChunkAST::lastSourceLocation() -> SourceLocation { if (auto loc = cxx::lastSourceLocation(attributeList)) return loc; if (auto loc = cxx::lastSourceLocation(rbracketLoc)) return loc; if (auto loc = cxx::lastSourceLocation(expression)) return loc; + if (auto loc = cxx::lastSourceLocation(typeQualifierList)) return loc; if (auto loc = cxx::lastSourceLocation(lbracketLoc)) return loc; return {}; } @@ -3670,6 +3682,7 @@ std::string_view kASTKindNames[] = { "placeholder-type-specifier", "const-qualifier", "volatile-qualifier", + "atomic-qualifier", "restrict-qualifier", "enum-specifier", "class-specifier", diff --git a/src/parser/cxx/ast.fbs b/src/parser/cxx/ast.fbs index 67b6b25d..2d174d67 100644 --- a/src/parser/cxx/ast.fbs +++ b/src/parser/cxx/ast.fbs @@ -268,6 +268,7 @@ union Specifier { PlaceholderTypeSpecifier, ConstQualifier, VolatileQualifier, + AtomicQualifier, RestrictQualifier, EnumSpecifier, ClassSpecifier, @@ -817,6 +818,7 @@ table FunctionDeclaratorChunk /* DeclaratorChunkAST */ { } table ArrayDeclaratorChunk /* DeclaratorChunkAST */ { + type_qualifier_list: [Specifier]; expression: Expression; attribute_list: [AttributeSpecifier]; lbracket_loc: uint32; @@ -1587,6 +1589,10 @@ table VolatileQualifier /* SpecifierAST */ { volatile_loc: uint32; } +table AtomicQualifier /* SpecifierAST */ { + atomic_loc: uint32; +} + table RestrictQualifier /* SpecifierAST */ { restrict_loc: uint32; } diff --git a/src/parser/cxx/ast.h b/src/parser/cxx/ast.h index e028d96c..e49d9e8c 100644 --- a/src/parser/cxx/ast.h +++ b/src/parser/cxx/ast.h @@ -3232,6 +3232,20 @@ class VolatileQualifierAST final : public SpecifierAST { auto lastSourceLocation() -> SourceLocation override; }; +class AtomicQualifierAST final : public SpecifierAST { + public: + static constexpr ASTKind Kind = ASTKind::AtomicQualifier; + + AtomicQualifierAST() : SpecifierAST(Kind) {} + + SourceLocation atomicLoc; + + void accept(ASTVisitor* visitor) override { visitor->visit(this); } + + auto firstSourceLocation() -> SourceLocation override; + auto lastSourceLocation() -> SourceLocation override; +}; + class RestrictQualifierAST final : public SpecifierAST { public: static constexpr ASTKind Kind = ASTKind::RestrictQualifier; @@ -3475,6 +3489,7 @@ class ArrayDeclaratorChunkAST final : public DeclaratorChunkAST { ArrayDeclaratorChunkAST() : DeclaratorChunkAST(Kind) {} SourceLocation lbracketLoc; + List* typeQualifierList = nullptr; ExpressionAST* expression = nullptr; SourceLocation rbracketLoc; List* attributeList = nullptr; @@ -4895,6 +4910,9 @@ auto visit(Visitor&& visitor, SpecifierAST* ast) { case VolatileQualifierAST::Kind: return std::invoke(std::forward(visitor), static_cast(ast)); + case AtomicQualifierAST::Kind: + return std::invoke(std::forward(visitor), + static_cast(ast)); case RestrictQualifierAST::Kind: return std::invoke(std::forward(visitor), static_cast(ast)); @@ -4952,6 +4970,7 @@ template <> case PlaceholderTypeSpecifierAST::Kind: case ConstQualifierAST::Kind: case VolatileQualifierAST::Kind: + case AtomicQualifierAST::Kind: case RestrictQualifierAST::Kind: case EnumSpecifierAST::Kind: case ClassSpecifierAST::Kind: diff --git a/src/parser/cxx/ast_fwd.h b/src/parser/cxx/ast_fwd.h index ffcece87..d43453c7 100644 --- a/src/parser/cxx/ast_fwd.h +++ b/src/parser/cxx/ast_fwd.h @@ -267,6 +267,7 @@ class DecltypeSpecifierAST; class PlaceholderTypeSpecifierAST; class ConstQualifierAST; class VolatileQualifierAST; +class AtomicQualifierAST; class RestrictQualifierAST; class EnumSpecifierAST; class ClassSpecifierAST; diff --git a/src/parser/cxx/ast_interpreter.cc b/src/parser/cxx/ast_interpreter.cc index b2b70fd6..bda122ca 100644 --- a/src/parser/cxx/ast_interpreter.cc +++ b/src/parser/cxx/ast_interpreter.cc @@ -522,6 +522,8 @@ struct ASTInterpreter::SpecifierVisitor { [[nodiscard]] auto operator()(RestrictQualifierAST* ast) -> SpecifierResult; + [[nodiscard]] auto operator()(AtomicQualifierAST* ast) -> SpecifierResult; + [[nodiscard]] auto operator()(EnumSpecifierAST* ast) -> SpecifierResult; [[nodiscard]] auto operator()(ClassSpecifierAST* ast) -> SpecifierResult; @@ -2727,6 +2729,11 @@ auto ASTInterpreter::SpecifierVisitor::operator()(RestrictQualifierAST* ast) return {}; } +auto ASTInterpreter::SpecifierVisitor::operator()(AtomicQualifierAST* ast) + -> SpecifierResult { + return {}; +} + auto ASTInterpreter::SpecifierVisitor::operator()(EnumSpecifierAST* ast) -> SpecifierResult { for (auto node : ListView{ast->attributeList}) { diff --git a/src/parser/cxx/ast_kind.h b/src/parser/cxx/ast_kind.h index 2f69e831..b3d5f09a 100644 --- a/src/parser/cxx/ast_kind.h +++ b/src/parser/cxx/ast_kind.h @@ -213,6 +213,7 @@ enum class ASTKind { PlaceholderTypeSpecifier, ConstQualifier, VolatileQualifier, + AtomicQualifier, RestrictQualifier, EnumSpecifier, ClassSpecifier, diff --git a/src/parser/cxx/ast_pretty_printer.cc b/src/parser/cxx/ast_pretty_printer.cc index b7187398..094bffed 100644 --- a/src/parser/cxx/ast_pretty_printer.cc +++ b/src/parser/cxx/ast_pretty_printer.cc @@ -422,6 +422,8 @@ struct ASTPrettyPrinter::SpecifierVisitor { void operator()(VolatileQualifierAST* ast); + void operator()(AtomicQualifierAST* ast); + void operator()(RestrictQualifierAST* ast); void operator()(EnumSpecifierAST* ast); @@ -3492,6 +3494,12 @@ void ASTPrettyPrinter::SpecifierVisitor::operator()(VolatileQualifierAST* ast) { } } +void ASTPrettyPrinter::SpecifierVisitor::operator()(AtomicQualifierAST* ast) { + if (ast->atomicLoc) { + accept.writeToken(ast->atomicLoc); + } +} + void ASTPrettyPrinter::SpecifierVisitor::operator()(RestrictQualifierAST* ast) { if (ast->restrictLoc) { accept.writeToken(ast->restrictLoc); @@ -3735,6 +3743,11 @@ void ASTPrettyPrinter::DeclaratorChunkVisitor::operator()( accept.writeToken(ast->lbracketLoc); nospace(); } + + for (auto it = ast->typeQualifierList; it; it = it->next) { + accept(it->value); + } + accept(ast->expression); if (ast->rbracketLoc) { nospace(); diff --git a/src/parser/cxx/ast_printer.cc b/src/parser/cxx/ast_printer.cc index 7510f78f..649b33b6 100644 --- a/src/parser/cxx/ast_printer.cc +++ b/src/parser/cxx/ast_printer.cc @@ -2155,6 +2155,10 @@ void ASTPrinter::visit(VolatileQualifierAST* ast) { out_ << std::format("{}\n", "volatile-qualifier"); } +void ASTPrinter::visit(AtomicQualifierAST* ast) { + out_ << std::format("{}\n", "atomic-qualifier"); +} + void ASTPrinter::visit(RestrictQualifierAST* ast) { out_ << std::format("{}\n", "restrict-qualifier"); } @@ -2402,6 +2406,15 @@ void ASTPrinter::visit(FunctionDeclaratorChunkAST* ast) { void ASTPrinter::visit(ArrayDeclaratorChunkAST* ast) { out_ << std::format("{}\n", "array-declarator-chunk"); + if (ast->typeQualifierList) { + ++indent_; + out_ << std::format("{:{}}", "", indent_ * 2); + out_ << std::format("{}\n", "type-qualifier-list"); + for (auto node : ListView{ast->typeQualifierList}) { + accept(node); + } + --indent_; + } accept(ast->expression, "expression"); if (ast->attributeList) { ++indent_; diff --git a/src/parser/cxx/ast_printer.h b/src/parser/cxx/ast_printer.h index 0c98771d..c0adf18c 100644 --- a/src/parser/cxx/ast_printer.h +++ b/src/parser/cxx/ast_printer.h @@ -223,6 +223,7 @@ class ASTPrinter : ASTVisitor { void visit(PlaceholderTypeSpecifierAST* ast) override; void visit(ConstQualifierAST* ast) override; void visit(VolatileQualifierAST* ast) override; + void visit(AtomicQualifierAST* ast) override; void visit(RestrictQualifierAST* ast) override; void visit(EnumSpecifierAST* ast) override; void visit(ClassSpecifierAST* ast) override; diff --git a/src/parser/cxx/ast_rewriter.cc b/src/parser/cxx/ast_rewriter.cc index 8a0cb468..9d365a08 100644 --- a/src/parser/cxx/ast_rewriter.cc +++ b/src/parser/cxx/ast_rewriter.cc @@ -507,6 +507,8 @@ struct ASTRewriter::SpecifierVisitor { [[nodiscard]] auto operator()(RestrictQualifierAST* ast) -> SpecifierAST*; + [[nodiscard]] auto operator()(AtomicQualifierAST* ast) -> SpecifierAST*; + [[nodiscard]] auto operator()(EnumSpecifierAST* ast) -> SpecifierAST*; [[nodiscard]] auto operator()(ClassSpecifierAST* ast) -> SpecifierAST*; @@ -3816,6 +3818,15 @@ auto ASTRewriter::SpecifierVisitor::operator()(RestrictQualifierAST* ast) return copy; } +auto ASTRewriter::SpecifierVisitor::operator()(AtomicQualifierAST* ast) + -> SpecifierAST* { + auto copy = make_node(arena()); + + copy->atomicLoc = ast->atomicLoc; + + return copy; +} + auto ASTRewriter::SpecifierVisitor::operator()(EnumSpecifierAST* ast) -> SpecifierAST* { auto copy = make_node(arena()); @@ -4111,6 +4122,16 @@ auto ASTRewriter::DeclaratorChunkVisitor::operator()( auto copy = make_node(arena()); copy->lbracketLoc = ast->lbracketLoc; + + auto typeQualifierListCtx = DeclSpecs{rewriter()}; + for (auto typeQualifierList = ©->typeQualifierList; + auto node : ListView{ast->typeQualifierList}) { + auto value = rewrite(node); + *typeQualifierList = make_list_node(arena(), value); + typeQualifierList = &(*typeQualifierList)->next; + typeQualifierListCtx.accept(value); + } + copy->expression = rewrite(ast->expression); copy->rbracketLoc = ast->rbracketLoc; diff --git a/src/parser/cxx/ast_slot.cc b/src/parser/cxx/ast_slot.cc index 700aeed1..64519fb9 100644 --- a/src/parser/cxx/ast_slot.cc +++ b/src/parser/cxx/ast_slot.cc @@ -264,6 +264,7 @@ std::string_view kMemberSlotNames[] = { "typeId", "typeIdList", "typeLoc", + "typeQualifierList", "typeSpecifier", "typeSpecifierList", "typeTraitLoc", @@ -450,7 +451,7 @@ void ASTSlot::visit(NamespaceAliasDefinitionAST* ast) { case 4: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 5: // semicolonLoc value_ = ast->semicolonLoc.index(); @@ -472,12 +473,12 @@ void ASTSlot::visit(UsingDeclarationAST* ast) { case 0: // usingLoc value_ = ast->usingLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{224}; + slotNameIndex_ = SlotNameIndex{225}; break; case 1: // usingDeclaratorList value_ = reinterpret_cast(ast->usingDeclaratorList); slotKind_ = ASTSlotKind::kNodeList; - slotNameIndex_ = SlotNameIndex{223}; + slotNameIndex_ = SlotNameIndex{224}; break; case 2: // semicolonLoc value_ = ast->semicolonLoc.index(); @@ -494,7 +495,7 @@ void ASTSlot::visit(UsingEnumDeclarationAST* ast) { case 0: // usingLoc value_ = ast->usingLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{224}; + slotNameIndex_ = SlotNameIndex{225}; break; case 1: // enumTypeSpecifier value_ = reinterpret_cast(ast->enumTypeSpecifier); @@ -521,7 +522,7 @@ void ASTSlot::visit(UsingDirectiveAST* ast) { case 1: // usingLoc value_ = ast->usingLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{224}; + slotNameIndex_ = SlotNameIndex{225}; break; case 2: // namespaceLoc value_ = ast->namespaceLoc.index(); @@ -536,7 +537,7 @@ void ASTSlot::visit(UsingDirectiveAST* ast) { case 4: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 5: // semicolonLoc value_ = ast->semicolonLoc.index(); @@ -600,7 +601,7 @@ void ASTSlot::visit(AliasDeclarationAST* ast) { case 0: // usingLoc value_ = ast->usingLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{224}; + slotNameIndex_ = SlotNameIndex{225}; break; case 1: // identifierLoc value_ = ast->identifierLoc.index(); @@ -667,7 +668,7 @@ void ASTSlot::visit(OpaqueEnumDeclarationAST* ast) { case 4: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 5: // colonLoc value_ = ast->colonLoc.index(); @@ -677,7 +678,7 @@ void ASTSlot::visit(OpaqueEnumDeclarationAST* ast) { case 6: // typeSpecifierList value_ = reinterpret_cast(ast->typeSpecifierList); slotKind_ = ASTSlotKind::kNodeList; - slotNameIndex_ = SlotNameIndex{216}; + slotNameIndex_ = SlotNameIndex{217}; break; case 7: // emicolonLoc value_ = ast->emicolonLoc.index(); @@ -1084,7 +1085,7 @@ void ASTSlot::visit(ParameterDeclarationAST* ast) { case 2: // typeSpecifierList value_ = reinterpret_cast(ast->typeSpecifierList); slotKind_ = ASTSlotKind::kNodeList; - slotNameIndex_ = SlotNameIndex{216}; + slotNameIndex_ = SlotNameIndex{217}; break; case 3: // declarator value_ = reinterpret_cast(ast->declarator); @@ -1531,7 +1532,7 @@ void ASTSlot::visit(WhileStatementAST* ast) { case 0: // whileLoc value_ = ast->whileLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{230}; + slotNameIndex_ = SlotNameIndex{231}; break; case 1: // lparenLoc value_ = ast->lparenLoc.index(); @@ -1573,7 +1574,7 @@ void ASTSlot::visit(DoStatementAST* ast) { case 2: // whileLoc value_ = ast->whileLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{230}; + slotNameIndex_ = SlotNameIndex{231}; break; case 3: // lparenLoc value_ = ast->lparenLoc.index(); @@ -2062,7 +2063,7 @@ void ASTSlot::visit(IdExpressionAST* ast) { case 2: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 3: // isTemplateIntroduced value_ = std::intptr_t(ast->isTemplateIntroduced != 0); @@ -2349,7 +2350,7 @@ void ASTSlot::visit(VaArgExpressionAST* ast) { case 0: // vaArgLoc value_ = ast->vaArgLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{225}; + slotNameIndex_ = SlotNameIndex{226}; break; case 1: // lparenLoc value_ = ast->lparenLoc.index(); @@ -2440,7 +2441,7 @@ void ASTSlot::visit(TypeConstructionAST* ast) { case 0: // typeSpecifier value_ = reinterpret_cast(ast->typeSpecifier); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{215}; + slotNameIndex_ = SlotNameIndex{216}; break; case 1: // lparenLoc value_ = ast->lparenLoc.index(); @@ -2467,7 +2468,7 @@ void ASTSlot::visit(BracedTypeConstructionAST* ast) { case 0: // typeSpecifier value_ = reinterpret_cast(ast->typeSpecifier); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{215}; + slotNameIndex_ = SlotNameIndex{216}; break; case 1: // bracedInitList value_ = reinterpret_cast(ast->bracedInitList); @@ -2541,7 +2542,7 @@ void ASTSlot::visit(MemberExpressionAST* ast) { case 4: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 5: // accessOp value_ = std::intptr_t(ast->accessOp); @@ -2701,7 +2702,7 @@ void ASTSlot::visit(TypeidExpressionAST* ast) { case 0: // typeidLoc value_ = ast->typeidLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{219}; + slotNameIndex_ = SlotNameIndex{220}; break; case 1: // lparenLoc value_ = ast->lparenLoc.index(); @@ -2728,7 +2729,7 @@ void ASTSlot::visit(TypeidOfTypeExpressionAST* ast) { case 0: // typeidLoc value_ = ast->typeidLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{219}; + slotNameIndex_ = SlotNameIndex{220}; break; case 1: // lparenLoc value_ = ast->lparenLoc.index(); @@ -3051,7 +3052,7 @@ void ASTSlot::visit(NewExpressionAST* ast) { case 4: // typeSpecifierList value_ = reinterpret_cast(ast->typeSpecifierList); slotKind_ = ASTSlotKind::kNodeList; - slotNameIndex_ = SlotNameIndex{216}; + slotNameIndex_ = SlotNameIndex{217}; break; case 5: // declarator value_ = reinterpret_cast(ast->declarator); @@ -3208,7 +3209,7 @@ void ASTSlot::visit(YieldExpressionAST* ast) { case 0: // yieldLoc value_ = ast->yieldLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{231}; + slotNameIndex_ = SlotNameIndex{232}; break; case 1: // expression value_ = reinterpret_cast(ast->expression); @@ -3303,7 +3304,7 @@ void ASTSlot::visit(TypeTraitExpressionAST* ast) { case 0: // typeTraitLoc value_ = ast->typeTraitLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{217}; + slotNameIndex_ = SlotNameIndex{218}; break; case 1: // lparenLoc value_ = ast->lparenLoc.index(); @@ -3727,7 +3728,7 @@ void ASTSlot::visit(UsingDeclaratorAST* ast) { case 0: // typenameLoc value_ = ast->typenameLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{220}; + slotNameIndex_ = SlotNameIndex{221}; break; case 1: // nestedNameSpecifier value_ = reinterpret_cast(ast->nestedNameSpecifier); @@ -3737,7 +3738,7 @@ void ASTSlot::visit(UsingDeclaratorAST* ast) { case 2: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 3: // ellipsisLoc value_ = ast->ellipsisLoc.index(); @@ -3791,7 +3792,7 @@ void ASTSlot::visit(TypeIdAST* ast) { case 0: // typeSpecifierList value_ = reinterpret_cast(ast->typeSpecifierList); slotKind_ = ASTSlotKind::kNodeList; - slotNameIndex_ = SlotNameIndex{216}; + slotNameIndex_ = SlotNameIndex{217}; break; case 1: // declarator value_ = reinterpret_cast(ast->declarator); @@ -3845,7 +3846,7 @@ void ASTSlot::visit(BaseSpecifierAST* ast) { case 1: // virtualOrAccessLoc value_ = ast->virtualOrAccessLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{227}; + slotNameIndex_ = SlotNameIndex{228}; break; case 2: // otherVirtualOrAccessLoc value_ = ast->otherVirtualOrAccessLoc.index(); @@ -3865,7 +3866,7 @@ void ASTSlot::visit(BaseSpecifierAST* ast) { case 5: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 6: // ellipsisLoc value_ = ast->ellipsisLoc.index(); @@ -4056,7 +4057,7 @@ void ASTSlot::visit(AttributeUsingPrefixAST* ast) { case 0: // usingLoc value_ = ast->usingLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{224}; + slotNameIndex_ = SlotNameIndex{225}; break; case 1: // attributeNamespaceLoc value_ = ast->attributeNamespaceLoc.index(); @@ -4302,7 +4303,7 @@ void ASTSlot::visit(TypedefSpecifierAST* ast) { case 0: // typedefLoc value_ = ast->typedefLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{218}; + slotNameIndex_ = SlotNameIndex{219}; break; } // switch @@ -4458,7 +4459,7 @@ void ASTSlot::visit(VirtualSpecifierAST* ast) { case 0: // virtualLoc value_ = ast->virtualLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{226}; + slotNameIndex_ = SlotNameIndex{227}; break; } // switch @@ -4509,7 +4510,7 @@ void ASTSlot::visit(VoidTypeSpecifierAST* ast) { case 0: // voidLoc value_ = ast->voidLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{228}; + slotNameIndex_ = SlotNameIndex{229}; break; } // switch @@ -4628,7 +4629,7 @@ void ASTSlot::visit(NamedTypeSpecifierAST* ast) { case 2: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 3: // isTemplateIntroduced value_ = std::intptr_t(ast->isTemplateIntroduced != 0); @@ -4672,7 +4673,7 @@ void ASTSlot::visit(UnderlyingTypeSpecifierAST* ast) { case 0: // underlyingTypeLoc value_ = ast->underlyingTypeLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{221}; + slotNameIndex_ = SlotNameIndex{222}; break; case 1: // lparenLoc value_ = ast->lparenLoc.index(); @@ -4719,7 +4720,7 @@ void ASTSlot::visit(ElaboratedTypeSpecifierAST* ast) { case 4: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 5: // classKey value_ = std::intptr_t(ast->classKey); @@ -4824,7 +4825,19 @@ void ASTSlot::visit(VolatileQualifierAST* ast) { case 0: // volatileLoc value_ = ast->volatileLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{229}; + slotNameIndex_ = SlotNameIndex{230}; + break; + } // switch + + slotCount_ = 1; +} + +void ASTSlot::visit(AtomicQualifierAST* ast) { + switch (slot_) { + case 0: // atomicLoc + value_ = ast->atomicLoc.index(); + slotKind_ = ASTSlotKind::kToken; + slotNameIndex_ = SlotNameIndex{9}; break; } // switch @@ -4868,7 +4881,7 @@ void ASTSlot::visit(EnumSpecifierAST* ast) { case 4: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 5: // colonLoc value_ = ast->colonLoc.index(); @@ -4878,7 +4891,7 @@ void ASTSlot::visit(EnumSpecifierAST* ast) { case 6: // typeSpecifierList value_ = reinterpret_cast(ast->typeSpecifierList); slotKind_ = ASTSlotKind::kNodeList; - slotNameIndex_ = SlotNameIndex{216}; + slotNameIndex_ = SlotNameIndex{217}; break; case 7: // lbraceLoc value_ = ast->lbraceLoc.index(); @@ -4925,7 +4938,7 @@ void ASTSlot::visit(ClassSpecifierAST* ast) { case 3: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 4: // finalLoc value_ = ast->finalLoc.index(); @@ -4977,7 +4990,7 @@ void ASTSlot::visit(TypenameSpecifierAST* ast) { case 0: // typenameLoc value_ = ast->typenameLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{220}; + slotNameIndex_ = SlotNameIndex{221}; break; case 1: // nestedNameSpecifier value_ = reinterpret_cast(ast->nestedNameSpecifier); @@ -4992,7 +5005,7 @@ void ASTSlot::visit(TypenameSpecifierAST* ast) { case 3: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 4: // isTemplateIntroduced value_ = std::intptr_t(ast->isTemplateIntroduced != 0); @@ -5009,7 +5022,7 @@ void ASTSlot::visit(SplicerTypeSpecifierAST* ast) { case 0: // typenameLoc value_ = ast->typenameLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{220}; + slotNameIndex_ = SlotNameIndex{221}; break; case 1: // splicer value_ = reinterpret_cast(ast->splicer); @@ -5097,7 +5110,7 @@ void ASTSlot::visit(BitfieldDeclaratorAST* ast) { case 0: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 1: // colonLoc value_ = ast->colonLoc.index(); @@ -5146,7 +5159,7 @@ void ASTSlot::visit(IdDeclaratorAST* ast) { case 2: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 3: // attributeList value_ = reinterpret_cast(ast->attributeList); @@ -5254,24 +5267,29 @@ void ASTSlot::visit(ArrayDeclaratorChunkAST* ast) { slotKind_ = ASTSlotKind::kToken; slotNameIndex_ = SlotNameIndex{124}; break; - case 1: // expression + case 1: // typeQualifierList + value_ = reinterpret_cast(ast->typeQualifierList); + slotKind_ = ASTSlotKind::kNodeList; + slotNameIndex_ = SlotNameIndex{215}; + break; + case 2: // expression value_ = reinterpret_cast(ast->expression); slotKind_ = ASTSlotKind::kNode; slotNameIndex_ = SlotNameIndex{78}; break; - case 2: // rbracketLoc + case 3: // rbracketLoc value_ = ast->rbracketLoc.index(); slotKind_ = ASTSlotKind::kToken; slotNameIndex_ = SlotNameIndex{168}; break; - case 3: // attributeList + case 4: // attributeList value_ = reinterpret_cast(ast->attributeList); slotKind_ = ASTSlotKind::kNodeList; slotNameIndex_ = SlotNameIndex{11}; break; } // switch - slotCount_ = 4; + slotCount_ = 5; } void ASTSlot::visit(NameIdAST* ast) { @@ -5810,7 +5828,7 @@ void ASTSlot::visit(TypeRequirementAST* ast) { case 0: // typenameLoc value_ = ast->typenameLoc.index(); slotKind_ = ASTSlotKind::kToken; - slotNameIndex_ = SlotNameIndex{220}; + slotNameIndex_ = SlotNameIndex{221}; break; case 1: // nestedNameSpecifier value_ = reinterpret_cast(ast->nestedNameSpecifier); @@ -5825,7 +5843,7 @@ void ASTSlot::visit(TypeRequirementAST* ast) { case 3: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 4: // semicolonLoc value_ = ast->semicolonLoc.index(); @@ -5908,7 +5926,7 @@ void ASTSlot::visit(ParenMemInitializerAST* ast) { case 1: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 2: // lparenLoc value_ = ast->lparenLoc.index(); @@ -5945,7 +5963,7 @@ void ASTSlot::visit(BracedMemInitializerAST* ast) { case 1: // unqualifiedId value_ = reinterpret_cast(ast->unqualifiedId); slotKind_ = ASTSlotKind::kNode; - slotNameIndex_ = SlotNameIndex{222}; + slotNameIndex_ = SlotNameIndex{223}; break; case 2: // bracedInitList value_ = reinterpret_cast(ast->bracedInitList); @@ -6121,7 +6139,7 @@ void ASTSlot::visit(TypeExceptionDeclarationAST* ast) { case 1: // typeSpecifierList value_ = reinterpret_cast(ast->typeSpecifierList); slotKind_ = ASTSlotKind::kNodeList; - slotNameIndex_ = SlotNameIndex{216}; + slotNameIndex_ = SlotNameIndex{217}; break; case 2: // declarator value_ = reinterpret_cast(ast->declarator); diff --git a/src/parser/cxx/ast_slot.h b/src/parser/cxx/ast_slot.h index 4bea762a..28a1d781 100644 --- a/src/parser/cxx/ast_slot.h +++ b/src/parser/cxx/ast_slot.h @@ -234,6 +234,7 @@ class ASTSlot final : ASTVisitor { void visit(PlaceholderTypeSpecifierAST* ast) override; void visit(ConstQualifierAST* ast) override; void visit(VolatileQualifierAST* ast) override; + void visit(AtomicQualifierAST* ast) override; void visit(RestrictQualifierAST* ast) override; void visit(EnumSpecifierAST* ast) override; void visit(ClassSpecifierAST* ast) override; diff --git a/src/parser/cxx/ast_visitor.cc b/src/parser/cxx/ast_visitor.cc index a618777b..ba0ffc37 100644 --- a/src/parser/cxx/ast_visitor.cc +++ b/src/parser/cxx/ast_visitor.cc @@ -788,6 +788,8 @@ void ASTVisitor::visit(ConstQualifierAST* ast) {} void ASTVisitor::visit(VolatileQualifierAST* ast) {} +void ASTVisitor::visit(AtomicQualifierAST* ast) {} + void ASTVisitor::visit(RestrictQualifierAST* ast) {} void ASTVisitor::visit(EnumSpecifierAST* ast) { @@ -880,6 +882,9 @@ void ASTVisitor::visit(FunctionDeclaratorChunkAST* ast) { } void ASTVisitor::visit(ArrayDeclaratorChunkAST* ast) { + for (auto node : ListView{ast->typeQualifierList}) { + accept(node); + } accept(ast->expression); for (auto node : ListView{ast->attributeList}) { accept(node); diff --git a/src/parser/cxx/ast_visitor.h b/src/parser/cxx/ast_visitor.h index cb0f805d..c103da59 100644 --- a/src/parser/cxx/ast_visitor.h +++ b/src/parser/cxx/ast_visitor.h @@ -222,6 +222,7 @@ class ASTVisitor { virtual void visit(PlaceholderTypeSpecifierAST* ast); virtual void visit(ConstQualifierAST* ast); virtual void visit(VolatileQualifierAST* ast); + virtual void visit(AtomicQualifierAST* ast); virtual void visit(RestrictQualifierAST* ast); virtual void visit(EnumSpecifierAST* ast); virtual void visit(ClassSpecifierAST* ast); diff --git a/src/parser/cxx/decl_specs.cc b/src/parser/cxx/decl_specs.cc index f7e64063..2d909f1e 100644 --- a/src/parser/cxx/decl_specs.cc +++ b/src/parser/cxx/decl_specs.cc @@ -69,6 +69,7 @@ struct DeclSpecs::Visitor { void operator()(ConstQualifierAST* ast); void operator()(VolatileQualifierAST* ast); void operator()(RestrictQualifierAST* ast); + void operator()(AtomicQualifierAST* ast); void operator()(EnumSpecifierAST* ast); void operator()(ClassSpecifierAST* ast); void operator()(TypenameSpecifierAST* ast); @@ -326,6 +327,10 @@ void DeclSpecs::Visitor::operator()(RestrictQualifierAST* ast) { specs.isRestrict = true; } +void DeclSpecs::Visitor::operator()(AtomicQualifierAST* ast) { + specs.isAtomic = true; +} + void DeclSpecs::Visitor::operator()(EnumSpecifierAST* ast) { specs.typeSpecifier_ = ast; if (ast->symbol) specs.type_ = ast->symbol->type(); diff --git a/src/parser/cxx/decl_specs.h b/src/parser/cxx/decl_specs.h index c97da624..34441650 100644 --- a/src/parser/cxx/decl_specs.h +++ b/src/parser/cxx/decl_specs.h @@ -74,6 +74,7 @@ class DeclSpecs { bool isConst = false; bool isVolatile = false; bool isRestrict = false; + bool isAtomic = true; // storage class specifiers bool isStatic = false; diff --git a/src/parser/cxx/flatbuffers/ast_decoder.cc b/src/parser/cxx/flatbuffers/ast_decoder.cc index 2b4262c7..5adcb238 100644 --- a/src/parser/cxx/flatbuffers/ast_decoder.cc +++ b/src/parser/cxx/flatbuffers/ast_decoder.cc @@ -536,6 +536,9 @@ auto ASTDecoder::decodeSpecifier(const void* ptr, io::Specifier type) case io::Specifier_VolatileQualifier: return decodeVolatileQualifier( reinterpret_cast(ptr)); + case io::Specifier_AtomicQualifier: + return decodeAtomicQualifier( + reinterpret_cast(ptr)); case io::Specifier_RestrictQualifier: return decodeRestrictQualifier( reinterpret_cast(ptr)); @@ -3551,6 +3554,15 @@ auto ASTDecoder::decodeVolatileQualifier(const io::VolatileQualifier* node) return ast; } +auto ASTDecoder::decodeAtomicQualifier(const io::AtomicQualifier* node) + -> AtomicQualifierAST* { + if (!node) return nullptr; + + auto ast = new (pool_) AtomicQualifierAST(); + ast->atomicLoc = SourceLocation(node->atomic_loc()); + return ast; +} + auto ASTDecoder::decodeRestrictQualifier(const io::RestrictQualifier* node) -> RestrictQualifierAST* { if (!node) return nullptr; @@ -3843,6 +3855,15 @@ auto ASTDecoder::decodeArrayDeclaratorChunk( auto ast = new (pool_) ArrayDeclaratorChunkAST(); ast->lbracketLoc = SourceLocation(node->lbracket_loc()); + if (node->type_qualifier_list()) { + auto* inserter = &ast->typeQualifierList; + for (std::uint32_t i = 0; i < node->type_qualifier_list()->size(); ++i) { + *inserter = new (pool_) List(decodeSpecifier( + node->type_qualifier_list()->Get(i), + io::Specifier(node->type_qualifier_list_type()->Get(i)))); + inserter = &(*inserter)->next; + } + } ast->expression = decodeExpression(node->expression(), node->expression_type()); ast->rbracketLoc = SourceLocation(node->rbracket_loc()); diff --git a/src/parser/cxx/flatbuffers/ast_encoder.cc b/src/parser/cxx/flatbuffers/ast_encoder.cc index f1addb8b..6e5cd23f 100644 --- a/src/parser/cxx/flatbuffers/ast_encoder.cc +++ b/src/parser/cxx/flatbuffers/ast_encoder.cc @@ -3963,6 +3963,14 @@ void ASTEncoder::visit(VolatileQualifierAST* ast) { type_ = io::Specifier_VolatileQualifier; } +void ASTEncoder::visit(AtomicQualifierAST* ast) { + io::AtomicQualifier::Builder builder{fbb_}; + builder.add_atomic_loc(ast->atomicLoc.index()); + + offset_ = builder.Finish().Union(); + type_ = io::Specifier_AtomicQualifier; +} + void ASTEncoder::visit(RestrictQualifierAST* ast) { io::RestrictQualifier::Builder builder{fbb_}; builder.add_restrict_loc(ast->restrictLoc.index()); @@ -4375,6 +4383,20 @@ void ASTEncoder::visit(FunctionDeclaratorChunkAST* ast) { } void ASTEncoder::visit(ArrayDeclaratorChunkAST* ast) { + std::vector> typeQualifierListOffsets; + std::vector> typeQualifierListTypes; + + for (auto node : ListView{ast->typeQualifierList}) { + if (!node) continue; + const auto [offset, type] = acceptSpecifier(node); + typeQualifierListOffsets.push_back(offset); + typeQualifierListTypes.push_back(type); + } + + auto typeQualifierListOffsetsVector = + fbb_.CreateVector(typeQualifierListOffsets); + auto typeQualifierListTypesVector = fbb_.CreateVector(typeQualifierListTypes); + const auto [expression, expressionType] = acceptExpression(ast->expression); std::vector> attributeListOffsets; @@ -4393,6 +4415,8 @@ void ASTEncoder::visit(ArrayDeclaratorChunkAST* ast) { io::ArrayDeclaratorChunk::Builder builder{fbb_}; builder.add_lbracket_loc(ast->lbracketLoc.index()); + builder.add_type_qualifier_list(typeQualifierListOffsetsVector); + builder.add_type_qualifier_list_type(typeQualifierListTypesVector); builder.add_expression(expression); builder.add_expression_type(static_cast(expressionType)); builder.add_rbracket_loc(ast->rbracketLoc.index()); diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index fa9f8bc2..c7ba3288 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -4670,8 +4670,8 @@ auto Parser::parse_explicit_specifier(SpecifierAST*& yyast, DeclSpecs& specs) auto Parser::parse_type_specifier(SpecifierAST*& yyast, DeclSpecs& specs) -> bool { - if (parse_simple_type_specifier(yyast, specs)) return true; if (parse_cv_qualifier(yyast, specs)) return true; + if (parse_simple_type_specifier(yyast, specs)) return true; if (parse_elaborated_type_specifier(yyast, specs)) return true; if (parse_splicer_specifier(yyast, specs)) return true; if (parse_typename_specifier(yyast, specs)) return true; @@ -4721,6 +4721,31 @@ auto Parser::parse_type_specifier_seq(List*& yyast, return true; } +void Parser::parse_optional_type_qualifier_seq(List*& yyast, + DeclSpecs& specs) { + if (!is_parsing_c()) { + return; + } + + auto it = &yyast; + + while (true) { + if (SpecifierAST* cv = nullptr; parse_cv_qualifier(cv, specs)) { + *it = make_list_node(pool_, cv); + it = &(*it)->next; + } else if (SourceLocation staticLoc; + match(TokenKind::T_STATIC, staticLoc)) { + auto spec = make_node(pool_); + *it = make_list_node(pool_, spec); + it = &(*it)->next; + } else { + break; + } + } + + specs.finish(); +} + auto Parser::parse_defining_type_specifier(SpecifierAST*& yyast, DeclSpecs& specs) -> bool { if (!specs.no_class_or_enum_specs && !specs.hasTypeSpecifier()) { @@ -5477,6 +5502,10 @@ auto Parser::parse_array_declarator(ArrayDeclaratorChunkAST*& yyast) -> bool { SourceLocation lbracketLoc; if (!match(TokenKind::T_LBRACKET, lbracketLoc)) return false; + List* typeQualifierList = nullptr; + DeclSpecs specs{unit}; + parse_optional_type_qualifier_seq(typeQualifierList, specs); + SourceLocation rbracketLoc; ExpressionAST* expression = nullptr; std::optional value; @@ -5495,6 +5524,7 @@ auto Parser::parse_array_declarator(ArrayDeclaratorChunkAST*& yyast) -> bool { yyast = modifier; modifier->lbracketLoc = lbracketLoc; + modifier->typeQualifierList = typeQualifierList; modifier->expression = expression; modifier->rbracketLoc = rbracketLoc; modifier->attributeList = attributes; @@ -5665,6 +5695,15 @@ auto Parser::parse_cv_qualifier(SpecifierAST*& yyast, DeclSpecs& declSpecs) declSpecs.isRestrict = true; return true; } + if (is_parsing_c() && lookat(TokenKind::T__ATOMIC) && + LA(1).isNot(TokenKind::T_LPAREN)) { + auto ast = make_node(pool_); + yyast = ast; + ast->atomicLoc = consumeToken(); + declSpecs.isAtomic = true; + return true; + } + return false; } diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index 492a0cba..9b253f7f 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -433,6 +433,8 @@ class Parser final { DeclSpecs& specs) -> bool; [[nodiscard]] auto parse_type_specifier_seq(List*& yyast, DeclSpecs& specs) -> bool; + void parse_optional_type_qualifier_seq(List*& yyast, + DeclSpecs& specs); [[nodiscard]] auto parse_defining_type_specifier(SpecifierAST*& yyast, DeclSpecs& specs) -> bool; [[nodiscard]] auto parse_defining_type_specifier_seq( diff --git a/src/parser/cxx/private/ast_decoder.h b/src/parser/cxx/private/ast_decoder.h index 29b72c0d..61b6e06c 100644 --- a/src/parser/cxx/private/ast_decoder.h +++ b/src/parser/cxx/private/ast_decoder.h @@ -422,6 +422,8 @@ class ASTDecoder { -> ConstQualifierAST*; auto decodeVolatileQualifier(const io::VolatileQualifier* node) -> VolatileQualifierAST*; + auto decodeAtomicQualifier(const io::AtomicQualifier* node) + -> AtomicQualifierAST*; auto decodeRestrictQualifier(const io::RestrictQualifier* node) -> RestrictQualifierAST*; auto decodeEnumSpecifier(const io::EnumSpecifier* node) -> EnumSpecifierAST*; diff --git a/src/parser/cxx/private/ast_encoder.h b/src/parser/cxx/private/ast_encoder.h index 2d3f489c..438c09c4 100644 --- a/src/parser/cxx/private/ast_encoder.h +++ b/src/parser/cxx/private/ast_encoder.h @@ -305,6 +305,7 @@ class ASTEncoder : ASTVisitor { void visit(PlaceholderTypeSpecifierAST* ast) override; void visit(ConstQualifierAST* ast) override; void visit(VolatileQualifierAST* ast) override; + void visit(AtomicQualifierAST* ast) override; void visit(RestrictQualifierAST* ast) override; void visit(EnumSpecifierAST* ast) override; void visit(ClassSpecifierAST* ast) override; From 2a6978e6451babbfbea048c41970dc08e25e4eae Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Sun, 13 Jul 2025 15:18:23 +0200 Subject: [PATCH 2/2] Temporarily disable warning for unrecognized CLI options. It is getting in the way of development, and we will handle it later. --- src/parser/cxx/cli.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/parser/cxx/cli.cc b/src/parser/cxx/cli.cc index 6a954e49..691447fc 100644 --- a/src/parser/cxx/cli.cc +++ b/src/parser/cxx/cli.cc @@ -350,7 +350,9 @@ void CLI::parse(int& argc, char**& argv) { continue; } +#if false std::cerr << std::format("unsupported option '{}'\n", arg); +#endif } }