diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-10-29 22:11:41 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-08 21:10:18 +0800 |
commit | 69048af1878e95e26b57febb701f884f513c7b93 (patch) | |
tree | 553c3d302a1e9ebf668b7d1629e33b09a525fbbe | |
parent | 98d429466bf783ff1a7ac59bf800061d3e67061a (diff) | |
download | gcc-69048af1878e95e26b57febb701f884f513c7b93.zip gcc-69048af1878e95e26b57febb701f884f513c7b93.tar.gz gcc-69048af1878e95e26b57febb701f884f513c7b93.tar.bz2 |
Added cfg stripping for ExternalItems
Fixed non-renaming of has_variadic_outer_attrs()
Fixed old as_string function for ExternalItem
Fixed parse_named_function_param arguments
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 80 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 33 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 170 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 32 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 83 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse.h | 3 |
6 files changed, 303 insertions, 98 deletions
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index cbeb7d4..1e95e47 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -3979,6 +3979,7 @@ EnumItemDiscriminant::as_string () const return str; } +#if 0 std::string ExternalItem::as_string () const { @@ -3993,9 +3994,7 @@ ExternalItem::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 (); - } } // start visibility on new line and with a space @@ -4003,21 +4002,35 @@ ExternalItem::as_string () const return str; } +#endif std::string ExternalStaticItem::as_string () const { - std::string str = ExternalItem::as_string (); + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* 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 (); + } + + // start visibility on new line and with a space + str += "\n" + visibility.as_string () + " "; str += "static "; if (has_mut) - { str += "mut "; - } // add name - str += get_item_name (); + str += item_name; // add type on new line str += "\n Type: " + item_type->as_string (); @@ -4028,12 +4041,27 @@ ExternalStaticItem::as_string () const std::string ExternalFunctionItem::as_string () const { - std::string str = ExternalItem::as_string (); + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* 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 (); + } + + // start visibility on new line and with a space + str += "\n" + visibility.as_string () + " "; str += "fn "; // add name - str += get_item_name (); + str += item_name; // generic params str += "\n Generic params: "; @@ -4061,19 +4089,29 @@ ExternalFunctionItem::as_string () const // function params str += "\n Function params: "; - if (function_params.empty ()) + if (function_params.empty () && !has_variadics) { str += "none"; } else { for (const auto ¶m : function_params) - { str += "\n " + param.as_string (); - } + if (has_variadics) { - str += "\n .. (variadic)"; + str += "\n variadic outer attrs: "; + if (has_variadic_outer_attrs ()) + { + + for (const auto &attr : variadic_outer_attrs) + str += "\n " + attr.as_string (); + } + else + { + str += "none"; + } + str += "\n ... (variadic)"; } } @@ -4083,13 +4121,9 @@ ExternalFunctionItem::as_string () const // where clause str += "\n Where clause: "; if (has_where_clause ()) - { str += where_clause.as_string (); - } else - { str += "none"; - } return str; } @@ -4097,7 +4131,19 @@ ExternalFunctionItem::as_string () const std::string NamedFunctionParam::as_string () const { - std::string str = name; + std::string str = "outer attributes: "; + + if (!has_outer_attrs ()) + { + str += "none"; + } + else + { + for (const auto& attr : outer_attrs) + str += "\n " + attr.as_string (); + } + + str += "\n" + name; str += "\n Type: " + param_type->as_string (); diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 31c547a..4c4b043 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1289,12 +1289,36 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; }; +// Abstract base class for an item used inside an extern block +class ExternalItem +{ +public: + virtual ~ExternalItem () {} + + // Unique pointer custom clone function + std::unique_ptr<ExternalItem> clone_external_item () const + { + return std::unique_ptr<ExternalItem> (clone_external_item_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; + +protected: + // Clone function implementation as pure virtual method + virtual ExternalItem *clone_external_item_impl () const = 0; +}; + /* A macro invocation item (or statement) AST node (i.e. semi-coloned macro * invocation) */ class MacroInvocationSemi : public MacroItem, public TraitItem, public InherentImplItem, - public TraitImplItem + public TraitImplItem, public ExternalItem { std::vector<Attribute> outer_attrs; SimplePath path; @@ -1394,6 +1418,13 @@ protected: { return clone_macro_invocation_semi_impl (); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MacroInvocationSemi *clone_external_item_impl () const override + { + return clone_macro_invocation_semi_impl (); + } }; // A crate AST object - holds all the data for a single compilation unit diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index c35e65f..8542638 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -2964,6 +2964,7 @@ protected: TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); } }; +#if 0 // Abstract base class for an item used inside an extern block class ExternalItem { @@ -3040,35 +3041,57 @@ protected: // possibly make this public if required std::string get_item_name () const { return item_name; } }; +#endif // A static item used in an extern block class ExternalStaticItem : public ExternalItem { + // bool has_outer_attrs; + std::vector<Attribute> outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier item_name; + Location locus; + bool has_mut; std::unique_ptr<Type> item_type; public: ExternalStaticItem (Identifier item_name, std::unique_ptr<Type> item_type, - bool is_mut, Visibility vis, - std::vector<Attribute> outer_attrs, Location locus) - : ExternalItem (std::move (item_name), std::move (vis), - std::move (outer_attrs), locus), - has_mut (is_mut), item_type (std::move (item_type)) + bool is_mut, Visibility vis, std::vector<Attribute> outer_attrs, + Location locus) + : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), + item_name (std::move (item_name)), locus (locus), has_mut (is_mut), + item_type (std::move (item_type)) {} // Copy constructor ExternalStaticItem (ExternalStaticItem const &other) - : ExternalItem (other), has_mut (other.has_mut), - item_type (other.item_type->clone_type ()) - {} + : outer_attrs (other.outer_attrs), visibility (other.visibility), item_name (other.item_name), + locus (other.locus), has_mut (other.has_mut) + { + // guard to prevent null dereference (only required if error state) + if (other.item_type != nullptr) + item_type = other.item_type->clone_type (); + } // Overloaded assignment operator to clone ExternalStaticItem &operator= (ExternalStaticItem const &other) { - ExternalItem::operator= (other); - item_type = other.item_type->clone_type (); + outer_attrs = other.outer_attrs; + visibility = other.visibility; + item_name = other.item_name; + locus = other.locus; has_mut = other.has_mut; + // guard to prevent null dereference (only required if error state) + if (other.item_type != nullptr) + item_type = other.item_type->clone_type (); + else + item_type = nullptr; + return *this; } @@ -3080,6 +3103,22 @@ public: void accept_vis (ASTVisitor &vis) override; + // Returns whether item has outer attributes. + bool has_outer_attrs () const { return !outer_attrs.empty (); } + + // Returns whether item has non-default visibility. + bool has_visibility () const { return !visibility.is_error (); } + + Location get_locus () const { return locus; } + + // Based on idea that type should never be null. + void mark_for_strip () override { item_type = nullptr; }; + bool is_marked_for_strip () const override { return item_type == nullptr; }; + + // 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; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -3094,17 +3133,22 @@ struct NamedFunctionParam { private: // bool has_name; // otherwise is _ - Identifier name; // TODO: handle wildcard in identifier? + std::string name; std::unique_ptr<Type> param_type; // TODO: should this store location data? + // seemingly new since writing this node + std::vector<Attribute> outer_attrs; + public: - // Returns whether the named function parameter has a name (i.e. name is not - // '_'). + /* Returns whether the named function parameter has a name (i.e. name is not + * '_'). */ bool has_name () const { return name != "_"; } + bool has_outer_attrs () const { return !outer_attrs.empty (); } + // Returns whether the named function parameter is in an error state. bool is_error () const { @@ -3115,17 +3159,21 @@ public: // Creates an error state named function parameter. static NamedFunctionParam create_error () { - return NamedFunctionParam ("", nullptr); + return NamedFunctionParam ("", nullptr, {}); } - NamedFunctionParam (Identifier name, std::unique_ptr<Type> param_type) - : name (std::move (name)), param_type (std::move (param_type)) + NamedFunctionParam (std::string name, std::unique_ptr<Type> param_type, std::vector<Attribute> outer_attrs) + : name (std::move (name)), param_type (std::move (param_type)), outer_attrs (std::move (outer_attrs)) {} // Copy constructor NamedFunctionParam (NamedFunctionParam const &other) - : name (other.name), param_type (other.param_type->clone_type ()) - {} + : name (other.name), outer_attrs (other.outer_attrs) + { + // guard to prevent null dereference (only required if error state) + if (other.param_type != nullptr) + param_type = other.param_type->clone_type (); + } ~NamedFunctionParam () = default; @@ -3133,8 +3181,14 @@ public: NamedFunctionParam &operator= (NamedFunctionParam const &other) { name = other.name; - param_type = other.param_type->clone_type (); // has_name = other.has_name; + outer_attrs = other.outer_attrs; + + // guard to prevent null dereference (only required if error state) + if (other.param_type != nullptr) + param_type = other.param_type->clone_type (); + else + param_type = nullptr; return *this; } @@ -3144,11 +3198,28 @@ public: NamedFunctionParam &operator= (NamedFunctionParam &&other) = default; std::string as_string () const; + + // Based on idea that nane should never be empty. + void mark_for_strip () { param_type = nullptr; }; + bool is_marked_for_strip () const { return is_error (); }; + + // 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; } }; // A function item used in an extern block class ExternalFunctionItem : public ExternalItem { + // bool has_outer_attrs; + std::vector<Attribute> outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier item_name; + Location locus; + // bool has_generics; // Generics generic_params; std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined @@ -3162,6 +3233,7 @@ class ExternalFunctionItem : public ExternalItem std::vector<NamedFunctionParam> function_params; bool has_variadics; + std::vector<Attribute> variadic_outer_attrs; public: // Returns whether item has generic parameters. @@ -3173,28 +3245,48 @@ public: // Returns whether item has a where clause. bool has_where_clause () const { return !where_clause.is_empty (); } + // Returns whether item has outer attributes. + bool has_outer_attrs () const { return !outer_attrs.empty (); } + + // Returns whether item has non-default visibility. + bool has_visibility () const { return !visibility.is_error (); } + + // Returns whether item has variadic parameters. + bool is_variadic () const { return has_variadics; } + + // Returns whether item has outer attributes on its variadic parameters. + bool has_variadic_outer_attrs () const { return !variadic_outer_attrs.empty (); } + + Location get_locus () const { return locus; } + ExternalFunctionItem ( Identifier item_name, std::vector<std::unique_ptr<GenericParam>> generic_params, std::unique_ptr<Type> return_type, WhereClause where_clause, - std::vector<NamedFunctionParam> function_params, bool has_variadics, + std::vector<NamedFunctionParam> function_params, bool has_variadics, std::vector<Attribute> variadic_outer_attrs, Visibility vis, std::vector<Attribute> outer_attrs, Location locus) - : ExternalItem (std::move (item_name), std::move (vis), - std::move (outer_attrs), locus), + : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), + item_name (std::move (item_name)), locus (locus), generic_params (std::move (generic_params)), return_type (std::move (return_type)), where_clause (std::move (where_clause)), function_params (std::move (function_params)), - has_variadics (has_variadics) - {} + has_variadics (has_variadics), variadic_outer_attrs (std::move (variadic_outer_attrs)) + { + // TODO: assert that if has variadic outer attrs, then has_variadics is true? + } // Copy constructor with clone ExternalFunctionItem (ExternalFunctionItem const &other) - : ExternalItem (other), return_type (other.return_type->clone_type ()), - where_clause (other.where_clause), + : outer_attrs (other.outer_attrs), visibility (other.visibility), item_name (other.item_name), + locus (other.locus), where_clause (other.where_clause), function_params (other.function_params), - has_variadics (other.has_variadics) + has_variadics (other.has_variadics), variadic_outer_attrs (other.variadic_outer_attrs) { + // guard to prevent null pointer dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -3203,11 +3295,20 @@ public: // Overloaded assignment operator with clone ExternalFunctionItem &operator= (ExternalFunctionItem const &other) { - ExternalItem::operator= (other); - return_type = other.return_type->clone_type (); + outer_attrs = other.outer_attrs; + visibility = other.visibility; + item_name = other.item_name; + locus = other.locus; where_clause = other.where_clause; function_params = other.function_params; has_variadics = other.has_variadics; + variadic_outer_attrs = other.variadic_outer_attrs; + + // guard to prevent null pointer dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) @@ -3224,6 +3325,17 @@ public: void accept_vis (ASTVisitor &vis) override; + // Based on idea that nane should never be empty. + void mark_for_strip () override { item_name = ""; }; + bool is_marked_for_strip () const override { return item_name.empty (); }; + + // 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; } + + std::vector<NamedFunctionParam> &get_function_params () { return function_params; } + const std::vector<NamedFunctionParam> &get_function_params () const { return function_params; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index a7d2a1a..80ad5d0 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -125,8 +125,35 @@ namespace Rust { void visit(AST::Trait& trait) override {} void visit(AST::InherentImpl& impl) override {} void visit(AST::TraitImpl& impl) override {} - void visit(AST::ExternalStaticItem& item) override {} - void visit(AST::ExternalFunctionItem& item) override {} + void visit(AST::ExternalStaticItem& item) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(item.get_outer_attrs())) { + item.mark_for_strip(); + return; + } + } + void visit(AST::ExternalFunctionItem& item) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(item.get_outer_attrs())) { + item.mark_for_strip(); + return; + } + + /* strip function parameters if required - this is specifically + * allowed by spec */ + auto& params = item.get_function_params(); + for (auto i = 0; i < params.size(); ) { + if (expander.fails_cfg (params[i].get_outer_attrs ())) + params.erase (params.begin() + i); + else + i++; + } + + /* TODO: assuming that variadic nature cannot be stripped. If this + * is not true, then have code here to do so. */ + } void visit(AST::ExternBlock& block) override { // initial strip test based on outer attrs expander.expand_cfg_attrs(block.get_outer_attrs()); @@ -154,7 +181,6 @@ namespace Rust { extern_items.erase (extern_items.begin() + i); else i++; - } } diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 4d54242..9c293dc 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -5632,62 +5632,51 @@ Parser<ManagedTokenSource>::parse_external_item () // parse parameters std::vector<AST::NamedFunctionParam> function_params; bool is_variadic = false; + std::vector<AST::Attribute> variadic_attrs; const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_PAREN) - { - AST::NamedFunctionParam param = parse_named_function_param (); + while (t->get_id () != RIGHT_PAREN) { + std::vector<AST::Attribute> maybe_variadic_attrs = parse_outer_attributes (); + if (lexer.peek_token ()->get_id () == ELLIPSIS) { + // variadic - use attrs for this + lexer.skip_token (); + is_variadic = true; + variadic_attrs = std::move (maybe_variadic_attrs); + t = lexer.peek_token (); + + if (t->get_id() != RIGHT_PAREN) { + rust_error_at (t->get_locus (), + "expected right parentheses after variadic in named function " + "parameters, found %qs", + t->get_token_description ()); + skip_after_semicolon (); + return nullptr; + } - if (param.is_error ()) - { - // is this an error? probably - rust_error_at (t->get_locus (), - "could not parse named function parameter in " - "external function"); - skip_after_semicolon (); - return nullptr; - } + break; + } + AST::NamedFunctionParam param = parse_named_function_param (std::move (maybe_variadic_attrs)); + if (param.is_error ()) { + rust_error_at (t->get_locus (), + "could not parse named function parameter in external function"); + skip_after_semicolon (); + return nullptr; + } function_params.push_back (std::move (param)); - t = lexer.peek_token (); - if (t->get_id () != COMMA) - { - if (t->get_id () != RIGHT_PAREN) - { - rust_error_at (t->get_locus (), - "expected comma or right parentheses in " - "named function parameters, found %qs", - t->get_token_description ()); - } - else - { - // end of loop + if (lexer.peek_token ()->get_id () != COMMA) break; - } - } + // skip comma lexer.skip_token (); - t = lexer.peek_token (); + } - // parse variadic ... if it exists - if (t->get_id () == ELLIPSIS - && lexer.peek_token (1)->get_id () == RIGHT_PAREN) - { - lexer.skip_token (); - - is_variadic = true; - - t = lexer.peek_token (); - } - } - - if (!skip_token (RIGHT_PAREN)) - { + if (!skip_token (RIGHT_PAREN)) { skip_after_semicolon (); return nullptr; - } + } // parse (optional) return type std::unique_ptr<AST::Type> return_type = parse_function_return_type (); @@ -5705,7 +5694,7 @@ Parser<ManagedTokenSource>::parse_external_item () new AST::ExternalFunctionItem ( std::move (ident), std::move (generic_params), std::move (return_type), std::move (where_clause), - std::move (function_params), is_variadic, std::move (vis), + std::move (function_params), is_variadic, std::move (variadic_attrs), std::move (vis), std::move (outer_attrs), locus)); } default: @@ -5722,10 +5711,10 @@ Parser<ManagedTokenSource>::parse_external_item () * identifier). */ template <typename ManagedTokenSource> AST::NamedFunctionParam -Parser<ManagedTokenSource>::parse_named_function_param () +Parser<ManagedTokenSource>::parse_named_function_param (std::vector<AST::Attribute> outer_attrs) { // parse identifier/_ - Identifier name; + std::string name; const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) @@ -5760,7 +5749,7 @@ Parser<ManagedTokenSource>::parse_named_function_param () return AST::NamedFunctionParam::create_error (); } - return AST::NamedFunctionParam (std::move (name), std::move (param_type)); + return AST::NamedFunctionParam (std::move (name), std::move (param_type), std::move (outer_attrs)); } // Parses a statement (will further disambiguate any statement). diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index e2f3a78..82d8d6f 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -230,7 +230,8 @@ private: parse_extern_block (AST::Visibility vis, std::vector<AST::Attribute> outer_attrs); std::unique_ptr<AST::ExternalItem> parse_external_item (); - AST::NamedFunctionParam parse_named_function_param (); + AST::NamedFunctionParam parse_named_function_param ( + std::vector<AST::Attribute> outer_attrs = std::vector<AST::Attribute> ()); AST::Method parse_method (); // Expression-related (Pratt parsed) |