diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/analysis/rust-scan.cc | 2 | ||||
-rw-r--r-- | gcc/rust/analysis/rust-type-resolution.cc | 36 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 50 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 93 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 37 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 34 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 143 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 4 |
8 files changed, 316 insertions, 83 deletions
diff --git a/gcc/rust/analysis/rust-scan.cc b/gcc/rust/analysis/rust-scan.cc index 402ac32..31c89e4 100644 --- a/gcc/rust/analysis/rust-scan.cc +++ b/gcc/rust/analysis/rust-scan.cc @@ -353,7 +353,7 @@ TopLevelScan::visit (AST::UseDeclaration &use_decl) void TopLevelScan::visit (AST::Function &function) { - functions[function.function_name] = &function; + functions[function.get_function_name ()] = &function; } void diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index fcf475e..c3a5587 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -471,7 +471,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr) AST::StructField *declField = NULL; for (auto &df : decl->get_fields ()) { - if (identifierBuffer->compare (df.field_name) == 0) + if (identifierBuffer->compare (df.get_field_name ()) == 0) { declField = &df; break; @@ -485,7 +485,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr) return; } - if (!typesAreCompatible (declField->field_type.get (), inferedType, + if (!typesAreCompatible (declField->get_field_type ().get (), inferedType, expr.get_locus_slow ())) return; } @@ -505,7 +505,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr) return; } - if (!typesAreCompatible (declField->field_type.get (), inferedType, + if (!typesAreCompatible (declField->get_field_type ().get (), inferedType, expr.get_locus_slow ())) return; } @@ -561,41 +561,41 @@ void TypeResolution::visit (AST::CallExpr &expr) { // this look up should probably be moved to name resolution - auto fndecl = lookupFndecl (expr.function.get ()); + auto fndecl = lookupFndecl (expr.get_function_expr ().get ()); if (fndecl == NULL) return; // check num args match - if (fndecl->function_params.size () != expr.params.size ()) + if (fndecl->get_function_params ().size () != expr.get_params ().size ()) { rust_error_at (expr.get_locus_slow (), "differing number of arguments vs parameters to function"); return; } - typeBuffer.push_back (fndecl->return_type.get ()); + typeBuffer.push_back (fndecl->get_return_type ().get ()); expr.fndeclRef = fndecl; auto before = typeBuffer.size (); - for (auto &item : expr.params) + for (auto &item : expr.get_params ()) item->accept_vis (*this); auto numInferedParams = typeBuffer.size () - before; - if (numInferedParams != expr.params.size ()) + if (numInferedParams != expr.get_params ().size ()) { rust_error_at (expr.get_locus (), "Failed to infer all parameters"); return; } auto offs = numInferedParams - 1; - for (auto it = fndecl->function_params.rbegin (); - it != fndecl->function_params.rend (); ++it) + for (auto it = fndecl->get_function_params ().rbegin (); + it != fndecl->get_function_params ().rend (); ++it) { AST::Type *argument = typeBuffer.back (); typeBuffer.pop_back (); if (!typesAreCompatible (it->type.get (), argument, - expr.params[offs]->get_locus_slow ())) + expr.get_params ()[offs]->get_locus_slow ())) return; offs--; } @@ -762,11 +762,11 @@ TypeResolution::visit (AST::Function &function) { // always emit the function with return type in the event of nil return type // its a marker for a void function - scope.InsertType (function.function_name, function.return_type.get ()); - scope.InsertFunction (function.function_name, &function); + scope.InsertType (function.get_function_name (), function.get_return_type ().get ()); + scope.InsertFunction (function.get_function_name (), &function); scope.Push (); - for (auto ¶m : function.function_params) + for (auto ¶m : function.get_function_params ()) { if (!isTypeInScope (param.type.get (), param.get_locus ())) return; @@ -787,12 +787,12 @@ TypeResolution::visit (AST::Function &function) // ensure the return type is resolved if (function.has_function_return_type ()) { - if (!isTypeInScope (function.return_type.get (), function.get_locus ())) + if (!isTypeInScope (function.get_return_type ().get (), function.get_locus ())) return; } // walk the expression body - for (auto &stmt : function.function_body->statements) + for (auto &stmt : function.get_definition ()->statements) { stmt->accept_vis (*this); } @@ -813,7 +813,7 @@ TypeResolution::visit (AST::StructStruct &struct_item) { for (auto &field : struct_item.get_fields ()) { - if (!isTypeInScope (field.field_type.get (), + if (!isTypeInScope (field.get_field_type ().get (), Linemap::unknown_location ())) { rust_fatal_error (Linemap::unknown_location (), @@ -822,7 +822,7 @@ TypeResolution::visit (AST::StructStruct &struct_item) } } - scope.InsertStruct (struct_item.struct_name, &struct_item); + scope.InsertStruct (struct_item.get_struct_name (), &struct_item); } void diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 8071226..f9dd99c 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -3721,9 +3721,7 @@ StructExprTuple::as_string () const /* note that this does not print them with "inner attribute" syntax - * just the body */ for (const auto &attr : inner_attrs) - { str += "\n" + indent_spaces (stay) + attr.as_string (); - } } indent_spaces (out); indent_spaces (out); @@ -3749,9 +3747,7 @@ StructExprStruct::as_string () const /* note that this does not print them with "inner attribute" syntax - * just the body */ for (const auto &attr : inner_attrs) - { str += "\n " + attr.as_string (); - } } return str; @@ -3761,13 +3757,9 @@ std::string StructBase::as_string () const { if (base_struct != nullptr) - { return base_struct->as_string (); - } else - { return "ERROR_MARK_STRING - invalid struct base had as string applied"; - } } std::string @@ -3802,25 +3794,59 @@ StructExprStructFields::as_string () const else { for (const auto &field : fields) - { str += "\n " + field->as_string (); - } } str += "\n Struct base: "; if (!has_struct_base ()) + str += "none"; + else + str += struct_base.as_string (); + + return str; +} + +std::string +EnumExprStruct::as_string () const +{ + std::string str ("StructExprStruct (or subclass): "); + + str += "\n Path: " + get_enum_variant_path ().as_string (); + + str += "\n Fields: "; + if (fields.empty ()) { str += "none"; } else { - str += struct_base.as_string (); + for (const auto &field : fields) + str += "\n " + field->as_string (); } return str; } std::string +EnumExprFieldWithVal::as_string () const +{ + // used to get value string + return value->as_string (); +} + +std::string +EnumExprFieldIdentifierValue::as_string () const +{ + return field_name + " : " + EnumExprFieldWithVal::as_string (); +} + +std::string +EnumExprFieldIndexValue::as_string () const +{ + return std::to_string (index) + " : " + EnumExprFieldWithVal::as_string (); +} + +std::string EnumItem::as_string () const { // outer attributes @@ -3834,9 +3860,7 @@ EnumItem::as_string () const /* note that this does not print them with "outer attribute" syntax - * just the body */ for (const auto &attr : outer_attrs) - { str += "\n " + attr.as_string (); - } } str += "\n" + variant_name; diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 1cf8f9c..6f68542 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1849,6 +1849,8 @@ public: return std::unique_ptr<EnumExprField> (clone_enum_expr_field_impl ()); } + virtual std::string as_string () const = 0; + virtual void accept_vis (ASTVisitor &vis) = 0; protected: @@ -1870,6 +1872,8 @@ public: void accept_vis (ASTVisitor &vis) override; + std::string as_string () const override { return field_name; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1908,6 +1912,15 @@ protected: // move constructors EnumExprFieldWithVal (EnumExprFieldWithVal &&other) = default; EnumExprFieldWithVal &operator= (EnumExprFieldWithVal &&other) = default; + +public: + std::string as_string () const override; + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_value () { + rust_assert (value != nullptr); + return value; + } }; // Identifier and value variant of EnumExprField AST node @@ -1924,6 +1937,8 @@ public: field_name (std::move (field_name)) {} + std::string as_string () const override; + void accept_vis (ASTVisitor &vis) override; protected: @@ -1949,6 +1964,8 @@ public: : EnumExprFieldWithVal (std::move (field_value)), index (field_index) {} + std::string as_string () const override; + void accept_vis (ASTVisitor &vis) override; protected: @@ -1971,10 +1988,6 @@ class EnumExprStruct : public EnumVariantExpr public: std::string as_string () const override; - /*inline std::vector<std::unique_ptr<EnumExprField>> get_fields() const - { return fields; - }*/ - EnumExprStruct (PathInExpression enum_variant_path, std::vector<std::unique_ptr<EnumExprField> > variant_fields, std::vector<Attribute> outer_attribs, Location locus) @@ -2037,10 +2050,6 @@ class EnumExprTuple : public EnumVariantExpr public: std::string as_string () const override; - /*inline std::vector<std::unique_ptr<Expr>> get_values() const { - return values; - }*/ - EnumExprTuple (PathInExpression enum_variant_path, std::vector<std::unique_ptr<Expr> > variant_values, std::vector<Attribute> outer_attribs, Location locus) @@ -2080,6 +2089,9 @@ public: void accept_vis (ASTVisitor &vis) override; + const std::vector<std::unique_ptr<Expr> > &get_elems () const { return values; } + std::vector<std::unique_ptr<Expr> > &get_elems () { return values; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2128,21 +2140,17 @@ class Function; // Function call expression AST node class CallExpr : public ExprWithoutBlock { -public: std::unique_ptr<Expr> function; // inlined form of CallParams std::vector<std::unique_ptr<Expr> > params; Location locus; +public: Function *fndeclRef; std::string as_string () const override; - /*inline std::vector<std::unique_ptr<Expr>> get_params() const { - return params; - }*/ - CallExpr (std::unique_ptr<Expr> function_expr, std::vector<std::unique_ptr<Expr> > function_params, std::vector<Attribute> outer_attribs, Location locus) @@ -2199,6 +2207,16 @@ public: void mark_for_strip () override { function = nullptr; } bool is_marked_for_strip () const override { return function == nullptr; } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector<std::unique_ptr<Expr> > &get_params () const { return params; } + std::vector<std::unique_ptr<Expr> > &get_params () { return params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_function_expr () { + rust_assert (function != nullptr); + return function; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2221,10 +2239,6 @@ class MethodCallExpr : public ExprWithoutBlock public: std::string as_string () const override; - /*inline std::vector<std::unique_ptr<Expr>> get_params() const { - return params; - }*/ - MethodCallExpr (std::unique_ptr<Expr> call_receiver, PathExprSegment method_path, std::vector<std::unique_ptr<Expr> > method_params, @@ -2281,6 +2295,18 @@ public: void mark_for_strip () override { receiver = nullptr; } bool is_marked_for_strip () const override { return receiver == nullptr; } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector<std::unique_ptr<Expr> > &get_params () const { return params; } + std::vector<std::unique_ptr<Expr> > &get_params () { return params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_receiver_expr () { + rust_assert (receiver != nullptr); + return receiver; + } + + PathExprSegment get_method_name () const { return method_name; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2349,6 +2375,14 @@ public: void mark_for_strip () override { receiver = nullptr; } bool is_marked_for_strip () const override { return receiver == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_receiver_expr () { + rust_assert (receiver != nullptr); + return receiver; + } + + Identifier get_field_name () const { return field; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2362,6 +2396,7 @@ protected: struct ClosureParam { private: + std::vector<Attribute> outer_attrs; std::unique_ptr<Pattern> pattern; // bool has_type_given; @@ -2373,15 +2408,18 @@ public: // Returns whether the type of the parameter has been given. bool has_type_given () const { return type != nullptr; } + bool has_outer_attrs () const { return !outer_attrs.empty (); } + // Constructor for closure parameter ClosureParam (std::unique_ptr<Pattern> param_pattern, - std::unique_ptr<Type> param_type = nullptr) - : pattern (std::move (param_pattern)), type (std::move (param_type)) + std::unique_ptr<Type> param_type = nullptr, std::vector<Attribute> outer_attrs = {}) + : outer_attrs (std::move(outer_attrs)), pattern (std::move (param_pattern)), + type (std::move (param_type)) {} // Copy constructor required due to cloning as a result of unique_ptrs ClosureParam (ClosureParam const &other) - : pattern (other.pattern->clone_pattern ()) + : outer_attrs (other.outer_attrs) { // guard to protect from null pointer dereference if (other.pattern != nullptr) @@ -2395,6 +2433,8 @@ public: // Assignment operator must be overloaded to clone as well ClosureParam &operator= (ClosureParam const &other) { + outer_attrs = other.outer_attrs; + // guard to protect from null pointer dereference if (other.pattern != nullptr) pattern = other.pattern->clone_pattern (); @@ -2419,6 +2459,9 @@ public: static ClosureParam create_error () { return ClosureParam (nullptr); } std::string as_string () const; + + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } }; // Base closure definition expression AST node - abstract @@ -2443,6 +2486,10 @@ public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector<ClosureParam> &get_params () const { return params; } + std::vector<ClosureParam> &get_params () { return params; } }; // Represents a non-type-specified closure expression AST node @@ -2500,6 +2547,12 @@ public: void mark_for_strip () override { closure_inner = nullptr; } bool is_marked_for_strip () const override { return closure_inner == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_definition_expr () { + rust_assert (closure_inner != nullptr); + return closure_inner; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 8a85edad..5891383 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1266,7 +1266,6 @@ class LetStmt; // Rust function declaration AST node class Function : public VisItem, public InherentImplItem, public TraitImplItem { -public: FunctionQualifiers qualifiers; Identifier function_name; @@ -1288,6 +1287,7 @@ public: Location locus; +public: std::vector<LetStmt *> locals; std::string as_string () const override; @@ -1396,6 +1396,22 @@ public: return function_body; } + FunctionQualifiers get_qualifiers () const { return qualifiers; } + + Identifier get_function_name () const { return function_name; } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () { + rust_assert (has_where_clause ()); + return where_clause; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Type> &get_return_type () { + rust_assert (return_type != nullptr); + return return_type; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1518,7 +1534,7 @@ protected: // Rust base struct declaration AST node - abstract base class class Struct : public VisItem { -public: +protected: // protected to enable access by derived classes - allows better as_string Identifier struct_name; @@ -1529,8 +1545,10 @@ public: // bool has_where_clause; WhereClause where_clause; +private: Location locus; +public: // Returns whether struct has generic parameters. bool has_generics () const { return !generic_params.empty (); } @@ -1543,6 +1561,8 @@ public: void mark_for_strip () override { struct_name = ""; } bool is_marked_for_strip () const override { return struct_name.empty (); } + Identifier get_struct_name () const { return struct_name; } + protected: Struct (Identifier struct_name, std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -1587,7 +1607,7 @@ protected: // A single field in a struct struct StructField { -public: +private: // bool has_outer_attributes; std::vector<Attribute> outer_attrs; @@ -1599,6 +1619,7 @@ public: // should this store location info? +public: // Returns whether struct field has any outer attributes. bool has_outer_attributes () const { return !outer_attrs.empty (); } @@ -1662,6 +1683,16 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + + Identifier get_field_name () const { return field_name; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Type> &get_field_type () { + rust_assert (field_type != nullptr); + return field_type; + } + + Visibility get_visibility () const { return visibility; } }; // Rust struct declaration with true struct type AST node diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index ca310ca..12ce47f 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -538,7 +538,7 @@ Compilation::visit (AST::StructExprFieldIdentifierValue &field) bool found = false; for (auto &df : decl->get_fields ()) { - if (field.get_field_name ().compare (df.field_name) == 0) + if (field.get_field_name ().compare (df.get_field_name ()) == 0) { found = true; break; @@ -651,15 +651,15 @@ void Compilation::visit (AST::CallExpr &expr) { Bexpression *fn = NULL; - VISIT_POP (expr.function->get_locus_slow (), expr.function, fn, exprs); + VISIT_POP (expr.get_function_expr ()->get_locus_slow (), expr.get_function_expr (), fn, exprs); if (fn == NULL) { - rust_error_at (expr.function->get_locus_slow (), "failed to resolve"); + rust_error_at (expr.get_function_expr ()->get_locus_slow (), "failed to resolve"); return; } std::vector<Bexpression *> args; - for (auto ¶m : expr.params) + for (auto ¶m : expr.get_params ()) { Bexpression *arg = NULL; VISIT_POP (param->get_locus_slow (), param, arg, exprs); @@ -949,7 +949,7 @@ Compilation::visit (AST::Function &function) std::vector<Backend::Btyped_identifier> parameters; std::vector<Backend::Btyped_identifier> results; - for (auto ¶m : function.function_params) + for (auto ¶m : function.get_function_params ()) { // translate the type translatedType = NULL; @@ -983,7 +983,7 @@ Compilation::visit (AST::Function &function) if (function.has_function_return_type ()) { translatedType = NULL; - function.return_type->accept_vis (*this); + function.get_return_type ()->accept_vis (*this); if (translatedType == NULL) { rust_fatal_error (function.get_locus (), @@ -1000,10 +1000,10 @@ Compilation::visit (AST::Function &function) Btype *fntype = backend->function_type (receiver, parameters, results, NULL, function.get_locus ()); Bfunction *fndecl - = backend->function (fntype, function.function_name, "" /* asm_name */, + = backend->function (fntype, function.get_function_name (), "" /* asm_name */, 0 /* flags */, function.get_locus ()); - scope.InsertFunction (function.function_name, fndecl, returnType); + scope.InsertFunction (function.get_function_name (), fndecl, returnType); scope.Push (); // setup the params @@ -1039,10 +1039,10 @@ Compilation::visit (AST::Function &function) Bblock *enclosingScope = NULL; Location start_location = function.get_locus (); Location end_location; - if (function.function_body->statements.size () > 0) + if (function.get_definition ()->statements.size () > 0) { end_location - = function.function_body->statements.back ()->get_locus_slow (); + = function.get_definition ()->statements.back ()->get_locus_slow (); } auto code_block = backend->block (fndecl, enclosingScope, vars, @@ -1060,10 +1060,10 @@ Compilation::visit (AST::Function &function) function.get_locus (), &ret_var_stmt); scope.AddStatement (ret_var_stmt); } - scope.PushCurrentFunction (function.function_name, fndecl, returnType, + scope.PushCurrentFunction (function.get_function_name (), fndecl, returnType, retDecl); - for (auto &stmt : function.function_body->statements) + for (auto &stmt : function.get_definition ()->statements) stmt->accept_vis (*this); scope.PopBlock (); @@ -1092,7 +1092,7 @@ Compilation::visit (AST::StructStruct &struct_item) for (auto &field : struct_item.get_fields ()) { translatedType = NULL; - field.field_type->accept_vis (*this); + field.get_field_type ()->accept_vis (*this); if (translatedType == NULL) { rust_fatal_error ( @@ -1102,12 +1102,12 @@ Compilation::visit (AST::StructStruct &struct_item) } fields.push_back (Backend::Btyped_identifier ( - field.field_name, translatedType, + field.get_field_name (), translatedType, struct_item.get_locus () /* StructField is mi sing locus */)); } auto compiledStruct - = backend->placeholder_struct_type (struct_item.struct_name, + = backend->placeholder_struct_type (struct_item.get_struct_name (), struct_item.get_locus ()); bool ok = backend->set_placeholder_struct_type (compiledStruct, fields); if (!ok) @@ -1117,8 +1117,8 @@ Compilation::visit (AST::StructStruct &struct_item) } type_decls.push_back (compiledStruct); - scope.InsertType (struct_item.struct_name, compiledStruct); - scope.InsertStructDecl (struct_item.struct_name, &struct_item); + scope.InsertType (struct_item.get_struct_name (), compiledStruct); + scope.InsertStructDecl (struct_item.get_struct_name (), &struct_item); } void diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 65918db..ed5f365 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -512,10 +512,18 @@ namespace Rust { } } void visit(AST::EnumExprFieldIdentifier& field) override { - + // as no attrs (at moment, at least), no stripping possible + } + void visit(AST::EnumExprFieldIdentifierValue& field) override { + /* as no attrs possible (at moment, at least), only sub-expression + * stripping is possible */ + field.get_value()->accept_vis(*this); + } + void visit(AST::EnumExprFieldIndexValue& field) override { + /* as no attrs possible (at moment, at least), only sub-expression + * stripping is possible */ + field.get_value()->accept_vis(*this); } - void visit(AST::EnumExprFieldIdentifierValue& field) override {} - void visit(AST::EnumExprFieldIndexValue& field) override {} void visit(AST::EnumExprStruct& expr) override { // initial strip test based on outer attrs expander.expand_cfg_attrs(expr.get_outer_attrs()); @@ -535,13 +543,128 @@ namespace Rust { // shouldn't strip in this } } - void visit(AST::EnumExprTuple& expr) override {} - void visit(AST::EnumExprFieldless& expr) override {} - void visit(AST::CallExpr& expr) override {} - void visit(AST::MethodCallExpr& expr) override {} - void visit(AST::FieldAccessExpr& expr) override {} - void visit(AST::ClosureExprInner& expr) override {} - void visit(AST::BlockExpr& expr) override {} + void visit(AST::EnumExprTuple& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + // supposedly spec doesn't allow inner attributes in enum exprs + + /* spec says outer attributes are specifically allowed for elements + * of tuple-style enum expressions, so full stripping possible */ + auto& values = expr.get_elems(); + for (int i = 0; i < values.size();) { + auto& value = values[i]; + + // mark for stripping if required + value->accept_vis(*this); + + if (value->is_marked_for_strip()) + values.erase(values.begin() + i); + else + i++; + } + } + void visit(AST::EnumExprFieldless& expr) override { + // can't be stripped as no attrs + } + void visit(AST::CallExpr& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* should not be outer attrs on "function" expression - outer attrs + * should be associated with call expr as a whole. only sub-expr + * expansion is possible. */ + expr.get_function_expr()->accept_vis(*this); + + /* spec says outer attributes are specifically allowed for elements + * of call expressions, so full stripping possible */ + auto& params = expr.get_params(); + for (int i = 0; i < params.size();) { + auto& param = params[i]; + + // mark for stripping if required + param->accept_vis(*this); + + if (param->is_marked_for_strip()) + params.erase(params.begin() + i); + else + i++; + } + } + void visit(AST::MethodCallExpr& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* should not be outer attrs on "receiver" expression - outer attrs + * should be associated with call expr as a whole. only sub-expr + * expansion is possible. */ + expr.get_receiver_expr()->accept_vis(*this); + + // no outer attrs on paths possible + + /* spec says outer attributes are specifically allowed for elements + * of method call expressions, so full stripping possible */ + auto& params = expr.get_params(); + for (int i = 0; i < params.size();) { + auto& param = params[i]; + + // mark for stripping if required + param->accept_vis(*this); + + if (param->is_marked_for_strip()) + params.erase(params.begin() + i); + else + i++; + } + } + void visit(AST::FieldAccessExpr& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* should not be outer attrs on "receiver" expression - outer attrs + * should be associated with call expr as a whole. only sub-expr + * expansion is possible. */ + expr.get_receiver_expr()->accept_vis(*this); + } + void visit(AST::ClosureExprInner& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* strip closure parameters if required - this is specifically + * allowed by spec */ + auto& params = expr.get_params(); + for (int i = 0; i < params.size();) { + auto& param_attrs = params[i].get_outer_attrs(); + expander.expand_cfg_attrs(param_attrs); + if (expander.fails_cfg(param_attrs)) + params.erase(params.begin() + i); + else + i++; + } + } + void visit(AST::BlockExpr& expr) override { + + } void visit(AST::ClosureExprInnerTyped& expr) override {} void visit(AST::ContinueExpr& expr) override {} void visit(AST::BreakExpr& expr) override {} diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 1ad997f..769cf41 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -8512,6 +8512,8 @@ template <typename ManagedTokenSource> AST::ClosureParam Parser<ManagedTokenSource>::parse_closure_param () { + std::vector<AST::Attribute> outer_attrs = parse_outer_attributes (); + // parse pattern (which is required) std::unique_ptr<AST::Pattern> pattern = parse_pattern (); if (pattern == nullptr) @@ -8537,7 +8539,7 @@ Parser<ManagedTokenSource>::parse_closure_param () } } - return AST::ClosureParam (std::move (pattern), std::move (type)); + return AST::ClosureParam (std::move (pattern), std::move (type), std::move (outer_attrs)); } // Parses a grouped or tuple expression (disambiguates). |