From 423462fb6785896c8031319d50ac38fbca3afb51 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Mon, 5 Oct 2020 22:23:06 +0800 Subject: Added proper cfg_attr expansion --- gcc/rust/ast/rust-ast-full-test.cc | 62 ++++++++++++++++++++++++++++++++---- gcc/rust/ast/rust-ast.h | 19 ++++------- gcc/rust/ast/rust-macro.h | 2 ++ gcc/rust/expand/rust-macro-expand.cc | 31 ++++++++++-------- gcc/rust/expand/rust-macro-expand.h | 6 +++- 5 files changed, 86 insertions(+), 34 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 0cdac5f..44a38ac 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -5048,18 +5048,19 @@ MacroParser::parse_meta_item_lit () bool AttrInputMetaItemContainer::check_cfg_predicate (const Session &session) const { - /* cfg value of container is purely based on cfg of each inner item - all - * must be true */ - for (const auto &inner_item : items) + /* NOTE: assuming that only first item must be true - cfg should only have one item, and cfg_attr only has first item as predicate. TODO ensure that this is correct. */ + if (items.empty ()) + return false; + + return items[0]->check_cfg_predicate (session); + + /*for (const auto &inner_item : items) { if (!inner_item->check_cfg_predicate (session)) return false; } - /* TODO: as far as I can tell, there should only be a single element to - * check here, so ensure there is only a single element in items too? */ - - return true; + return true;*/ } bool @@ -5346,6 +5347,53 @@ MetaItemPathLit::to_attribute () const new AttrInputLiteral (lit))); } +std::vector AttrInputMetaItemContainer::separate_cfg_attrs () const { + rust_assert (!items.empty ()); + + if (items.size () == 1) + return {}; + + std::vector attrs; + attrs.reserve (items.size () - 1); + + for (auto it = items.begin () + 1; it != items.end (); ++it) { + Attribute attr = (*it)->to_attribute (); + if (attr.is_empty ()) { + // TODO should this be an error that causes us to chuck out everything? + continue; + } + attrs.push_back (std::move (attr)); + } + + attrs.shrink_to_fit (); + return attrs; + } + +bool Attribute::check_cfg_predicate (const Session &session) + { + /* assume that cfg predicate actually can exist, i.e. attribute has cfg or + * cfg_attr path */ + if (!has_attr_input () || (path.as_string () != "cfg" && path.as_string () != "cfg_attr")) + return false; + + // TODO: maybe replace with storing a "has been parsed" variable? + parse_attr_to_meta_item (); + // can't be const because of this anyway + + return attr_input->check_cfg_predicate (session); + } + +std::vector Attribute::separate_cfg_attrs () { + if (!has_attr_input () || path.as_string () != "cfg_attr") + return {}; + + // TODO: maybe replace with storing a "has been parsed" variable? + parse_attr_to_meta_item (); + // can't be const because of this anyway + + return attr_input->separate_cfg_attrs (); + } + /* Visitor implementations - these are short but inlining can't happen anyway * due to virtual functions and I didn't want to make the ast header includes * any longer than they already are. */ diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index ad3722f..cfb5f9b 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -83,6 +83,8 @@ public: // Parse attribute input to meta item, if possible virtual AttrInput *parse_to_meta_item () const { return nullptr; } + virtual std::vector separate_cfg_attrs () const { return {}; } + protected: // pure virtual clone implementation virtual AttrInput *clone_attr_input_impl () const = 0; @@ -590,20 +592,9 @@ public: /* Determines whether cfg predicate is true and item with attribute should not * be stripped. */ - bool check_cfg_predicate (const Session &session) - { - /* assume that cfg predicate actually can exist, i.e. attribute has cfg or - * cfg_attr path */ - - if (!has_attr_input ()) - return false; + bool check_cfg_predicate (const Session &session); - // TODO: maybe replace with storing a "has been parsed" variable? - parse_attr_to_meta_item (); - // can't be const because of this anyway - - return attr_input->check_cfg_predicate (session); - } + std::vector separate_cfg_attrs (); protected: // not virtual as currently no subclasses of Attribute, but could be in future @@ -683,6 +674,8 @@ public: clone_attr_input_meta_item_container_impl ()); } + std::vector separate_cfg_attrs () const override; + protected: // Use covariance to implement clone function as returning this type AttrInputMetaItemContainer *clone_attr_input_impl () const override diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index b51b149..9ecbb51 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -572,6 +572,8 @@ protected: }; // Object that parses macros from a token stream. +/* TODO: would "AttributeParser" be a better name? MetaItems are only for + * attributes, I believe */ struct MacroParser { private: diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 8df1d1a..6afe8a5 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -25,19 +25,23 @@ namespace Rust { } /* Determines whether cfg predicate is true and item with attribute should not - * be stripped. */ - bool check_cfg_predicate() {} - - /* Determines whether cfg predicate is true and item with attribute should not - * be stripped. */ - bool check_cfg(AST::Attribute& attr) {} + * be stripped. TODO can this be const reference or does it have to mutate? */ + bool MacroExpander::check_cfg(AST::Attribute& attr) {} // Expands cfg_attr attributes. - void expand_attrs_cfgattr(std::vector& attrs) { - for (auto it = attrs.begin(); it != attrs.end();) { - auto& attr = *it; + void MacroExpander::expand_cfg_attrs(std::vector& attrs) { + for (int i = 0; i < attrs.size (); ) { + auto& attr = attrs[i]; if (attr.get_path() == "cfg_attr") { - if (check_cfg(attr)) { + if (attr.check_cfg_predicate (session)) { + // split off cfg_attr + std::vector new_attrs = attr.separate_cfg_attrs (); + + // remove attr from vector + attrs.erase (attrs.begin () + i); + + // add new attrs to vector + attrs.insert (attrs.begin() + i, std::make_move_iterator (new_attrs.begin ()), std::make_move_iterator (new_attrs.end ())); } /* do something - if feature (first token in tree) is in fact enabled, @@ -47,17 +51,18 @@ namespace Rust { * recursive, so check for expanded attributes being recursive and * possibly recursively call the expand_attrs? */ } else { - ++it; + i++; } } + attrs.shrink_to_fit (); } void MacroExpander::expand_crate() { /* fill macro/decorator map from init list? not sure where init list comes * from? */ - // expand crate attributes - expand_attrs_cfgattr(crate.inner_attrs); + // expand crate cfg_attr attributes + expand_cfg_attrs(crate.inner_attrs); // expand module attributes? diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 92cb06d..7e684a9 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -27,7 +27,7 @@ struct MacroExpander ExpansionCfg cfg; unsigned int expansion_depth = 0; - MacroExpander (AST::Crate &crate, ExpansionCfg cfg) : cfg (cfg), crate (crate) + MacroExpander (AST::Crate &crate, ExpansionCfg cfg, Session &session) : cfg (cfg), crate (crate), session (session) {} ~MacroExpander () = default; @@ -40,11 +40,15 @@ struct MacroExpander // should this be public or private? void expand_invoc (std::unique_ptr &invoc); + void expand_cfg_attrs(std::vector& attrs); + bool check_cfg(AST::Attribute& attr); + /* TODO: make it extend ASTVisitor so that individual items can be accessed * properly? */ private: AST::Crate &crate; + Session &session; }; } // namespace Rust -- cgit v1.1 From eb644945a4f1bcac234a099f904812dcbbafcc93 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sun, 11 Oct 2020 22:11:02 +0800 Subject: Added cfg stripping code (will top-level strip currently) Rearranged order of definitions in rust-ast.h, should fix compile error Attempted error fix for Attribute-AttrInput interaction and Crate stripping Fixed constructor arguments for MacroExpander --- gcc/rust/ast/rust-ast-full-test.cc | 24 +++- gcc/rust/ast/rust-ast.h | 259 +++++++++++++++++++---------------- gcc/rust/expand/rust-macro-expand.cc | 33 +++-- gcc/rust/expand/rust-macro-expand.h | 2 +- gcc/rust/rust-session-manager.cc | 2 +- 5 files changed, 184 insertions(+), 136 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 44a38ac..e269645 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -171,13 +171,29 @@ Attribute::as_string () const { std::string path_str = path.as_string (); if (attr_input == nullptr) - { return path_str; - } else - { return path_str + attr_input->as_string (); - } +} + +// Copy constructor must deep copy attr_input as unique pointer +Attribute::Attribute (Attribute const &other) : path (other.path), locus (other.locus) +{ + // guard to protect from null pointer dereference + if (other.attr_input != nullptr) + attr_input = other.attr_input->clone_attr_input (); +} + +// overload assignment operator to use custom clone method +Attribute &Attribute::operator= (Attribute const &other) +{ + path = other.path; + locus = other.locus; + // guard to protect from null pointer dereference + if (other.attr_input != nullptr) + attr_input = other.attr_input->clone_attr_input (); + + return *this; } std::string diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index cfb5f9b..90e3504 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -62,34 +62,6 @@ Location? };*/ // decided to not have node as a "node" would never need to be stored -// Attribute body - abstract base class -class AttrInput -{ -public: - virtual ~AttrInput () {} - - // Unique pointer custom clone function - std::unique_ptr clone_attr_input () const - { - return std::unique_ptr (clone_attr_input_impl ()); - } - - virtual std::string as_string () const = 0; - - virtual void accept_vis (ASTVisitor &vis) = 0; - - virtual bool check_cfg_predicate (const Session &session) const = 0; - - // Parse attribute input to meta item, if possible - virtual AttrInput *parse_to_meta_item () const { return nullptr; } - - virtual std::vector separate_cfg_attrs () const { return {}; } - -protected: - // pure virtual clone implementation - virtual AttrInput *clone_attr_input_impl () const = 0; -}; - // forward decl for use in token tree method class Token; @@ -281,95 +253,6 @@ public: bool is_error () const { return value_as_string == ""; } }; -// A token tree with delimiters -class DelimTokenTree : public TokenTree, public AttrInput -{ - DelimType delim_type; - std::vector> token_trees; - Location locus; - -protected: - DelimTokenTree *clone_delim_tok_tree_impl () const - { - return new DelimTokenTree (*this); - } - - /* Use covariance to implement clone function as returning a DelimTokenTree - * object */ - DelimTokenTree *clone_attr_input_impl () const override - { - return clone_delim_tok_tree_impl (); - } - - /* Use covariance to implement clone function as returning a DelimTokenTree - * object */ - DelimTokenTree *clone_token_tree_impl () const override - { - return clone_delim_tok_tree_impl (); - } - -public: - DelimTokenTree (DelimType delim_type, - std::vector> token_trees - = std::vector> (), - Location locus = Location ()) - : delim_type (delim_type), token_trees (std::move (token_trees)), - locus (locus) - {} - - // Copy constructor with vector clone - DelimTokenTree (DelimTokenTree const &other) - : delim_type (other.delim_type), locus (other.locus) - { - token_trees.reserve (other.token_trees.size ()); - for (const auto &e : other.token_trees) - token_trees.push_back (e->clone_token_tree ()); - } - - // overloaded assignment operator with vector clone - DelimTokenTree &operator= (DelimTokenTree const &other) - { - delim_type = other.delim_type; - locus = other.locus; - - token_trees.reserve (other.token_trees.size ()); - for (const auto &e : other.token_trees) - token_trees.push_back (e->clone_token_tree ()); - - return *this; - } - - // move constructors - DelimTokenTree (DelimTokenTree &&other) = default; - DelimTokenTree &operator= (DelimTokenTree &&other) = default; - - static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); } - - std::string as_string () const override; - - void accept_vis (ASTVisitor &vis) override; - - bool - check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override - { - // this should never be called - should be converted first - return false; - } - - AttrInput *parse_to_meta_item () const override; - - std::vector> to_token_stream () const override; - - std::unique_ptr clone_delim_token_tree () const - { - return std::unique_ptr (clone_delim_tok_tree_impl ()); - } -}; - -/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to - * be defined */ -class AttrInputLiteral; - /* TODO: move applicable stuff into here or just don't include it because * nothing uses it A segment of a path (maybe) */ class PathSegment @@ -462,6 +345,9 @@ public: } }; +// forward decl for Attribute +class AttrInput; + // aka Attr // Attribute AST representation struct Attribute @@ -490,15 +376,17 @@ public: ~Attribute () = default; // Copy constructor must deep copy attr_input as unique pointer - Attribute (Attribute const &other) : path (other.path), locus (other.locus) + /*Attribute (Attribute const &other) : path (other.path), locus (other.locus) { // guard to protect from null pointer dereference if (other.attr_input != nullptr) attr_input = other.attr_input->clone_attr_input (); - } + }*/ + // no point in being defined inline as requires virtual call anyway + Attribute (const Attribute &other); // overload assignment operator to use custom clone method - Attribute &operator= (Attribute const &other) + /*Attribute &operator= (Attribute const &other) { path = other.path; locus = other.locus; @@ -507,7 +395,9 @@ public: attr_input = other.attr_input->clone_attr_input (); return *this; - } + }*/ + // no point in being defined inline as requires virtual call anyway + Attribute &operator= (const Attribute &other); // default move semantics Attribute (Attribute &&other) = default; @@ -604,6 +494,123 @@ protected: } }; +// Attribute body - abstract base class +class AttrInput +{ +public: + virtual ~AttrInput () {} + + // Unique pointer custom clone function + std::unique_ptr clone_attr_input () const + { + return std::unique_ptr (clone_attr_input_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual bool check_cfg_predicate (const Session &session) const = 0; + + // Parse attribute input to meta item, if possible + virtual AttrInput *parse_to_meta_item () const { return nullptr; } + + virtual std::vector separate_cfg_attrs () const { return {}; } + +protected: + // pure virtual clone implementation + virtual AttrInput *clone_attr_input_impl () const = 0; +}; + +// A token tree with delimiters +class DelimTokenTree : public TokenTree, public AttrInput +{ + DelimType delim_type; + std::vector> token_trees; + Location locus; + +protected: + DelimTokenTree *clone_delim_tok_tree_impl () const + { + return new DelimTokenTree (*this); + } + + /* Use covariance to implement clone function as returning a DelimTokenTree + * object */ + DelimTokenTree *clone_attr_input_impl () const override + { + return clone_delim_tok_tree_impl (); + } + + /* Use covariance to implement clone function as returning a DelimTokenTree + * object */ + DelimTokenTree *clone_token_tree_impl () const override + { + return clone_delim_tok_tree_impl (); + } + +public: + DelimTokenTree (DelimType delim_type, + std::vector> token_trees + = std::vector> (), + Location locus = Location ()) + : delim_type (delim_type), token_trees (std::move (token_trees)), + locus (locus) + {} + + // Copy constructor with vector clone + DelimTokenTree (DelimTokenTree const &other) + : delim_type (other.delim_type), locus (other.locus) + { + token_trees.reserve (other.token_trees.size ()); + for (const auto &e : other.token_trees) + token_trees.push_back (e->clone_token_tree ()); + } + + // overloaded assignment operator with vector clone + DelimTokenTree &operator= (DelimTokenTree const &other) + { + delim_type = other.delim_type; + locus = other.locus; + + token_trees.reserve (other.token_trees.size ()); + for (const auto &e : other.token_trees) + token_trees.push_back (e->clone_token_tree ()); + + return *this; + } + + // move constructors + DelimTokenTree (DelimTokenTree &&other) = default; + DelimTokenTree &operator= (DelimTokenTree &&other) = default; + + static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); } + + std::string as_string () const override; + + void accept_vis (ASTVisitor &vis) override; + + bool + check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override + { + // this should never be called - should be converted first + return false; + } + + AttrInput *parse_to_meta_item () const override; + + std::vector> to_token_stream () const override; + + std::unique_ptr clone_delim_token_tree () const + { + return std::unique_ptr (clone_delim_tok_tree_impl ()); + } +}; + +/* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to + * be defined */ +class AttrInputLiteral; + // Forward decl - defined in rust-macro.h class MetaNameValueStr; @@ -1452,6 +1459,16 @@ public: // Get crate representation as string (e.g. for debugging). std::string as_string () const; + + // Delete all crate information, e.g. if fails cfg. + void strip_crate () { + inner_attrs.clear (); + inner_attrs.shrink_to_fit (); + + items.clear (); + items.shrink_to_fit (); + // TODO: is this the best way to do this? + } }; // Base path expression AST node - abstract diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 6afe8a5..4a39be3 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -24,24 +24,31 @@ namespace Rust { - derive container macro - unreachable*/ } - /* Determines whether cfg predicate is true and item with attribute should not - * be stripped. TODO can this be const reference or does it have to mutate? */ - bool MacroExpander::check_cfg(AST::Attribute& attr) {} + /* Determines whether any cfg predicate is false and hence item with attributes should + * be stripped. */ + bool MacroExpander::fails_cfg(std::vector& attrs) { + for (auto& attr : attrs) { + if (attr.get_path() == "cfg" && !attr.check_cfg_predicate(session)) + return true; + } + return false; + } // Expands cfg_attr attributes. void MacroExpander::expand_cfg_attrs(std::vector& attrs) { - for (int i = 0; i < attrs.size (); ) { + for (int i = 0; i < attrs.size();) { auto& attr = attrs[i]; if (attr.get_path() == "cfg_attr") { - if (attr.check_cfg_predicate (session)) { + if (attr.check_cfg_predicate(session)) { // split off cfg_attr - std::vector new_attrs = attr.separate_cfg_attrs (); + std::vector new_attrs = attr.separate_cfg_attrs(); // remove attr from vector - attrs.erase (attrs.begin () + i); + attrs.erase(attrs.begin() + i); // add new attrs to vector - attrs.insert (attrs.begin() + i, std::make_move_iterator (new_attrs.begin ()), std::make_move_iterator (new_attrs.end ())); + attrs.insert(attrs.begin() + i, std::make_move_iterator(new_attrs.begin()), + std::make_move_iterator(new_attrs.end())); } /* do something - if feature (first token in tree) is in fact enabled, @@ -54,16 +61,24 @@ namespace Rust { i++; } } - attrs.shrink_to_fit (); + attrs.shrink_to_fit(); } void MacroExpander::expand_crate() { /* fill macro/decorator map from init list? not sure where init list comes * from? */ + // TODO: does cfg apply for inner attributes? research. + // the apparent answer (from playground test) is yes + // expand crate cfg_attr attributes expand_cfg_attrs(crate.inner_attrs); + if (fails_cfg(crate.inner_attrs)) { + // basically, delete whole crate + crate.strip_crate(); + // TODO: maybe create warning here? probably not desired behaviour + } // expand module attributes? // expand module tree recursively diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 7e684a9..a7fe076 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -41,7 +41,7 @@ struct MacroExpander void expand_invoc (std::unique_ptr &invoc); void expand_cfg_attrs(std::vector& attrs); - bool check_cfg(AST::Attribute& attr); + bool fails_cfg(std::vector& attr); /* TODO: make it extend ASTVisitor so that individual items can be accessed * properly? */ diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 20c7e34..7940df7 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -715,7 +715,7 @@ Session::expansion (AST::Crate &crate) // create extctxt? from parse session, cfg, and resolver? /* expand by calling cxtctxt object's monotonic_expander's expand_crate * method. */ - MacroExpander expander (crate, cfg); + MacroExpander expander (crate, cfg, *this); expander.expand_crate (); // error reporting - check unused macros, get missing fragment specifiers -- cgit v1.1 From 98d429466bf783ff1a7ac59bf800061d3e67061a Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sun, 25 Oct 2020 17:04:55 +0800 Subject: Added strip-marking to statements, items and expressions (to allow them to be stripped from their parents) Fixed compile errors and added more stripping behaviour for extern blocks --- gcc/rust/ast/rust-ast-full-test.cc | 41 +- gcc/rust/ast/rust-ast.h | 98 ++-- gcc/rust/ast/rust-expr.h | 1000 +++++++++++++++++----------------- gcc/rust/ast/rust-item.h | 319 ++++++----- gcc/rust/ast/rust-macro.h | 44 +- gcc/rust/ast/rust-path.h | 77 ++- gcc/rust/ast/rust-pattern.h | 21 +- gcc/rust/ast/rust-stmt.h | 85 ++- gcc/rust/ast/rust-type.h | 98 +--- gcc/rust/expand/rust-macro-expand.cc | 219 +++++++- gcc/rust/rust-session-manager.cc | 3 +- 11 files changed, 1153 insertions(+), 852 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index e269645..cbeb7d4 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -192,6 +192,8 @@ Attribute &Attribute::operator= (Attribute const &other) // guard to protect from null pointer dereference if (other.attr_input != nullptr) attr_input = other.attr_input->clone_attr_input (); + else + attr_input = nullptr; return *this; } @@ -323,7 +325,13 @@ std::string VisItem::as_string () const { // FIXME: can't do formatting on string to make identation occur. - std::string str = Item::as_string (); + std::string str; + + if (!outer_attrs.empty ()) + { + for (const auto &attr : outer_attrs) + str += attr.as_string () + "\n"; + } if (has_visibility ()) { @@ -334,7 +342,7 @@ VisItem::as_string () const } // Creates a string that reflects the outer attributes stored. -std::string +/*std::string Item::as_string () const { std::string str; @@ -348,7 +356,7 @@ Item::as_string () const } return str; -} +}*/ std::string Module::as_string () const @@ -1400,8 +1408,14 @@ TypeAlias::as_string () const std::string MacroInvocationSemi::as_string () const { + std::string str; + // get outer attrs - std::string str = MacroItem::as_string (); + if (!outer_attrs.empty ()) + { + for (const auto &attr : outer_attrs) + str += attr.as_string () + "\n"; + } str += "\n" + path.as_string () + "!"; @@ -1498,7 +1512,16 @@ MacroRule::as_string () const std::string MacroRulesDefinition::as_string () const { - std::string str ("macro_rules!"); + std::string str; + + // get outer attrs + if (!outer_attrs.empty ()) + { + for (const auto &attr : outer_attrs) + str += attr.as_string () + "\n"; + } + + str += "macro_rules!"; str += rule_name; @@ -1510,9 +1533,7 @@ MacroRulesDefinition::as_string () const else { for (const auto &rule : rules) - { str += "\n " + rule.as_string (); - } } str += "\n Delim type: "; @@ -5403,9 +5424,9 @@ std::vector Attribute::separate_cfg_attrs () { if (!has_attr_input () || path.as_string () != "cfg_attr") return {}; - // TODO: maybe replace with storing a "has been parsed" variable? - parse_attr_to_meta_item (); - // can't be const because of this anyway + // TODO: maybe replace with storing a "has been parsed" variable? + parse_attr_to_meta_item (); + // can't be const because of this anyway return attr_input->separate_cfg_attrs (); } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 90e3504..31c547a 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -591,7 +591,7 @@ public: void accept_vis (ASTVisitor &vis) override; bool - check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override + check_cfg_predicate (const Session&) const override { // this should never be called - should be converted first return false; @@ -764,6 +764,9 @@ public: * methods. */ virtual Location get_locus_slow () const { return Location (); } + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; + protected: // Clone function implementation as pure virtual method virtual Stmt *clone_stmt_impl () const = 0; @@ -772,10 +775,6 @@ protected: // Rust "item" AST node (declaration of top-level/module-level allowed stuff) class Item : public Stmt { - std::vector outer_attrs; - - // TODO: should outer attrs be defined here or in each derived class? - public: // Unique pointer custom clone function std::unique_ptr clone_item () const @@ -783,29 +782,22 @@ public: return std::unique_ptr (clone_item_impl ()); } - std::string as_string () const; + std::string as_string () const = 0; /* Adds crate names to the vector passed by reference, if it can - * (polymorphism). */ + * (polymorphism). TODO: remove, unused. */ virtual void add_crate_name (std::vector &names ATTRIBUTE_UNUSED) const {} - virtual void accept_vis (ASTVisitor &vis ATTRIBUTE_UNUSED) {} - protected: - // Constructor - Item (std::vector outer_attribs = std::vector ()) - : outer_attrs (std::move (outer_attribs)) - {} - // Clone function implementation as pure virtual method virtual Item *clone_item_impl () const = 0; /* Save having to specify two clone methods in derived classes by making * statement clone return item clone. Hopefully won't affect performance too * much. */ - Item *clone_stmt_impl () const override { return clone_item_impl (); } + Item *clone_stmt_impl () const final override { return clone_item_impl (); } }; // forward decl of ExprWithoutBlock @@ -849,6 +841,9 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; + protected: // Constructor Expr (std::vector outer_attribs = std::vector ()) @@ -882,7 +877,7 @@ protected: /* Save having to specify two clone methods in derived classes by making expr * clone return exprwithoutblock clone. Hopefully won't affect performance too * much. */ - ExprWithoutBlock *clone_expr_impl () const override + ExprWithoutBlock *clone_expr_impl () const final override { return clone_expr_without_block_impl (); } @@ -935,6 +930,10 @@ public: return std::unique_ptr (clone_identifier_expr_impl ()); } + // "Error state" if ident is empty, so base stripping on this. + void mark_for_strip () override { ident = {}; } + bool is_marked_for_strip () const override { return ident.empty (); } + protected: // Clone method implementation IdentifierExpr *clone_expr_without_block_impl () const override @@ -946,9 +945,6 @@ protected: { return new IdentifierExpr (*this); } - - IdentifierExpr (IdentifierExpr const &other) = default; - IdentifierExpr &operator= (IdentifierExpr const &other) = default; }; // Pattern base AST node @@ -994,7 +990,7 @@ public: /* HACK: convert to trait bound. Virtual method overriden by classes that * enable this. */ - virtual TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const + virtual TraitBound *to_trait_bound (bool) const { return nullptr; } @@ -1025,7 +1021,7 @@ protected: /* Save having to specify two clone methods in derived classes by making type * clone return typenobounds clone. Hopefully won't affect performance too * much. */ - TypeNoBounds *clone_type_impl () const override + TypeNoBounds *clone_type_impl () const final override { return clone_type_no_bounds_impl (); } @@ -1207,10 +1203,12 @@ class MacroItem : public Item { /*public: std::string as_string() const;*/ + //std::vector outer_attrs; + protected: - MacroItem (std::vector outer_attribs) - : Item (std::move (outer_attribs)) - {} + /*MacroItem (std::vector outer_attribs) + : outer_attrs (std::move (outer_attribs)) + {}*/ }; // Item used in trait declarations - abstract base class @@ -1298,6 +1296,7 @@ class MacroInvocationSemi : public MacroItem, public InherentImplItem, public TraitImplItem { + std::vector outer_attrs; SimplePath path; // all delim types except curly must have invocation end with a semicolon DelimType delim_type; @@ -1310,36 +1309,15 @@ public: MacroInvocationSemi (SimplePath macro_path, DelimType delim_type, std::vector> token_trees, std::vector outer_attribs, Location locus) - : MacroItem (std::move (outer_attribs)), path (std::move (macro_path)), + : outer_attrs (std::move (outer_attribs)), path (std::move (macro_path)), delim_type (delim_type), token_trees (std::move (token_trees)), locus (locus) {} - /* TODO: possible issue with Item and TraitItem hierarchies both having outer - * attributes - * - storage inefficiency at least. - * Best current idea is to make Item preferred and have TraitItem get virtual - * functions for attributes or something. Or just redo the "composition" - * approach, but then this prevents polymorphism and would entail redoing - * quite a bit of the parser. */ - - // Move constructors - MacroInvocationSemi (MacroInvocationSemi &&other) = default; - MacroInvocationSemi &operator= (MacroInvocationSemi &&other) = default; - - void accept_vis (ASTVisitor &vis) override; - - // Clones this macro invocation semi. - std::unique_ptr clone_macro_invocation_semi () const - { - return std::unique_ptr ( - clone_macro_invocation_semi_impl ()); - } -protected: // Copy constructor with vector clone MacroInvocationSemi (MacroInvocationSemi const &other) : MacroItem (other), TraitItem (other), InherentImplItem (other), - TraitImplItem (other), path (other.path), delim_type (other.delim_type), + TraitImplItem (other), outer_attrs(other.outer_attrs), path (other.path), delim_type (other.delim_type), locus (other.locus) { token_trees.reserve (other.token_trees.size ()); @@ -1354,6 +1332,7 @@ protected: TraitItem::operator= (other); InherentImplItem::operator= (other); TraitImplItem::operator= (other); + outer_attrs = other.outer_attrs; path = other.path; delim_type = other.delim_type; locus = other.locus; @@ -1365,6 +1344,24 @@ protected: return *this; } + // Move constructors + MacroInvocationSemi (MacroInvocationSemi &&other) = default; + MacroInvocationSemi &operator= (MacroInvocationSemi &&other) = default; + + void accept_vis (ASTVisitor &vis) override; + + // Clones this macro invocation semi. + std::unique_ptr clone_macro_invocation_semi () const + { + return std::unique_ptr ( + clone_macro_invocation_semi_impl ()); + } + + // Invalid if path is empty, so base stripping on that. + void mark_for_strip () override { path = SimplePath::create_empty (); } + bool is_marked_for_strip () const override { return path.is_empty (); } + +protected: MacroInvocationSemi *clone_macro_invocation_semi_impl () const { return new MacroInvocationSemi (*this); @@ -1391,13 +1388,6 @@ protected: return clone_macro_invocation_semi_impl (); } - // FIXME: remove if item impl virtual override works properly - // Use covariance to implement clone function as returning this object rather - // than base - /*MacroInvocationSemi* clone_statement_impl() const override { - return clone_macro_invocation_semi_impl (); - }*/ - /* Use covariance to implement clone function as returning this object rather * than base */ MacroInvocationSemi *clone_trait_item_impl () const override diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index fd6913f..4647829 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -23,7 +23,7 @@ protected: virtual ExprWithBlock *clone_expr_with_block_impl () const = 0; // prevent having to define multiple clone expressions - ExprWithBlock *clone_expr_impl () const override + ExprWithBlock *clone_expr_impl () const final override { return clone_expr_with_block_impl (); } @@ -73,19 +73,16 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - LiteralExpr *clone_expr_impl () const override - { - return new LiteralExpr (*this); - } + // Invalid if literal is in error state, so base stripping on that. + void mark_for_strip () override { literal = Literal::create_error (); } + bool is_marked_for_strip () const override { return literal.is_error (); } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ LiteralExpr *clone_expr_without_block_impl () const override { - return new LiteralExpr (*this); + return clone_literal_expr_impl (); } /* not virtual as currently no subclasses of LiteralExpr, but could be in @@ -121,7 +118,7 @@ public: /* this can never be a cfg predicate - cfg and cfg_attr require a token-tree * cfg */ bool - check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override + check_cfg_predicate (const Session&) const override { return false; } @@ -212,18 +209,26 @@ protected: // Copy constructor (only for initialisation of expr purposes) OperatorExpr (OperatorExpr const &other) - : ExprWithoutBlock (other), locus (other.locus), - main_or_left_expr (other.main_or_left_expr->clone_expr ()) - {} + : ExprWithoutBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.main_or_left_expr != nullptr) + main_or_left_expr = other.main_or_left_expr->clone_expr (); + } // Overload assignment operator to deep copy expr OperatorExpr &operator= (OperatorExpr const &other) { ExprWithoutBlock::operator= (other); - main_or_left_expr = other.main_or_left_expr->clone_expr (); locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.main_or_left_expr != nullptr) + main_or_left_expr = other.main_or_left_expr->clone_expr (); + else + main_or_left_expr = nullptr; + return *this; } @@ -234,6 +239,10 @@ protected: public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { main_or_left_expr = nullptr; } + bool is_marked_for_strip () const override { return main_or_left_expr == nullptr; } }; /* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be @@ -249,9 +258,8 @@ public: BorrowExpr (std::unique_ptr borrow_lvalue, bool is_mut_borrow, bool is_double_borrow, std::vector outer_attribs, Location locus) - : OperatorExpr (std::move (borrow_lvalue), std::move (outer_attribs), - locus), - is_mut (is_mut_borrow), double_borrow (is_double_borrow) + : OperatorExpr (std::move (borrow_lvalue), std::move (outer_attribs), + locus), is_mut (is_mut_borrow), double_borrow (is_double_borrow) {} void accept_vis (ASTVisitor &vis) override; @@ -259,13 +267,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - BorrowExpr *clone_expr_impl () const override - { - return new BorrowExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ BorrowExpr *clone_expr_without_block_impl () const override { return new BorrowExpr (*this); @@ -289,13 +290,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - DereferenceExpr *clone_expr_impl () const override - { - return new DereferenceExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ DereferenceExpr *clone_expr_without_block_impl () const override { return new DereferenceExpr (*this); @@ -320,13 +314,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ErrorPropagationExpr *clone_expr_impl () const override - { - return new ErrorPropagationExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ErrorPropagationExpr *clone_expr_without_block_impl () const override { return new ErrorPropagationExpr (*this); @@ -368,13 +355,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - NegationExpr *clone_expr_impl () const override - { - return new NegationExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ NegationExpr *clone_expr_without_block_impl () const override { return new NegationExpr (*this); @@ -450,13 +430,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ArithmeticOrLogicalExpr *clone_expr_impl () const override - { - return new ArithmeticOrLogicalExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ArithmeticOrLogicalExpr *clone_expr_without_block_impl () const override { return new ArithmeticOrLogicalExpr (*this); @@ -527,13 +500,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ComparisonExpr *clone_expr_impl () const override - { - return new ComparisonExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ComparisonExpr *clone_expr_without_block_impl () const override { return new ComparisonExpr (*this); @@ -597,13 +563,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - LazyBooleanExpr *clone_expr_impl () const override - { - return new LazyBooleanExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ LazyBooleanExpr *clone_expr_without_block_impl () const override { return new LazyBooleanExpr (*this); @@ -652,13 +611,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TypeCastExpr *clone_expr_impl () const override - { - return new TypeCastExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ TypeCastExpr *clone_expr_without_block_impl () const override { return new TypeCastExpr (*this); @@ -712,13 +664,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - AssignmentExpr *clone_expr_impl () const override - { - return new AssignmentExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ AssignmentExpr *clone_expr_without_block_impl () const override { return new AssignmentExpr (*this); @@ -791,13 +736,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - CompoundAssignmentExpr *clone_expr_impl () const override - { - return new CompoundAssignmentExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ CompoundAssignmentExpr *clone_expr_without_block_impl () const override { return new CompoundAssignmentExpr (*this); @@ -828,18 +766,27 @@ public: // Copy constructor includes clone for expr_in_parens GroupedExpr (GroupedExpr const &other) : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), - expr_in_parens (other.expr_in_parens->clone_expr ()), locus (other.locus) - {} + locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.expr_in_parens != nullptr) + expr_in_parens = other.expr_in_parens->clone_expr (); + } // Overloaded assignment operator to clone expr_in_parens GroupedExpr &operator= (GroupedExpr const &other) { ExprWithoutBlock::operator= (other); inner_attrs = other.inner_attrs; - expr_in_parens = other.expr_in_parens->clone_expr (); locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.expr_in_parens != nullptr) + expr_in_parens = other.expr_in_parens->clone_expr (); + else + expr_in_parens = nullptr; + return *this; } @@ -852,14 +799,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - GroupedExpr *clone_expr_impl () const override - { - return new GroupedExpr (*this); - } + // Invalid if inner expr is null, so base stripping on that. + void mark_for_strip () override { expr_in_parens = nullptr; } + bool is_marked_for_strip () const override { return expr_in_parens == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ GroupedExpr *clone_expr_without_block_impl () const override @@ -988,6 +932,9 @@ class ArrayExpr : public ExprWithoutBlock std::unique_ptr internal_elements; Location locus; + + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; public: std::string as_string () const override; @@ -1009,7 +956,7 @@ public: // Copy constructor requires cloning ArrayElems for polymorphism to hold ArrayExpr (ArrayExpr const &other) : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), - locus (other.locus) + locus (other.locus), marked_for_strip (other.marked_for_strip) { if (other.has_array_elems ()) internal_elements = other.internal_elements->clone_array_elems (); @@ -1020,11 +967,15 @@ public: { ExprWithoutBlock::operator= (other); inner_attrs = other.inner_attrs; - if (other.has_array_elems ()) - internal_elements = other.internal_elements->clone_array_elems (); locus = other.locus; + marked_for_strip = other.marked_for_strip; // outer_attrs = other.outer_attrs; + if (other.has_array_elems ()) + internal_elements = other.internal_elements->clone_array_elems (); + else + internal_elements = nullptr; + return *this; } @@ -1037,11 +988,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ArrayExpr *clone_expr_impl () const override { return new ArrayExpr (*this); } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ArrayExpr *clone_expr_without_block_impl () const override @@ -1075,19 +1026,32 @@ public: // Copy constructor requires special cloning due to unique_ptr ArrayIndexExpr (ArrayIndexExpr const &other) - : ExprWithoutBlock (other), array_expr (other.array_expr->clone_expr ()), - index_expr (other.index_expr->clone_expr ()), locus (other.locus) - {} + : ExprWithoutBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.array_expr != nullptr) + array_expr = other.array_expr->clone_expr (); + if (other.index_expr != nullptr) + index_expr = other.index_expr->clone_expr (); + } // Overload assignment operator to clone unique_ptrs ArrayIndexExpr &operator= (ArrayIndexExpr const &other) { ExprWithoutBlock::operator= (other); - array_expr = other.array_expr->clone_expr (); - index_expr = other.index_expr->clone_expr (); // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.array_expr != nullptr) + array_expr = other.array_expr->clone_expr (); + else + array_expr = nullptr; + if (other.index_expr != nullptr) + index_expr = other.index_expr->clone_expr (); + else + index_expr = nullptr; + return *this; } @@ -1100,14 +1064,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ArrayIndexExpr *clone_expr_impl () const override - { - return new ArrayIndexExpr (*this); - } + // Invalid if either expr is null, so base stripping on that. + void mark_for_strip () override { array_expr = nullptr; index_expr = nullptr; } + bool is_marked_for_strip () const override { return array_expr == nullptr && index_expr == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ArrayIndexExpr *clone_expr_without_block_impl () const override @@ -1126,6 +1087,9 @@ class TupleExpr : public ExprWithoutBlock Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override; @@ -1142,7 +1106,7 @@ public: // copy constructor with vector clone TupleExpr (TupleExpr const &other) : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), - locus (other.locus) + locus (other.locus), marked_for_strip (other.marked_for_strip) { tuple_elems.reserve (other.tuple_elems.size ()); for (const auto &e : other.tuple_elems) @@ -1155,6 +1119,7 @@ public: ExprWithoutBlock::operator= (other); inner_attrs = other.inner_attrs; locus = other.locus; + marked_for_strip = other.marked_for_strip; tuple_elems.reserve (other.tuple_elems.size ()); for (const auto &e : other.tuple_elems) @@ -1175,11 +1140,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - TupleExpr *clone_expr_impl () const override { return new TupleExpr (*this); } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ TupleExpr *clone_expr_without_block_impl () const override @@ -1213,19 +1178,27 @@ public: // Copy constructor requires a clone for tuple_expr TupleIndexExpr (TupleIndexExpr const &other) - : ExprWithoutBlock (other), tuple_expr (other.tuple_expr->clone_expr ()), - tuple_index (other.tuple_index), locus (other.locus) - {} + : ExprWithoutBlock (other), tuple_index (other.tuple_index), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.tuple_expr != nullptr) + tuple_expr = other.tuple_expr->clone_expr (); + } // Overload assignment operator in order to clone TupleIndexExpr &operator= (TupleIndexExpr const &other) { ExprWithoutBlock::operator= (other); - tuple_expr = other.tuple_expr->clone_expr (); tuple_index = other.tuple_index; locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.tuple_expr != nullptr) + tuple_expr = other.tuple_expr->clone_expr (); + else + tuple_expr = nullptr; + return *this; } @@ -1238,14 +1211,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - TupleIndexExpr *clone_expr_impl () const override - { - return new TupleIndexExpr (*this); - } + // Invalid if tuple expr is null, so base stripping on that. + void mark_for_strip () override { tuple_expr = nullptr; } + bool is_marked_for_strip () const override { return tuple_expr == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ TupleIndexExpr *clone_expr_without_block_impl () const override @@ -1271,6 +1241,10 @@ public: const PathInExpression &get_struct_name () const { return struct_name; } std::string as_string () const override; + + // Invalid if path is empty, so base stripping on that. + void mark_for_strip () override { struct_name = PathInExpression::create_error (); } + bool is_marked_for_strip () const override { return struct_name.is_error (); } }; // Actual AST node of the struct creator (with no fields). Not abstract! @@ -1301,13 +1275,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprStruct *clone_expr_impl () const override - { - return new StructExprStruct (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprStruct *clone_expr_without_block_impl () const override { return new StructExprStruct (*this); @@ -1332,7 +1299,7 @@ public: /* HACK: gets around base_struct pointer being null (e.g. if no struct base * exists) */ if (other.base_struct != nullptr) - other.base_struct->clone_expr (); + base_struct = other.base_struct->clone_expr (); } // Destructor @@ -1341,7 +1308,11 @@ public: // Overload assignment operator to clone base_struct StructBase &operator= (StructBase const &other) { - base_struct = other.base_struct->clone_expr (); + // prevent null pointer dereference + if (other.base_struct != nullptr) + base_struct = other.base_struct->clone_expr (); + else + base_struct = nullptr; return *this; } @@ -1557,13 +1528,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprStructFields *clone_expr_impl () const override - { - return new StructExprStructFields (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprStructFields *clone_expr_without_block_impl () const override { return new StructExprStructFields (*this); @@ -1595,13 +1559,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprStructBase *clone_expr_impl () const override - { - return new StructExprStructBase (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprStructBase *clone_expr_without_block_impl () const override { return new StructExprStructBase (*this); @@ -1669,13 +1626,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprTuple *clone_expr_impl () const override - { - return new StructExprTuple (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprTuple *clone_expr_without_block_impl () const override { return new StructExprTuple (*this); @@ -1708,13 +1658,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprUnit *clone_expr_impl () const override - { - return new StructExprUnit (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprUnit *clone_expr_without_block_impl () const override { return new StructExprUnit (*this); @@ -1738,6 +1681,10 @@ protected: public: // TODO: maybe remove and have string version gotten here directly PathInExpression get_enum_variant_path () const { return enum_variant_path; } + + // Invalid if path is in error state, so base stripping on that. + void mark_for_strip () override { enum_variant_path = PathInExpression::create_error (); } + bool is_marked_for_strip () const override { return enum_variant_path.is_error (); } }; /* Base AST node for a single enum expression field (in enum instance creation) @@ -1828,9 +1775,6 @@ public: field_name (std::move (field_name)) {} - // copy constructor, destructor, and assignment operator should not need - // defining - void accept_vis (ASTVisitor &vis) override; protected: @@ -1924,13 +1868,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - EnumExprStruct *clone_expr_impl () const override - { - return new EnumExprStruct (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ EnumExprStruct *clone_expr_without_block_impl () const override { return new EnumExprStruct (*this); @@ -1993,13 +1930,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - EnumExprTuple *clone_expr_impl () const override - { - return new EnumExprTuple (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ EnumExprTuple *clone_expr_without_block_impl () const override { return new EnumExprTuple (*this); @@ -2033,13 +1963,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - EnumExprFieldless *clone_expr_impl () const override - { - return new EnumExprFieldless (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ EnumExprFieldless *clone_expr_without_block_impl () const override { return new EnumExprFieldless (*this); @@ -2077,9 +2000,11 @@ public: // copy constructor requires clone CallExpr (CallExpr const &other) - : ExprWithoutBlock (other), function (other.function->clone_expr ()), - locus (other.locus) - /*, params(other.params),*/ { + : ExprWithoutBlock (other), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.function != nullptr) + function = other.function->clone_expr (); + params.reserve (other.params.size ()); for (const auto &e : other.params) params.push_back (e->clone_expr ()); @@ -2089,11 +2014,15 @@ public: CallExpr &operator= (CallExpr const &other) { ExprWithoutBlock::operator= (other); - function = other.function->clone_expr (); locus = other.locus; - // params = other.params; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.function != nullptr) + function = other.function->clone_expr (); + else + function = nullptr; + params.reserve (other.params.size ()); for (const auto &e : other.params) params.push_back (e->clone_expr ()); @@ -2113,11 +2042,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - CallExpr *clone_expr_impl () const override { return new CallExpr (*this); } + // Invalid if function expr is null, so base stripping on that. + void mark_for_strip () override { function = nullptr; } + bool is_marked_for_strip () const override { return function == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ CallExpr *clone_expr_without_block_impl () const override @@ -2155,9 +2084,11 @@ public: // copy constructor required due to cloning MethodCallExpr (MethodCallExpr const &other) - : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()), - method_name (other.method_name), locus (other.locus) - /*, params(other.params),*/ { + : ExprWithoutBlock (other), method_name (other.method_name), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.receiver != nullptr) + receiver = other.receiver->clone_expr (); + params.reserve (other.params.size ()); for (const auto &e : other.params) params.push_back (e->clone_expr ()); @@ -2167,12 +2098,16 @@ public: MethodCallExpr &operator= (MethodCallExpr const &other) { ExprWithoutBlock::operator= (other); - receiver = other.receiver->clone_expr (); method_name = other.method_name; locus = other.locus; - // params = other.params; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.receiver != nullptr) + receiver = other.receiver->clone_expr (); + else + receiver = nullptr; + params.reserve (other.params.size ()); for (const auto &e : other.params) params.push_back (e->clone_expr ()); @@ -2189,14 +2124,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - MethodCallExpr *clone_expr_impl () const override - { - return new MethodCallExpr (*this); - } + // Invalid if receiver expr is null, so base stripping on that. + void mark_for_strip () override { receiver = nullptr; } + bool is_marked_for_strip () const override { return receiver == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ MethodCallExpr *clone_expr_without_block_impl () const override @@ -2227,19 +2159,27 @@ public: // Copy constructor required due to unique_ptr cloning FieldAccessExpr (FieldAccessExpr const &other) - : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()), - field (other.field), locus (other.locus) - {} + : ExprWithoutBlock (other), field (other.field), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.receiver != nullptr) + receiver = other.receiver->clone_expr (); + } // Overload assignment operator to clone unique_ptr FieldAccessExpr &operator= (FieldAccessExpr const &other) { ExprWithoutBlock::operator= (other); - receiver = other.receiver->clone_expr (); field = other.field; locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.receiver != nullptr) + receiver = other.receiver->clone_expr (); + else + receiver = nullptr; + return *this; } @@ -2252,14 +2192,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - FieldAccessExpr *clone_expr_impl () const override - { - return new FieldAccessExpr (*this); - } + // Invalid if receiver expr is null, so base stripping on that. + void mark_for_strip () override { receiver = nullptr; } + bool is_marked_for_strip () const override { return receiver == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ FieldAccessExpr *clone_expr_without_block_impl () const override @@ -2294,6 +2231,8 @@ public: : pattern (other.pattern->clone_pattern ()) { // guard to protect from null pointer dereference + if (other.pattern != nullptr) + pattern = other.pattern->clone_pattern (); if (other.type != nullptr) type = other.type->clone_type (); } @@ -2303,8 +2242,15 @@ public: // Assignment operator must be overloaded to clone as well ClosureParam &operator= (ClosureParam const &other) { - pattern = other.pattern->clone_pattern (); - type = other.type->clone_type (); + // guard to protect from null pointer dereference + if (other.pattern != nullptr) + pattern = other.pattern->clone_pattern (); + else + pattern = nullptr; + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; return *this; } @@ -2367,18 +2313,27 @@ public: // Copy constructor must be defined to allow copying via cloning of unique_ptr ClosureExprInner (ClosureExprInner const &other) - : ClosureExpr (other), closure_inner (other.closure_inner->clone_expr ()) - {} + : ClosureExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.closure_inner != nullptr) + closure_inner = other.closure_inner->clone_expr (); + } // Overload assignment operator to clone closure_inner ClosureExprInner &operator= (ClosureExprInner const &other) { ClosureExpr::operator= (other); - closure_inner = other.closure_inner->clone_expr (); // params = other.params; // has_move = other.has_move; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.closure_inner != nullptr) + closure_inner = other.closure_inner->clone_expr (); + else + closure_inner = nullptr; + return *this; } @@ -2388,14 +2343,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ClosureExprInner *clone_expr_impl () const override - { - return new ClosureExprInner (*this); - } + // Invalid if inner expr is null, so base stripping on that. + void mark_for_strip () override { closure_inner = nullptr; } + bool is_marked_for_strip () const override { return closure_inner == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ClosureExprInner *clone_expr_without_block_impl () const override @@ -2437,8 +2389,7 @@ public: // Copy constructor with clone BlockExpr (BlockExpr const &other) - : ExprWithBlock (other), /*statements(other.statements),*/ - inner_attrs (other.inner_attrs), locus (other.locus) + : ExprWithBlock (other), inner_attrs (other.inner_attrs), locus (other.locus) { // guard to protect from null pointer dereference if (other.expr != nullptr) @@ -2453,12 +2404,16 @@ public: BlockExpr &operator= (BlockExpr const &other) { ExprWithBlock::operator= (other); - // statements = other.statements; - expr = other.expr->clone_expr_without_block (); inner_attrs = other.inner_attrs; locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to protect from null pointer dereference + if (other.expr != nullptr) + expr = other.expr->clone_expr_without_block (); + else + expr = nullptr; + statements.reserve (other.statements.size ()); for (const auto &e : other.statements) statements.push_back (e->clone_stmt ()); @@ -2481,14 +2436,16 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - BlockExpr *clone_expr_impl () const override - { - return clone_block_expr_impl (); + // Invalid if has no statements or final expr, so base stripping on that. + void mark_for_strip () override + { + expr = nullptr; + statements.clear (); + statements.shrink_to_fit (); } + bool is_marked_for_strip () const override { return expr == nullptr && statements.empty (); } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ BlockExpr *clone_expr_with_block_impl () const override @@ -2507,6 +2464,7 @@ protected: // Represents a type-specified closure expression AST node class ClosureExprInnerTyped : public ClosureExpr { + // TODO: spec says typenobounds std::unique_ptr return_type; std::unique_ptr expr; // only used because may be polymorphic in future @@ -2529,20 +2487,33 @@ public: // Copy constructor requires cloning ClosureExprInnerTyped (ClosureExprInnerTyped const &other) - : ClosureExpr (other), return_type (other.return_type->clone_type ()), - expr (other.expr->clone_block_expr ()) - {} + : ClosureExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_block_expr (); + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + } // Overload assignment operator to clone unique_ptrs ClosureExprInnerTyped &operator= (ClosureExprInnerTyped const &other) { ClosureExpr::operator= (other); - return_type = other.return_type->clone_type (); - expr = other.expr->clone_block_expr (); // params = other.params; // has_move = other.has_move; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_block_expr (); + else + expr = nullptr; + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + return *this; } @@ -2552,14 +2523,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ClosureExprInnerTyped *clone_expr_impl () const override - { - return new ClosureExprInnerTyped (*this); - } + /* Invalid if inner expr is null, so base stripping on that. Technically, type should also not be null. */ + void mark_for_strip () override { expr = nullptr; } + bool is_marked_for_strip () const override { return expr == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ClosureExprInnerTyped *clone_expr_without_block_impl () const override @@ -2575,6 +2543,9 @@ class ContinueExpr : public ExprWithoutBlock Lifetime label; Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override; @@ -2594,14 +2565,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ContinueExpr *clone_expr_impl () const override - { - return new ContinueExpr (*this); - } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ContinueExpr *clone_expr_without_block_impl () const override @@ -2622,6 +2590,9 @@ class BreakExpr : public ExprWithoutBlock Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override; @@ -2643,7 +2614,7 @@ public: // Copy constructor defined to use clone for unique pointer BreakExpr (BreakExpr const &other) - : ExprWithoutBlock (other), label (other.label), locus (other.locus) + : ExprWithoutBlock (other), label (other.label), locus (other.locus), marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference if (other.break_expr != nullptr) @@ -2655,10 +2626,16 @@ public: { ExprWithoutBlock::operator= (other); label = other.label; - break_expr = other.break_expr->clone_expr (); locus = other.locus; + marked_for_strip = other.marked_for_strip; // outer_attrs = other.outer_attrs; + // guard to protect from null pointer dereference + if (other.break_expr != nullptr) + break_expr = other.break_expr->clone_expr (); + else + break_expr = nullptr; + return *this; } @@ -2671,11 +2648,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - BreakExpr *clone_expr_impl () const override { return new BreakExpr (*this); } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ BreakExpr *clone_expr_without_block_impl () const override @@ -2718,16 +2695,29 @@ public: // Copy constructor with cloning RangeFromToExpr (RangeFromToExpr const &other) - : RangeExpr (other), from (other.from->clone_expr ()), - to (other.to->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + if (other.to != nullptr) + to = other.to->clone_expr (); + } // Overload assignment operator to clone unique pointers RangeFromToExpr &operator= (RangeFromToExpr const &other) { RangeExpr::operator= (other); - from = other.from->clone_expr (); - to = other.to->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + else + from = nullptr; + if (other.to != nullptr) + to = other.to->clone_expr (); + else + to = nullptr; return *this; } @@ -2738,14 +2728,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeFromToExpr *clone_expr_impl () const override - { - return new RangeFromToExpr (*this); - } + // Invalid if either expr is null, so base stripping on that. + void mark_for_strip () override { from = nullptr; to = nullptr; } + bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeFromToExpr *clone_expr_without_block_impl () const override @@ -2769,14 +2756,23 @@ public: // Copy constructor with clone RangeFromExpr (RangeFromExpr const &other) - : RangeExpr (other), from (other.from->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + } // Overload assignment operator to clone unique_ptr RangeFromExpr &operator= (RangeFromExpr const &other) { RangeExpr::operator= (other); - from = other.from->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + else + from = nullptr; return *this; } @@ -2787,14 +2783,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeFromExpr *clone_expr_impl () const override - { - return new RangeFromExpr (*this); - } + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { from = nullptr; } + bool is_marked_for_strip () const override { return from == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeFromExpr *clone_expr_without_block_impl () const override @@ -2819,14 +2812,23 @@ public: // Copy constructor with clone RangeToExpr (RangeToExpr const &other) - : RangeExpr (other), to (other.to->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.to != nullptr) + to = other.to->clone_expr (); + } // Overload assignment operator to clone unique_ptr RangeToExpr &operator= (RangeToExpr const &other) { RangeExpr::operator= (other); - to = other.to->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.to != nullptr) + to = other.to->clone_expr (); + else + to = nullptr; return *this; } @@ -2837,14 +2839,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeToExpr *clone_expr_impl () const override - { - return new RangeToExpr (*this); - } + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { to = nullptr; } + bool is_marked_for_strip () const override { return to == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeToExpr *clone_expr_without_block_impl () const override @@ -2857,6 +2856,9 @@ protected: // constructs a std::ops::RangeFull object class RangeFullExpr : public RangeExpr { + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override; @@ -2865,14 +2867,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeFullExpr *clone_expr_impl () const override - { - return new RangeFullExpr (*this); - } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeFullExpr *clone_expr_without_block_impl () const override @@ -2900,16 +2899,29 @@ public: // Copy constructor with clone RangeFromToInclExpr (RangeFromToInclExpr const &other) - : RangeExpr (other), from (other.from->clone_expr ()), - to (other.to->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + if (other.to != nullptr) + to = other.to->clone_expr (); + } // Overload assignment operator to use clone RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other) { RangeExpr::operator= (other); - from = other.from->clone_expr (); - to = other.to->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + else + from = nullptr; + if (other.to != nullptr) + to = other.to->clone_expr (); + else + to = nullptr; return *this; } @@ -2920,14 +2932,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeFromToInclExpr *clone_expr_impl () const override - { - return new RangeFromToInclExpr (*this); - } + // Invalid if either expr is null, so base stripping on that. + void mark_for_strip () override { from = nullptr; to = nullptr; } + bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeFromToInclExpr *clone_expr_without_block_impl () const override @@ -2952,14 +2961,23 @@ public: // Copy constructor with clone RangeToInclExpr (RangeToInclExpr const &other) - : RangeExpr (other), to (other.to->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.to != nullptr) + to = other.to->clone_expr (); + } // Overload assignment operator to clone pointer RangeToInclExpr &operator= (RangeToInclExpr const &other) { RangeExpr::operator= (other); - to = other.to->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.to != nullptr) + to = other.to->clone_expr (); + else + to = nullptr; return *this; } @@ -2970,14 +2988,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeToInclExpr *clone_expr_impl () const override - { - return new RangeToInclExpr (*this); - } + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { to = nullptr; } + bool is_marked_for_strip () const override { return to == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeToInclExpr *clone_expr_without_block_impl () const override @@ -2994,6 +3009,9 @@ public: Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + std::string as_string () const override; /* Returns whether the object has an expression returned (i.e. not void return @@ -3009,7 +3027,7 @@ public: // Copy constructor with clone ReturnExpr (ReturnExpr const &other) - : ExprWithoutBlock (other), locus (other.locus) + : ExprWithoutBlock (other), locus (other.locus), marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference if (other.return_expr != nullptr) @@ -3020,10 +3038,16 @@ public: ReturnExpr &operator= (ReturnExpr const &other) { ExprWithoutBlock::operator= (other); - return_expr = other.return_expr->clone_expr (); locus = other.locus; + marked_for_strip = other.marked_for_strip; // outer_attrs = other.outer_attrs; + // guard to protect from null pointer dereference + if (other.return_expr != nullptr) + return_expr = other.return_expr->clone_expr (); + else + return_expr = nullptr; + return *this; } @@ -3036,14 +3060,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ReturnExpr *clone_expr_impl () const override - { - return new ReturnExpr (*this); - } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ReturnExpr *clone_expr_without_block_impl () const override @@ -3074,18 +3095,26 @@ public: // Copy constructor with clone UnsafeBlockExpr (UnsafeBlockExpr const &other) - : ExprWithBlock (other), expr (other.expr->clone_block_expr ()), - locus (other.locus) - {} + : ExprWithBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_block_expr (); + } // Overloaded assignment operator to clone UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other) { ExprWithBlock::operator= (other); - expr = other.expr->clone_block_expr (); locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_block_expr (); + else + expr = nullptr; + return *this; } @@ -3098,14 +3127,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - UnsafeBlockExpr *clone_expr_impl () const override - { - return new UnsafeBlockExpr (*this); - } + // Invalid if block is null, so base stripping on that. + void mark_for_strip () override { expr = nullptr; } + bool is_marked_for_strip () const override { return expr == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ UnsafeBlockExpr *clone_expr_with_block_impl () const override @@ -3164,19 +3190,27 @@ protected: // Copy constructor for BaseLoopExpr with clone BaseLoopExpr (BaseLoopExpr const &other) - : ExprWithBlock (other), loop_label (other.loop_label), - loop_block (other.loop_block->clone_block_expr ()), locus (other.locus) - {} + : ExprWithBlock (other), loop_label (other.loop_label), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.loop_block != nullptr) + loop_block = other.loop_block->clone_block_expr (); + } // Overloaded assignment operator to clone BaseLoopExpr &operator= (BaseLoopExpr const &other) { ExprWithBlock::operator= (other); - loop_block = other.loop_block->clone_block_expr (); loop_label = other.loop_label; locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.loop_block != nullptr) + loop_block = other.loop_block->clone_block_expr (); + else + loop_block = nullptr; + return *this; } @@ -3189,6 +3223,10 @@ public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + + // Invalid if loop block is null, so base stripping on that. + void mark_for_strip () override { loop_block = nullptr; } + bool is_marked_for_strip () const override { return loop_block == nullptr; } }; // 'Loop' expression (i.e. the infinite loop) AST node @@ -3210,10 +3248,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - LoopExpr *clone_expr_impl () const override { return new LoopExpr (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ LoopExpr *clone_expr_with_block_impl () const override { return new LoopExpr (*this); @@ -3265,13 +3299,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - WhileLoopExpr *clone_expr_impl () const override - { - return new WhileLoopExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ WhileLoopExpr *clone_expr_with_block_impl () const override { return new WhileLoopExpr (*this); @@ -3338,13 +3365,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - WhileLetLoopExpr *clone_expr_impl () const override - { - return new WhileLetLoopExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ WhileLetLoopExpr *clone_expr_with_block_impl () const override { return new WhileLetLoopExpr (*this); @@ -3400,13 +3420,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ForLoopExpr *clone_expr_impl () const override - { - return new ForLoopExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ForLoopExpr *clone_expr_with_block_impl () const override { return new ForLoopExpr (*this); @@ -3437,18 +3450,31 @@ public: // Copy constructor with clone IfExpr (IfExpr const &other) - : ExprWithBlock (other), condition (other.condition->clone_expr ()), - if_block (other.if_block->clone_block_expr ()), locus (other.locus) - {} + : ExprWithBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.condition != nullptr) + condition = other.condition->clone_expr (); + if (other.if_block != nullptr) + if_block = other.if_block->clone_block_expr (); + } // Overloaded assignment operator to clone expressions IfExpr &operator= (IfExpr const &other) { ExprWithBlock::operator= (other); - condition = other.condition->clone_expr (); - if_block = other.if_block->clone_block_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.condition != nullptr) + condition = other.condition->clone_expr (); + else + condition = nullptr; + if (other.if_block != nullptr) + if_block = other.if_block->clone_block_expr (); + else + if_block = nullptr; + return *this; } @@ -3477,19 +3503,19 @@ public: Expr *get_if_condition () { return condition.get (); } BlockExpr *get_if_block () { return if_block.get (); } -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfExpr *clone_expr_impl () const override { return new IfExpr (*this); } + // Invalid if if block or condition is null, so base stripping on that. + void mark_for_strip () override { if_block = nullptr; condition = nullptr; } + bool is_marked_for_strip () const override { return if_block == nullptr && condition == nullptr; } +protected: // Base clone function but still concrete as concrete base class virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); } /* Use covariance to implement clone function as returning this object rather * than base */ - IfExpr *clone_expr_with_block_impl () const override + IfExpr *clone_expr_with_block_impl () const final override { - return new IfExpr (*this); + return clone_if_expr_impl (); } }; @@ -3536,20 +3562,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfExprConseqElse *clone_expr_impl () const override - { - return new IfExprConseqElse (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfExprConseqElse *clone_expr_with_block_impl () const override - { - return new IfExprConseqElse (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfExprConseqElse *clone_if_expr_impl () const override { return new IfExprConseqElse (*this); @@ -3602,20 +3614,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfExprConseqIf *clone_expr_impl () const override - { - return new IfExprConseqIf (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfExprConseqIf *clone_expr_with_block_impl () const override - { - return new IfExprConseqIf (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfExprConseqIf *clone_if_expr_impl () const override { return new IfExprConseqIf (*this); @@ -3646,11 +3644,14 @@ public: // copy constructor with clone IfLetExpr (IfLetExpr const &other) - : ExprWithBlock (other), - /*match_arm_patterns(other.match_arm_patterns),*/ value ( - other.value->clone_expr ()), - if_block (other.if_block->clone_block_expr ()), locus (other.locus) + : ExprWithBlock (other), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.value != nullptr) + value = other.value->clone_expr (); + if (other.if_block != nullptr) + if_block = other.if_block->clone_block_expr (); + match_arm_patterns.reserve (other.match_arm_patterns.size ()); for (const auto &e : other.match_arm_patterns) match_arm_patterns.push_back (e->clone_pattern ()); @@ -3660,11 +3661,18 @@ public: IfLetExpr &operator= (IfLetExpr const &other) { ExprWithBlock::operator= (other); - // match_arm_patterns = other.match_arm_patterns; - value = other.value->clone_expr (); - if_block = other.if_block->clone_block_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.value != nullptr) + value = other.value->clone_expr (); + else + value = nullptr; + if (other.if_block != nullptr) + if_block = other.if_block->clone_block_expr (); + else + if_block = nullptr; + match_arm_patterns.reserve (other.match_arm_patterns.size ()); for (const auto &e : other.match_arm_patterns) match_arm_patterns.push_back (e->clone_pattern ()); @@ -3687,16 +3695,16 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExpr *clone_expr_impl () const override { return new IfLetExpr (*this); } + // Invalid if block or value is null, so base stripping on that. + void mark_for_strip () override { if_block = nullptr; value = nullptr; } + bool is_marked_for_strip () const override { return if_block == nullptr && value == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExpr *clone_expr_with_block_impl () const override + * than base (or rather this or any derived object) */ + IfLetExpr *clone_expr_with_block_impl () const final override { - return new IfLetExpr (*this); + return clone_if_let_expr_impl (); } // Base clone function but still concrete as concrete base class @@ -3748,20 +3756,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfExprConseqIfLet *clone_expr_impl () const override - { - return new IfExprConseqIfLet (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfExprConseqIfLet *clone_expr_with_block_impl () const override - { - return new IfExprConseqIfLet (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfExprConseqIfLet *clone_if_expr_impl () const override { return new IfExprConseqIfLet (*this); @@ -3814,20 +3808,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfLetExprConseqElse *clone_expr_impl () const override - { - return new IfLetExprConseqElse (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExprConseqElse *clone_expr_with_block_impl () const override - { - return new IfLetExprConseqElse (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfLetExprConseqElse *clone_if_let_expr_impl () const override { return new IfLetExprConseqElse (*this); @@ -3879,20 +3859,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfLetExprConseqIf *clone_expr_impl () const override - { - return new IfLetExprConseqIf (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExprConseqIf *clone_expr_with_block_impl () const override - { - return new IfLetExprConseqIf (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfLetExprConseqIf *clone_if_let_expr_impl () const override { return new IfLetExprConseqIf (*this); @@ -3944,20 +3910,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfLetExprConseqIfLet *clone_expr_impl () const override - { - return new IfLetExprConseqIfLet (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExprConseqIfLet *clone_expr_with_block_impl () const override - { - return new IfLetExprConseqIfLet (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfLetExprConseqIfLet *clone_if_let_expr_impl () const override { return new IfLetExprConseqIfLet (*this); @@ -4012,6 +3964,8 @@ public: if (other.guard_expr != nullptr) guard_expr = other.guard_expr->clone_expr (); + else + guard_expr = nullptr; match_arm_patterns.reserve (other.match_arm_patterns.size ()); for (const auto &e : other.match_arm_patterns) @@ -4224,10 +4178,13 @@ public: // Copy constructor requires clone due to unique_ptr MatchExpr (MatchExpr const &other) - : ExprWithBlock (other), branch_value (other.branch_value->clone_expr ()), - inner_attrs (other.inner_attrs), match_arms (other.match_arms), - locus (other.locus) + : ExprWithBlock (other), inner_attrs (other.inner_attrs), + match_arms (other.match_arms), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.branch_value != nullptr) + branch_value = other.branch_value->clone_expr (); + /*match_arms.reserve (other.match_arms.size ()); for (const auto &e : other.match_arms) match_arms.push_back (e->clone_match_case ());*/ @@ -4237,12 +4194,17 @@ public: MatchExpr &operator= (MatchExpr const &other) { ExprWithBlock::operator= (other); - branch_value = other.branch_value->clone_expr (); inner_attrs = other.inner_attrs; match_arms = other.match_arms; // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.branch_value != nullptr) + branch_value = other.branch_value->clone_expr (); + else + branch_value = nullptr; + /*match_arms.reserve (other.match_arms.size ()); for (const auto &e : other.match_arms) match_arms.push_back (e->clone_match_case ());*/ @@ -4259,11 +4221,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - MatchExpr *clone_expr_impl () const override { return new MatchExpr (*this); } + // Invalid if branch value is null, so base stripping on that. + void mark_for_strip () override { branch_value = nullptr; } + bool is_marked_for_strip () const override { return branch_value == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ MatchExpr *clone_expr_with_block_impl () const override @@ -4289,17 +4251,25 @@ public: // copy constructor with clone AwaitExpr (AwaitExpr const &other) - : ExprWithoutBlock (other), - awaited_expr (other.awaited_expr->clone_expr ()), locus (other.locus) - {} + : ExprWithoutBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.awaited_expr != nullptr) + awaited_expr = other.awaited_expr->clone_expr (); + } // overloaded assignment operator with clone AwaitExpr &operator= (AwaitExpr const &other) { ExprWithoutBlock::operator= (other); - awaited_expr = other.awaited_expr->clone_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.awaited_expr != nullptr) + awaited_expr = other.awaited_expr->clone_expr (); + else + awaited_expr = nullptr; + return *this; } @@ -4314,6 +4284,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if awaited expr is null, so base stripping on that. + void mark_for_strip () override { awaited_expr = nullptr; } + bool is_marked_for_strip () const override { return awaited_expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4341,18 +4315,26 @@ public: // copy constructor with clone AsyncBlockExpr (AsyncBlockExpr const &other) - : ExprWithBlock (other), has_move (other.has_move), - block_expr (other.block_expr->clone_block_expr ()), locus (other.locus) - {} + : ExprWithBlock (other), has_move (other.has_move), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + } // overloaded assignment operator to clone AsyncBlockExpr &operator= (AsyncBlockExpr const &other) { ExprWithBlock::operator= (other); has_move = other.has_move; - block_expr = other.block_expr->clone_block_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + else + block_expr = nullptr; + return *this; } @@ -4367,6 +4349,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if block is null, so base stripping on that. + void mark_for_strip () override { block_expr = nullptr; } + bool is_marked_for_strip () const override { return block_expr == nullptr; } + 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 b5d9247..c35e65f 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -715,24 +715,24 @@ protected: class VisItem : public Item { Visibility visibility; + std::vector outer_attrs; protected: // Visibility constructor VisItem (Visibility visibility, std::vector outer_attrs = std::vector ()) - : Item (std::move (outer_attrs)), visibility (std::move (visibility)) + : visibility (std::move (visibility)), outer_attrs(std::move (outer_attrs)) {} // Visibility copy constructor - VisItem (VisItem const &other) : Item (other), visibility (other.visibility) + VisItem (VisItem const &other) : visibility (other.visibility), outer_attrs(other.outer_attrs) {} // Overload assignment operator to clone VisItem &operator= (VisItem const &other) { - Item::operator= (other); visibility = other.visibility; - // outer_attrs = other.outer_attrs; + outer_attrs = other.outer_attrs; return *this; } @@ -747,6 +747,13 @@ public: bool has_visibility () const { return !visibility.is_error (); } std::string as_string () const override; + + // TODO: this mutable getter seems really dodgy. Think up better way. + Visibility &get_vis () { return visibility; } + const Visibility &get_vis () const { return visibility; } + + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } }; // Rust module item - abstract base class @@ -767,6 +774,10 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { module_name = ""; } + bool is_marked_for_strip () const override { return module_name.empty (); } }; // Module with a body, defined in file @@ -837,17 +848,14 @@ protected: { return new ModuleBodied (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ModuleBodied* clone_statement_impl() const override { - return new ModuleBodied(*this); - }*/ }; // Module without a body, loaded from external file class ModuleNoBody : public Module { + /* TODO: are modules loaded from file unique? As in, can you load the same file into two different + * other files? Because this may make the difference between simply replacing this with the module + * "definition" (as loaded from another file) vs this having to "reference" a module with body. */ public: std::string as_string () const override; @@ -867,12 +875,6 @@ protected: { return new ModuleNoBody (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ModuleNoBody* clone_statement_impl() const override { - return new ModuleNoBody(*this); - }*/ }; // Rust extern crate declaration AST node @@ -920,6 +922,10 @@ public: names.push_back (referenced_crate); } + // Invalid if crate name is empty, so base stripping on that. + void mark_for_strip () override { referenced_crate = ""; } + bool is_marked_for_strip () const override { return referenced_crate.empty (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -927,12 +933,6 @@ protected: { return new ExternCrate (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ExternCrate* clone_statement_impl() const override { - return new ExternCrate(*this); - }*/ }; // The path-ish thing referred to in a use declaration - abstract base class @@ -1153,19 +1153,27 @@ public: // Copy constructor with clone UseDeclaration (UseDeclaration const &other) - : VisItem (other), use_tree (other.use_tree->clone_use_tree ()), - locus (other.locus) - {} + : VisItem (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.use_tree != nullptr) + use_tree = other.use_tree->clone_use_tree (); + } // Overloaded assignment operator to clone UseDeclaration &operator= (UseDeclaration const &other) { VisItem::operator= (other); - use_tree = other.use_tree->clone_use_tree (); // visibility = other.visibility->clone_visibility(); // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.use_tree != nullptr) + use_tree = other.use_tree->clone_use_tree (); + else + use_tree = nullptr; + return *this; } @@ -1177,6 +1185,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if use tree is null, so base stripping on that. + void mark_for_strip () override { use_tree = nullptr; } + bool is_marked_for_strip () const override { return use_tree == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1184,12 +1196,6 @@ protected: { return new UseDeclaration (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual UseDeclaration* clone_statement_impl() const override { - return new UseDeclaration(*this); - }*/ }; // Parameters used in a function - TODO inline? @@ -1264,11 +1270,16 @@ public: : VisItem (other), qualifiers (other.qualifiers), function_name (other.function_name), function_params (other.function_params), - return_type (other.return_type->clone_type ()), - where_clause (other.where_clause), - function_body (other.function_body->clone_block_expr ()), - locus (other.locus) + where_clause (other.where_clause), locus (other.locus) { + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + + // guard to prevent null dereference (only required if error state) + if (other.function_body != nullptr) + function_body = other.function_body->clone_block_expr (); + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -1280,15 +1291,24 @@ public: VisItem::operator= (other); function_name = other.function_name; qualifiers = other.qualifiers; - // generic_params = other.generic_params; function_params = other.function_params; - return_type = other.return_type->clone_type (); where_clause = other.where_clause; - function_body = other.function_body->clone_block_expr (); // visibility = other.visibility->clone_visibility(); // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + + // guard to prevent null dereference (only required if error state) + if (other.function_body != nullptr) + function_body = other.function_body->clone_block_expr (); + else + function_body = nullptr; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -1304,6 +1324,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if block is null, so base stripping on that. + void mark_for_strip () override { function_body = nullptr; } + bool is_marked_for_strip () const override { return function_body == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1322,12 +1346,6 @@ protected: { return new Function (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual Function* clone_statement_impl() const override { - return new Function(*this); - }*/ }; // Rust type alias (i.e. typedef) AST node @@ -1370,9 +1388,12 @@ public: // Copy constructor TypeAlias (TypeAlias const &other) : VisItem (other), new_type_name (other.new_type_name), - where_clause (other.where_clause), - existing_type (other.existing_type->clone_type ()), locus (other.locus) + where_clause (other.where_clause), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.existing_type != nullptr) + existing_type = other.existing_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 ()); @@ -1383,13 +1404,17 @@ public: { VisItem::operator= (other); new_type_name = other.new_type_name; - // generic_params = other.generic_params; where_clause = other.where_clause; - existing_type = other.existing_type->clone_type (); // visibility = other.visibility->clone_visibility(); // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.existing_type != nullptr) + existing_type = other.existing_type->clone_type (); + else + existing_type = nullptr; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -1405,6 +1430,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if existing type is null, so base stripping on that. + void mark_for_strip () override { existing_type = nullptr; } + bool is_marked_for_strip () const override { return existing_type == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1416,12 +1445,6 @@ protected: { return new TypeAlias (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual TypeAlias* clone_statement_impl() const override { - return new TypeAlias(*this); - }*/ }; // Rust base struct declaration AST node - abstract base class @@ -1448,6 +1471,10 @@ public: Location get_locus () const { return locus; } + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { struct_name = ""; } + bool is_marked_for_strip () const override { return struct_name.empty (); } + protected: Struct (Identifier struct_name, std::vector> generic_params, @@ -1584,8 +1611,7 @@ public: std::vector outer_attrs, Location locus) : Struct (std::move (struct_name), std::move (generic_params), std::move (where_clause), std::move (vis), locus, - std::move (outer_attrs)), - is_unit (true) + std::move (outer_attrs)), is_unit (true) {} // TODO: can a unit struct have generic fields? assuming yes for now. @@ -1603,12 +1629,6 @@ protected: { return new StructStruct (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual StructStruct* clone_statement_impl() const override { - return new StructStruct(*this); - }*/ }; // A single field in a tuple @@ -1702,12 +1722,6 @@ protected: { return new TupleStruct (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual TupleStruct* clone_statement_impl() const override { - return new TupleStruct(*this); - }*/ }; /* An item used in an "enum" tagged union - not abstract: base represents a @@ -1937,16 +1951,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { enum_name = ""; } + bool is_marked_for_strip () const override { return enum_name.empty (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ Enum *clone_item_impl () const override { return new Enum (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual Enum* clone_statement_impl() const override { - return new Enum(*this); - }*/ }; // Rust untagged union used for C compat AST node @@ -2020,16 +2032,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { union_name = ""; } + bool is_marked_for_strip () const override { return union_name.empty (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ Union *clone_item_impl () const override { return new Union (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual Union* clone_statement_impl() const override { - return new Union(*this); - }*/ }; /* "Constant item" AST node - used for constant, compile-time expressions @@ -2041,7 +2051,7 @@ class ConstantItem : public VisItem, // either has an identifier or "_" - maybe handle in identifier? // bool identifier_is_underscore; // if no identifier declared, identifier will be "_" - Identifier identifier; + std::string identifier; std::unique_ptr type; std::unique_ptr const_expr; @@ -2051,7 +2061,7 @@ class ConstantItem : public VisItem, public: std::string as_string () const override; - ConstantItem (Identifier ident, Visibility vis, std::unique_ptr type, + ConstantItem (std::string ident, Visibility vis, std::unique_ptr type, std::unique_ptr const_expr, std::vector outer_attrs, Location locus) : VisItem (std::move (vis), std::move (outer_attrs)), @@ -2060,20 +2070,32 @@ public: {} ConstantItem (ConstantItem const &other) - : VisItem (other), identifier (other.identifier), - type (other.type->clone_type ()), - const_expr (other.const_expr->clone_expr ()), locus (other.locus) - {} + : VisItem (other), identifier (other.identifier), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.type != nullptr) + type = other.type->clone_type (); + if (other.const_expr != nullptr) + const_expr = other.const_expr->clone_expr (); + } // Overload assignment operator to clone ConstantItem &operator= (ConstantItem const &other) { VisItem::operator= (other); identifier = other.identifier; - type = other.type->clone_type (); - const_expr = other.const_expr->clone_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + if (other.const_expr != nullptr) + const_expr = other.const_expr->clone_expr (); + else + const_expr = nullptr; + return *this; } @@ -2083,12 +2105,16 @@ public: /* Returns whether constant item is an "unnamed" (wildcard underscore used * as identifier) constant. */ - bool is_unnamed () const { return identifier == std::string ("_"); } + bool is_unnamed () const { return identifier == "_"; } Location get_locus () const { return locus; } void accept_vis (ASTVisitor &vis) override; + // Invalid if type or expression are null, so base stripping on that. + void mark_for_strip () override { type = nullptr; const_expr = nullptr; } + bool is_marked_for_strip () const override { return type == nullptr && const_expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2110,12 +2136,6 @@ protected: { return new ConstantItem (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ConstantItem* clone_statement_impl() const override { - return new ConstantItem(*this); - }*/ }; /* Static item AST node - items within module scope with fixed storage @@ -2142,9 +2162,14 @@ public: // Copy constructor with clone StaticItem (StaticItem const &other) : VisItem (other), has_mut (other.has_mut), name (other.name), - type (other.type->clone_type ()), expr (other.expr->clone_expr ()), locus (other.locus) - {} + { + // guard to prevent null dereference (only required if error state) + if (other.type != nullptr) + type = other.type->clone_type (); + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + } // Overloaded assignment operator to clone StaticItem &operator= (StaticItem const &other) @@ -2152,10 +2177,18 @@ public: VisItem::operator= (other); name = other.name; has_mut = other.has_mut; - type = other.type->clone_type (); - expr = other.expr->clone_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + else + expr = nullptr; + return *this; } @@ -2167,6 +2200,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if type or expression are null, so base stripping on that. + void mark_for_strip () override { type = nullptr; expr = nullptr; } + bool is_marked_for_strip () const override { return type == nullptr && expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2174,12 +2211,6 @@ protected: { return new StaticItem (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual StaticItem* clone_statement_impl() const override { - return new StaticItem(*this); - }*/ }; // Function declaration in traits @@ -2606,7 +2637,6 @@ protected: class Trait : public VisItem { bool has_unsafe; - Identifier name; // bool has_generics; @@ -2706,16 +2736,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if trait name is empty, so base stripping on that. + void mark_for_strip () override { name = ""; } + bool is_marked_for_strip () const override { return name.empty (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ Trait *clone_item_impl () const override { return new Trait (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual Trait* clone_statement_impl() const override { - return new Trait(*this); - }*/ }; // Implementation item declaration AST node - abstract base class @@ -2751,6 +2779,10 @@ public: Location get_locus () const { return locus; } + // Invalid if trait type is null, so base stripping on that. + void mark_for_strip () override { trait_type = nullptr; } + bool is_marked_for_strip () const override { return trait_type == nullptr; } + protected: // Mega-constructor Impl (std::vector> generic_params, @@ -2766,10 +2798,13 @@ protected: // Copy constructor Impl (Impl const &other) - : VisItem (other), trait_type (other.trait_type->clone_type ()), - where_clause (other.where_clause), inner_attrs (other.inner_attrs), - locus (other.locus) + : VisItem (other), where_clause (other.where_clause), + inner_attrs (other.inner_attrs), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.trait_type != nullptr) + trait_type = other.trait_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 ()); @@ -2779,11 +2814,16 @@ protected: Impl &operator= (Impl const &other) { VisItem::operator= (other); - trait_type = other.trait_type->clone_type (); where_clause = other.where_clause; inner_attrs = other.inner_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.trait_type != nullptr) + trait_type = other.trait_type->clone_type (); + else + trait_type = nullptr; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -2853,12 +2893,6 @@ protected: { return new InherentImpl (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual InherentImpl* clone_statement_impl() const override { - return new InherentImpl(*this); - }*/ }; // The "impl footrait for foo" impl block declaration AST node @@ -2928,12 +2962,6 @@ protected: /* Use covariance to implement clone function as returning this object * rather than base */ TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual TraitImpl* clone_statement_impl() const override { - return new TraitImpl(*this); - }*/ }; // Abstract base class for an item used inside an extern block @@ -2951,6 +2979,10 @@ class ExternalItem public: virtual ~ExternalItem () {} + /* TODO: spec syntax rules state that "MacroInvocationSemi" can be used as + * ExternalItem, but text body isn't so clear. Adding MacroInvocationSemi + * support would require a lot of refactoring. */ + // Returns whether item has outer attributes. bool has_outer_attrs () const { return !outer_attrs.empty (); } @@ -2969,6 +3001,11 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + // TODO: make virtual? Would be more flexible. + // Based on idea that name should never be empty. + void mark_for_strip () { item_name = ""; }; + bool is_marked_for_strip () const { return item_name.empty (); }; + protected: ExternalItem (Identifier item_name, Visibility vis, std::vector outer_attrs, Location locus) @@ -3209,6 +3246,9 @@ class ExternBlock : public VisItem std::vector> extern_items; Location locus; + + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; public: std::string as_string () const override; @@ -3234,7 +3274,7 @@ public: // Copy constructor with vector clone ExternBlock (ExternBlock const &other) : VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs), - locus (other.locus) + locus (other.locus), marked_for_strip (other.marked_for_strip) { extern_items.reserve (other.extern_items.size ()); for (const auto &e : other.extern_items) @@ -3248,6 +3288,7 @@ public: abi = other.abi; inner_attrs = other.inner_attrs; locus = other.locus; + marked_for_strip = other.marked_for_strip; extern_items.reserve (other.extern_items.size ()); for (const auto &e : other.extern_items) @@ -3264,6 +3305,18 @@ public: void accept_vis (ASTVisitor &vis) override; + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + + // TODO: think of better way to do this + const std::vector>& get_extern_items () const { return extern_items; } + std::vector>& get_extern_items () { return extern_items; } + + // TODO: think of better way to do this + const std::vector& get_inner_attrs () const { return inner_attrs; } + std::vector& get_inner_attrs () { return inner_attrs; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -3271,12 +3324,6 @@ protected: { return new ExternBlock (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ExternBlock* clone_statement_impl() const override { - return new ExternBlock(*this); - }*/ }; // Replaced with forward decls - defined in "rust-macro.h" diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 9ecbb51..8d50b88 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -124,7 +124,7 @@ private: public: // Returns whether macro match repetition has separator token. - bool has_sep () const { return sep != NULL; } + bool has_sep () const { return sep != nullptr; } MacroMatchRepetition (std::vector > matches, MacroRepOp op, std::unique_ptr sep) @@ -133,8 +133,12 @@ public: // Copy constructor with clone MacroMatchRepetition (MacroMatchRepetition const &other) - : op (other.op), sep (other.sep->clone_token ()) + : op (other.op) { + // guard to protect from null pointer dereference + if (other.sep != nullptr) + sep = other.sep->clone_token (); + matches.reserve (other.matches.size ()); for (const auto &e : other.matches) matches.push_back (e->clone_macro_match ()); @@ -144,7 +148,12 @@ public: MacroMatchRepetition &operator= (MacroMatchRepetition const &other) { op = other.op; - sep = other.sep->clone_token (); + + // guard to protect from null pointer dereference + if (other.sep != nullptr) + sep = other.sep->clone_token (); + else + sep = nullptr; matches.reserve (other.matches.size ()); for (const auto &e : other.matches) @@ -280,8 +289,9 @@ public: // A macro rules definition item AST node class MacroRulesDefinition : public MacroItem { + std::vector outer_attrs; Identifier rule_name; - // MacroRulesDef rules_def; // TODO: inline + // MacroRulesDef rules_def; // only curly without required semicolon at end DelimType delim_type; // MacroRules rules; @@ -295,12 +305,16 @@ public: MacroRulesDefinition (Identifier rule_name, DelimType delim_type, std::vector rules, std::vector outer_attrs, Location locus) - : MacroItem (std::move (outer_attrs)), rule_name (std::move (rule_name)), + : outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)), delim_type (delim_type), rules (std::move (rules)), locus (locus) {} void accept_vis (ASTVisitor &vis) override; + // Invalid if rule name is empty, so base stripping on that. + void mark_for_strip () override { rule_name = ""; } + bool is_marked_for_strip () const override { return rule_name.empty (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -334,6 +348,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if path is empty, so base stripping on that. + void mark_for_strip () override { path = SimplePath::create_empty (); } + bool is_marked_for_strip () const override { return path.is_empty (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -341,14 +359,7 @@ protected: { return new MacroInvocation (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - MacroInvocation *clone_expr_impl () const override - { - return new MacroInvocation (*this); - } - + /* Use covariance to implement clone function as returning this object rather * than base */ MacroInvocation *clone_expr_without_block_impl () const override @@ -358,13 +369,6 @@ protected: /* Use covariance to implement clone function as returning this object rather * than base */ - MacroInvocation *clone_type_impl () const override - { - return new MacroInvocation (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_type_no_bounds_impl () const override { return new MacroInvocation (*this); diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 3006780..32147d3 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -70,9 +70,12 @@ public: // Copy constructor has to deep copy the type as it is a unique pointer GenericArgsBinding (GenericArgsBinding const &other) - : identifier (other.identifier), type (other.type->clone_type ()), - locus (other.locus) - {} + : identifier (other.identifier), locus (other.locus) + { + // guard to protect from null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + } // default destructor ~GenericArgsBinding () = default; @@ -81,8 +84,14 @@ public: GenericArgsBinding &operator= (GenericArgsBinding const &other) { identifier = other.identifier; - type = other.type->clone_type (); locus = other.locus; + + // guard to protect from null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + return *this; } @@ -231,6 +240,9 @@ protected: * and creates a SimplePath from them. */ SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const; + // Removes all segments of the path. + void remove_all_segments () { segments.clear (); segments.shrink_to_fit (); } + public: /* Returns whether the path is a single segment (excluding qualified path * initial as segment). */ @@ -286,6 +298,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if path is empty (error state), so base stripping on that. + void mark_for_strip () override { remove_all_segments (); } + bool is_marked_for_strip () const override { return is_error (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -446,13 +462,6 @@ public: // Constructor TypePathFunction (std::vector> inputs, - Type *type = nullptr) - : inputs (std::move (inputs)), return_type (type), is_invalid (false) - {} - // FIXME: deprecated - - // Constructor - TypePathFunction (std::vector> inputs, std::unique_ptr type = nullptr) : inputs (std::move (inputs)), return_type (std::move (type)), is_invalid (false) @@ -460,9 +469,12 @@ public: // Copy constructor with clone TypePathFunction (TypePathFunction const &other) - : return_type (other.return_type->clone_type ()), - is_invalid (other.is_invalid) + : is_invalid (other.is_invalid) { + // guard to protect from null pointer dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + inputs.reserve (other.inputs.size ()); for (const auto &e : other.inputs) inputs.push_back (e->clone_type ()); @@ -473,9 +485,14 @@ public: // Overloaded assignment operator to clone type TypePathFunction &operator= (TypePathFunction const &other) { - return_type = other.return_type->clone_type (); is_invalid = other.is_invalid; + // guard to protect from null pointer dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + inputs.reserve (other.inputs.size ()); for (const auto &e : other.inputs) inputs.push_back (e->clone_type ()); @@ -539,10 +556,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TypePath *clone_type_impl () const override { return new TypePath (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ TypePath *clone_type_no_bounds_impl () const override { return new TypePath (*this); @@ -635,9 +648,12 @@ public: // Copy constructor uses custom deep copy for Type to preserve polymorphism QualifiedPathType (QualifiedPathType const &other) - : type_to_invoke_on (other.type_to_invoke_on->clone_type ()), - trait_path (other.trait_path), locus (other.locus) - {} + : trait_path (other.trait_path), locus (other.locus) + { + // guard to prevent null dereference + if (other.type_to_invoke_on != nullptr) + type_to_invoke_on = other.type_to_invoke_on->clone_type (); + } // default destructor ~QualifiedPathType () = default; @@ -645,9 +661,15 @@ public: // overload assignment operator to use custom clone method QualifiedPathType &operator= (QualifiedPathType const &other) { - type_to_invoke_on = other.type_to_invoke_on->clone_type (); trait_path = other.trait_path; locus = other.locus; + + // guard to prevent null dereference + if (other.type_to_invoke_on != nullptr) + type_to_invoke_on = other.type_to_invoke_on->clone_type (); + else + type_to_invoke_on = nullptr; + return *this; } @@ -710,6 +732,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if path_type is error, so base stripping on that. + void mark_for_strip () override { path_type = QualifiedPathType::create_error (); } + bool is_marked_for_strip () const override { return is_error (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -737,13 +763,6 @@ class QualifiedPathInType : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - QualifiedPathInType *clone_type_impl () const override - { - return new QualifiedPathInType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ QualifiedPathInType *clone_type_no_bounds_impl () const override { return new QualifiedPathInType (*this); diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 4e639a5..63abe7a 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -77,7 +77,7 @@ public: : variable_ident (other.variable_ident), is_ref (other.is_ref), is_mut (other.is_mut), locus (other.locus) { - // fix to get prevent null pointer dereference + // fix to prevent null pointer dereference if (other.to_bind != nullptr) to_bind = other.to_bind->clone_pattern (); } @@ -90,9 +90,11 @@ public: is_mut = other.is_mut; locus = other.locus; - // fix to get prevent null pointer dereference + // fix to prevent null pointer dereference if (other.to_bind != nullptr) to_bind = other.to_bind->clone_pattern (); + else + to_bind = nullptr; return *this; } @@ -1006,15 +1008,24 @@ public: // Copy constructor requires clone TuplePattern (TuplePattern const &other) - : items (other.items->clone_tuple_pattern_items ()), locus (other.locus) - {} + : locus (other.locus) + { + // guard to prevent null dereference + if (other.items != nullptr) + items = other.items->clone_tuple_pattern_items (); + } // Overload assignment operator to clone TuplePattern &operator= (TuplePattern const &other) { - items = other.items->clone_tuple_pattern_items (); locus = other.locus; + // guard to prevent null dereference + if (other.items != nullptr) + items = other.items->clone_tuple_pattern_items (); + else + items = nullptr; + return *this; } diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index ce7a37a..127ea21 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -12,6 +12,9 @@ class EmptyStmt : public Stmt { Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override { return std::string (1, ';'); } @@ -21,6 +24,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -68,21 +75,41 @@ public: // Copy constructor with clone LetStmt (LetStmt const &other) - : outer_attrs (other.outer_attrs), - variables_pattern (other.variables_pattern->clone_pattern ()), - type (other.type->clone_type ()), - init_expr (other.init_expr->clone_expr ()), locus (other.locus) - {} + : outer_attrs (other.outer_attrs), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.variables_pattern != nullptr) + variables_pattern = other.variables_pattern->clone_pattern (); + + // guard to prevent null dereference (always required) + if (other.init_expr != nullptr) + init_expr = other.init_expr->clone_expr (); + if (other.type != nullptr) + type = other.type->clone_type (); + } // Overloaded assignment operator to clone LetStmt &operator= (LetStmt const &other) { - variables_pattern = other.variables_pattern->clone_pattern (); - init_expr = other.init_expr->clone_expr (); - type = other.type->clone_type (); outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.variables_pattern != nullptr) + variables_pattern = other.variables_pattern->clone_pattern (); + else + variables_pattern = nullptr; + + // guard to prevent null dereference (always required) + if (other.init_expr != nullptr) + init_expr = other.init_expr->clone_expr (); + else + init_expr = nullptr; + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + return *this; } @@ -94,6 +121,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if pattern is null, so base stripping on that. + void mark_for_strip () override { variables_pattern = nullptr; } + bool is_marked_for_strip () const override { return variables_pattern == nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -138,8 +169,12 @@ public: // Copy constructor with clone ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) - : ExprStmt (other), expr (other.expr->clone_expr_without_block ()) - {} + : ExprStmt (other) + { + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_expr_without_block (); + } /*ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) : ExprStmt (other), expr (other.expr->clone_expr ()) {}*/ @@ -148,9 +183,14 @@ public: ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other) { ExprStmt::operator= (other); - expr = other.expr->clone_expr_without_block (); //expr = other.expr->clone_expr (); + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_expr_without_block (); + else + expr = nullptr; + return *this; } @@ -160,6 +200,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { expr = nullptr; } + bool is_marked_for_strip () const override { return expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -185,14 +229,23 @@ public: // Copy constructor with clone ExprStmtWithBlock (ExprStmtWithBlock const &other) - : ExprStmt (other), expr (other.expr->clone_expr_with_block ()) - {} + : ExprStmt (other) + { + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_expr_with_block (); + } // Overloaded assignment operator to clone ExprStmtWithBlock &operator= (ExprStmtWithBlock const &other) { ExprStmt::operator= (other); - expr = other.expr->clone_expr_with_block (); + + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_expr_with_block (); + else + expr = nullptr; return *this; } @@ -203,6 +256,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { expr = nullptr; } + bool is_marked_for_strip () const override { return expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index b396a44..78b57eb 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -177,13 +177,6 @@ class ParenthesisedType : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ParenthesisedType *clone_type_impl () const override - { - return new ParenthesisedType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ParenthesisedType *clone_type_no_bounds_impl () const override { return new ParenthesisedType (*this); @@ -242,13 +235,6 @@ class ImplTraitTypeOneBound : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ImplTraitTypeOneBound *clone_type_impl () const override - { - return new ImplTraitTypeOneBound (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override { return new ImplTraitTypeOneBound (*this); @@ -278,13 +264,6 @@ class TraitObjectTypeOneBound : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TraitObjectTypeOneBound *clone_type_impl () const override - { - return new TraitObjectTypeOneBound (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override { return new TraitObjectTypeOneBound (*this); @@ -362,10 +341,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleType *clone_type_impl () const override { return new TupleType (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ TupleType *clone_type_no_bounds_impl () const override { return new TupleType (*this); @@ -382,10 +357,6 @@ class NeverType : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - NeverType *clone_type_impl () const override { return new NeverType (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ NeverType *clone_type_no_bounds_impl () const override { return new NeverType (*this); @@ -455,13 +426,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - RawPointerType *clone_type_impl () const override - { - return new RawPointerType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ RawPointerType *clone_type_no_bounds_impl () const override { return new RawPointerType (*this); @@ -522,13 +486,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ReferenceType *clone_type_impl () const override - { - return new ReferenceType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ReferenceType *clone_type_no_bounds_impl () const override { return new ReferenceType (*this); @@ -577,10 +534,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ArrayType *clone_type_impl () const override { return new ArrayType (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ArrayType *clone_type_no_bounds_impl () const override { return new ArrayType (*this); @@ -627,10 +580,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - SliceType *clone_type_impl () const override { return new SliceType (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ SliceType *clone_type_no_bounds_impl () const override { return new SliceType (*this); @@ -647,13 +596,6 @@ class InferredType : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - InferredType *clone_type_impl () const override - { - return new InferredType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ InferredType *clone_type_no_bounds_impl () const override { return new InferredType (*this); @@ -699,9 +641,12 @@ public: // Copy constructor with clone MaybeNamedParam (MaybeNamedParam const &other) - : param_type (other.param_type->clone_type ()), - param_kind (other.param_kind), name (other.name), locus (other.locus) - {} + : param_kind (other.param_kind), name (other.name), locus (other.locus) + { + // guard to prevent null dereference + if (other.param_type != nullptr) + param_type = other.param_type->clone_type (); + } ~MaybeNamedParam () = default; @@ -710,9 +655,14 @@ public: { name = other.name; param_kind = other.param_kind; - param_type = other.param_type->clone_type (); locus = other.locus; + // guard to prevent null dereference + if (other.param_type != nullptr) + param_type = other.param_type->clone_type (); + else + param_type = nullptr; + return *this; } @@ -773,10 +723,12 @@ public: BareFunctionType (BareFunctionType const &other) : for_lifetimes (other.for_lifetimes), function_qualifiers (other.function_qualifiers), params (other.params), - is_variadic (other.is_variadic), - return_type (other.return_type->clone_type_no_bounds ()), - locus (other.locus) - {} + is_variadic (other.is_variadic), locus (other.locus) + { + // guard to prevent null dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type_no_bounds (); + } // Overload assignment operator to deep copy BareFunctionType &operator= (BareFunctionType const &other) @@ -785,9 +737,14 @@ public: function_qualifiers = other.function_qualifiers; params = other.params; is_variadic = other.is_variadic; - return_type = other.return_type->clone_type_no_bounds (); locus = other.locus; + // guard to prevent null dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type_no_bounds (); + else + return_type = nullptr; + return *this; } @@ -804,13 +761,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - BareFunctionType *clone_type_impl () const override - { - return new BareFunctionType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ BareFunctionType *clone_type_no_bounds_impl () const override { return new BareFunctionType (*this); diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 4a39be3..a7d2a1a 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -1,8 +1,217 @@ #include "rust-macro-expand.h" #include "rust-ast-full.h" // is full really required? +#include "rust-ast-visitor.h" namespace Rust { + // Visitor used to expand attributes. + class AttrVisitor : public AST::ASTVisitor { + private: + MacroExpander& expander; + + public: + AttrVisitor(MacroExpander& expander) : expander(expander) {} + + void visit(AST::Token& tok) override {} + void visit(AST::DelimTokenTree& delim_tok_tree) override {} + void visit(AST::AttrInputMetaItemContainer& input) override {} + void visit(AST::IdentifierExpr& ident_expr) override {} + void visit(AST::Lifetime& lifetime) override {} + void visit(AST::LifetimeParam& lifetime_param) override {} + void visit(AST::MacroInvocationSemi& macro) override {} + + void visit(AST::PathInExpression& path) override {} + void visit(AST::TypePathSegment& segment) override {} + void visit(AST::TypePathSegmentGeneric& segment) override {} + void visit(AST::TypePathSegmentFunction& segment) override {} + void visit(AST::TypePath& path) override {} + void visit(AST::QualifiedPathInExpression& path) override {} + void visit(AST::QualifiedPathInType& path) override {} + + void visit(AST::LiteralExpr& expr) override {} + void visit(AST::AttrInputLiteral& attr_input) override {} + void visit(AST::MetaItemLitExpr& meta_item) override {} + void visit(AST::MetaItemPathLit& meta_item) override {} + void visit(AST::BorrowExpr& expr) override {} + void visit(AST::DereferenceExpr& expr) override {} + void visit(AST::ErrorPropagationExpr& expr) override {} + void visit(AST::NegationExpr& expr) override {} + void visit(AST::ArithmeticOrLogicalExpr& expr) override {} + void visit(AST::ComparisonExpr& expr) override {} + void visit(AST::LazyBooleanExpr& expr) override {} + void visit(AST::TypeCastExpr& expr) override {} + void visit(AST::AssignmentExpr& expr) override {} + void visit(AST::CompoundAssignmentExpr& expr) override {} + void visit(AST::GroupedExpr& expr) override {} + void visit(AST::ArrayElemsValues& elems) override {} + void visit(AST::ArrayElemsCopied& elems) override {} + void visit(AST::ArrayExpr& expr) override {} + void visit(AST::ArrayIndexExpr& expr) override {} + void visit(AST::TupleExpr& expr) override {} + void visit(AST::TupleIndexExpr& expr) override {} + void visit(AST::StructExprStruct& expr) override {} + void visit(AST::StructExprFieldIdentifier& field) override {} + void visit(AST::StructExprFieldIdentifierValue& field) override {} + void visit(AST::StructExprFieldIndexValue& field) override {} + void visit(AST::StructExprStructFields& expr) override {} + void visit(AST::StructExprStructBase& expr) override {} + void visit(AST::StructExprTuple& expr) override {} + void visit(AST::StructExprUnit& expr) override {} + void visit(AST::EnumExprFieldIdentifier& field) override {} + void visit(AST::EnumExprFieldIdentifierValue& field) override {} + void visit(AST::EnumExprFieldIndexValue& field) override {} + void visit(AST::EnumExprStruct& expr) override {} + 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::ClosureExprInnerTyped& expr) override {} + void visit(AST::ContinueExpr& expr) override {} + void visit(AST::BreakExpr& expr) override {} + void visit(AST::RangeFromToExpr& expr) override {} + void visit(AST::RangeFromExpr& expr) override {} + void visit(AST::RangeToExpr& expr) override {} + void visit(AST::RangeFullExpr& expr) override {} + void visit(AST::RangeFromToInclExpr& expr) override {} + void visit(AST::RangeToInclExpr& expr) override {} + void visit(AST::ReturnExpr& expr) override {} + void visit(AST::UnsafeBlockExpr& expr) override {} + void visit(AST::LoopExpr& expr) override {} + void visit(AST::WhileLoopExpr& expr) override {} + void visit(AST::WhileLetLoopExpr& expr) override {} + void visit(AST::ForLoopExpr& expr) override {} + void visit(AST::IfExpr& expr) override {} + void visit(AST::IfExprConseqElse& expr) override {} + void visit(AST::IfExprConseqIf& expr) override {} + void visit(AST::IfExprConseqIfLet& expr) override {} + void visit(AST::IfLetExpr& expr) override {} + void visit(AST::IfLetExprConseqElse& expr) override {} + void visit(AST::IfLetExprConseqIf& expr) override {} + void visit(AST::IfLetExprConseqIfLet& expr) override {} + void visit(AST::MatchExpr& expr) override {} + void visit(AST::AwaitExpr& expr) override {} + void visit(AST::AsyncBlockExpr& expr) override {} + + void visit(AST::TypeParam& param) override {} + void visit(AST::LifetimeWhereClauseItem& item) override {} + void visit(AST::TypeBoundWhereClauseItem& item) override {} + void visit(AST::Method& method) override {} + void visit(AST::ModuleBodied& module) override {} + void visit(AST::ModuleNoBody& module) override {} + void visit(AST::ExternCrate& crate) override {} + void visit(AST::UseTreeGlob& use_tree) override {} + void visit(AST::UseTreeList& use_tree) override {} + void visit(AST::UseTreeRebind& use_tree) override {} + void visit(AST::UseDeclaration& use_decl) override {} + void visit(AST::Function& function) override {} + void visit(AST::TypeAlias& type_alias) override {} + void visit(AST::StructStruct& struct_item) override {} + void visit(AST::TupleStruct& tuple_struct) override {} + void visit(AST::EnumItem& item) override {} + void visit(AST::EnumItemTuple& item) override {} + void visit(AST::EnumItemStruct& item) override {} + void visit(AST::EnumItemDiscriminant& item) override {} + void visit(AST::Enum& enum_item) override {} + void visit(AST::Union& union_item) override {} + void visit(AST::ConstantItem& const_item) override {} + void visit(AST::StaticItem& static_item) override {} + void visit(AST::TraitItemFunc& item) override {} + void visit(AST::TraitItemMethod& item) override {} + void visit(AST::TraitItemConst& item) override {} + void visit(AST::TraitItemType& item) override {} + 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::ExternBlock& block) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(block.get_outer_attrs()); + if (expander.fails_cfg(block.get_outer_attrs())) { + block.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(block.get_inner_attrs()); + if (expander.fails_cfg(block.get_inner_attrs())) { + block.mark_for_strip(); + return; + } + + // strip external items if required + auto& extern_items = block.get_extern_items(); + for (auto i = 0; i < extern_items.size(); ) { + auto& item = extern_items[i]; + + // mark for stripping if required + item->accept_vis(*this); + + if (item->is_marked_for_strip ()) + extern_items.erase (extern_items.begin() + i); + else + i++; + + } + } + + void visit(AST::MacroMatchFragment& match) override {} + void visit(AST::MacroMatchRepetition& match) override {} + void visit(AST::MacroMatcher& matcher) override {} + void visit(AST::MacroRulesDefinition& rules_def) override {} + void visit(AST::MacroInvocation& macro_invoc) override {} + void visit(AST::MetaItemPath& meta_item) override {} + void visit(AST::MetaItemSeq& meta_item) override {} + void visit(AST::MetaWord& meta_item) override {} + void visit(AST::MetaNameValueStr& meta_item) override {} + void visit(AST::MetaListPaths& meta_item) override {} + void visit(AST::MetaListNameValueStr& meta_item) override {} + + void visit(AST::LiteralPattern& pattern) override {} + void visit(AST::IdentifierPattern& pattern) override {} + void visit(AST::WildcardPattern& pattern) override {} + void visit(AST::RangePatternBoundLiteral& bound) override {} + void visit(AST::RangePatternBoundPath& bound) override {} + void visit(AST::RangePatternBoundQualPath& bound) override {} + void visit(AST::RangePattern& pattern) override {} + void visit(AST::ReferencePattern& pattern) override {} + void visit(AST::StructPatternFieldTuplePat& field) override {} + void visit(AST::StructPatternFieldIdentPat& field) override {} + void visit(AST::StructPatternFieldIdent& field) override {} + void visit(AST::StructPattern& pattern) override {} + void visit(AST::TupleStructItemsNoRange& tuple_items) override {} + void visit(AST::TupleStructItemsRange& tuple_items) override {} + void visit(AST::TupleStructPattern& pattern) override {} + void visit(AST::TuplePatternItemsMultiple& tuple_items) override {} + void visit(AST::TuplePatternItemsRanged& tuple_items) override {} + void visit(AST::TuplePattern& pattern) override {} + void visit(AST::GroupedPattern& pattern) override {} + void visit(AST::SlicePattern& pattern) override {} + + void visit(AST::EmptyStmt& stmt) override {} + void visit(AST::LetStmt& stmt) override {} + void visit(AST::ExprStmtWithoutBlock& stmt) override {} + void visit(AST::ExprStmtWithBlock& stmt) override {} + + void visit(AST::TraitBound& bound) override {} + void visit(AST::ImplTraitType& type) override {} + void visit(AST::TraitObjectType& type) override {} + void visit(AST::ParenthesisedType& type) override {} + void visit(AST::ImplTraitTypeOneBound& type) override {} + void visit(AST::TraitObjectTypeOneBound& type) override {} + void visit(AST::TupleType& type) override {} + void visit(AST::NeverType& type) override {} + void visit(AST::RawPointerType& type) override {} + void visit(AST::ReferenceType& type) override {} + void visit(AST::ArrayType& type) override {} + void visit(AST::SliceType& type) override {} + void visit(AST::InferredType& type) override {} + void visit(AST::BareFunctionType& type) override {} + }; + void MacroExpander::expand_invoc(std::unique_ptr& invoc) { /* if current expansion depth > recursion limit, create an error (maybe fatal * error) and return */ @@ -24,7 +233,7 @@ namespace Rust { - derive container macro - unreachable*/ } - /* Determines whether any cfg predicate is false and hence item with attributes should + /* Determines whether any cfg predicate is false and hence item with attributes should * be stripped. */ bool MacroExpander::fails_cfg(std::vector& attrs) { for (auto& attr : attrs) { @@ -81,6 +290,14 @@ namespace Rust { } // expand module attributes? + // expand attributes recursively + AttrVisitor attr_visitor(*this); + for (auto& i : crate.items) { + i->accept_vis(attr_visitor); + } + // TODO: should recursive attribute and macro expansion be done in the same transversal? Or in + // separate ones like currently? + // expand module tree recursively // post-process diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 7940df7..fd50bf1 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -626,8 +626,7 @@ Session::injection (AST::Crate &crate) * rustc also has a "quote" macro that is defined differently and is * supposedly not stable so eh. */ /* TODO: actually implement injection of these macros. In particular, derive - * macros, cfg, and - * test should be prioritised since they seem to be used the most. */ + * macros, cfg, and test should be prioritised since they seem to be used the most. */ // crate injection std::vector names; -- cgit v1.1 From 69048af1878e95e26b57febb701f884f513c7b93 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Thu, 29 Oct 2020 22:11:41 +0800 Subject: 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 --- gcc/rust/ast/rust-ast-full-test.cc | 80 +++++++++++++---- gcc/rust/ast/rust-ast.h | 33 ++++++- gcc/rust/ast/rust-item.h | 170 +++++++++++++++++++++++++++++------ gcc/rust/expand/rust-macro-expand.cc | 32 ++++++- gcc/rust/parse/rust-parse-impl.h | 83 ++++++++--------- gcc/rust/parse/rust-parse.h | 3 +- 6 files changed, 303 insertions(+), 98 deletions(-) (limited to 'gcc/rust') 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 clone_external_item () const + { + return std::unique_ptr (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 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 outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier item_name; + Location locus; + bool has_mut; std::unique_ptr item_type; public: ExternalStaticItem (Identifier item_name, std::unique_ptr item_type, - bool is_mut, Visibility vis, - std::vector 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 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 &get_outer_attrs () { return outer_attrs; } + const std::vector &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 param_type; // TODO: should this store location data? + // seemingly new since writing this node + std::vector 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 param_type) - : name (std::move (name)), param_type (std::move (param_type)) + NamedFunctionParam (std::string name, std::unique_ptr param_type, std::vector 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 &get_outer_attrs () { return outer_attrs; } + const std::vector &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 outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier item_name; + Location locus; + // bool has_generics; // Generics generic_params; std::vector> generic_params; // inlined @@ -3162,6 +3233,7 @@ class ExternalFunctionItem : public ExternalItem std::vector function_params; bool has_variadics; + std::vector 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> generic_params, std::unique_ptr return_type, WhereClause where_clause, - std::vector function_params, bool has_variadics, + std::vector function_params, bool has_variadics, std::vector variadic_outer_attrs, Visibility vis, std::vector 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 &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + + std::vector &get_function_params () { return function_params; } + const std::vector &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::parse_external_item () // parse parameters std::vector function_params; bool is_variadic = false; + std::vector 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 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 return_type = parse_function_return_type (); @@ -5705,7 +5694,7 @@ Parser::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::parse_external_item () * identifier). */ template AST::NamedFunctionParam -Parser::parse_named_function_param () +Parser::parse_named_function_param (std::vector outer_attrs) { // parse identifier/_ - Identifier name; + std::string name; const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) @@ -5760,7 +5749,7 @@ Parser::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 outer_attrs); std::unique_ptr parse_external_item (); - AST::NamedFunctionParam parse_named_function_param (); + AST::NamedFunctionParam parse_named_function_param ( + std::vector outer_attrs = std::vector ()); AST::Method parse_method (); // Expression-related (Pratt parsed) -- cgit v1.1 From 1271b772038d1e01cfed35ea5c764ceedc9842f9 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Thu, 5 Nov 2020 22:27:44 +0800 Subject: Added more trait item stripping Fixed lack of AST:: prepending in rust-parse-impl.h - should prevent compilation error Fixed expr renaming in Method as_string, should prevent compile error Fixed issue with changing location accessibility for AST nodes Fixed rust-compile.cc not using get_locus() instead of .locus --- gcc/rust/analysis/rust-type-resolution.cc | 24 +-- gcc/rust/ast/rust-ast-full-test.cc | 12 +- gcc/rust/ast/rust-ast.h | 20 +-- gcc/rust/ast/rust-item.h | 239 +++++++++++++++++++++++++----- gcc/rust/backend/rust-compile.cc | 86 +++++------ gcc/rust/expand/rust-macro-expand.cc | 177 ++++++++++++++++++++-- gcc/rust/parse/rust-parse-impl.h | 105 ++++++++----- gcc/rust/parse/rust-parse.h | 3 +- 8 files changed, 498 insertions(+), 168 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 3503a83..aef02ce 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -161,7 +161,7 @@ TypeResolution::visit (AST::IdentifierExpr &ident_expr) bool ok = scope.LookupType (ident_expr.ident, &type); if (!ok) { - rust_error_at (ident_expr.locus, "unknown identifier"); + rust_error_at (ident_expr.get_locus (), "unknown identifier"); return; } @@ -272,7 +272,7 @@ TypeResolution::visit (AST::LiteralExpr &expr) if (type.empty ()) { - rust_error_at (expr.locus, "unknown literal: %s", + rust_error_at (expr.get_locus (), "unknown literal: %s", expr.literal.as_string ().c_str ()); return; } @@ -282,7 +282,7 @@ TypeResolution::visit (AST::LiteralExpr &expr) if (ok) typeBuffer.push_back (val); else - rust_error_at (expr.locus, "unknown literal type: %s", type.c_str ()); + rust_error_at (expr.get_locus (), "unknown literal type: %s", type.c_str ()); } void @@ -318,7 +318,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) expr.visit_lhs (*this); if (typeBuffer.size () <= before) { - rust_error_at (expr.locus, "unable to determine lhs type"); + rust_error_at (expr.get_locus (), "unable to determine lhs type"); return; } @@ -329,7 +329,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) expr.visit_rhs (*this); if (typeBuffer.size () <= before) { - rust_error_at (expr.locus, "unable to determine rhs type"); + rust_error_at (expr.get_locus (), "unable to determine rhs type"); return; } @@ -361,7 +361,7 @@ TypeResolution::visit (AST::AssignmentExpr &expr) expr.visit_lhs (*this); if (typeBuffer.size () <= before) { - rust_error_at (expr.locus, "unable to determine lhs type"); + rust_error_at (expr.get_locus (), "unable to determine lhs type"); return; } @@ -372,7 +372,7 @@ TypeResolution::visit (AST::AssignmentExpr &expr) expr.visit_rhs (*this); if (typeBuffer.size () <= before) { - rust_error_at (expr.locus, "unable to determine rhs type"); + rust_error_at (expr.get_locus (), "unable to determine rhs type"); return; } @@ -583,7 +583,7 @@ TypeResolution::visit (AST::CallExpr &expr) auto numInferedParams = typeBuffer.size () - before; if (numInferedParams != expr.params.size ()) { - rust_error_at (expr.locus, "Failed to infer all parameters"); + rust_error_at (expr.get_locus (), "Failed to infer all parameters"); return; } @@ -768,14 +768,14 @@ TypeResolution::visit (AST::Function &function) for (auto ¶m : function.function_params) { - if (!isTypeInScope (param.type.get (), param.locus)) + if (!isTypeInScope (param.type.get (), param.get_locus ())) return; auto before = letPatternBuffer.size (); param.param_name->accept_vis (*this); if (letPatternBuffer.size () <= before) { - rust_error_at (param.locus, "failed to analyse parameter name"); + rust_error_at (param.get_locus (), "failed to analyse parameter name"); return; } @@ -787,7 +787,7 @@ TypeResolution::visit (AST::Function &function) // ensure the return type is resolved if (function.has_function_return_type ()) { - if (!isTypeInScope (function.return_type.get (), function.locus)) + if (!isTypeInScope (function.return_type.get (), function.get_locus ())) return; } @@ -1006,7 +1006,7 @@ TypeResolution::visit (AST::LetStmt &stmt) scope.InsertLocal (stmt.as_string (), &stmt); if (!stmt.has_init_expr () && !stmt.has_type ()) { - rust_error_at (stmt.locus, + rust_error_at (stmt.get_locus (), "E0282: type annotations or init expression needed"); return; } diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 1e95e47..8071226 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -678,33 +678,23 @@ Method::as_string () const else { for (const auto ¶m : function_params) - { str += "\n " + param.as_string (); - } } str += "\n Return type: "; if (has_return_type ()) - { str += return_type->as_string (); - } else - { str += "none (void)"; - } str += "\n Where clause: "; if (has_where_clause ()) - { str += where_clause.as_string (); - } else - { str += "none"; - } str += "\n Block expr (body): \n "; - str += expr->as_string (); + str += function_body->as_string (); return str; } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 4c4b043..e0f46ac 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1221,21 +1221,12 @@ class TraitItem // NOTE: all children should have outer attributes protected: - // Constructor - /*TraitItem(std::vector outer_attrs = std::vector()) - : outer_attrs(std::move(outer_attrs)) {}*/ - // Clone function implementation as pure virtual method virtual TraitItem *clone_trait_item_impl () const = 0; public: virtual ~TraitItem () {} - // Returns whether TraitItem has outer attributes. - /*bool has_outer_attrs() const { - return !outer_attrs.empty(); - }*/ - // Unique pointer custom clone function std::unique_ptr clone_trait_item () const { @@ -1245,6 +1236,9 @@ public: 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; }; /* Abstract base class for items used within an inherent impl block (the impl @@ -1267,6 +1261,9 @@ public: 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; }; // Abstract base class for items used in a trait impl @@ -1276,7 +1273,7 @@ protected: virtual TraitImplItem *clone_trait_impl_item_impl () const = 0; public: - virtual ~TraitImplItem (){}; + virtual ~TraitImplItem () {}; // Unique pointer custom clone function std::unique_ptr clone_trait_impl_item () const @@ -1287,6 +1284,9 @@ public: 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; }; // Abstract base class for an item used inside an extern block diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 8542638..a56d1b5 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -434,31 +434,45 @@ public: // A function parameter struct FunctionParam { +private: + std::vector outer_attrs; + Location locus; + public: std::unique_ptr param_name; std::unique_ptr type; - Location locus; - FunctionParam (std::unique_ptr param_name, - std::unique_ptr param_type, Location locus) - : param_name (std::move (param_name)), type (std::move (param_type)), - locus (locus) + std::unique_ptr param_type, std::vector outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), locus (locus), + param_name (std::move (param_name)), type (std::move (param_type)) {} // Copy constructor uses clone - FunctionParam (FunctionParam const &other) - : param_name (other.param_name->clone_pattern ()), - type (other.type->clone_type ()), locus (other.locus) - {} + FunctionParam (FunctionParam const &other) : locus (other.locus) + { + // guard to prevent nullptr dereference + if (other.param_name != nullptr) + param_name = other.param_name->clone_pattern (); + if (other.type != nullptr) + type = other.type->clone_type (); + } // Overload assignment operator to use clone FunctionParam &operator= (FunctionParam const &other) { - param_name = other.param_name->clone_pattern (); - type = other.type->clone_type (); locus = other.locus; + // guard to prevent nullptr dereference + if (other.param_name != nullptr) + param_name = other.param_name->clone_pattern (); + else + param_name = nullptr; + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + return *this; } @@ -472,12 +486,16 @@ public: // Creates an error FunctionParam. static FunctionParam create_error () { - return FunctionParam (nullptr, nullptr, Location ()); + return FunctionParam (nullptr, nullptr, {}, Location ()); } std::string as_string () const; Location get_locus () const { return locus; } + + // TODO: seems kinda dodgy. Think of better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } }; // Visibility of item - if the item has it, then it is some form of public @@ -596,7 +614,7 @@ class Method : public InherentImplItem, public TraitImplItem // bool has_where_clause; WhereClause where_clause; - std::unique_ptr expr; + std::unique_ptr function_body; Location locus; @@ -604,7 +622,7 @@ public: // Returns whether the method is in an error state. bool is_error () const { - return expr == nullptr || method_name.empty () || self_param.is_error (); + return function_body == nullptr || method_name.empty () || self_param.is_error (); } // Creates an error state method. @@ -614,7 +632,7 @@ public: std::vector> (), SelfParam::create_error (), std::vector (), nullptr, WhereClause::create_empty (), nullptr, - Visibility::create_error (), std::vector ()); + Visibility::create_error (), std::vector (), {}); } // Returns whether the method has generic parameters. @@ -638,7 +656,7 @@ public: SelfParam self_param, std::vector function_params, std::unique_ptr return_type, WhereClause where_clause, std::unique_ptr function_body, Visibility vis, - std::vector outer_attrs, Location locus = Location ()) + std::vector outer_attrs, Location locus) : outer_attrs (std::move (outer_attrs)), vis (std::move (vis)), qualifiers (std::move (qualifiers)), method_name (std::move (method_name)), @@ -646,7 +664,7 @@ public: self_param (std::move (self_param)), function_params (std::move (function_params)), return_type (std::move (return_type)), - where_clause (std::move (where_clause)), expr (std::move (function_body)), + where_clause (std::move (where_clause)), function_body (std::move (function_body)), locus (locus) {} @@ -657,10 +675,16 @@ public: : outer_attrs (other.outer_attrs), vis (other.vis), qualifiers (other.qualifiers), method_name (other.method_name), self_param (other.self_param), function_params (other.function_params), - return_type (other.return_type->clone_type ()), - where_clause (other.where_clause), expr (other.expr->clone_block_expr ()), - locus (other.locus) + where_clause (other.where_clause), locus (other.locus) { + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + + // guard to prevent null dereference (only required if error state) + if (other.function_body != nullptr) + function_body = other.function_body->clone_block_expr (); + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -675,11 +699,21 @@ public: qualifiers = other.qualifiers; self_param = other.self_param; function_params = other.function_params; - return_type = other.return_type->clone_type (); where_clause = other.where_clause; - expr = other.expr->clone_block_expr (); locus = other.locus; + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + + // guard to prevent null dereference (only required if error state) + if (other.function_body != nullptr) + function_body = other.function_body->clone_block_expr (); + else + function_body = nullptr; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -695,6 +729,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if block is null, so base stripping on that. + void mark_for_strip () override { function_body = nullptr; } + bool is_marked_for_strip () const override { return function_body == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2268,9 +2306,12 @@ public: TraitFunctionDecl (TraitFunctionDecl const &other) : qualifiers (other.qualifiers), function_name (other.function_name), function_params (other.function_params), - return_type (other.return_type->clone_type ()), where_clause (other.where_clause) { + // guard to prevent nullptr 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 ()); @@ -2284,9 +2325,14 @@ public: function_name = other.function_name; qualifiers = other.qualifiers; function_params = other.function_params; - return_type = other.return_type->clone_type (); where_clause = other.where_clause; + // guard to prevent nullptr 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) generic_params.push_back (e->clone_generic_param ()); @@ -2299,6 +2345,14 @@ public: TraitFunctionDecl &operator= (TraitFunctionDecl &&other) = default; std::string as_string () const; + + // Invalid if function name is empty, so base stripping on that. + void mark_for_strip () { function_name = ""; } + bool is_marked_for_strip () const { return function_name.empty (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_function_params () { return function_params; } + const std::vector &get_function_params () const { return function_params; } }; // Actual trait item function declaration within traits @@ -2323,6 +2377,7 @@ public: TraitItemFunc (TraitItemFunc const &other) : outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus) { + // guard to prevent null dereference if (other.block_expr != nullptr) block_expr = other.block_expr->clone_block_expr (); } @@ -2334,8 +2389,12 @@ public: outer_attrs = other.outer_attrs; decl = other.decl; locus = other.locus; + + // guard to prevent null dereference if (other.block_expr != nullptr) block_expr = other.block_expr->clone_block_expr (); + else + block_expr = nullptr; return *this; } @@ -2350,6 +2409,17 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if trait decl is empty, so base stripping on that. + void mark_for_strip () override { decl.mark_for_strip (); } + bool is_marked_for_strip () const override { return decl.is_marked_for_strip (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + + std::vector &get_function_params () { return decl.get_function_params (); } + const std::vector &get_function_params () const { return decl.get_function_params (); } + protected: // Clone function implementation as (not pure) virtual method TraitItemFunc *clone_trait_item_impl () const override @@ -2416,9 +2486,12 @@ public: TraitMethodDecl (TraitMethodDecl const &other) : qualifiers (other.qualifiers), function_name (other.function_name), self_param (other.self_param), function_params (other.function_params), - return_type (other.return_type->clone_type ()), where_clause (other.where_clause) { + // guard to prevent nullptr 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 ()); @@ -2433,9 +2506,14 @@ public: qualifiers = other.qualifiers; self_param = other.self_param; function_params = other.function_params; - return_type = other.return_type->clone_type (); where_clause = other.where_clause; + // guard to prevent nullptr 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) generic_params.push_back (e->clone_generic_param ()); @@ -2448,6 +2526,14 @@ public: TraitMethodDecl &operator= (TraitMethodDecl &&other) = default; std::string as_string () const; + + // Invalid if method name is empty, so base stripping on that. + void mark_for_strip () { function_name = ""; } + bool is_marked_for_strip () const { return function_name.empty (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_function_params () { return function_params; } + const std::vector &get_function_params () const { return function_params; } }; // Actual trait item method declaration within traits @@ -2471,8 +2557,12 @@ public: // Copy constructor with clone TraitItemMethod (TraitItemMethod const &other) : outer_attrs (other.outer_attrs), decl (other.decl), - block_expr (other.block_expr->clone_block_expr ()), locus (other.locus) - {} + locus (other.locus) + { + // guard to prevent null dereference + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + } // Overloaded assignment operator to clone TraitItemMethod &operator= (TraitItemMethod const &other) @@ -2480,9 +2570,14 @@ public: TraitItem::operator= (other); outer_attrs = other.outer_attrs; decl = other.decl; - block_expr = other.block_expr->clone_block_expr (); locus = other.locus; + // guard to prevent null dereference + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + else + block_expr = nullptr; + return *this; } @@ -2496,6 +2591,17 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if trait decl is empty, so base stripping on that. + void mark_for_strip () override { decl.mark_for_strip (); } + bool is_marked_for_strip () const override { return decl.is_marked_for_strip (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + + std::vector &get_function_params () { return decl.get_function_params (); } + const std::vector &get_function_params () const { return decl.get_function_params (); } + protected: // Clone function implementation as (not pure) virtual method TraitItemMethod *clone_trait_item_impl () const override @@ -2529,10 +2635,16 @@ public: // Copy constructor with clones TraitItemConst (TraitItemConst const &other) - : outer_attrs (other.outer_attrs), name (other.name), - type (other.type->clone_type ()), expr (other.expr->clone_expr ()), - locus (other.locus) - {} + : outer_attrs (other.outer_attrs), name (other.name), locus (other.locus) + { + // guard to prevent null dereference + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + + // guard to prevent null dereference (only for error state) + if (other.type != nullptr) + type = other.type->clone_type (); + } // Overloaded assignment operator to clone TraitItemConst &operator= (TraitItemConst const &other) @@ -2540,10 +2652,20 @@ public: TraitItem::operator= (other); outer_attrs = other.outer_attrs; name = other.name; - type = other.type->clone_type (); - expr = other.expr->clone_expr (); locus = other.locus; + // guard to prevent null dereference + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + else + expr = nullptr; + + // guard to prevent null dereference (only for error state) + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + return *this; } @@ -2557,6 +2679,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if type is null, so base stripping on that. + void mark_for_strip () override { type = nullptr; } + bool is_marked_for_strip () const override { return type == nullptr; } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + protected: // Clone function implementation as (not pure) virtual method TraitItemConst *clone_trait_item_impl () const override @@ -2625,6 +2755,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { name = ""; } + bool is_marked_for_strip () const override { return name.empty (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + protected: // Clone function implementation as (not pure) virtual method TraitItemType *clone_trait_item_impl () const override @@ -2651,6 +2789,8 @@ class Trait : public VisItem // bool has_where_clause; WhereClause where_clause; + std::vector inner_attrs; + // bool has_trait_items; std::vector> trait_items; @@ -2671,25 +2811,28 @@ public: // Returns whether trait has trait items. bool has_trait_items () const { return !trait_items.empty (); } + // Returns whether trait has inner attributes. + bool has_inner_attrs () const { return !inner_attrs.empty (); } + // Mega-constructor Trait (Identifier name, bool is_unsafe, std::vector> generic_params, std::vector> type_param_bounds, WhereClause where_clause, std::vector> trait_items, Visibility vis, - std::vector outer_attrs, Location locus) + std::vector outer_attrs, std::vector inner_attrs, Location locus) : VisItem (std::move (vis), std::move (outer_attrs)), has_unsafe (is_unsafe), name (std::move (name)), generic_params (std::move (generic_params)), type_param_bounds (std::move (type_param_bounds)), - where_clause (std::move (where_clause)), + where_clause (std::move (where_clause)), inner_attrs (std::move (inner_attrs)), trait_items (std::move (trait_items)), locus (locus) {} // Copy constructor with vector clone Trait (Trait const &other) : VisItem (other), has_unsafe (other.has_unsafe), name (other.name), - where_clause (other.where_clause), locus (other.locus) + where_clause (other.where_clause), inner_attrs (other.inner_attrs), locus (other.locus) { generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) @@ -2711,6 +2854,7 @@ public: name = other.name; has_unsafe = other.has_unsafe; where_clause = other.where_clause; + inner_attrs = other.inner_attrs; locus = other.locus; generic_params.reserve (other.generic_params.size ()); @@ -2740,6 +2884,13 @@ public: void mark_for_strip () override { name = ""; } bool is_marked_for_strip () const override { return name.empty (); } + // TODO: think of better way to do this + const std::vector& get_inner_attrs () const { return inner_attrs; } + std::vector& get_inner_attrs () { return inner_attrs; } + + const std::vector>& get_trait_items () const { return trait_items; } + std::vector>& get_trait_items () { return trait_items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2783,6 +2934,10 @@ public: void mark_for_strip () override { trait_type = nullptr; } bool is_marked_for_strip () const override { return trait_type == nullptr; } + // TODO: think of better way to do this + const std::vector& get_inner_attrs () const { return inner_attrs; } + std::vector& get_inner_attrs () { return inner_attrs; } + protected: // Mega-constructor Impl (std::vector> generic_params, @@ -2886,6 +3041,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: think of better way to do this + const std::vector>& get_impl_items () const { return impl_items; } + std::vector>& get_impl_items () { return impl_items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2958,6 +3117,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: think of better way to do this + const std::vector>& get_impl_items () const { return impl_items; } + std::vector>& get_impl_items () { return impl_items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 6374a45..af0f454 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -173,10 +173,10 @@ Compilation::visit (AST::IdentifierExpr &ident_expr) Bvariable *var = NULL; if (!scope.LookupVar (ident_expr.as_string (), &var)) { - rust_fatal_error (ident_expr.locus, "unknown var"); + rust_fatal_error (ident_expr.get_locus (), "unknown var"); return; } - exprs.push_back (backend->var_expression (var, ident_expr.locus)); + exprs.push_back (backend->var_expression (var, ident_expr.get_locus ())); } void @@ -199,7 +199,7 @@ Compilation::visit (AST::PathInExpression &path) if (scope.LookupFunction (path.as_string (), &fn)) { auto expr - = backend->function_code_expression (fn, path.get_locus_slow ()); + = backend->function_code_expression (fn, path.get_locus ()); exprs.push_back (expr); translatedType = scope.GetFnRetType (fn); return; @@ -221,14 +221,14 @@ Compilation::visit (AST::TypePath &path) { if (path.segments.size () > 1) { - rust_error_at (path.locus, "unable to compile multi segment types yet"); + rust_error_at (path.get_locus (), "unable to compile multi segment types yet"); return; } Btype *type = NULL; if (!scope.LookupType (path.as_string (), &type)) { - rust_error_at (path.locus, "unknown type"); + rust_error_at (path.get_locus (), "unknown type"); return; } translatedType = type; @@ -254,16 +254,16 @@ Compilation::visit (AST::LiteralExpr &expr) case AST::Literal::FLOAT: compiled - = compileFloatLiteral (expr.as_string (), expr.get_locus_slow ()); + = compileFloatLiteral (expr.as_string (), expr.get_locus ()); break; case AST::Literal::INT: compiled - = compileIntegerLiteral (expr.as_string (), expr.get_locus_slow ()); + = compileIntegerLiteral (expr.as_string (), expr.get_locus ()); break; default: - rust_fatal_error (expr.get_locus_slow (), "unknown literal"); + rust_fatal_error (expr.get_locus (), "unknown literal"); return; } @@ -311,11 +311,11 @@ Compilation::visit (AST::NegationExpr &expr) op = OPERATOR_NOT; break; default: - rust_fatal_error (expr.get_locus_slow (), "failed to compile operator"); + rust_fatal_error (expr.get_locus (), "failed to compile operator"); return; } - auto unary = backend->unary_expression (op, root, expr.get_locus_slow ()); + auto unary = backend->unary_expression (op, root, expr.get_locus ()); exprs.push_back (unary); } @@ -372,12 +372,12 @@ Compilation::visit (AST::ArithmeticOrLogicalExpr &expr) op = OPERATOR_RSHIFT; break; default: - rust_fatal_error (expr.get_locus_slow (), "failed to compile operator"); + rust_fatal_error (expr.get_locus (), "failed to compile operator"); return; } auto binExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus_slow ()); + = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); exprs.push_back (binExpr); } @@ -422,12 +422,12 @@ Compilation::visit (AST::ComparisonExpr &expr) op = OPERATOR_LE; break; default: - rust_fatal_error (expr.get_locus_slow (), "failed to compile operator"); + rust_fatal_error (expr.get_locus (), "failed to compile operator"); return; } auto compExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus_slow ()); + = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); exprs.push_back (compExpr); } @@ -460,12 +460,12 @@ Compilation::visit (AST::LazyBooleanExpr &expr) op = OPERATOR_ANDAND; break; default: - rust_fatal_error (expr.get_locus_slow (), "failed to compile operator"); + rust_fatal_error (expr.get_locus (), "failed to compile operator"); return; } auto compExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus_slow ()); + = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); exprs.push_back (compExpr); } @@ -493,7 +493,7 @@ Compilation::visit (AST::AssignmentExpr &expr) } auto s = backend->assignment_statement (scope.GetCurrentFndecl (), lhs, rhs, - expr.get_locus_slow ()); + expr.get_locus ()); scope.AddStatement (s); } @@ -582,14 +582,14 @@ Compilation::visit (AST::StructExprStructFields &expr) AST::StructStruct *decl = NULL; if (!scope.LookupStructDecl (expr.get_struct_name ().as_string (), &decl)) { - rust_error_at (expr.get_locus_slow (), "unknown type"); + rust_error_at (expr.get_locus (), "unknown type"); return; } Btype *structType = NULL; if (!scope.LookupType (expr.get_struct_name ().as_string (), &structType)) { - rust_fatal_error (expr.get_locus_slow (), "unknown type"); + rust_fatal_error (expr.get_locus (), "unknown type"); return; } @@ -601,10 +601,10 @@ Compilation::visit (AST::StructExprStructFields &expr) for (auto &field : expr.fields) { Bexpression *value = NULL; - VISIT_POP (expr.get_locus_slow (), field, value, exprs); + VISIT_POP (expr.get_locus (), field, value, exprs); if (value == NULL) { - rust_fatal_error (expr.get_locus_slow (), + rust_fatal_error (expr.get_locus (), "failed to compile value to struct"); return; } @@ -614,7 +614,7 @@ Compilation::visit (AST::StructExprStructFields &expr) structBuffer.pop_back (); auto cons = backend->constructor_expression (structType, constructor, - expr.get_locus_slow ()); + expr.get_locus ()); exprs.push_back (cons); } @@ -674,7 +674,7 @@ Compilation::visit (AST::CallExpr &expr) } auto call = backend->call_expression (scope.GetCurrentFndecl (), fn, args, - NULL, expr.locus); + NULL, expr.get_locus ()); exprs.push_back (call); } @@ -751,7 +751,7 @@ Compilation::visit (AST::ReturnExpr &expr) std::vector retstmts; retstmts.push_back (ret); auto s = backend->return_statement (scope.GetCurrentFndecl (), retstmts, - expr.locus); + expr.get_locus ()); scope.AddStatement (s); } @@ -791,7 +791,7 @@ Compilation::visit (AST::IfExpr &expr) Bblock *then_block = scope.PopBlock (); auto stmt = backend->if_statement (scope.GetCurrentFndecl (), cond, - then_block, NULL, expr.get_locus_slow ()); + then_block, NULL, expr.get_locus ()); stmts.push_back (stmt); } @@ -816,7 +816,7 @@ Compilation::visit (AST::IfExprConseqElse &expr) auto stmt = backend->if_statement (scope.GetCurrentFndecl (), cond, then_block, - else_block, expr.get_locus_slow ()); + else_block, expr.get_locus ()); stmts.push_back (stmt); } @@ -856,7 +856,7 @@ Compilation::visit (AST::IfExprConseqIf &expr) auto stmt = backend->if_statement (scope.GetCurrentFndecl (), cond, then_block, - else_block, expr.get_locus_slow ()); + else_block, expr.get_locus ()); stmts.push_back (stmt); } @@ -956,7 +956,7 @@ Compilation::visit (AST::Function &function) param.type->accept_vis (*this); if (translatedType == NULL) { - rust_error_at (param.locus, "failed to generate type for parameter"); + rust_error_at (param.get_locus (), "failed to generate type for parameter"); return; } @@ -964,7 +964,7 @@ Compilation::visit (AST::Function &function) param.param_name->accept_vis (*this); if (patternBuffer.size () <= before) { - rust_error_at (param.locus, "failed to analyse parameter name"); + rust_error_at (param.get_locus (), "failed to analyse parameter name"); return; } @@ -975,7 +975,7 @@ Compilation::visit (AST::Function &function) patternBuffer.pop_back (); parameters.push_back ( Backend::Btyped_identifier (paramName.variable_ident, - translatedType, param.locus)); + translatedType, param.get_locus ())); } } @@ -986,7 +986,7 @@ Compilation::visit (AST::Function &function) function.return_type->accept_vis (*this); if (translatedType == NULL) { - rust_fatal_error (function.locus, + rust_fatal_error (function.get_locus (), "failed to generate type for function"); return; } @@ -998,10 +998,10 @@ Compilation::visit (AST::Function &function) } Btype *fntype = backend->function_type (receiver, parameters, results, NULL, - function.locus); + function.get_locus ()); Bfunction *fndecl = backend->function (fntype, function.function_name, "" /* asm_name */, - 0 /* flags */, function.locus); + 0 /* flags */, function.get_locus ()); scope.InsertFunction (function.function_name, fndecl, returnType); scope.Push (); @@ -1020,7 +1020,7 @@ Compilation::visit (AST::Function &function) if (!backend->function_set_parameters (fndecl, param_vars)) { - rust_error_at (function.locus, "failed to setup parameter variables"); + rust_error_at (function.get_locus (), "failed to setup parameter variables"); return; } @@ -1029,7 +1029,7 @@ Compilation::visit (AST::Function &function) { if (!compileVarDecl (fndecl, decl, vars)) { - rust_error_at (decl->locus, "failed to compile var decl"); + rust_error_at (decl->get_locus (), "failed to compile var decl"); return; } } @@ -1037,7 +1037,7 @@ Compilation::visit (AST::Function &function) // is null for top level functions - nested functions will have an enclosing // scope Bblock *enclosingScope = NULL; - Location start_location = function.locus; + Location start_location = function.get_locus (); Location end_location; if (function.function_body->statements.size () > 0) { @@ -1057,7 +1057,7 @@ Compilation::visit (AST::Function &function) Bstatement *ret_var_stmt = NULL; retDecl = backend->temporary_variable (fndecl, code_block, returnType, NULL, address_is_taken, - function.locus, &ret_var_stmt); + function.get_locus (), &ret_var_stmt); scope.AddStatement (ret_var_stmt); } scope.PushCurrentFunction (function.function_name, fndecl, returnType, @@ -1071,7 +1071,7 @@ Compilation::visit (AST::Function &function) auto body = backend->block_statement (code_block); if (!backend->function_set_body (fndecl, body)) { - rust_error_at (function.locus, "failed to set body to function"); + rust_error_at (function.get_locus (), "failed to set body to function"); return; } @@ -1096,23 +1096,23 @@ Compilation::visit (AST::StructStruct &struct_item) if (translatedType == NULL) { rust_fatal_error ( - struct_item.locus /* StructField is mi sing locus */, + struct_item.get_locus () /* StructField is mi sing locus */, "failed to compile struct field"); return; } fields.push_back (Backend::Btyped_identifier ( field.field_name, translatedType, - struct_item.locus /* StructField is mi sing locus */)); + struct_item.get_locus () /* StructField is mi sing locus */)); } auto compiledStruct = backend->placeholder_struct_type (struct_item.struct_name, - struct_item.locus); + struct_item.get_locus ()); bool ok = backend->set_placeholder_struct_type (compiledStruct, fields); if (!ok) { - rust_fatal_error (struct_item.locus, "failed to compile struct"); + rust_fatal_error (struct_item.get_locus (), "failed to compile struct"); return; } @@ -1304,7 +1304,7 @@ Compilation::visit (AST::LetStmt &stmt) Bvariable *var = NULL; if (!scope.LookupVar (pattern.variable_ident, &var)) { - rust_error_at (stmt.locus, "failed to find var decl for %s", + rust_error_at (stmt.get_locus (), "failed to find var decl for %s", pattern.variable_ident.c_str ()); return; } diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 80ad5d0..c7524dc 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -105,7 +105,14 @@ namespace Rust { void visit(AST::UseTreeGlob& use_tree) override {} void visit(AST::UseTreeList& use_tree) override {} void visit(AST::UseTreeRebind& use_tree) override {} - void visit(AST::UseDeclaration& use_decl) override {} + void visit(AST::UseDeclaration& use_decl) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(use_decl.get_outer_attrs()); + if (expander.fails_cfg(use_decl.get_outer_attrs())) { + use_decl.mark_for_strip(); + return; + } + } void visit(AST::Function& function) override {} void visit(AST::TypeAlias& type_alias) override {} void visit(AST::StructStruct& struct_item) override {} @@ -117,14 +124,158 @@ namespace Rust { void visit(AST::Enum& enum_item) override {} void visit(AST::Union& union_item) override {} void visit(AST::ConstantItem& const_item) override {} - void visit(AST::StaticItem& static_item) override {} - void visit(AST::TraitItemFunc& item) override {} - void visit(AST::TraitItemMethod& item) override {} - void visit(AST::TraitItemConst& item) override {} - void visit(AST::TraitItemType& item) override {} - void visit(AST::Trait& trait) override {} - void visit(AST::InherentImpl& impl) override {} - void visit(AST::TraitImpl& impl) override {} + void visit(AST::StaticItem& static_item) override { + + } + void visit(AST::TraitItemFunc& item) override { + // initial 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 (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::TraitItemMethod& item) override { + // initial 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; + } + + /* assuming you can't strip self param - wouldn't be a method + * anymore. spec allows outer attrs on self param, but doesn't + * specify whether cfg is used. */ + + /* strip function parameters if required - this is specifically + * allowed by spec */ + auto& params = item.get_function_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::TraitItemConst& item) override { + // initial 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; + } + /* TODO: is there any way to invalidate the expr? Are attributes + * even allowed on it? */ + } + void visit(AST::TraitItemType& item) override { + // initial 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::Trait& trait) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(trait.get_outer_attrs()); + if (expander.fails_cfg(trait.get_outer_attrs())) { + trait.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(trait.get_inner_attrs()); + if (expander.fails_cfg(trait.get_inner_attrs())) { + trait.mark_for_strip(); + return; + } + + // strip trait items if required + auto& trait_items = trait.get_trait_items(); + for (int i = 0; i < trait_items.size(); ) { + auto& item = trait_items[i]; + + // mark for stripping if required + item->accept_vis(*this); + + if (item->is_marked_for_strip ()) + trait_items.erase (trait_items.begin() + i); + else + i++; + } + } + void visit(AST::InherentImpl& impl) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(impl.get_outer_attrs()); + if (expander.fails_cfg(impl.get_outer_attrs())) { + impl.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(impl.get_inner_attrs()); + if (expander.fails_cfg(impl.get_inner_attrs())) { + impl.mark_for_strip(); + return; + } + + // strip external items if required + auto& impl_items = impl.get_impl_items(); + for (int i = 0; i < impl_items.size(); ) { + auto& item = impl_items[i]; + + // mark for stripping if required + item->accept_vis(*this); + + if (item->is_marked_for_strip ()) + impl_items.erase (impl_items.begin() + i); + else + i++; + } + } + void visit(AST::TraitImpl& impl) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(impl.get_outer_attrs()); + if (expander.fails_cfg(impl.get_outer_attrs())) { + impl.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(impl.get_inner_attrs()); + if (expander.fails_cfg(impl.get_inner_attrs())) { + impl.mark_for_strip(); + return; + } + + // strip external items if required + auto& impl_items = impl.get_impl_items(); + for (int i = 0; i < impl_items.size(); ) { + auto& item = impl_items[i]; + + // mark for stripping if required + item->accept_vis(*this); + + if (item->is_marked_for_strip ()) + impl_items.erase (impl_items.begin() + i); + else + i++; + } + } void visit(AST::ExternalStaticItem& item) override { // strip test based on outer attrs expander.expand_cfg_attrs(item.get_outer_attrs()); @@ -144,8 +295,10 @@ namespace Rust { /* 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 ())) + 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++; @@ -171,7 +324,7 @@ namespace Rust { // strip external items if required auto& extern_items = block.get_extern_items(); - for (auto i = 0; i < extern_items.size(); ) { + for (int i = 0; i < extern_items.size(); ) { auto& item = extern_items[i]; // mark for stripping if required diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9c293dc..1ad997f 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -464,6 +464,7 @@ Parser::parse_inner_attributes () } } + inner_attributes.shrink_to_fit (); return inner_attributes; } @@ -962,6 +963,7 @@ Parser::parse_items () } } + items.shrink_to_fit (); return items; } @@ -1073,6 +1075,7 @@ Parser::parse_outer_attributes () } } + outer_attributes.shrink_to_fit (); return outer_attributes; /* TODO: this shares basically all code with parse_inner_attributes except @@ -2442,9 +2445,7 @@ Parser::parse_function ( // parse function parameters (only if next token isn't right paren) std::vector function_params; if (lexer.peek_token ()->get_id () != RIGHT_PAREN) - { - function_params = parse_function_params (); - } + function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -2745,6 +2746,7 @@ Parser::parse_generic_params () std::make_move_iterator(type_params.end())); }*/ + generic_params.shrink_to_fit (); return generic_params; } @@ -2902,6 +2904,7 @@ Parser::parse_generic_params (EndTokenPred is_end_token) std::make_move_iterator(type_params.end())); }*/ + generic_params.shrink_to_fit (); return generic_params; } @@ -3149,6 +3152,7 @@ Parser::parse_type_params () lexer.skip_token (); } + type_params.shrink_to_fit (); return type_params; } @@ -3180,6 +3184,7 @@ Parser::parse_type_params (EndTokenPred is_end_token) lexer.skip_token (); } + type_params.shrink_to_fit (); return type_params; /* TODO: this shares most code with parse_lifetime_params - good place to use * template (i.e. parse_non_ptr_sequence if doable) */ @@ -3236,24 +3241,24 @@ Parser::parse_type_param () std::move (outer_attr))); } -// Parses regular (i.e. non-generic) parameters in functions or methods. +/* Parses regular (i.e. non-generic) parameters in functions or methods. Also + * has end token handling. */ template +template std::vector -Parser::parse_function_params () +Parser::parse_function_params (EndTokenPred is_end_token) { std::vector params; - // HACK: return early if RIGHT_PAREN is found - if (lexer.peek_token ()->get_id () == RIGHT_PAREN) - { + if (is_end_token (lexer.peek_token ()->get_id ())) return params; - } AST::FunctionParam initial_param = parse_function_param (); // Return empty parameter list if no parameter there - if (initial_param.is_error ()) + if (initial_param.is_error ()) { + // TODO: is this an error? return params; } @@ -3268,13 +3273,9 @@ Parser::parse_function_params () // skip comma if applies lexer.skip_token (); - /* HACK: break if next token is a right (closing) paren - this is not - * strictly true via grammar rule but seems to be true in practice (i.e. - * with trailing comma). */ - if (lexer.peek_token ()->get_id () == RIGHT_PAREN) - { + // TODO: strictly speaking, shouldn't there be no trailing comma? + if (is_end_token (lexer.peek_token ()->get_id ())) break; - } // now, as right paren would break, function param is required AST::FunctionParam param = parse_function_param (); @@ -3291,6 +3292,7 @@ Parser::parse_function_params () t = lexer.peek_token (); } + params.shrink_to_fit (); return params; } @@ -3300,6 +3302,10 @@ template AST::FunctionParam Parser::parse_function_param () { + // parse outer attributes if they exist + std::vector outer_attrs = parse_outer_attributes (); + + // TODO: should saved location be at start of outer attributes or pattern? Location locus = lexer.peek_token ()->get_locus (); std::unique_ptr param_pattern = parse_pattern (); @@ -3324,7 +3330,7 @@ Parser::parse_function_param () } return AST::FunctionParam (std::move (param_pattern), std::move (param_type), - locus); + std::move (outer_attrs), locus); } /* Parses a function or method return type syntactical construction. Also @@ -3334,9 +3340,8 @@ std::unique_ptr Parser::parse_function_return_type () { if (lexer.peek_token ()->get_id () != RETURN_TYPE) - { return nullptr; - } + // skip return type, as it now obviously exists lexer.skip_token (); @@ -3391,6 +3396,7 @@ Parser::parse_where_clause () t = lexer.peek_token (); } + where_clause_items.shrink_to_fit (); return AST::WhereClause (std::move (where_clause_items)); } @@ -3542,8 +3548,8 @@ Parser::parse_type_param_bounds () return type_param_bounds; } -// Parses type parameter bounds in where clause or generic arguments, with end -// token handling. +/* Parses type parameter bounds in where clause or generic arguments, with end + * token handling. */ template template std::vector > @@ -4092,6 +4098,7 @@ Parser::parse_tuple_fields () t = lexer.peek_token (); } + fields.shrink_to_fit (); return fields; // TODO: this shares basically all code with function params and struct fields @@ -4196,6 +4203,7 @@ Parser::parse_enum_items () items.push_back (std::move (item)); } + items.shrink_to_fit (); return items; /* TODO: use template if doable (parse_non_ptr_sequence) */ @@ -4237,6 +4245,7 @@ Parser::parse_enum_items (EndTokenPred is_end_tok) items.push_back (std::move (item)); } + items.shrink_to_fit (); return items; /* TODO: use template if doable (parse_non_ptr_sequence) */ @@ -4530,6 +4539,9 @@ Parser::parse_trait ( return nullptr; } + // parse inner attrs (if they exist) + std::vector inner_attrs = parse_inner_attributes (); + // parse trait items std::vector > trait_items; @@ -4555,11 +4567,12 @@ Parser::parse_trait ( return nullptr; } + trait_items.shrink_to_fit (); return std::unique_ptr ( new AST::Trait (std::move (ident), is_unsafe, std::move (generic_params), std::move (type_param_bounds), std::move (where_clause), std::move (trait_items), std::move (vis), - std::move (outer_attrs), locus)); + std::move (outer_attrs), std::move (inner_attrs), locus)); } // Parses a trait item used inside traits (not trait, the Item). @@ -4613,27 +4626,25 @@ Parser::parse_trait_item () return nullptr; } - // now for function vs method disambiguation - method has opening "self" - // param + /* now for function vs method disambiguation - method has opening "self" + * param */ AST::SelfParam self_param = parse_self_param (); - // FIXME: ensure that self param doesn't accidently consume tokens for a - // function + /* FIXME: ensure that self param doesn't accidently consume tokens for a + * function */ bool is_method = false; if (!self_param.is_error ()) { is_method = true; - // skip comma so function and method regular params can be parsed in - // same way + /* skip comma so function and method regular params can be parsed in + * same way */ if (lexer.peek_token ()->get_id () == COMMA) - { lexer.skip_token (); - } } // parse trait function params std::vector function_params - = parse_function_params (); + = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -4914,6 +4925,8 @@ Parser::parse_impl (AST::Visibility vis, // DEBUG fprintf (stderr, "successfully parsed inherent impl\n"); + impl_items.shrink_to_fit (); + return std::unique_ptr (new AST::InherentImpl ( std::move (impl_items), std::move (generic_params), std::move (type), std::move (where_clause), std::move (vis), std::move (inner_attrs), @@ -4987,6 +5000,8 @@ Parser::parse_impl (AST::Visibility vis, // DEBUG fprintf (stderr, "successfully parsed trait impl\n"); + impl_items.shrink_to_fit (); + return std::unique_ptr ( new AST::TraitImpl (std::move (type_path), is_unsafe, has_exclam, std::move (impl_items), std::move (generic_params), @@ -5138,24 +5153,22 @@ Parser::parse_inherent_impl_function_or_method ( // now for function vs method disambiguation - method has opening "self" param AST::SelfParam self_param = parse_self_param (); - // FIXME: ensure that self param doesn't accidently consume tokens for a - // function one idea is to lookahead up to 4 tokens to see whether self is one - // of them + /* FIXME: ensure that self param doesn't accidently consume tokens for a + * function one idea is to lookahead up to 4 tokens to see whether self is one + * of them */ bool is_method = false; if (!self_param.is_error ()) { is_method = true; - // skip comma so function and method regular params can be parsed in same - // way + /* skip comma so function and method regular params can be parsed in same + * way */ if (lexer.peek_token ()->get_id () == COMMA) - { lexer.skip_token (); - } } // parse trait function params - std::vector function_params = parse_function_params (); + std::vector function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -5400,7 +5413,7 @@ Parser::parse_trait_impl_function_or_method ( std::vector function_params; if (lexer.peek_token ()->get_id () != RIGHT_PAREN) { - function_params = parse_function_params (); + function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (function_params.empty ()) { @@ -5534,6 +5547,8 @@ Parser::parse_extern_block ( // skip somewhere return nullptr; } + + extern_items.shrink_to_fit (); return std::unique_ptr ( new AST::ExternBlock (std::move (abi), std::move (extern_items), @@ -5689,6 +5704,8 @@ Parser::parse_external_item () // skip somewhere? return nullptr; } + + function_params.shrink_to_fit (); return std::unique_ptr ( new AST::ExternalFunctionItem ( @@ -6220,6 +6237,7 @@ Parser::parse_type_path_function () // parse optional return type std::unique_ptr return_type = parse_function_return_type (); + inputs.shrink_to_fit (); return AST::TypePathFunction (std::move (inputs), std::move (return_type)); } @@ -6392,6 +6410,8 @@ Parser::parse_qualified_path_in_expression ( t = lexer.peek_token (); } + segments.shrink_to_fit (); + // FIXME: outer attr parsing return AST::QualifiedPathInExpression (std::move (qual_path_type), std::move (segments), locus, @@ -6667,7 +6687,7 @@ Parser::parse_method () lexer.skip_token (); // parse function parameters - std::vector function_params = parse_function_params (); + std::vector function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -7066,6 +7086,8 @@ Parser::parse_block_expr ( // grammar allows for empty block expressions + stmts.shrink_to_fit (); + return std::unique_ptr ( new AST::BlockExpr (std::move (stmts), std::move (expr), std::move (inner_attrs), std::move (outer_attrs), @@ -7154,6 +7176,7 @@ Parser::parse_closure_expr ( t = lexer.peek_token (); } + params.shrink_to_fit (); break; default: rust_error_at (t->get_locus (), diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 82d8d6f..5202abf 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -164,7 +164,8 @@ private: template std::vector > parse_type_params (EndTokenPred is_end_token); std::unique_ptr parse_type_param (); - std::vector parse_function_params (); + template + std::vector parse_function_params (EndTokenPred is_end_token); AST::FunctionParam parse_function_param (); std::unique_ptr parse_function_return_type (); AST::WhereClause parse_where_clause (); -- cgit v1.1 From 164e38246f0f469fa83f5fa3f56fc53fa1b46450 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sat, 7 Nov 2020 22:29:44 +0800 Subject: Added more cfg-stripping --- gcc/rust/ast/rust-item.h | 36 ++++++++++++++-- gcc/rust/expand/rust-macro-expand.cc | 84 ++++++++++++++++++++++++++++-------- 2 files changed, 97 insertions(+), 23 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index a56d1b5..a4ff3eb 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1585,9 +1585,12 @@ public: // Copy constructor StructField (StructField const &other) : outer_attrs (other.outer_attrs), visibility (other.visibility), - field_name (other.field_name), - field_type (other.field_type->clone_type ()) - {} + field_name (other.field_name) + { + // guard to prevent null dereference + if (other.field_type != nullptr) + field_type = other.field_type->clone_type (); + } ~StructField () = default; @@ -1595,10 +1598,15 @@ public: StructField &operator= (StructField const &other) { field_name = other.field_name; - field_type = other.field_type->clone_type (); visibility = other.visibility; outer_attrs = other.outer_attrs; + // guard to prevent null dereference + if (other.field_type != nullptr) + field_type = other.field_type->clone_type (); + else + field_type = nullptr; + return *this; } @@ -1620,6 +1628,10 @@ public: } std::string as_string () const; + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } }; // Rust struct declaration with true struct type AST node @@ -2074,6 +2086,10 @@ public: void mark_for_strip () override { union_name = ""; } bool is_marked_for_strip () const override { return union_name.empty (); } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_variants () { return variants; } + const std::vector &get_variants () const { return variants; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2420,6 +2436,12 @@ public: std::vector &get_function_params () { return decl.get_function_params (); } const std::vector &get_function_params () const { return decl.get_function_params (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_definition () { + rust_assert (has_definition()); + return block_expr; + } + protected: // Clone function implementation as (not pure) virtual method TraitItemFunc *clone_trait_item_impl () const override @@ -2602,6 +2624,12 @@ public: std::vector &get_function_params () { return decl.get_function_params (); } const std::vector &get_function_params () const { return decl.get_function_params (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_definition () { + rust_assert (has_definition()); + return block_expr; + } + protected: // Clone function implementation as (not pure) virtual method TraitItemMethod *clone_trait_item_impl () const override diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index c7524dc..ad97e2cd 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -12,6 +12,28 @@ namespace Rust { public: AttrVisitor(MacroExpander& expander) : expander(expander) {} + void expand_struct_fields(std::vector& fields) { + for (int i = 0; i < fields.size(); ) { + auto& field_attrs = fields[i].get_outer_attrs (); + expander.expand_cfg_attrs(field_attrs); + if (expander.fails_cfg (field_attrs)) + fields.erase (fields.begin() + i); + else + i++; + } + } + + void expand_function_params(std::vector& 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::Token& tok) override {} void visit(AST::DelimTokenTree& delim_tok_tree) override {} void visit(AST::AttrInputMetaItemContainer& input) override {} @@ -122,10 +144,37 @@ namespace Rust { void visit(AST::EnumItemStruct& item) override {} void visit(AST::EnumItemDiscriminant& item) override {} void visit(AST::Enum& enum_item) override {} - void visit(AST::Union& union_item) override {} - void visit(AST::ConstantItem& const_item) override {} - void visit(AST::StaticItem& static_item) override { + void visit(AST::Union& union_item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(union_item.get_outer_attrs()); + if (expander.fails_cfg(union_item.get_outer_attrs())) { + union_item.mark_for_strip(); + return; + } + /* strip union fields if required - this is presumably + * allowed by spec */ + expand_struct_fields(union_item.get_variants()); + } + void visit(AST::ConstantItem& const_item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(const_item.get_outer_attrs()); + if (expander.fails_cfg(const_item.get_outer_attrs())) { + const_item.mark_for_strip(); + return; + } + /* TODO: is there any way to invalidate the expr? Are attributes + * even allowed on it? */ + } + void visit(AST::StaticItem& static_item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(static_item.get_outer_attrs()); + if (expander.fails_cfg(static_item.get_outer_attrs())) { + static_item.mark_for_strip(); + return; + } + /* TODO: is there any way to invalidate the expr? Are attributes + * even allowed on it? */ } void visit(AST::TraitItemFunc& item) override { // initial test based on outer attrs @@ -137,14 +186,11 @@ namespace Rust { /* strip function parameters if required - this is specifically * allowed by spec */ - auto& params = item.get_function_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++; + expand_function_params(item.get_function_params()); + + if (item.has_definition()) { + item.get_definition()->accept_vis(*this); + // TODO: can block as a whole be invalidated here? Assuming no } } void visit(AST::TraitItemMethod& item) override { @@ -161,14 +207,11 @@ namespace Rust { /* strip function parameters if required - this is specifically * allowed by spec */ - auto& params = item.get_function_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++; + expand_function_params(item.get_function_params()); + + if (item.has_definition()) { + item.get_definition()->accept_vis(*this); + // TODO: can block as a whole be invalidated here? Assuming no } } void visit(AST::TraitItemConst& item) override { @@ -303,6 +346,9 @@ namespace Rust { else i++; } + /* NOTE: these are extern function params, which may have different + * rules and restrictions to "normal" function params. So expansion + * handled separately. */ /* TODO: assuming that variadic nature cannot be stripped. If this * is not true, then have code here to do so. */ -- cgit v1.1 From 37bbf2b8cbd4578f0fbe7cbbd573493481f62a45 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Tue, 10 Nov 2020 12:22:20 +0800 Subject: Added cfg stripping for some expressions Attempt to fix compile error --- gcc/rust/analysis/rust-type-resolution.cc | 18 +- gcc/rust/ast/rust-ast.h | 11 +- gcc/rust/ast/rust-expr.h | 153 +++++- gcc/rust/ast/rust-item.h | 104 ++++- gcc/rust/ast/rust-macro.h | 4 + gcc/rust/ast/rust-path.h | 1 - gcc/rust/ast/rust-stmt.h | 24 +- gcc/rust/backend/rust-compile.cc | 50 +- gcc/rust/expand/rust-macro-expand.cc | 746 +++++++++++++++++++++++++----- 9 files changed, 951 insertions(+), 160 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index aef02ce..87cf828 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -158,7 +158,7 @@ void TypeResolution::visit (AST::IdentifierExpr &ident_expr) { AST::Type *type = NULL; - bool ok = scope.LookupType (ident_expr.ident, &type); + bool ok = scope.LookupType (ident_expr.get_ident (), &type); if (!ok) { rust_error_at (ident_expr.get_locus (), "unknown identifier"); @@ -235,7 +235,7 @@ void TypeResolution::visit (AST::LiteralExpr &expr) { std::string type; - switch (expr.literal.get_lit_type ()) + switch (expr.get_lit_type ()) { case AST::Literal::CHAR: type = "char"; @@ -273,7 +273,7 @@ TypeResolution::visit (AST::LiteralExpr &expr) if (type.empty ()) { rust_error_at (expr.get_locus (), "unknown literal: %s", - expr.literal.as_string ().c_str ()); + expr.get_literal ().as_string ().c_str ()); return; } @@ -338,7 +338,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) // scope will require knowledge of the type // do the lhsType and the rhsType match - typesAreCompatible (lhsType, rhsType, expr.right_expr->get_locus_slow ()); + typesAreCompatible (lhsType, rhsType, expr.get_right_expr ()->get_locus_slow ()); } void @@ -382,7 +382,7 @@ TypeResolution::visit (AST::AssignmentExpr &expr) // do the lhsType and the rhsType match if (!typesAreCompatible (lhsType, rhsType, - expr.right_expr->get_locus_slow ())) + expr.get_right_expr ()->get_locus_slow ())) return; // is the lhs mutable? @@ -469,7 +469,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr) if (identifierBuffer != NULL) { AST::StructField *declField = NULL; - for (auto &df : decl->fields) + for (auto &df : decl->get_fields ()) { if (identifierBuffer->compare (df.field_name) == 0) { @@ -493,9 +493,9 @@ TypeResolution::visit (AST::StructExprStructFields &expr) else if (tupleIndexBuffer != NULL) { AST::StructField *declField = NULL; - if (*tupleIndexBuffer < decl->fields.size ()) + if (*tupleIndexBuffer < decl->get_fields ().size ()) { - declField = &decl->fields[*tupleIndexBuffer]; + declField = &decl->get_fields ()[*tupleIndexBuffer]; } tupleIndexBuffer = NULL; @@ -811,7 +811,7 @@ TypeResolution::visit (AST::TypeAlias &type_alias) void TypeResolution::visit (AST::StructStruct &struct_item) { - for (auto &field : struct_item.fields) + for (auto &field : struct_item.get_fields ()) { if (!isTypeInScope (field.field_type.get (), Linemap::unknown_location ())) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index e0f46ac..c186f22 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -810,7 +810,9 @@ class Expr std::vector outer_attrs; public: + // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector &get_outer_attrs () const { return outer_attrs; } + std::vector &get_outer_attrs () { return outer_attrs; } // Unique pointer custom clone function std::unique_ptr clone_expr () const @@ -905,11 +907,10 @@ public: */ class IdentifierExpr : public ExprWithoutBlock { -public: Identifier ident; - Location locus; +public: IdentifierExpr (Identifier ident, Location locus = Location (), std::vector outer_attrs = std::vector ()) @@ -922,6 +923,8 @@ public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + Identifier get_ident () const { return ident; } + void accept_vis (ASTVisitor &vis) override; // Clones this object. @@ -1385,6 +1388,10 @@ public: void mark_for_strip () override { path = SimplePath::create_empty (); } bool is_marked_for_strip () const override { return path.is_empty (); } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector &get_outer_attrs () const { return outer_attrs; } + std::vector &get_outer_attrs () { return outer_attrs; } + protected: MacroInvocationSemi *clone_macro_invocation_semi_impl () const { diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 4647829..a92a8ad 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -41,10 +41,10 @@ public: // Literals? Or literal base? class LiteralExpr : public ExprWithoutBlock { -public: Literal literal; Location locus; +public: std::string as_string () const override { return literal.as_string (); } Literal::LitType get_lit_type () const { return literal.get_lit_type (); } @@ -71,6 +71,8 @@ public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + Literal get_literal () const { return literal; } + void accept_vis (ASTVisitor &vis) override; // Invalid if literal is in error state, so base stripping on that. @@ -118,10 +120,7 @@ public: /* this can never be a cfg predicate - cfg and cfg_attr require a token-tree * cfg */ bool - check_cfg_predicate (const Session&) const override - { - return false; - } + check_cfg_predicate (const Session&) const override { return false; } protected: /* Use covariance to implement clone function as returning this object rather @@ -264,6 +263,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_borrowed_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -287,6 +292,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_dereferenced_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -311,6 +322,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_propagating_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -330,6 +347,7 @@ public: NOT }; +private: /* Note: overload negation via std::ops::Neg and not via std::ops::Not * Negation only works for signed integer and floating-point types, NOT only * works for boolean and integer types (via bitwise NOT) */ @@ -350,7 +368,11 @@ public: void accept_vis (ASTVisitor &vis) override; - Expr *get_expr () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_negated_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -379,6 +401,7 @@ public: RIGHT_SHIFT // std::ops::Shr }; +private: // Note: overloading trait specified in comments ExprType expr_type; @@ -422,7 +445,17 @@ public: void accept_vis (ASTVisitor &vis) override; - Expr *get_lhs () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } void visit_lhs (ASTVisitor &vis) { main_or_left_expr->accept_vis (vis); } void visit_rhs (ASTVisitor &vis) { right_expr->accept_vis (vis); } @@ -450,6 +483,7 @@ public: LESS_OR_EQUAL // std::cmp::PartialEq::le }; +private: // Note: overloading trait specified in comments ExprType expr_type; @@ -493,7 +527,17 @@ public: void accept_vis (ASTVisitor &vis) override; - Expr *get_lhs () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2) * maybe? */ @@ -516,6 +560,7 @@ public: LOGICAL_AND }; +private: ExprType expr_type; std::unique_ptr right_expr; @@ -558,7 +603,17 @@ public: void accept_vis (ASTVisitor &vis) override; - Expr *get_lhs () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -602,12 +657,18 @@ public: return *this; } - // move constructors as not supported in c++03 + // move constructors TypeCastExpr (TypeCastExpr &&other) = default; TypeCastExpr &operator= (TypeCastExpr &&other) = default; void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_casted_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -620,9 +681,9 @@ protected: // Binary assignment expression. class AssignmentExpr : public OperatorExpr { -public: std::unique_ptr right_expr; +public: std::string as_string () const override; // Call OperatorExpr constructor to initialise left_expr @@ -659,7 +720,17 @@ public: void visit_lhs (ASTVisitor &vis) { main_or_left_expr->accept_vis (vis); } void visit_rhs (ASTVisitor &vis) { right_expr->accept_vis (vis); } - Expr *get_lhs () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -733,6 +804,18 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -753,7 +836,8 @@ class GroupedExpr : public ExprWithoutBlock public: std::string as_string () const override; - std::vector get_inner_attrs () const { return inner_attrs; } + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } GroupedExpr (std::unique_ptr parenthesised_expr, std::vector inner_attribs, @@ -803,6 +887,12 @@ public: void mark_for_strip () override { expr_in_parens = nullptr; } bool is_marked_for_strip () const override { return expr_in_parens == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_expr_in_parens () { + rust_assert (expr_in_parens != nullptr); + return expr_in_parens; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -872,6 +962,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector > &get_values () const { return values; } + std::vector > &get_values () { return values; } + protected: ArrayElemsValues *clone_array_elems_impl () const override { @@ -918,6 +1012,18 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_elem_to_copy () { + rust_assert (elem_to_copy != nullptr); + return elem_to_copy; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_num_copies () { + rust_assert (num_copies != nullptr); + return num_copies; + } + protected: ArrayElemsCopied *clone_array_elems_impl () const override { @@ -939,7 +1045,8 @@ class ArrayExpr : public ExprWithoutBlock public: std::string as_string () const override; - std::vector get_inner_attrs () const { return inner_attrs; } + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } // Returns whether array expr has array elems or if it is just empty. bool has_array_elems () const { return internal_elements != nullptr; } @@ -992,6 +1099,12 @@ public: void mark_for_strip () override { marked_for_strip = true; } bool is_marked_for_strip () const override { return marked_for_strip; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_array_elems () { + rust_assert (internal_elements != nullptr); + return internal_elements; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1068,6 +1181,18 @@ public: void mark_for_strip () override { array_expr = nullptr; index_expr = nullptr; } bool is_marked_for_strip () const override { return array_expr == nullptr && index_expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_array_expr () { + rust_assert (array_expr != nullptr); + return array_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_index_expr () { + rust_assert (index_expr != nullptr); + return index_expr; + } + 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 a4ff3eb..8a85edad 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -733,6 +733,19 @@ public: void mark_for_strip () override { function_body = nullptr; } bool is_marked_for_strip () const override { return function_body == nullptr; } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + + std::vector &get_function_params () { return function_params; } + const std::vector &get_function_params () const { return function_params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_definition () { + rust_assert (function_body != nullptr); + return function_body; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -879,6 +892,13 @@ public: * the module. */ void add_crate_name (std::vector &names) const override; + // TODO: think of better way to do this - mutable getter seems dodgy + const std::vector& get_inner_attrs () const { return inner_attrs; } + std::vector& get_inner_attrs () { return inner_attrs; } + + const std::vector>& get_items () const { return items; } + std::vector>& get_items () { return items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1366,6 +1386,16 @@ public: void mark_for_strip () override { function_body = nullptr; } bool is_marked_for_strip () const override { return function_body == nullptr; } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_function_params () { return function_params; } + const std::vector &get_function_params () const { return function_params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_definition () { + rust_assert (function_body != nullptr); + return function_body; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1637,10 +1667,10 @@ public: // Rust struct declaration with true struct type AST node class StructStruct : public Struct { -public: std::vector fields; bool is_unit; +public: std::string as_string () const override; // Mega-constructor with all possible fields @@ -1672,6 +1702,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_fields () { return fields; } + const std::vector &get_fields () const { return fields; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1712,19 +1746,27 @@ public: // Copy constructor with clone TupleField (TupleField const &other) - : outer_attrs (other.outer_attrs), visibility (other.visibility), - field_type (other.field_type->clone_type ()) - {} + : outer_attrs (other.outer_attrs), visibility (other.visibility) + { + // guard to prevent null dereference (only required if error) + if (other.field_type != nullptr) + field_type = other.field_type->clone_type (); + } ~TupleField () = default; // Overloaded assignment operator to clone TupleField &operator= (TupleField const &other) { - field_type = other.field_type->clone_type (); visibility = other.visibility; outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error) + if (other.field_type != nullptr) + field_type = other.field_type->clone_type (); + else + field_type = nullptr; + return *this; } @@ -1742,6 +1784,10 @@ public: } std::string as_string () const; + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } }; // Rust tuple declared using struct keyword AST node @@ -1765,6 +1811,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_fields () { return fields; } + const std::vector &get_fields () const { return fields; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1808,6 +1858,14 @@ public: // not pure virtual as not abstract virtual void accept_vis (ASTVisitor &vis); + // Based on idea that name is never empty. + void mark_for_strip () { variant_name = ""; } + bool is_marked_for_strip () const { return variant_name.empty (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + protected: // Clone function implementation as (not pure) virtual method virtual EnumItem *clone_enum_item_impl () const @@ -1836,6 +1894,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_tuple_fields () { return tuple_fields; } + const std::vector &get_tuple_fields () const { return tuple_fields; } + protected: // Clone function implementation as (not pure) virtual method EnumItemTuple *clone_enum_item_impl () const override @@ -1865,6 +1927,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_struct_fields () { return struct_fields; } + const std::vector &get_struct_fields () const { return struct_fields; } + protected: // Clone function implementation as (not pure) virtual method EnumItemStruct *clone_enum_item_impl () const override @@ -1909,6 +1975,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_expr () { + rust_assert (expression != nullptr); + return expression; + } + protected: // Clone function implementation as (not pure) virtual method EnumItemDiscriminant *clone_enum_item_impl () const override @@ -2005,6 +2077,10 @@ public: void mark_for_strip () override { enum_name = ""; } bool is_marked_for_strip () const override { return enum_name.empty (); } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector> &get_variants () { return items; } + const std::vector> &get_variants () const { return items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2169,6 +2245,12 @@ public: void mark_for_strip () override { type = nullptr; const_expr = nullptr; } bool is_marked_for_strip () const override { return type == nullptr && const_expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_expr () { + rust_assert (const_expr != nullptr); + return const_expr; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2258,6 +2340,12 @@ public: void mark_for_strip () override { type = nullptr; expr = nullptr; } bool is_marked_for_strip () const override { return type == nullptr && expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_expr () { + rust_assert (expr != nullptr); + return expr; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2715,6 +2803,12 @@ public: std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_expr () { + rust_assert (expr != nullptr); + return expr; + } + protected: // Clone function implementation as (not pure) virtual method TraitItemConst *clone_trait_item_impl () const override diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 8d50b88..2a97854 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -315,6 +315,10 @@ public: void mark_for_strip () override { rule_name = ""; } bool is_marked_for_strip () const override { return rule_name.empty (); } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 32147d3..c59e6bd 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -328,7 +328,6 @@ class TypePathSegment * GenericArgs are, so could disallow that in constructor, which won't give * that much size overhead. */ PathIdentSegment ident_segment; - Location locus; protected: diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 127ea21..f7c47d7 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -38,10 +38,10 @@ protected: * introduces new name into scope */ class LetStmt : public Stmt { -public: // bool has_outer_attrs; std::vector outer_attrs; +public: std::unique_ptr variables_pattern; // bool has_type; @@ -125,6 +125,16 @@ public: void mark_for_strip () override { variables_pattern = nullptr; } bool is_marked_for_strip () const override { return variables_pattern == nullptr; } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_init_expr () { + rust_assert (init_expr != nullptr); + return init_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -204,6 +214,12 @@ public: void mark_for_strip () override { expr = nullptr; } bool is_marked_for_strip () const override { return expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_expr () { + rust_assert (expr != nullptr); + return expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -260,6 +276,12 @@ public: void mark_for_strip () override { expr = nullptr; } bool is_marked_for_strip () const override { return expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_expr () { + rust_assert (expr != nullptr); + return expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index af0f454..0589347 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -246,7 +246,7 @@ void Compilation::visit (AST::LiteralExpr &expr) { Bexpression *compiled; - switch (expr.literal.get_lit_type ()) + switch (expr.get_lit_type ()) { case AST::Literal::BOOL: compiled = compileBooleanLiteral (expr.as_string ()); @@ -293,16 +293,16 @@ void Compilation::visit (AST::NegationExpr &expr) { Bexpression *root = NULL; - VISIT_POP (expr.get_expr ()->get_locus_slow (), expr.get_expr (), root, + VISIT_POP (expr.get_negated_expr ()->get_locus_slow (), expr.get_negated_expr ().get (), root, exprs); if (root == NULL) { - rust_error_at (expr.get_expr ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_negated_expr ()->get_locus_slow (), "failed to compile"); return; } Operator op; - switch (expr.negation_type) + switch (expr.get_negation_type ()) { case AST::NegationExpr::NEGATE: op = OPERATOR_MINUS; @@ -323,23 +323,23 @@ void Compilation::visit (AST::ArithmeticOrLogicalExpr &expr) { Bexpression *lhs = NULL; - VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs); + VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); if (lhs == NULL) { - rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); return; } Bexpression *rhs = NULL; - VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs); + VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); if (rhs == NULL) { - rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); return; } Operator op; - switch (expr.expr_type) + switch (expr.get_expr_type ()) { case AST::ArithmeticOrLogicalExpr::ADD: op = OPERATOR_PLUS; @@ -385,23 +385,23 @@ void Compilation::visit (AST::ComparisonExpr &expr) { Bexpression *lhs = NULL; - VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs); + VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); if (lhs == NULL) { - rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); return; } Bexpression *rhs = NULL; - VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs); + VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); if (rhs == NULL) { - rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); return; } Operator op; - switch (expr.expr_type) + switch (expr.get_expr_type ()) { case AST::ComparisonExpr::EQUAL: op = OPERATOR_EQEQ; @@ -435,23 +435,23 @@ void Compilation::visit (AST::LazyBooleanExpr &expr) { Bexpression *lhs = NULL; - VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs); + VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); if (lhs == NULL) { - rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); return; } Bexpression *rhs = NULL; - VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs); + VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); if (rhs == NULL) { - rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); return; } Operator op; - switch (expr.expr_type) + switch (expr.get_expr_type ()) { case AST::LazyBooleanExpr::LOGICAL_OR: op = OPERATOR_OROR; @@ -477,18 +477,18 @@ void Compilation::visit (AST::AssignmentExpr &expr) { Bexpression *lhs = NULL; - VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs); + VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); if (lhs == NULL) { - rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); return; } Bexpression *rhs = NULL; - VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs); + VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); if (rhs == NULL) { - rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); return; } @@ -536,7 +536,7 @@ Compilation::visit (AST::StructExprFieldIdentifierValue &field) AST::StructStruct *decl = structBuffer.back (); size_t index = 0; bool found = false; - for (auto &df : decl->fields) + for (auto &df : decl->get_fields ()) { if (field.field_name.compare (df.field_name) == 0) { @@ -1089,7 +1089,7 @@ void Compilation::visit (AST::StructStruct &struct_item) { std::vector fields; - for (auto &field : struct_item.fields) + for (auto &field : struct_item.get_fields ()) { translatedType = NULL; field.field_type->accept_vis (*this); diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index ad97e2cd..164b5a5 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -13,62 +13,338 @@ namespace Rust { AttrVisitor(MacroExpander& expander) : expander(expander) {} void expand_struct_fields(std::vector& fields) { - for (int i = 0; i < fields.size(); ) { - auto& field_attrs = fields[i].get_outer_attrs (); + for (int i = 0; i < fields.size();) { + auto& field_attrs = fields[i].get_outer_attrs(); expander.expand_cfg_attrs(field_attrs); - if (expander.fails_cfg (field_attrs)) - fields.erase (fields.begin() + i); + if (expander.fails_cfg(field_attrs)) + fields.erase(fields.begin() + i); + else + i++; + } + } + + void expand_tuple_fields(std::vector& fields) { + for (int i = 0; i < fields.size();) { + auto& field_attrs = fields[i].get_outer_attrs(); + expander.expand_cfg_attrs(field_attrs); + if (expander.fails_cfg(field_attrs)) + fields.erase(fields.begin() + i); else i++; } } void expand_function_params(std::vector& params) { - for (int i = 0; i < params.size(); ) { - auto& param_attrs = params[i].get_outer_attrs (); + 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); + if (expander.fails_cfg(param_attrs)) + params.erase(params.begin() + i); + else + i++; + } + } + + void visit(AST::Token& tok) override { + // shouldn't require? + } + void visit(AST::DelimTokenTree& delim_tok_tree) override { + // shouldn't require? + } + void visit(AST::AttrInputMetaItemContainer& input) override { + // shouldn't require? + } + void visit(AST::IdentifierExpr& ident_expr) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(ident_expr.get_outer_attrs()); + if (expander.fails_cfg(ident_expr.get_outer_attrs())) { + ident_expr.mark_for_strip(); + return; + } + } + void visit(AST::Lifetime& lifetime) override { + // shouldn't require? + } + void visit(AST::LifetimeParam& lifetime_param) override { + // supposedly does not require - cfg does nothing + } + void visit(AST::MacroInvocationSemi& macro_invoc) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(macro_invoc.get_outer_attrs()); + if (expander.fails_cfg(macro_invoc.get_outer_attrs())) { + macro_invoc.mark_for_strip(); + return; + } + + // I don't think any macro token trees can be stripped in any way + } + + void visit(AST::PathInExpression& path) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(path.get_outer_attrs()); + if (expander.fails_cfg(path.get_outer_attrs())) { + path.mark_for_strip(); + return; + } + } + void visit(AST::TypePathSegment& segment) override { + // shouldn't require? + } + void visit(AST::TypePathSegmentGeneric& segment) override { + // shouldn't require? + } + void visit(AST::TypePathSegmentFunction& segment) override { + // shouldn't require? + } + void visit(AST::TypePath& path) override { + // shouldn't require? + } + void visit(AST::QualifiedPathInExpression& path) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(path.get_outer_attrs()); + if (expander.fails_cfg(path.get_outer_attrs())) { + path.mark_for_strip(); + return; + } + } + void visit(AST::QualifiedPathInType& path) override { + // shouldn't require? + } + + void visit(AST::LiteralExpr& 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; + } + } + void visit(AST::AttrInputLiteral& attr_input) override { + // shouldn't require? + } + void visit(AST::MetaItemLitExpr& meta_item) override { + // shouldn't require? + } + void visit(AST::MetaItemPathLit& meta_item) override { + // shouldn't require? + } + void visit(AST::BorrowExpr& 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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + expr.get_borrowed_expr()->accept_vis(*this); + } + void visit(AST::DereferenceExpr& 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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + expr.get_dereferenced_expr()->accept_vis(*this); + } + void visit(AST::ErrorPropagationExpr& 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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + expr.get_propagating_expr()->accept_vis(*this); + } + void visit(AST::NegationExpr& 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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + expr.get_negated_expr()->accept_vis(*this); + } + void visit(AST::ArithmeticOrLogicalExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr()->accept_vis(*this); + + // ensure that they are not marked for strip + rust_assert(!expr.get_left_expr()->is_marked_for_strip()); + rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + } + void visit(AST::ComparisonExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr()->accept_vis(*this); + + // ensure that they are not marked for strip + rust_assert(!expr.get_left_expr()->is_marked_for_strip()); + rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + } + void visit(AST::LazyBooleanExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr()->accept_vis(*this); + + // ensure that they are not marked for strip + rust_assert(!expr.get_left_expr()->is_marked_for_strip()); + rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + } + void visit(AST::TypeCastExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_casted_expr()->accept_vis(*this); + + // ensure that they are not marked for strip + rust_assert(!expr.get_casted_expr()->is_marked_for_strip()); + } + void visit(AST::AssignmentExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr()->accept_vis(*this); + + // ensure that they are not marked for strip + rust_assert(!expr.get_left_expr()->is_marked_for_strip()); + rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + } + void visit(AST::CompoundAssignmentExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr()->accept_vis(*this); + + // ensure that they are not marked for strip + rust_assert(!expr.get_left_expr()->is_marked_for_strip()); + rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + } + void visit(AST::GroupedExpr& 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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + expr.get_expr_in_parens()->accept_vis(*this); + } + void visit(AST::ArrayElemsValues& elems) override { + /* apparently outer attributes are allowed in "elements of array + * expressions" according to spec */ + auto& values = elems.get_values(); + 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::ArrayElemsCopied& elems) override { + /* apparently outer attributes are allowed in "elements of array + * expressions" according to spec. on the other hand, it would not + * make conceptual sense to be able to remove either expression. As + * such, not implementing. TODO clear up the ambiguity here */ + + // only intend stripping for internal sub-expressions + elems.get_elem_to_copy()->accept_vis(*this); + elems.get_num_copies()->accept_vis(*this); + } + void visit(AST::ArrayExpr& 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 test based on inner attrs - spec says there are separate + * inner attributes, not just outer attributes of inner exprs */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* assuming you can't strip away the ArrayElems type, but can strip + * internal expressions and whatever */ + if (expr.has_array_elems()) + expr.get_array_elems()->accept_vis(*this); + } + void visit(AST::ArrayIndexExpr& expr) override { + /* it is unclear whether outer attributes are supposed to be + * allowed, but conceptually it wouldn't make much sense, so + * assuming no. TODO */ - void visit(AST::Token& tok) override {} - void visit(AST::DelimTokenTree& delim_tok_tree) override {} - void visit(AST::AttrInputMetaItemContainer& input) override {} - void visit(AST::IdentifierExpr& ident_expr) override {} - void visit(AST::Lifetime& lifetime) override {} - void visit(AST::LifetimeParam& lifetime_param) override {} - void visit(AST::MacroInvocationSemi& macro) override {} - - void visit(AST::PathInExpression& path) override {} - void visit(AST::TypePathSegment& segment) override {} - void visit(AST::TypePathSegmentGeneric& segment) override {} - void visit(AST::TypePathSegmentFunction& segment) override {} - void visit(AST::TypePath& path) override {} - void visit(AST::QualifiedPathInExpression& path) override {} - void visit(AST::QualifiedPathInType& path) override {} - - void visit(AST::LiteralExpr& expr) override {} - void visit(AST::AttrInputLiteral& attr_input) override {} - void visit(AST::MetaItemLitExpr& meta_item) override {} - void visit(AST::MetaItemPathLit& meta_item) override {} - void visit(AST::BorrowExpr& expr) override {} - void visit(AST::DereferenceExpr& expr) override {} - void visit(AST::ErrorPropagationExpr& expr) override {} - void visit(AST::NegationExpr& expr) override {} - void visit(AST::ArithmeticOrLogicalExpr& expr) override {} - void visit(AST::ComparisonExpr& expr) override {} - void visit(AST::LazyBooleanExpr& expr) override {} - void visit(AST::TypeCastExpr& expr) override {} - void visit(AST::AssignmentExpr& expr) override {} - void visit(AST::CompoundAssignmentExpr& expr) override {} - void visit(AST::GroupedExpr& expr) override {} - void visit(AST::ArrayElemsValues& elems) override {} - void visit(AST::ArrayElemsCopied& elems) override {} - void visit(AST::ArrayExpr& expr) override {} - void visit(AST::ArrayIndexExpr& expr) override {} + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + expr.get_array_expr()->accept_vis(*this); + expr.get_index_expr()->accept_vis(*this); + } void visit(AST::TupleExpr& expr) override {} void visit(AST::TupleIndexExpr& expr) override {} void visit(AST::StructExprStruct& expr) override {} @@ -117,16 +393,90 @@ namespace Rust { void visit(AST::AwaitExpr& expr) override {} void visit(AST::AsyncBlockExpr& expr) override {} - void visit(AST::TypeParam& param) override {} - void visit(AST::LifetimeWhereClauseItem& item) override {} - void visit(AST::TypeBoundWhereClauseItem& item) override {} - void visit(AST::Method& method) override {} - void visit(AST::ModuleBodied& module) override {} - void visit(AST::ModuleNoBody& module) override {} - void visit(AST::ExternCrate& crate) override {} - void visit(AST::UseTreeGlob& use_tree) override {} - void visit(AST::UseTreeList& use_tree) override {} - void visit(AST::UseTreeRebind& use_tree) override {} + void visit(AST::TypeParam& param) override { + // shouldn't require? + } + void visit(AST::LifetimeWhereClauseItem& item) override { + // shouldn't require? + } + void visit(AST::TypeBoundWhereClauseItem& item) override { + // shouldn't require? + } + void visit(AST::Method& method) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(method.get_outer_attrs()); + if (expander.fails_cfg(method.get_outer_attrs())) { + method.mark_for_strip(); + return; + } + + /* assuming you can't strip self param - wouldn't be a method + * anymore. spec allows outer attrs on self param, but doesn't + * specify whether cfg is used. */ + + /* strip method parameters if required - this is specifically + * allowed by spec */ + expand_function_params(method.get_function_params()); + + /* body should always exist - if error state, should have returned + * before now */ + method.get_definition()->accept_vis(*this); + // TODO: can block as a whole be invalidated here? Assuming no + } + void visit(AST::ModuleBodied& module) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(module.get_outer_attrs()); + if (expander.fails_cfg(module.get_outer_attrs())) { + module.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(module.get_inner_attrs()); + if (expander.fails_cfg(module.get_inner_attrs())) { + module.mark_for_strip(); + return; + } + + // strip items if required + auto& items = module.get_items(); + for (int i = 0; i < items.size();) { + auto& item = items[i]; + + // mark for stripping if required + item->accept_vis(*this); + + if (item->is_marked_for_strip()) + items.erase(items.begin() + i); + else + i++; + } + } + void visit(AST::ModuleNoBody& module) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(module.get_outer_attrs()); + if (expander.fails_cfg(module.get_outer_attrs())) { + module.mark_for_strip(); + return; + } + } + void visit(AST::ExternCrate& crate) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(crate.get_outer_attrs()); + if (expander.fails_cfg(crate.get_outer_attrs())) { + crate.mark_for_strip(); + return; + } + } + void visit(AST::UseTreeGlob& use_tree) override { + // shouldn't require? + } + void visit(AST::UseTreeList& use_tree) override { + // shouldn't require? + } + void visit(AST::UseTreeRebind& use_tree) override { + // shouldn't require? + } void visit(AST::UseDeclaration& use_decl) override { // strip test based on outer attrs expander.expand_cfg_attrs(use_decl.get_outer_attrs()); @@ -135,15 +485,123 @@ namespace Rust { return; } } - void visit(AST::Function& function) override {} - void visit(AST::TypeAlias& type_alias) override {} - void visit(AST::StructStruct& struct_item) override {} - void visit(AST::TupleStruct& tuple_struct) override {} - void visit(AST::EnumItem& item) override {} - void visit(AST::EnumItemTuple& item) override {} - void visit(AST::EnumItemStruct& item) override {} - void visit(AST::EnumItemDiscriminant& item) override {} - void visit(AST::Enum& enum_item) override {} + void visit(AST::Function& function) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(function.get_outer_attrs()); + if (expander.fails_cfg(function.get_outer_attrs())) { + function.mark_for_strip(); + return; + } + + /* strip function parameters if required - this is specifically + * allowed by spec */ + expand_function_params(function.get_function_params()); + + /* body should always exist - if error state, should have returned + * before now */ + function.get_definition()->accept_vis(*this); + // TODO: can block as a whole be invalidated here? Assuming no + } + void visit(AST::TypeAlias& type_alias) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(type_alias.get_outer_attrs()); + if (expander.fails_cfg(type_alias.get_outer_attrs())) { + type_alias.mark_for_strip(); + return; + } + } + void visit(AST::StructStruct& struct_item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(struct_item.get_outer_attrs()); + if (expander.fails_cfg(struct_item.get_outer_attrs())) { + struct_item.mark_for_strip(); + return; + } + + /* strip struct fields if required - this is presumably + * allowed by spec */ + expand_struct_fields(struct_item.get_fields()); + } + void visit(AST::TupleStruct& tuple_struct) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(tuple_struct.get_outer_attrs()); + if (expander.fails_cfg(tuple_struct.get_outer_attrs())) { + tuple_struct.mark_for_strip(); + return; + } + + /* strip struct fields if required - this is presumably + * allowed by spec */ + expand_tuple_fields(tuple_struct.get_fields()); + } + void visit(AST::EnumItem& item) override { + // initial 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::EnumItemTuple& item) override { + // initial 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 item fields if required - this is presumably + * allowed by spec */ + expand_tuple_fields(item.get_tuple_fields()); + } + void visit(AST::EnumItemStruct& item) override { + // initial 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 item fields if required - this is presumably + * allowed by spec */ + expand_struct_fields(item.get_struct_fields()); + } + void visit(AST::EnumItemDiscriminant& item) override { + // initial 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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + item.get_expr()->accept_vis(*this); + } + void visit(AST::Enum& enum_item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(enum_item.get_outer_attrs()); + if (expander.fails_cfg(enum_item.get_outer_attrs())) { + enum_item.mark_for_strip(); + return; + } + + /* strip enum fields if required - this is presumably + * allowed by spec */ + auto& variants = enum_item.get_variants(); + for (int i = 0; i < variants.size();) { + auto& variant = variants[i]; + + // mark for stripping if required + variant->accept_vis(*this); + + if (variant->is_marked_for_strip()) + variants.erase(variants.begin() + i); + else + i++; + } + } void visit(AST::Union& union_item) override { // initial test based on outer attrs expander.expand_cfg_attrs(union_item.get_outer_attrs()); @@ -151,7 +609,7 @@ namespace Rust { union_item.mark_for_strip(); return; } - + /* strip union fields if required - this is presumably * allowed by spec */ expand_struct_fields(union_item.get_variants()); @@ -163,8 +621,11 @@ namespace Rust { const_item.mark_for_strip(); return; } - /* TODO: is there any way to invalidate the expr? Are attributes - * even allowed on it? */ + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + const_item.get_expr()->accept_vis(*this); } void visit(AST::StaticItem& static_item) override { // initial test based on outer attrs @@ -173,8 +634,11 @@ namespace Rust { static_item.mark_for_strip(); return; } - /* TODO: is there any way to invalidate the expr? Are attributes - * even allowed on it? */ + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + static_item.get_expr()->accept_vis(*this); } void visit(AST::TraitItemFunc& item) override { // initial test based on outer attrs @@ -184,7 +648,7 @@ namespace Rust { return; } - /* strip function parameters if required - this is specifically + /* strip function parameters if required - this is specifically * allowed by spec */ expand_function_params(item.get_function_params()); @@ -201,11 +665,11 @@ namespace Rust { return; } - /* assuming you can't strip self param - wouldn't be a method + /* assuming you can't strip self param - wouldn't be a method * anymore. spec allows outer attrs on self param, but doesn't * specify whether cfg is used. */ - /* strip function parameters if required - this is specifically + /* strip function parameters if required - this is specifically * allowed by spec */ expand_function_params(item.get_function_params()); @@ -221,8 +685,12 @@ namespace Rust { item.mark_for_strip(); return; } - /* TODO: is there any way to invalidate the expr? Are attributes - * even allowed on it? */ + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped */ + if (item.has_expression()) + item.get_expr()->accept_vis(*this); } void visit(AST::TraitItemType& item) override { // initial test based on outer attrs @@ -249,14 +717,14 @@ namespace Rust { // strip trait items if required auto& trait_items = trait.get_trait_items(); - for (int i = 0; i < trait_items.size(); ) { + for (int i = 0; i < trait_items.size();) { auto& item = trait_items[i]; // mark for stripping if required item->accept_vis(*this); - if (item->is_marked_for_strip ()) - trait_items.erase (trait_items.begin() + i); + if (item->is_marked_for_strip()) + trait_items.erase(trait_items.begin() + i); else i++; } @@ -276,16 +744,16 @@ namespace Rust { return; } - // strip external items if required + // strip inherent impl items if required auto& impl_items = impl.get_impl_items(); - for (int i = 0; i < impl_items.size(); ) { + for (int i = 0; i < impl_items.size();) { auto& item = impl_items[i]; // mark for stripping if required item->accept_vis(*this); - if (item->is_marked_for_strip ()) - impl_items.erase (impl_items.begin() + i); + if (item->is_marked_for_strip()) + impl_items.erase(impl_items.begin() + i); else i++; } @@ -305,16 +773,16 @@ namespace Rust { return; } - // strip external items if required + // strip trait impl items if required auto& impl_items = impl.get_impl_items(); - for (int i = 0; i < impl_items.size(); ) { + for (int i = 0; i < impl_items.size();) { auto& item = impl_items[i]; // mark for stripping if required item->accept_vis(*this); - if (item->is_marked_for_strip ()) - impl_items.erase (impl_items.begin() + i); + if (item->is_marked_for_strip()) + impl_items.erase(impl_items.begin() + i); else i++; } @@ -335,22 +803,22 @@ namespace Rust { return; } - /* strip function parameters if required - this is specifically + /* strip function parameters if required - this is specifically * allowed by spec */ auto& params = item.get_function_params(); - for (int i = 0; i < params.size(); ) { - auto& param_attrs = params[i].get_outer_attrs (); + 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); + if (expander.fails_cfg(param_attrs)) + params.erase(params.begin() + i); else i++; } - /* NOTE: these are extern function params, which may have different - * rules and restrictions to "normal" function params. So expansion + /* NOTE: these are extern function params, which may have different + * rules and restrictions to "normal" function params. So expansion * handled separately. */ - /* TODO: assuming that variadic nature cannot be stripped. If this + /* 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 { @@ -370,14 +838,14 @@ namespace Rust { // strip external items if required auto& extern_items = block.get_extern_items(); - for (int i = 0; i < extern_items.size(); ) { + for (int i = 0; i < extern_items.size();) { auto& item = extern_items[i]; // mark for stripping if required item->accept_vis(*this); - if (item->is_marked_for_strip ()) - extern_items.erase (extern_items.begin() + i); + if (item->is_marked_for_strip()) + extern_items.erase(extern_items.begin() + i); else i++; } @@ -386,8 +854,26 @@ namespace Rust { void visit(AST::MacroMatchFragment& match) override {} void visit(AST::MacroMatchRepetition& match) override {} void visit(AST::MacroMatcher& matcher) override {} - void visit(AST::MacroRulesDefinition& rules_def) override {} - void visit(AST::MacroInvocation& macro_invoc) override {} + void visit(AST::MacroRulesDefinition& rules_def) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(rules_def.get_outer_attrs()); + if (expander.fails_cfg(rules_def.get_outer_attrs())) { + rules_def.mark_for_strip(); + return; + } + + // I don't think any macro rules can be stripped in any way + } + void visit(AST::MacroInvocation& macro_invoc) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(macro_invoc.get_outer_attrs()); + if (expander.fails_cfg(macro_invoc.get_outer_attrs())) { + macro_invoc.mark_for_strip(); + return; + } + + // I don't think any macro token trees can be stripped in any way + } void visit(AST::MetaItemPath& meta_item) override {} void visit(AST::MetaItemSeq& meta_item) override {} void visit(AST::MetaWord& meta_item) override {} @@ -395,6 +881,7 @@ namespace Rust { void visit(AST::MetaListPaths& meta_item) override {} void visit(AST::MetaListNameValueStr& meta_item) override {} + // stripping shouldn't be required or possible for patterns void visit(AST::LiteralPattern& pattern) override {} void visit(AST::IdentifierPattern& pattern) override {} void visit(AST::WildcardPattern& pattern) override {} @@ -416,11 +903,55 @@ namespace Rust { void visit(AST::GroupedPattern& pattern) override {} void visit(AST::SlicePattern& pattern) override {} - void visit(AST::EmptyStmt& stmt) override {} - void visit(AST::LetStmt& stmt) override {} - void visit(AST::ExprStmtWithoutBlock& stmt) override {} - void visit(AST::ExprStmtWithBlock& stmt) override {} + void visit(AST::EmptyStmt& stmt) override { + // assuming no outer attributes, so nothing can happen + } + void visit(AST::LetStmt& stmt) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(stmt.get_outer_attrs()); + if (expander.fails_cfg(stmt.get_outer_attrs())) { + stmt.mark_for_strip(); + return; + } + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped */ + if (stmt.has_init_expr()) + stmt.get_init_expr()->accept_vis(*this); + } + void visit(AST::ExprStmtWithoutBlock& stmt) override { + // outer attributes associated with expr, so rely on expr + // guard - should prevent null pointer expr + if (stmt.is_marked_for_strip()) + return; + + // strip if expr is to be stripped + auto& expr = stmt.get_expr(); + expr->accept_vis(*this); + if (expr->is_marked_for_strip()) { + stmt.mark_for_strip(); + return; + } + } + void visit(AST::ExprStmtWithBlock& stmt) override { + // outer attributes associated with expr, so rely on expr + + // guard - should prevent null pointer expr + if (stmt.is_marked_for_strip()) + return; + + // strip if expr is to be stripped + auto& expr = stmt.get_expr(); + expr->accept_vis(*this); + if (expr->is_marked_for_strip()) { + stmt.mark_for_strip(); + return; + } + } + + // stripping shouldn't be required or possible for types void visit(AST::TraitBound& bound) override {} void visit(AST::ImplTraitType& type) override {} void visit(AST::TraitObjectType& type) override {} @@ -515,10 +1046,19 @@ namespace Rust { } // expand module attributes? - // expand attributes recursively + // expand attributes recursively and strip items if required AttrVisitor attr_visitor(*this); - for (auto& i : crate.items) { - i->accept_vis(attr_visitor); + auto& items = crate.items; + for (int i = 0; i < items.size();) { + auto& item = items[i]; + + // mark for stripping if required + item->accept_vis(attr_visitor); + + if (item->is_marked_for_strip()) + items.erase(items.begin() + i); + else + i++; } // TODO: should recursive attribute and macro expansion be done in the same transversal? Or in // separate ones like currently? -- cgit v1.1 From f5ae2781823b3a2bcded1ac3446de83cc52403a9 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Thu, 12 Nov 2020 22:22:41 +0800 Subject: Added more expression stripping Fixed compile errors and started on enum expr stripping --- gcc/rust/analysis/rust-type-resolution.cc | 14 +-- gcc/rust/analysis/rust-type-resolution.h | 4 +- gcc/rust/ast/rust-expr.h | 84 ++++++++----- gcc/rust/ast/rust-stmt.h | 4 +- gcc/rust/backend/rust-compile.cc | 18 +-- gcc/rust/expand/rust-macro-expand.cc | 200 ++++++++++++++++++++++++++++-- 6 files changed, 264 insertions(+), 60 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 87cf828..fcf475e 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -427,15 +427,15 @@ TypeResolution::visit (AST::StructExprFieldIdentifier &field) void TypeResolution::visit (AST::StructExprFieldIdentifierValue &field) { - identifierBuffer = &field.field_name; - field.value->accept_vis (*this); + identifierBuffer = std::unique_ptr (new std::string (field.get_field_name ())); + field.get_value ()->accept_vis (*this); } void TypeResolution::visit (AST::StructExprFieldIndexValue &field) { - tupleIndexBuffer = &field.index; - field.value->accept_vis (*this); + tupleIndexBuffer = std::unique_ptr (new int (field.get_index ())); + field.get_value ()->accept_vis (*this); } void @@ -448,7 +448,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr) return; } - for (auto &field : expr.fields) + for (auto &field : expr.get_fields ()) { identifierBuffer = NULL; tupleIndexBuffer = NULL; @@ -1069,14 +1069,14 @@ TypeResolution::visit (AST::LetStmt &stmt) void TypeResolution::visit (AST::ExprStmtWithoutBlock &stmt) { - stmt.expr->accept_vis (*this); + stmt.get_expr ()->accept_vis (*this); } void TypeResolution::visit (AST::ExprStmtWithBlock &stmt) { scope.Push (); - stmt.expr->accept_vis (*this); + stmt.get_expr ()->accept_vis (*this); auto localMap = scope.PeekLocals (); for (auto &[_, value] : localMap) { diff --git a/gcc/rust/analysis/rust-type-resolution.h b/gcc/rust/analysis/rust-type-resolution.h index af4594e..0c6413b 100644 --- a/gcc/rust/analysis/rust-type-resolution.h +++ b/gcc/rust/analysis/rust-type-resolution.h @@ -301,8 +301,8 @@ private: bool isTypeInScope (AST::Type *type, Location locus); TypeScoping scope; - std::string *identifierBuffer; - int *tupleIndexBuffer; + std::unique_ptr identifierBuffer; + std::unique_ptr tupleIndexBuffer; }; } // namespace Analysis diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index a92a8ad..1cf8f9c 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1218,7 +1218,8 @@ class TupleExpr : public ExprWithoutBlock public: std::string as_string () const override; - std::vector get_inner_attrs () const { return inner_attrs; } + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } TupleExpr (std::vector > tuple_elements, std::vector inner_attribs, @@ -1269,6 +1270,10 @@ public: void mark_for_strip () override { marked_for_strip = true; } bool is_marked_for_strip () const override { return marked_for_strip; } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector > &get_tuple_elems () const { return tuple_elems; } + std::vector > &get_tuple_elems () { return tuple_elems; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1340,6 +1345,12 @@ public: void mark_for_strip () override { tuple_expr = nullptr; } bool is_marked_for_strip () const override { return tuple_expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_tuple_expr () { + rust_assert (tuple_expr != nullptr); + return tuple_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1382,7 +1393,8 @@ class StructExprStruct : public StructExpr public: std::string as_string () const override; - std::vector get_inner_attrs () const { return inner_attrs; } + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } // Constructor has to call protected constructor of base class StructExprStruct (PathInExpression struct_path, @@ -1410,9 +1422,10 @@ protected: * struct */ struct StructBase { -public: +private: std::unique_ptr base_struct; +public: // TODO: should this store location data? StructBase (std::unique_ptr base_struct_ptr) : base_struct (std::move (base_struct_ptr)) @@ -1453,6 +1466,12 @@ public: bool is_invalid () const { return base_struct == nullptr; } std::string as_string () const; + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_base_struct () { + rust_assert (base_struct != nullptr); + return base_struct; + } }; /* Base AST node for a single struct expression field (in struct instance @@ -1480,11 +1499,10 @@ protected: // Identifier-only variant of StructExprField AST node class StructExprFieldIdentifier : public StructExprField { -public: Identifier field_name; // TODO: should this store location data? - +public: StructExprFieldIdentifier (Identifier field_identifier) : field_name (std::move (field_identifier)) {} @@ -1506,7 +1524,6 @@ protected: * abstract */ class StructExprFieldWithVal : public StructExprField { -public: std::unique_ptr value; protected: @@ -1533,16 +1550,21 @@ protected: public: std::string as_string () const override; + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_value () { + rust_assert (value != nullptr); + return value; + } }; // Identifier and value variant of StructExprField AST node class StructExprFieldIdentifierValue : public StructExprFieldWithVal { -public: Identifier field_name; // TODO: should this store location data? - +public: StructExprFieldIdentifierValue (Identifier field_identifier, std::unique_ptr field_value) : StructExprFieldWithVal (std::move (field_value)), @@ -1553,6 +1575,8 @@ public: void accept_vis (ASTVisitor &vis) override; + std::string get_field_name () const { return field_name; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1565,11 +1589,10 @@ protected: // Tuple index and value variant of StructExprField AST node class StructExprFieldIndexValue : public StructExprFieldWithVal { -public: TupleIndex index; // TODO: should this store location data? - +public: StructExprFieldIndexValue (TupleIndex tuple_index, std::unique_ptr field_value) : StructExprFieldWithVal (std::move (field_value)), index (tuple_index) @@ -1579,6 +1602,8 @@ public: void accept_vis (ASTVisitor &vis) override; + TupleIndex get_index () const { return index; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1591,25 +1616,17 @@ protected: // AST node of a struct creator with fields class StructExprStructFields : public StructExprStruct { -public: // std::vector fields; std::vector > fields; // bool has_struct_base; StructBase struct_base; +public: std::string as_string () const override; bool has_struct_base () const { return !struct_base.is_invalid (); } - /*inline std::vector> get_fields() - const { return fields; - }*/ - - /*inline StructBase get_struct_base() const { - return has_struct_base ? struct_base : StructBase::error(); - }*/ - // Constructor for StructExprStructFields when no struct base is used StructExprStructFields ( PathInExpression struct_path, @@ -1650,6 +1667,13 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector > &get_fields () { return fields; } + const std::vector > &get_fields () const { return fields; } + + StructBase &get_struct_base () { return struct_base; } + const StructBase &get_struct_base () const { return struct_base; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1660,6 +1684,8 @@ protected: }; // AST node of the functional update struct creator +/* TODO: remove and replace with StructExprStructFields, except with empty + * vector of fields? */ class StructExprStructBase : public StructExprStruct { StructBase struct_base; @@ -1667,10 +1693,6 @@ class StructExprStructBase : public StructExprStruct public: std::string as_string () const override; - /*inline StructBase get_struct_base() const { - return struct_base; - }*/ - StructExprStructBase (PathInExpression struct_path, StructBase base_struct, std::vector inner_attribs, std::vector outer_attribs, Location locus) @@ -1681,6 +1703,9 @@ public: void accept_vis (ASTVisitor &vis) override; + StructBase &get_struct_base () { return struct_base; } + const StructBase &get_struct_base () const { return struct_base; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1702,10 +1727,7 @@ public: std::string as_string () const override; const std::vector &get_inner_attrs () const { return inner_attrs; } - - /*inline std::vector> get_exprs() const { - return exprs; - }*/ + std::vector &get_inner_attrs () { return inner_attrs; } StructExprTuple (PathInExpression struct_path, std::vector > tuple_exprs, @@ -1748,6 +1770,9 @@ public: void accept_vis (ASTVisitor &vis) override; + const std::vector > &get_elems () const { return exprs; } + std::vector > &get_elems () { return exprs; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1766,7 +1791,6 @@ public: std::string as_string () const override { return get_struct_name ().as_string (); - // return struct_name.as_string(); } StructExprUnit (PathInExpression struct_path, @@ -1990,6 +2014,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector > &get_fields () { return fields; } + const std::vector > &get_fields () const { return fields; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index f7c47d7..0bb1021 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -160,7 +160,6 @@ protected: * difficulties, can only be guaranteed to hold an expression). */ class ExprStmtWithoutBlock : public ExprStmt { -public: // TODO: ensure that this works std::unique_ptr expr; /* HACK: cannot ensure type safety of ExprWithoutBlock due to Pratt parsing, @@ -168,6 +167,7 @@ public: * or redesign AST. */ // std::unique_ptr expr; +public: std::string as_string () const override; ExprStmtWithoutBlock (std::unique_ptr expr, Location locus) @@ -232,9 +232,9 @@ protected: // Statement containing an expression with a block class ExprStmtWithBlock : public ExprStmt { -public: std::unique_ptr expr; +public: std::string as_string () const override; std::vector locals; diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 0589347..ca310ca 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.field_name.compare (df.field_name) == 0) + if (field.get_field_name ().compare (df.field_name) == 0) { found = true; break; @@ -546,16 +546,16 @@ Compilation::visit (AST::StructExprFieldIdentifierValue &field) } if (!found) { - rust_fatal_error (field.value->get_locus_slow (), + rust_fatal_error (field.get_value ()->get_locus_slow (), "failed to lookup field index"); return; } Bexpression *value = NULL; - VISIT_POP (field.value->get_locus_slow (), field.value.get (), value, exprs); + VISIT_POP (field.get_value ()->get_locus_slow (), field.get_value ().get (), value, exprs); if (value == NULL) { - rust_fatal_error (field.value->get_locus_slow (), + rust_fatal_error (field.get_value ()->get_locus_slow (), "failed to compile value to struct"); return; } @@ -566,10 +566,10 @@ void Compilation::visit (AST::StructExprFieldIndexValue &field) { Bexpression *value = NULL; - VISIT_POP (field.value->get_locus_slow (), field.value.get (), value, exprs); + VISIT_POP (field.get_value ()->get_locus_slow (), field.get_value ().get (), value, exprs); if (value == NULL) { - rust_fatal_error (field.value->get_locus_slow (), + rust_fatal_error (field.get_value ()->get_locus_slow (), "failed to compile value to struct"); return; } @@ -598,7 +598,7 @@ Compilation::visit (AST::StructExprStructFields &expr) // FIXME type resolution pass should ensures these are in correct order // and have defaults if required - for (auto &field : expr.fields) + for (auto &field : expr.get_fields ()) { Bexpression *value = NULL; VISIT_POP (expr.get_locus (), field, value, exprs); @@ -1332,7 +1332,7 @@ Compilation::visit (AST::LetStmt &stmt) void Compilation::visit (AST::ExprStmtWithoutBlock &stmt) { - stmt.expr->accept_vis (*this); + stmt.get_expr ()->accept_vis (*this); } void @@ -1348,7 +1348,7 @@ Compilation::visit (AST::ExprStmtWithBlock &stmt) start_location, end_location); scope.PushBlock (code_block); - stmt.expr->accept_vis (*this); + stmt.get_expr ()->accept_vis (*this); // get trailing if required for (auto &s : stmts) diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 164b5a5..65918db 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -345,20 +345,196 @@ namespace Rust { expr.get_array_expr()->accept_vis(*this); expr.get_index_expr()->accept_vis(*this); } - void visit(AST::TupleExpr& expr) override {} - void visit(AST::TupleIndexExpr& expr) override {} - void visit(AST::StructExprStruct& expr) override {} - void visit(AST::StructExprFieldIdentifier& field) override {} - void visit(AST::StructExprFieldIdentifierValue& field) override {} - void visit(AST::StructExprFieldIndexValue& field) override {} - void visit(AST::StructExprStructFields& expr) override {} - void visit(AST::StructExprStructBase& expr) override {} - void visit(AST::StructExprTuple& expr) override {} - void visit(AST::StructExprUnit& expr) override {} - void visit(AST::EnumExprFieldIdentifier& field) override {} + void visit(AST::TupleExpr& expr) override { + /* according to spec, outer attributes are allowed on "elements of + * tuple expressions" */ + + // 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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* apparently outer attributes are allowed in "elements of tuple + * expressions" according to spec */ + auto& values = expr.get_tuple_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::TupleIndexExpr& 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; + } + + /* wouldn't strip this directly (as outer attrs should be + * associated with this level), but any sub-expressions would be + * stripped. Thus, no need to erase when strip check called. */ + expr.get_tuple_expr()->accept_vis(*this); + } + void visit(AST::StructExprStruct& 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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + } + void visit(AST::StructExprFieldIdentifier& field) override { + // as no attrs (at moment, at least), no stripping possible + } + void visit(AST::StructExprFieldIdentifierValue& 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::StructExprFieldIndexValue& 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::StructExprStructFields& 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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* spec does not specify whether expressions are allowed to be + * stripped at top level of struct fields, but I wouldn't think + * that they would be, so operating under the assumption that only + * sub-expressions can be stripped. */ + for (auto& field : expr.get_fields()) { + field->accept_vis(*this); + // shouldn't strip in this + } + + /* struct base presumably can't be stripped, as the '..' is before + * the expression. as such, can only strip sub-expressions. */ + if (expr.has_struct_base()) + expr.get_struct_base().get_base_struct()->accept_vis(*this); + } + void visit(AST::StructExprStructBase& 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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* struct base presumably can't be stripped, as the '..' is before + * the expression. as such, can only strip sub-expressions. */ + rust_assert(!expr.get_struct_base().is_invalid()); + expr.get_struct_base().get_base_struct()->accept_vis(*this); + } + void visit(AST::StructExprTuple& 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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + /* spec says outer attributes are specifically allowed for elements + * of tuple-style struct 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::StructExprUnit& 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; + } + } + void visit(AST::EnumExprFieldIdentifier& field) override { + + } void visit(AST::EnumExprFieldIdentifierValue& field) override {} void visit(AST::EnumExprFieldIndexValue& field) override {} - void visit(AST::EnumExprStruct& expr) override {} + void visit(AST::EnumExprStruct& 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 does not specify whether expressions are allowed to be + * stripped at top level of expression fields, but I wouldn't think + * that they would be, so operating under the assumption that only + * sub-expressions can be stripped. */ + for (auto& field : expr.get_fields()) { + field->accept_vis(*this); + // shouldn't strip in this + } + } void visit(AST::EnumExprTuple& expr) override {} void visit(AST::EnumExprFieldless& expr) override {} void visit(AST::CallExpr& expr) override {} -- cgit v1.1 From 25de39b1f0e307b0ff6de485d9ac5648e9295f3d Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sat, 14 Nov 2020 21:26:11 +0800 Subject: Added more expr stripping --- gcc/rust/analysis/rust-scan.cc | 2 +- gcc/rust/analysis/rust-type-resolution.cc | 36 ++++---- gcc/rust/ast/rust-ast-full-test.cc | 50 ++++++++--- gcc/rust/ast/rust-expr.h | 93 ++++++++++++++----- gcc/rust/ast/rust-item.h | 37 +++++++- gcc/rust/backend/rust-compile.cc | 34 +++---- gcc/rust/expand/rust-macro-expand.cc | 143 +++++++++++++++++++++++++++--- gcc/rust/parse/rust-parse-impl.h | 4 +- 8 files changed, 316 insertions(+), 83 deletions(-) (limited to 'gcc/rust') 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 (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 &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> get_fields() const - { return fields; - }*/ - EnumExprStruct (PathInExpression enum_variant_path, std::vector > variant_fields, std::vector outer_attribs, Location locus) @@ -2037,10 +2050,6 @@ class EnumExprTuple : public EnumVariantExpr public: std::string as_string () const override; - /*inline std::vector> get_values() const { - return values; - }*/ - EnumExprTuple (PathInExpression enum_variant_path, std::vector > variant_values, std::vector outer_attribs, Location locus) @@ -2080,6 +2089,9 @@ public: void accept_vis (ASTVisitor &vis) override; + const std::vector > &get_elems () const { return values; } + std::vector > &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 function; // inlined form of CallParams std::vector > params; Location locus; +public: Function *fndeclRef; std::string as_string () const override; - /*inline std::vector> get_params() const { - return params; - }*/ - CallExpr (std::unique_ptr function_expr, std::vector > function_params, std::vector 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 > &get_params () const { return params; } + std::vector > &get_params () { return params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &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> get_params() const { - return params; - }*/ - MethodCallExpr (std::unique_ptr call_receiver, PathExprSegment method_path, std::vector > 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 > &get_params () const { return params; } + std::vector > &get_params () { return params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &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 &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 outer_attrs; std::unique_ptr 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 param_pattern, - std::unique_ptr param_type = nullptr) - : pattern (std::move (param_pattern)), type (std::move (param_type)) + std::unique_ptr param_type = nullptr, std::vector 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 &get_outer_attrs () const { return outer_attrs; } + std::vector &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 &get_params () const { return params; } + std::vector &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 &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 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 &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> generic_params, @@ -1587,7 +1607,7 @@ protected: // A single field in a struct struct StructField { -public: +private: // bool has_outer_attributes; std::vector 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 &get_outer_attrs () { return outer_attrs; } const std::vector &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 &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 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 parameters; std::vector 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 AST::ClosureParam Parser::parse_closure_param () { + std::vector outer_attrs = parse_outer_attributes (); + // parse pattern (which is required) std::unique_ptr pattern = parse_pattern (); if (pattern == nullptr) @@ -8537,7 +8539,7 @@ Parser::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). -- cgit v1.1 From 4ec3b8d62b1b6ae79d55b71b423dcb04129884c6 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sun, 15 Nov 2020 22:18:49 +0800 Subject: Added more expr cfg stripping Fixed compile errors Fixed compile errors relating to block expr visibility changes --- gcc/rust/analysis/rust-type-resolution.cc | 4 +- gcc/rust/ast/rust-expr.h | 79 ++++++- gcc/rust/backend/rust-compile.cc | 8 +- gcc/rust/expand/rust-macro-expand.cc | 374 ++++++++++++++++++++++++++---- 4 files changed, 409 insertions(+), 56 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index c3a5587..5aa2905 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -615,7 +615,7 @@ void TypeResolution::visit (AST::BlockExpr &expr) { scope.Push (); - for (auto &stmt : expr.statements) + for (auto &stmt : expr.get_statements ()) { stmt->accept_vis (*this); } @@ -792,7 +792,7 @@ TypeResolution::visit (AST::Function &function) } // walk the expression body - for (auto &stmt : function.get_definition ()->statements) + for (auto &stmt : function.get_definition ()->get_statements ()) { stmt->accept_vis (*this); } diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 6f68542..66ffe16 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -2565,7 +2565,6 @@ protected: // A block AST node class BlockExpr : public ExprWithBlock { -public: std::vector inner_attrs; // bool has_statements; @@ -2575,13 +2574,14 @@ public: Location locus; +public: std::string as_string () const override; // Returns whether the block contains statements. bool has_statements () const { return !statements.empty (); } - // Returns whether the block contains an expression - bool has_expr () const { return expr != nullptr; } + // Returns whether the block contains a final expression. + bool has_tail_expr () const { return expr != nullptr; } BlockExpr (std::vector > block_statements, std::unique_ptr block_expr, @@ -2651,6 +2651,22 @@ public: } bool is_marked_for_strip () const override { return expr == nullptr && statements.empty (); } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } + + const std::vector > &get_statements () const { return statements; } + std::vector > &get_statements () { return statements; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_tail_expr () { + rust_assert (expr != nullptr); + return expr; + } + + // Removes the tail expression from the block. + void strip_tail_expr () { expr = nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2729,10 +2745,17 @@ public: void accept_vis (ASTVisitor &vis) override; - /* Invalid if inner expr is null, so base stripping on that. Technically, type should also not be null. */ + /* Invalid if inner expr is null, so base stripping on that. Technically, + * type should also not be null. */ void mark_for_strip () override { expr = nullptr; } bool is_marked_for_strip () const override { return expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_definition_block () { + rust_assert (expr != nullptr); + return expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2858,6 +2881,12 @@ public: void mark_for_strip () override { marked_for_strip = true; } bool is_marked_for_strip () const override { return marked_for_strip; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_break_expr () { + rust_assert (break_expr != nullptr); + return break_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2938,6 +2967,18 @@ public: void mark_for_strip () override { from = nullptr; to = nullptr; } bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_from_expr () { + rust_assert (from != nullptr); + return from; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_to_expr () { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2993,6 +3034,12 @@ public: void mark_for_strip () override { from = nullptr; } bool is_marked_for_strip () const override { return from == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_from_expr () { + rust_assert (from != nullptr); + return from; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3049,6 +3096,12 @@ public: void mark_for_strip () override { to = nullptr; } bool is_marked_for_strip () const override { return to == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_to_expr () { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3142,6 +3195,18 @@ public: void mark_for_strip () override { from = nullptr; to = nullptr; } bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_from_expr () { + rust_assert (from != nullptr); + return from; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_to_expr () { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3198,6 +3263,12 @@ public: void mark_for_strip () override { to = nullptr; } bool is_marked_for_strip () const override { return to == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_to_expr () { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 12ce47f..17d9cde 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -701,7 +701,7 @@ Compilation::visit (AST::BlockExpr &expr) start_location, end_location); scope.PushBlock (code_block); - for (auto &stmt : expr.statements) + for (auto &stmt : expr.get_statements ()) { stmt->accept_vis (*this); } @@ -1039,10 +1039,10 @@ Compilation::visit (AST::Function &function) Bblock *enclosingScope = NULL; Location start_location = function.get_locus (); Location end_location; - if (function.get_definition ()->statements.size () > 0) + if (function.get_definition ()->get_statements ().size () > 0) { end_location - = function.get_definition ()->statements.back ()->get_locus_slow (); + = function.get_definition ()->get_statements ().back ()->get_locus_slow (); } auto code_block = backend->block (fndecl, enclosingScope, vars, @@ -1063,7 +1063,7 @@ Compilation::visit (AST::Function &function) scope.PushCurrentFunction (function.get_function_name (), fndecl, returnType, retDecl); - for (auto &stmt : function.get_definition ()->statements) + for (auto &stmt : function.get_definition ()->get_statements ()) stmt->accept_vis (*this); scope.PopBlock (); diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index ed5f365..417f51b 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -2,6 +2,7 @@ #include "rust-ast-full.h" // is full really required? #include "rust-ast-visitor.h" +#include "rust-diagnostics.h" namespace Rust { // Visitor used to expand attributes. @@ -139,7 +140,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_borrowed_expr()->accept_vis(*this); + auto& borrowed_expr = expr.get_borrowed_expr(); + borrowed_expr->accept_vis(*this); + if (borrowed_expr->is_marked_for_strip()) + rust_error_at(borrowed_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::DereferenceExpr& expr) override { // initial strip test based on outer attrs @@ -152,7 +157,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_dereferenced_expr()->accept_vis(*this); + auto& dereferenced_expr = expr.get_dereferenced_expr(); + dereferenced_expr->accept_vis(*this); + if (dereferenced_expr->is_marked_for_strip()) + rust_error_at(dereferenced_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ErrorPropagationExpr& expr) override { // initial strip test based on outer attrs @@ -165,7 +174,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_propagating_expr()->accept_vis(*this); + auto& propagating_expr = expr.get_propagating_expr(); + propagating_expr->accept_vis(*this); + if (propagating_expr->is_marked_for_strip()) + rust_error_at(propagating_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::NegationExpr& expr) override { // initial strip test based on outer attrs @@ -178,7 +191,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_negated_expr()->accept_vis(*this); + auto& negated_expr = expr.get_negated_expr(); + negated_expr->accept_vis(*this); + if (negated_expr->is_marked_for_strip()) + rust_error_at(negated_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ArithmeticOrLogicalExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -192,8 +209,12 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); + if (expr.get_right_expr()->is_marked_for_strip()) + rust_error_at(expr.get_right_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ComparisonExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -207,8 +228,12 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); + if (expr.get_right_expr()->is_marked_for_strip()) + rust_error_at(expr.get_right_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::LazyBooleanExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -222,19 +247,25 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); + if (expr.get_right_expr()->is_marked_for_strip()) + rust_error_at(expr.get_right_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::TypeCastExpr& expr) override { /* outer attributes never allowed before these. while cannot strip - * two direct descendant expressions, can strip ones below that */ + * direct descendant expression, can strip ones below that */ /* should have no possibility for outer attrs as would be parsed * with outer expr */ expr.get_casted_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_casted_expr()->is_marked_for_strip()); + if (expr.get_casted_expr()->is_marked_for_strip()) + rust_error_at(expr.get_casted_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before cast exprs"); } void visit(AST::AssignmentExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -248,8 +279,12 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); + if (expr.get_right_expr()->is_marked_for_strip()) + rust_error_at(expr.get_right_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::CompoundAssignmentExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -263,8 +298,12 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); + if (expr.get_right_expr()->is_marked_for_strip()) + rust_error_at(expr.get_right_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::GroupedExpr& expr) override { // initial strip test based on outer attrs @@ -285,7 +324,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_expr_in_parens()->accept_vis(*this); + auto& inner_expr = expr.get_expr_in_parens(); + inner_expr->accept_vis(*this); + if (inner_expr->is_marked_for_strip()) + rust_error_at(inner_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ArrayElemsValues& elems) override { /* apparently outer attributes are allowed in "elements of array @@ -310,8 +353,17 @@ namespace Rust { * such, not implementing. TODO clear up the ambiguity here */ // only intend stripping for internal sub-expressions - elems.get_elem_to_copy()->accept_vis(*this); - elems.get_num_copies()->accept_vis(*this); + auto& copied_expr = elems.get_elem_to_copy(); + copied_expr->accept_vis(*this); + if (copied_expr->is_marked_for_strip()) + rust_error_at(copied_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + auto& copy_count = elems.get_num_copies(); + copy_count->accept_vis(*this); + if (copy_count->is_marked_for_strip()) + rust_error_at(copy_count->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ArrayExpr& expr) override { // initial strip test based on outer attrs @@ -336,14 +388,29 @@ namespace Rust { } void visit(AST::ArrayIndexExpr& expr) override { /* it is unclear whether outer attributes are supposed to be - * allowed, but conceptually it wouldn't make much sense, so - * assuming no. TODO */ + * allowed, but conceptually it wouldn't make much sense, but + * having expansion code anyway. TODO */ + // 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 any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_array_expr()->accept_vis(*this); - expr.get_index_expr()->accept_vis(*this); + auto& array_expr = expr.get_array_expr(); + array_expr->accept_vis(*this); + if (array_expr->is_marked_for_strip()) + rust_error_at(array_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + auto& index_expr = expr.get_index_expr(); + index_expr->accept_vis(*this); + if (index_expr->is_marked_for_strip()) + rust_error_at(index_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::TupleExpr& expr) override { /* according to spec, outer attributes are allowed on "elements of @@ -390,7 +457,11 @@ namespace Rust { /* wouldn't strip this directly (as outer attrs should be * associated with this level), but any sub-expressions would be * stripped. Thus, no need to erase when strip check called. */ - expr.get_tuple_expr()->accept_vis(*this); + auto& tuple_expr = expr.get_tuple_expr(); + tuple_expr->accept_vis(*this); + if (tuple_expr->is_marked_for_strip()) + rust_error_at(tuple_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::StructExprStruct& expr) override { // initial strip test based on outer attrs @@ -414,12 +485,20 @@ namespace Rust { void visit(AST::StructExprFieldIdentifierValue& field) override { /* as no attrs possible (at moment, at least), only sub-expression * stripping is possible */ - field.get_value()->accept_vis(*this); + auto& value = field.get_value(); + value->accept_vis(*this); + if (value->is_marked_for_strip()) + rust_error_at(value->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::StructExprFieldIndexValue& field) override { /* as no attrs possible (at moment, at least), only sub-expression * stripping is possible */ - field.get_value()->accept_vis(*this); + auto& value = field.get_value(); + value->accept_vis(*this); + if (value->is_marked_for_strip()) + rust_error_at(value->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::StructExprStructFields& expr) override { // initial strip test based on outer attrs @@ -448,8 +527,13 @@ namespace Rust { /* struct base presumably can't be stripped, as the '..' is before * the expression. as such, can only strip sub-expressions. */ - if (expr.has_struct_base()) - expr.get_struct_base().get_base_struct()->accept_vis(*this); + if (expr.has_struct_base()) { + auto& base_struct_expr = expr.get_struct_base().get_base_struct(); + base_struct_expr->accept_vis(*this); + if (base_struct_expr->is_marked_for_strip()) + rust_error_at(base_struct_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } } void visit(AST::StructExprStructBase& expr) override { // initial strip test based on outer attrs @@ -470,7 +554,11 @@ namespace Rust { /* struct base presumably can't be stripped, as the '..' is before * the expression. as such, can only strip sub-expressions. */ rust_assert(!expr.get_struct_base().is_invalid()); - expr.get_struct_base().get_base_struct()->accept_vis(*this); + auto& base_struct_expr = expr.get_struct_base().get_base_struct(); + base_struct_expr->accept_vis(*this); + if (base_struct_expr->is_marked_for_strip()) + rust_error_at(base_struct_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::StructExprTuple& expr) override { // initial strip test based on outer attrs @@ -517,12 +605,20 @@ namespace Rust { 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); + auto& value = field.get_value(); + value->accept_vis(*this); + if (value->is_marked_for_strip()) + rust_error_at(value->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } 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); + auto& value = field.get_value(); + value->accept_vis(*this); + if (value->is_marked_for_strip()) + rust_error_at(value->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::EnumExprStruct& expr) override { // initial strip test based on outer attrs @@ -582,7 +678,11 @@ namespace Rust { /* 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); + auto& function = expr.get_function_expr(); + function->accept_vis(*this); + if (function->is_marked_for_strip()) + rust_error_at(function->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); /* spec says outer attributes are specifically allowed for elements * of call expressions, so full stripping possible */ @@ -610,7 +710,11 @@ namespace Rust { /* 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); + auto& receiver = expr.get_receiver_expr(); + receiver->accept_vis(*this); + if (receiver->is_marked_for_strip()) + rust_error_at(receiver->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); // no outer attrs on paths possible @@ -638,9 +742,13 @@ namespace Rust { } /* should not be outer attrs on "receiver" expression - outer attrs - * should be associated with call expr as a whole. only sub-expr + * should be associated with field expr as a whole. only sub-expr * expansion is possible. */ - expr.get_receiver_expr()->accept_vis(*this); + auto& receiver = expr.get_receiver_expr(); + receiver->accept_vis(*this); + if (receiver->is_marked_for_strip()) + rust_error_at(receiver->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ClosureExprInner& expr) override { // initial strip test based on outer attrs @@ -661,19 +769,193 @@ namespace Rust { else i++; } + + // can't strip expression itself, but can strip sub-expressions + auto& definition_expr = expr.get_definition_expr(); + definition_expr->accept_vis(*this); + if (definition_expr->is_marked_for_strip()) + rust_error_at(definition_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::BlockExpr& expr) override { - - } - void visit(AST::ClosureExprInnerTyped& expr) override {} - void visit(AST::ContinueExpr& expr) override {} - void visit(AST::BreakExpr& expr) override {} - void visit(AST::RangeFromToExpr& expr) override {} - void visit(AST::RangeFromExpr& expr) override {} - void visit(AST::RangeToExpr& expr) override {} - void visit(AST::RangeFullExpr& expr) override {} - void visit(AST::RangeFromToInclExpr& expr) override {} - void visit(AST::RangeToInclExpr& 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 test based on inner attrs - spec says there are inner + * attributes, not just outer attributes of inner stmts */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + // strip all statements + auto& stmts = expr.get_statements(); + for (int i = 0; i < stmts.size();) { + auto& stmt = stmts[i]; + + // mark for stripping if required + stmt->accept_vis(*this); + + if (stmt->is_marked_for_strip()) + stmts.erase(stmts.begin() + i); + else + i++; + } + + // strip tail expression if exists - can actually fully remove it + if (expr.has_tail_expr()) { + auto& tail_expr = expr.get_tail_expr(); + + tail_expr->accept_vis(*this); + + if (tail_expr->is_marked_for_strip()) + expr.strip_tail_expr(); + } + } + void visit(AST::ClosureExprInnerTyped& 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++; + } + + // can't strip expression itself, but can strip sub-expressions + auto& definition_block = expr.get_definition_block(); + definition_block->accept_vis(*this); + if (definition_block->is_marked_for_strip()) + rust_error_at(definition_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::ContinueExpr& 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; + } + } + void visit(AST::BreakExpr& 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; + } + + /* spec does not say that you can have outer attributes on + * expression, so assuming you can't. stripping for sub-expressions + * is the only thing that can be done */ + if (expr.has_break_expr()) { + auto& break_expr = expr.get_break_expr(); + + break_expr->accept_vis(*this); + + if (break_expr->is_marked_for_strip()) + rust_error_at(break_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + } + void visit(AST::RangeFromToExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_from_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_to_expr()->accept_vis(*this); + + // ensure that they are not marked for strip + if (expr.get_from_expr()->is_marked_for_strip()) + rust_error_at(expr.get_from_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before range exprs"); + if (expr.get_to_expr()->is_marked_for_strip()) + rust_error_at(expr.get_to_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + void visit(AST::RangeFromExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * direct descendant expression, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + auto& from_expr = expr.get_from_expr(); + + from_expr->accept_vis(*this); + + if (from_expr->is_marked_for_strip()) + rust_error_at(from_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before range exprs"); + } + void visit(AST::RangeToExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * direct descendant expression, can strip ones below that */ + + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + auto& to_expr = expr.get_to_expr(); + + to_expr->accept_vis(*this); + + if (to_expr->is_marked_for_strip()) + rust_error_at(to_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + void visit(AST::RangeFullExpr& expr) override { + // outer attributes never allowed before these, so no stripping + } + void visit(AST::RangeFromToInclExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_from_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_to_expr()->accept_vis(*this); + + // ensure that they are not marked for strip + if (expr.get_from_expr()->is_marked_for_strip()) + rust_error_at(expr.get_from_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before range exprs"); + if (expr.get_to_expr()->is_marked_for_strip()) + rust_error_at(expr.get_to_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + void visit(AST::RangeToInclExpr& expr) override { + /* outer attributes never allowed before these. while cannot strip + * direct descendant expression, can strip ones below that */ + + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + auto& to_expr = expr.get_to_expr(); + + to_expr->accept_vis(*this); + + if (to_expr->is_marked_for_strip()) + rust_error_at(to_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } void visit(AST::ReturnExpr& expr) override {} void visit(AST::UnsafeBlockExpr& expr) override {} void visit(AST::LoopExpr& expr) override {} -- cgit v1.1 From 9b252167a77316750f34c455222e5f30724e51e4 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Tue, 17 Nov 2020 22:00:30 +0800 Subject: Added more expression cfg stripping Fixed compile errors --- gcc/rust/ast/rust-ast-full-test.cc | 12 +- gcc/rust/ast/rust-expr.h | 164 ++++++++++- gcc/rust/backend/rust-compile.cc | 22 +- gcc/rust/expand/rust-macro-expand.cc | 532 ++++++++++++++++++++++++++++++++--- 4 files changed, 660 insertions(+), 70 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index f9dd99c..5601a1a 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -1700,10 +1700,8 @@ ReturnExpr::as_string () const { std::string str ("return "); - if (has_return_expr ()) - { + if (has_returned_expr ()) str += return_expr->as_string (); - } return str; } @@ -2255,13 +2253,9 @@ WhileLetLoopExpr::as_string () const str += "\n Label: "; if (!has_loop_label ()) - { str += "none"; - } else - { str += loop_label.as_string (); - } str += "\n Match arm patterns: "; if (match_arm_patterns.empty ()) @@ -2271,12 +2265,10 @@ WhileLetLoopExpr::as_string () const else { for (const auto &pattern : match_arm_patterns) - { str += "\n " + pattern->as_string (); - } } - str += "\n Scrutinee expr: " + condition->as_string (); + str += "\n Scrutinee expr: " + scrutinee->as_string (); str += "\n Loop block: " + loop_block->as_string (); diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 66ffe16..df77611 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -3281,7 +3281,6 @@ protected: // Return expression AST node representation class ReturnExpr : public ExprWithoutBlock { -public: std::unique_ptr return_expr; Location locus; @@ -3289,11 +3288,12 @@ public: // TODO: find another way to store this to save memory? bool marked_for_strip = false; +public: std::string as_string () const override; /* Returns whether the object has an expression returned (i.e. not void return * type). */ - bool has_return_expr () const { return return_expr != nullptr; } + bool has_returned_expr () const { return return_expr != nullptr; } // Constructor for ReturnExpr. ReturnExpr (Location locus, std::unique_ptr returned_expr = nullptr, @@ -3341,6 +3341,12 @@ public: void mark_for_strip () override { marked_for_strip = true; } bool is_marked_for_strip () const override { return marked_for_strip; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_returned_expr () { + rust_assert (return_expr != nullptr); + return return_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3358,7 +3364,6 @@ class UnsafeBlockExpr : public ExprWithBlock { // Or just have it extend BlockExpr std::unique_ptr expr; - Location locus; public: @@ -3408,6 +3413,12 @@ public: void mark_for_strip () override { expr = nullptr; } bool is_marked_for_strip () const override { return expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_block_expr () { + rust_assert (expr != nullptr); + return expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3422,7 +3433,6 @@ protected: class LoopLabel /*: public Node*/ { Lifetime label; // or type LIFETIME_OR_LABEL - Location locus; public: @@ -3504,6 +3514,12 @@ public: // Invalid if loop block is null, so base stripping on that. void mark_for_strip () override { loop_block = nullptr; } bool is_marked_for_strip () const override { return loop_block == nullptr; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_loop_block () { + rust_assert (loop_block != nullptr); + return loop_block; + } }; // 'Loop' expression (i.e. the infinite loop) AST node @@ -3573,6 +3589,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_predicate_expr () { + rust_assert (condition != nullptr); + return condition; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3587,14 +3609,14 @@ class WhileLetLoopExpr : public BaseLoopExpr { // MatchArmPatterns patterns; std::vector > match_arm_patterns; // inlined - std::unique_ptr condition; + std::unique_ptr scrutinee; public: std::string as_string () const override; // Constructor with a loop label WhileLetLoopExpr (std::vector > match_arm_patterns, - std::unique_ptr condition, + std::unique_ptr scrutinee, std::unique_ptr loop_block, Location locus, LoopLabel loop_label = LoopLabel::error (), std::vector outer_attribs @@ -3602,14 +3624,14 @@ public: : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label), std::move (outer_attribs)), match_arm_patterns (std::move (match_arm_patterns)), - condition (std::move (condition)) + scrutinee (std::move (scrutinee)) {} // Copy constructor with clone WhileLetLoopExpr (WhileLetLoopExpr const &other) : BaseLoopExpr (other), - /*match_arm_patterns(other.match_arm_patterns),*/ condition ( - other.condition->clone_expr ()) + /*match_arm_patterns(other.match_arm_patterns),*/ scrutinee ( + other.scrutinee->clone_expr ()) { match_arm_patterns.reserve (other.match_arm_patterns.size ()); for (const auto &e : other.match_arm_patterns) @@ -3621,7 +3643,7 @@ public: { BaseLoopExpr::operator= (other); // match_arm_patterns = other.match_arm_patterns; - condition = other.condition->clone_expr (); + scrutinee = other.scrutinee->clone_expr (); // loop_block = other.loop_block->clone_block_expr(); // loop_label = other.loop_label; // outer_attrs = other.outer_attrs; @@ -3639,6 +3661,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_scrutinee_expr () { + rust_assert (scrutinee != nullptr); + return scrutinee; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3694,6 +3722,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_iterator_expr () { + rust_assert (iterator_expr != nullptr); + return iterator_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3777,8 +3811,17 @@ public: void vis_if_condition (ASTVisitor &vis) { condition->accept_vis (vis); } void vis_if_block (ASTVisitor &vis) { if_block->accept_vis (vis); } - Expr *get_if_condition () { return condition.get (); } - BlockExpr *get_if_block () { return if_block.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_condition_expr () { + rust_assert (condition != nullptr); + return condition; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_if_block () { + rust_assert (if_block != nullptr); + return if_block; + } // Invalid if if block or condition is null, so base stripping on that. void mark_for_strip () override { if_block = nullptr; condition = nullptr; } @@ -3836,6 +3879,12 @@ public: void vis_else_block (ASTVisitor &vis) { else_block->accept_vis (vis); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_else_block () { + rust_assert (else_block != nullptr); + return else_block; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3888,6 +3937,12 @@ public: conseq_if_expr->accept_vis (vis); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_conseq_if_expr () { + rust_assert (conseq_if_expr != nullptr); + return conseq_if_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3976,6 +4031,18 @@ public: void mark_for_strip () override { if_block = nullptr; value = nullptr; } bool is_marked_for_strip () const override { return if_block == nullptr && value == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_value_expr () { + rust_assert (value != nullptr); + return value; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_if_block () { + rust_assert (if_block != nullptr); + return if_block; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base (or rather this or any derived object) */ @@ -4030,6 +4097,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_conseq_if_let_expr () { + rust_assert (if_let_expr != nullptr); + return if_let_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4082,6 +4155,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_else_block () { + rust_assert (else_block != nullptr); + return else_block; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4133,6 +4212,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_conseq_if_expr () { + rust_assert (if_expr != nullptr); + return if_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4184,6 +4269,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_conseq_if_let_expr () { + rust_assert (if_let_expr != nullptr); + return if_let_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4265,6 +4356,16 @@ public: } std::string as_string () const; + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_guard_expr () { + rust_assert (has_match_arm_guard ()); + return guard_expr; + } + + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector &get_outer_attrs () const { return outer_attrs; } + std::vector &get_outer_attrs () { return outer_attrs; } }; /* @@ -4330,6 +4431,18 @@ public: ~MatchCase () = default; std::string as_string () const; + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_expr () { + rust_assert (expr != nullptr); + return expr; + } + + // TODO: is this better? Or is a "vis_block" better? + MatchArm &get_arm () { + rust_assert (!arm.is_error ()); + return arm; + } }; #if 0 @@ -4502,6 +4615,19 @@ public: void mark_for_strip () override { branch_value = nullptr; } bool is_marked_for_strip () const override { return branch_value == nullptr; } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_scrutinee_expr () { + rust_assert (branch_value != nullptr); + return branch_value; + } + + const std::vector &get_match_cases () const { return match_arms; } + std::vector &get_match_cases () { return match_arms; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4515,7 +4641,6 @@ protected: class AwaitExpr : public ExprWithoutBlock { std::unique_ptr awaited_expr; - Location locus; public: @@ -4565,6 +4690,12 @@ public: void mark_for_strip () override { awaited_expr = nullptr; } bool is_marked_for_strip () const override { return awaited_expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_awaited_expr () { + rust_assert (awaited_expr != nullptr); + return awaited_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4580,7 +4711,6 @@ class AsyncBlockExpr : public ExprWithBlock // TODO: should this extend BlockExpr rather than be a composite of it? bool has_move; std::unique_ptr block_expr; - Location locus; public: @@ -4630,6 +4760,12 @@ public: void mark_for_strip () override { block_expr = nullptr; } bool is_marked_for_strip () const override { return block_expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_block_expr () { + rust_assert (block_expr != nullptr); + return block_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 17d9cde..eb01b12 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -740,10 +740,10 @@ void Compilation::visit (AST::ReturnExpr &expr) { Bexpression *ret = NULL; - VISIT_POP (expr.return_expr->get_locus_slow (), expr.return_expr, ret, exprs); + VISIT_POP (expr.get_returned_expr ()->get_locus_slow (), expr.get_returned_expr ().get (), ret, exprs); if (ret == NULL) { - rust_fatal_error (expr.return_expr->get_locus_slow (), + rust_fatal_error (expr.get_returned_expr ()->get_locus_slow (), "failed to compile"); return; } @@ -778,11 +778,11 @@ void Compilation::visit (AST::IfExpr &expr) { Bexpression *cond = NULL; - VISIT_POP (expr.get_if_condition ()->get_locus_slow (), - expr.get_if_condition (), cond, exprs); + VISIT_POP (expr.get_condition_expr ()->get_locus_slow (), + expr.get_condition_expr ().get (), cond, exprs); if (cond == NULL) { - rust_error_at (expr.get_if_condition ()->get_locus_slow (), + rust_error_at (expr.get_condition_expr ()->get_locus_slow (), "failed to compile"); return; } @@ -799,11 +799,11 @@ void Compilation::visit (AST::IfExprConseqElse &expr) { Bexpression *cond = NULL; - VISIT_POP (expr.get_if_condition ()->get_locus_slow (), - expr.get_if_condition (), cond, exprs); + VISIT_POP (expr.get_condition_expr ()->get_locus_slow (), + expr.get_condition_expr ().get (), cond, exprs); if (cond == NULL) { - rust_error_at (expr.get_if_condition ()->get_locus_slow (), + rust_error_at (expr.get_condition_expr ()->get_locus_slow (), "failed to compile"); return; } @@ -824,11 +824,11 @@ void Compilation::visit (AST::IfExprConseqIf &expr) { Bexpression *cond = NULL; - VISIT_POP (expr.get_if_condition ()->get_locus_slow (), - expr.get_if_condition (), cond, exprs); + VISIT_POP (expr.get_condition_expr ()->get_locus_slow (), + expr.get_condition_expr ().get (), cond, exprs); if (cond == NULL) { - rust_error_at (expr.get_if_condition ()->get_locus_slow (), + rust_error_at (expr.get_condition_expr ()->get_locus_slow (), "failed to compile"); return; } diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 417f51b..7dd9750 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -956,23 +956,436 @@ namespace Rust { rust_error_at(to_expr->get_locus_slow(), "cannot strip expression in this position - outer attributes not allowed"); } - void visit(AST::ReturnExpr& expr) override {} - void visit(AST::UnsafeBlockExpr& expr) override {} - void visit(AST::LoopExpr& expr) override {} - void visit(AST::WhileLoopExpr& expr) override {} - void visit(AST::WhileLetLoopExpr& expr) override {} - void visit(AST::ForLoopExpr& expr) override {} - void visit(AST::IfExpr& expr) override {} - void visit(AST::IfExprConseqElse& expr) override {} - void visit(AST::IfExprConseqIf& expr) override {} - void visit(AST::IfExprConseqIfLet& expr) override {} - void visit(AST::IfLetExpr& expr) override {} - void visit(AST::IfLetExprConseqElse& expr) override {} - void visit(AST::IfLetExprConseqIf& expr) override {} - void visit(AST::IfLetExprConseqIfLet& expr) override {} - void visit(AST::MatchExpr& expr) override {} - void visit(AST::AwaitExpr& expr) override {} - void visit(AST::AsyncBlockExpr& expr) override {} + void visit(AST::ReturnExpr& 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; + } + + /* spec does not say that you can have outer attributes on + * expression, so assuming you can't. stripping for sub-expressions + * is the only thing that can be done */ + if (expr.has_returned_expr()) { + auto& returned_expr = expr.get_returned_expr(); + + returned_expr->accept_vis(*this); + + if (returned_expr->is_marked_for_strip()) + rust_error_at(returned_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + /* TODO: conceptually, you would maybe be able to remove a returned + * expr - e.g. if you had conditional compilation returning void or + * returning a type. On the other hand, I think that function + * return type cannot be conditionally compiled, so I assumed you + * can't do this either. */ + } + void visit(AST::UnsafeBlockExpr& 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; + } + + // can't strip block itself, but can strip sub-expressions + auto& block_expr = expr.get_block_expr(); + block_expr->accept_vis(*this); + if (block_expr->is_marked_for_strip()) + rust_error_at(block_expr->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::LoopExpr& 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; + } + + // can't strip block itself, but can strip sub-expressions + auto& loop_block = expr.get_loop_block(); + loop_block->accept_vis(*this); + if (loop_block->is_marked_for_strip()) + rust_error_at(loop_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::WhileLoopExpr& 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; + } + + // can't strip predicate expr itself, but can strip sub-expressions + auto& predicate_expr = expr.get_predicate_expr(); + predicate_expr->accept_vis(*this); + if (predicate_expr->is_marked_for_strip()) + rust_error_at(predicate_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip block itself, but can strip sub-expressions + auto& loop_block = expr.get_loop_block(); + loop_block->accept_vis(*this); + if (loop_block->is_marked_for_strip()) + rust_error_at(loop_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::WhileLetLoopExpr& 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; + } + + // can't strip scrutinee expr itself, but can strip sub-expressions + auto& scrutinee_expr = expr.get_scrutinee_expr(); + scrutinee_expr->accept_vis(*this); + if (scrutinee_expr->is_marked_for_strip()) + rust_error_at(scrutinee_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip block itself, but can strip sub-expressions + auto& loop_block = expr.get_loop_block(); + loop_block->accept_vis(*this); + if (loop_block->is_marked_for_strip()) + rust_error_at(loop_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::ForLoopExpr& 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; + } + + // can't strip scrutinee expr itself, but can strip sub-expressions + auto& iterator_expr = expr.get_iterator_expr(); + iterator_expr->accept_vis(*this); + if (iterator_expr->is_marked_for_strip()) + rust_error_at(iterator_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip block itself, but can strip sub-expressions + auto& loop_block = expr.get_loop_block(); + loop_block->accept_vis(*this); + if (loop_block->is_marked_for_strip()) + rust_error_at(loop_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::IfExpr& 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; + } + + // can't strip condition expr itself, but can strip sub-expressions + auto& condition_expr = expr.get_condition_expr(); + condition_expr->accept_vis(*this); + if (condition_expr->is_marked_for_strip()) + rust_error_at(condition_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto& if_block = expr.get_if_block(); + if_block->accept_vis(*this); + if (if_block->is_marked_for_strip()) + rust_error_at(if_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::IfExprConseqElse& 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; + } + + // can't strip condition expr itself, but can strip sub-expressions + auto& condition_expr = expr.get_condition_expr(); + condition_expr->accept_vis(*this); + if (condition_expr->is_marked_for_strip()) + rust_error_at(condition_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto& if_block = expr.get_if_block(); + if_block->accept_vis(*this); + if (if_block->is_marked_for_strip()) + rust_error_at(if_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + + // can't strip else block itself, but can strip sub-expressions + auto& else_block = expr.get_else_block(); + else_block->accept_vis(*this); + if (else_block->is_marked_for_strip()) + rust_error_at(else_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::IfExprConseqIf& 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; + } + + // can't strip condition expr itself, but can strip sub-expressions + auto& condition_expr = expr.get_condition_expr(); + condition_expr->accept_vis(*this); + if (condition_expr->is_marked_for_strip()) + rust_error_at(condition_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto& if_block = expr.get_if_block(); + if_block->accept_vis(*this); + if (if_block->is_marked_for_strip()) + rust_error_at(if_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + + // can't strip if expr itself, but can strip sub-expressions + auto& conseq_if_expr = expr.get_conseq_if_expr(); + conseq_if_expr->accept_vis(*this); + if (conseq_if_expr->is_marked_for_strip()) + rust_error_at(conseq_if_expr->get_locus_slow(), + "cannot strip consequent if expression in this position - outer attributes not allowed"); + } + void visit(AST::IfExprConseqIfLet& 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; + } + + // can't strip condition expr itself, but can strip sub-expressions + auto& condition_expr = expr.get_condition_expr(); + condition_expr->accept_vis(*this); + if (condition_expr->is_marked_for_strip()) + rust_error_at(condition_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto& if_block = expr.get_if_block(); + if_block->accept_vis(*this); + if (if_block->is_marked_for_strip()) + rust_error_at(if_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + + // can't strip if let expr itself, but can strip sub-expressions + auto& conseq_if_let_expr = expr.get_conseq_if_let_expr(); + conseq_if_let_expr->accept_vis(*this); + if (conseq_if_let_expr->is_marked_for_strip()) + rust_error_at(conseq_if_let_expr->get_locus_slow(), + "cannot strip consequent if let expression in this position - outer attributes not allowed"); + } + void visit(AST::IfLetExpr& 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; + } + + // can't strip value expr itself, but can strip sub-expressions + auto& value_expr = expr.get_value_expr(); + value_expr->accept_vis(*this); + if (value_expr->is_marked_for_strip()) + rust_error_at(value_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto& if_block = expr.get_if_block(); + if_block->accept_vis(*this); + if (if_block->is_marked_for_strip()) + rust_error_at(if_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::IfLetExprConseqElse& 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; + } + + // can't strip value expr itself, but can strip sub-expressions + auto& value_expr = expr.get_value_expr(); + value_expr->accept_vis(*this); + if (value_expr->is_marked_for_strip()) + rust_error_at(value_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto& if_block = expr.get_if_block(); + if_block->accept_vis(*this); + if (if_block->is_marked_for_strip()) + rust_error_at(if_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + + // can't strip else block itself, but can strip sub-expressions + auto& else_block = expr.get_else_block(); + else_block->accept_vis(*this); + if (else_block->is_marked_for_strip()) + rust_error_at(else_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::IfLetExprConseqIf& 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; + } + + // can't strip value expr itself, but can strip sub-expressions + auto& value_expr = expr.get_value_expr(); + value_expr->accept_vis(*this); + if (value_expr->is_marked_for_strip()) + rust_error_at(value_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto& if_block = expr.get_if_block(); + if_block->accept_vis(*this); + if (if_block->is_marked_for_strip()) + rust_error_at(if_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + + // can't strip if expr itself, but can strip sub-expressions + auto& conseq_if_expr = expr.get_conseq_if_expr(); + conseq_if_expr->accept_vis(*this); + if (conseq_if_expr->is_marked_for_strip()) + rust_error_at(conseq_if_expr->get_locus_slow(), + "cannot strip consequent if expression in this position - outer attributes not allowed"); + } + void visit(AST::IfLetExprConseqIfLet& 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; + } + + // can't strip value expr itself, but can strip sub-expressions + auto& value_expr = expr.get_value_expr(); + value_expr->accept_vis(*this); + if (value_expr->is_marked_for_strip()) + rust_error_at(value_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto& if_block = expr.get_if_block(); + if_block->accept_vis(*this); + if (if_block->is_marked_for_strip()) + rust_error_at(if_block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + + // can't strip if let expr itself, but can strip sub-expressions + auto& conseq_if_let_expr = expr.get_conseq_if_let_expr(); + conseq_if_let_expr->accept_vis(*this); + if (conseq_if_let_expr->is_marked_for_strip()) + rust_error_at(conseq_if_let_expr->get_locus_slow(), + "cannot strip consequent if let expression in this position - outer attributes not allowed"); + } + void visit(AST::MatchExpr& 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; + } + + // inner attr strip test + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + // can't strip scrutinee expr itself, but can strip sub-expressions + auto& scrutinee_expr = expr.get_scrutinee_expr(); + scrutinee_expr->accept_vis(*this); + if (scrutinee_expr->is_marked_for_strip()) + rust_error_at(scrutinee_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // strip match cases + auto& match_cases = expr.get_match_cases(); + for (int i = 0; i < match_cases.size(); ) { + auto& match_case = match_cases[i]; + + // strip match case based on outer attributes in match arm + auto& match_arm = match_case.get_arm(); + expander.expand_cfg_attrs(match_arm.get_outer_attrs()); + if (expander.fails_cfg(match_arm.get_outer_attrs())) { + // strip match case + match_cases.erase(match_cases.begin() + i); + continue; + } + + /* assuming that guard expression cannot be stripped as + * strictly speaking you would have to strip the whole guard to + * make syntactical sense, which you can't do. as such, only + * strip sub-expressions */ + if (match_arm.has_match_arm_guard()) { + auto& guard_expr = match_arm.get_guard_expr(); + guard_expr->accept_vis(*this); + if (guard_expr->is_marked_for_strip()) + rust_error_at(guard_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + + // strip sub-expressions from match cases + auto& case_expr = match_case.get_expr(); + case_expr->accept_vis(*this); + if (case_expr->is_marked_for_strip()) + rust_error_at(case_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + // increment to next case if haven't continued + i++; + } + } + void visit(AST::AwaitExpr& 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; + } + + /* can't strip awaited expr itself, but can strip sub-expressions + * - this is because you can't have no expr to await */ + auto& awaited_expr = expr.get_awaited_expr(); + awaited_expr->accept_vis(*this); + if (awaited_expr->is_marked_for_strip()) + rust_error_at(awaited_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + void visit(AST::AsyncBlockExpr& 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; + } + + // can't strip block itself, but can strip sub-expressions + auto& block_expr = expr.get_block_expr(); + block_expr->accept_vis(*this); + if (block_expr->is_marked_for_strip()) + rust_error_at(block_expr->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } void visit(AST::TypeParam& param) override { // shouldn't require? @@ -1001,8 +1414,12 @@ namespace Rust { /* body should always exist - if error state, should have returned * before now */ - method.get_definition()->accept_vis(*this); - // TODO: can block as a whole be invalidated here? Assuming no + // can't strip block itself, but can strip sub-expressions + auto& block_expr = method.get_definition(); + block_expr->accept_vis(*this); + if (block_expr->is_marked_for_strip()) + rust_error_at(block_expr->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); } void visit(AST::ModuleBodied& module) override { // strip test based on outer attrs @@ -1080,8 +1497,12 @@ namespace Rust { /* body should always exist - if error state, should have returned * before now */ - function.get_definition()->accept_vis(*this); - // TODO: can block as a whole be invalidated here? Assuming no + // can't strip block itself, but can strip sub-expressions + auto& block_expr = function.get_definition(); + block_expr->accept_vis(*this); + if (block_expr->is_marked_for_strip()) + rust_error_at(block_expr->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); } void visit(AST::TypeAlias& type_alias) override { // initial test based on outer attrs @@ -1158,7 +1579,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - item.get_expr()->accept_vis(*this); + auto& expr = item.get_expr(); + expr->accept_vis(*this); + if (expr->is_marked_for_strip()) + rust_error_at(expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::Enum& enum_item) override { // initial test based on outer attrs @@ -1206,7 +1631,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - const_item.get_expr()->accept_vis(*this); + auto& expr = const_item.get_expr(); + expr->accept_vis(*this); + if (expr->is_marked_for_strip()) + rust_error_at(expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::StaticItem& static_item) override { // initial test based on outer attrs @@ -1219,7 +1648,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - static_item.get_expr()->accept_vis(*this); + auto& expr = static_item.get_expr(); + expr->accept_vis(*this); + if (expr->is_marked_for_strip()) + rust_error_at(expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::TraitItemFunc& item) override { // initial test based on outer attrs @@ -1234,8 +1667,14 @@ namespace Rust { expand_function_params(item.get_function_params()); if (item.has_definition()) { - item.get_definition()->accept_vis(*this); - // TODO: can block as a whole be invalidated here? Assuming no + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto& block = item.get_definition(); + block->accept_vis(*this); + if (block->is_marked_for_strip()) + rust_error_at(block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); } } void visit(AST::TraitItemMethod& item) override { @@ -1255,8 +1694,14 @@ namespace Rust { expand_function_params(item.get_function_params()); if (item.has_definition()) { - item.get_definition()->accept_vis(*this); - // TODO: can block as a whole be invalidated here? Assuming no + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto& block = item.get_definition(); + block->accept_vis(*this); + if (block->is_marked_for_strip()) + rust_error_at(block->get_locus_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); } } void visit(AST::TraitItemConst& item) override { @@ -1270,8 +1715,13 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped */ - if (item.has_expression()) - item.get_expr()->accept_vis(*this); + if (item.has_expression()) { + auto& expr = item.get_expr(); + expr->accept_vis(*this); + if (expr->is_marked_for_strip()) + rust_error_at(expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } } void visit(AST::TraitItemType& item) override { // initial test based on outer attrs @@ -1474,7 +1924,9 @@ namespace Rust { void visit(AST::StructPatternFieldTuplePat& field) override {} void visit(AST::StructPatternFieldIdentPat& field) override {} void visit(AST::StructPatternFieldIdent& field) override {} - void visit(AST::StructPattern& pattern) override {} + void visit(AST::StructPattern& pattern) override { + // TODO: apparently struct pattern fields can have outer attrs. so can they be stripped? + } void visit(AST::TupleStructItemsNoRange& tuple_items) override {} void visit(AST::TupleStructItemsRange& tuple_items) override {} void visit(AST::TupleStructPattern& pattern) override {} @@ -1498,8 +1950,13 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped */ - if (stmt.has_init_expr()) - stmt.get_init_expr()->accept_vis(*this); + if (stmt.has_init_expr()) { + auto& init_expr = stmt.get_init_expr(); + init_expr->accept_vis(*this); + if (init_expr->is_marked_for_strip()) + rust_error_at(init_expr->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } } void visit(AST::ExprStmtWithoutBlock& stmt) override { // outer attributes associated with expr, so rely on expr @@ -1543,10 +2000,15 @@ namespace Rust { void visit(AST::NeverType& type) override {} void visit(AST::RawPointerType& type) override {} void visit(AST::ReferenceType& type) override {} - void visit(AST::ArrayType& type) override {} + void visit(AST::ArrayType& type) override { + // TODO: array type contains a "constant expression" - could this have strippable sub-exprs? + } void visit(AST::SliceType& type) override {} void visit(AST::InferredType& type) override {} - void visit(AST::BareFunctionType& type) override {} + void visit(AST::BareFunctionType& type) override { + // TODO: bare function type contains "maybe-named params" that have outer attributes - could this be strippable? + // apparently "attribute rules are same as on regular function params", so looks like a yes + } }; void MacroExpander::expand_invoc(std::unique_ptr& invoc) { -- cgit v1.1 From db39766514144dbbad34d9db3977c3a72d1216c3 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sun, 29 Nov 2020 22:47:31 +0800 Subject: Added new pattern stripping Fixed get_locus_slow call in StructPatternField compile error Added and improved cfg stripping Fixed compilation errors --- gcc/rust/analysis/rust-type-resolution.cc | 22 +- gcc/rust/ast/rust-ast-full-test.cc | 86 +--- gcc/rust/ast/rust-ast.h | 16 +- gcc/rust/ast/rust-expr.h | 50 +- gcc/rust/ast/rust-item.h | 272 ++++++++++- gcc/rust/ast/rust-path.h | 86 +++- gcc/rust/ast/rust-pattern.h | 194 +++++++- gcc/rust/ast/rust-stmt.h | 7 +- gcc/rust/ast/rust-type.h | 21 +- gcc/rust/backend/rust-compile.cc | 24 +- gcc/rust/expand/rust-macro-expand.cc | 786 +++++++++++++++++++++++++++--- gcc/rust/parse/rust-parse-impl.h | 82 ++-- gcc/rust/parse/rust-parse.h | 1 + 13 files changed, 1377 insertions(+), 270 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 5aa2905..439543e 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -594,7 +594,7 @@ TypeResolution::visit (AST::CallExpr &expr) AST::Type *argument = typeBuffer.back (); typeBuffer.pop_back (); - if (!typesAreCompatible (it->type.get (), argument, + if (!typesAreCompatible (it->get_type ().get (), argument, expr.get_params ()[offs]->get_locus_slow ())) return; offs--; @@ -768,11 +768,11 @@ TypeResolution::visit (AST::Function &function) for (auto ¶m : function.get_function_params ()) { - if (!isTypeInScope (param.type.get (), param.get_locus ())) + if (!isTypeInScope (param.get_type ().get (), param.get_locus ())) return; auto before = letPatternBuffer.size (); - param.param_name->accept_vis (*this); + param.get_pattern ()->accept_vis (*this); if (letPatternBuffer.size () <= before) { rust_error_at (param.get_locus (), "failed to analyse parameter name"); @@ -781,11 +781,11 @@ TypeResolution::visit (AST::Function &function) auto paramName = letPatternBuffer.back (); letPatternBuffer.pop_back (); - scope.InsertType (paramName.variable_ident, param.type.get ()); + scope.InsertType (paramName.get_ident (), param.get_type ().get ()); } // ensure the return type is resolved - if (function.has_function_return_type ()) + if (function.has_return_type ()) { if (!isTypeInScope (function.get_return_type ().get (), function.get_locus ())) return; @@ -1015,12 +1015,12 @@ TypeResolution::visit (AST::LetStmt &stmt) if (stmt.has_init_expr ()) { auto before = typeBuffer.size (); - stmt.init_expr->accept_vis (*this); + stmt.get_init_expr ()->accept_vis (*this); if (typeBuffer.size () <= before) { rust_error_at ( - stmt.init_expr->get_locus_slow (), + stmt.get_init_expr ()->get_locus_slow (), "unable to determine type for declaration from init expr"); return; } @@ -1030,7 +1030,7 @@ TypeResolution::visit (AST::LetStmt &stmt) if (inferedType == NULL) { - rust_error_at (stmt.init_expr->get_locus_slow (), + rust_error_at (stmt.get_init_expr ()->get_locus_slow (), "void type found for statement initialisation"); return; } @@ -1039,7 +1039,7 @@ TypeResolution::visit (AST::LetStmt &stmt) if (stmt.has_type () && stmt.has_init_expr ()) { if (!typesAreCompatible (stmt.type.get (), inferedType, - stmt.init_expr->get_locus_slow ())) + stmt.get_init_expr ()->get_locus_slow ())) { return; } @@ -1059,9 +1059,9 @@ TypeResolution::visit (AST::LetStmt &stmt) } // get all the names part of this declaration and add the types to the scope - stmt.variables_pattern->accept_vis (*this); + stmt.get_pattern ()->accept_vis (*this); for (auto &pattern : letPatternBuffer) - scope.InsertType (pattern.variable_ident, inferedType); + scope.InsertType (pattern.get_ident (), inferedType); letPatternBuffer.clear (); } diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 5601a1a..26a3356 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -1103,7 +1103,7 @@ Function::as_string () const if ("" != qstr) str += qstr + " "; - if (has_function_return_type ()) + if (has_return_type ()) { // DEBUG: null pointer check if (return_type == nullptr) @@ -1168,9 +1168,7 @@ Function::as_string () const } if (has_where_clause ()) - { str += " where " + where_clause.as_string (); - } str += "\n"; @@ -1201,9 +1199,7 @@ WhereClause::as_string () const else { for (const auto &item : where_clause_items) - { str += "\n " + item->as_string (); - } } return str; @@ -1228,9 +1224,7 @@ BlockExpr::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 (); - } } // statements @@ -1260,13 +1254,9 @@ BlockExpr::as_string () const // final expression str += "\n" + indent_spaces (stay) + "final expression: "; if (expr == nullptr) - { str += "none"; - } else - { str += "\n" + expr->as_string (); - } str += "\n" + indent_spaces (out) + "}"; return str; @@ -1278,9 +1268,7 @@ TraitImpl::as_string () const std::string str = VisItem::as_string (); if (has_unsafe) - { str += "unsafe "; - } str += "impl "; @@ -1293,20 +1281,14 @@ TraitImpl::as_string () const else { for (const auto ¶m : generic_params) - { str += "\n " + param->as_string (); - } } str += "\n Has exclam: "; if (has_exclam) - { str += "true"; - } else - { str += "false"; - } str += "\n TypePath (to trait): " + trait_path.as_string (); @@ -1314,13 +1296,9 @@ TraitImpl::as_string () const str += "\n Where clause: "; if (!has_where_clause ()) - { str += "none"; - } else - { str += where_clause.as_string (); - } // inner attributes str += "\n inner attributes: "; @@ -1333,9 +1311,7 @@ TraitImpl::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 (); - } } str += "\n trait impl items: "; @@ -1346,9 +1322,7 @@ TraitImpl::as_string () const else { for (const auto &item : impl_items) - { str += "\n " + item->as_string (); - } } return str; @@ -1464,9 +1438,7 @@ ExternBlock::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 (); - } } str += "\n external items: "; @@ -1477,9 +1449,7 @@ ExternBlock::as_string () const else { for (const auto &item : extern_items) - { str += "\n " + item->as_string (); - } } return str; @@ -1558,9 +1528,7 @@ PathInExpression::as_string () const std::string str; if (has_opening_scope_resolution) - { str = "::"; - } return str + PathPattern::as_string (); } @@ -1591,9 +1559,7 @@ ClosureParam::as_string () const std::string str (pattern->as_string ()); if (has_type_given ()) - { str += " : " + type->as_string (); - } return str; } @@ -1603,13 +1569,9 @@ ClosureExpr::as_string () const { std::string str ("ClosureExpr:\n Has move: "); if (has_move) - { str += "true"; - } else - { str += "false"; - } str += "\n Params: "; if (params.empty ()) @@ -1619,9 +1581,7 @@ ClosureExpr::as_string () const else { for (const auto ¶m : params) - { str += "\n " + param.as_string (); - } } return str; @@ -1645,9 +1605,7 @@ PathPattern::as_string () const std::string str; for (const auto &segment : segments) - { str += segment.as_string () + "::"; - } // basically a hack - remove last two characters of string (remove final ::) str.erase (str.length () - 2); @@ -1662,9 +1620,7 @@ QualifiedPathType::as_string () const str += type_to_invoke_on->as_string (); if (has_as_clause ()) - { str += " as " + trait_path.as_string (); - } return str + ">"; } @@ -1681,14 +1637,10 @@ BorrowExpr::as_string () const std::string str ("&"); if (double_borrow) - { str += "&"; - } if (is_mut) - { str += "mut "; - } str += main_or_left_expr->as_string (); @@ -1722,9 +1674,7 @@ GroupedExpr::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 (); - } } str += "\n Expr in parens: " + expr_in_parens->as_string (); @@ -1744,9 +1694,7 @@ ContinueExpr::as_string () const std::string str ("continue "); if (has_label ()) - { str += label.as_string (); - } return str; } @@ -1881,9 +1829,7 @@ MethodCallExpr::as_string () const for (const auto ¶m : params) { if (param == nullptr) - { return "ERROR_MARK_STRING - method call expr param is null"; - } str += "\n " + param->as_string (); } @@ -2022,9 +1968,7 @@ IfLetExpr::as_string () const else { for (const auto &pattern : match_arm_patterns) - { str += "\n " + pattern->as_string (); - } } str += "\n Scrutinee expr: " + value->as_string (); @@ -2213,9 +2157,7 @@ CallExpr::as_string () const for (const auto ¶m : params) { if (param == nullptr) - { return "ERROR_MARK_STRING - call expr param is null"; - } str += "\n " + param->as_string (); } @@ -2231,13 +2173,9 @@ WhileLoopExpr::as_string () const str += "\n Label: "; if (!has_loop_label ()) - { str += "none"; - } else - { str += loop_label.as_string (); - } str += "\n Conditional expr: " + condition->as_string (); @@ -2282,13 +2220,9 @@ LoopExpr::as_string () const str += "\n Label: "; if (!has_loop_label ()) - { str += "none"; - } else - { str += loop_label.as_string (); - } str += "\n Loop block: " + loop_block->as_string (); @@ -2311,20 +2245,14 @@ ArrayExpr::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 (); - } } str += "\n Array elems: "; if (!has_array_elems ()) - { str += "none"; - } else - { str += internal_elements->as_string (); - } return str; } @@ -2341,14 +2269,10 @@ BreakExpr::as_string () const std::string str ("break "); if (has_label ()) - { str += label.as_string () + " "; - } if (has_break_expr ()) - { str += break_expr->as_string (); - } return str; } @@ -2373,9 +2297,7 @@ MatchArm::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 += "\nPatterns: "; @@ -2386,20 +2308,14 @@ MatchArm::as_string () const else { for (const auto &pattern : match_arm_patterns) - { str += "\n " + pattern->as_string (); - } } str += "\nGuard expr: "; if (!has_match_arm_guard ()) - { str += "none"; - } else - { str += guard_expr->as_string (); - } return str; } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index c186f22..b5e56ba 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -968,6 +968,14 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + // as only one kind of pattern can be stripped, have default of nothing + virtual void mark_for_strip () {} + virtual bool is_marked_for_strip () const { return false; } + + /* HACK: slow way of getting location from base expression through virtual + * methods. */ + virtual Location get_locus_slow () const = 0; + protected: // Clone pattern implementation as pure virtual method virtual Pattern *clone_pattern_impl () const = 0; @@ -1002,6 +1010,12 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + // as only two kinds of types can be stripped, have default of nothing + virtual void mark_for_strip () {} + virtual bool is_marked_for_strip () const { return false; } + + virtual Location get_locus_slow () const = 0; + protected: // Clone function implementation as pure virtual method virtual Type *clone_type_impl () const = 0; @@ -1081,7 +1095,7 @@ public: {} // Creates an "error" lifetime. - static Lifetime error () { return Lifetime (NAMED, std::string ("")); } + static Lifetime error () { return Lifetime (NAMED, ""); } // Returns true if the lifetime is in an error state. bool is_error () const diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index df77611..34dfc25 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -669,6 +669,12 @@ public: return main_or_left_expr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type_to_cast_to () { + rust_assert (type_to_convert_to != nullptr); + return type_to_convert_to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1375,6 +1381,7 @@ protected: public: const PathInExpression &get_struct_name () const { return struct_name; } + PathInExpression &get_struct_name () { return struct_name; } std::string as_string () const override; @@ -1828,8 +1835,8 @@ protected: {} public: - // TODO: maybe remove and have string version gotten here directly - PathInExpression get_enum_variant_path () const { return enum_variant_path; } + const PathInExpression& get_enum_variant_path () const { return enum_variant_path; } + PathInExpression& get_enum_variant_path () { return enum_variant_path; } // Invalid if path is in error state, so base stripping on that. void mark_for_strip () override { enum_variant_path = PathInExpression::create_error (); } @@ -2305,7 +2312,8 @@ public: return receiver; } - PathExprSegment get_method_name () const { return method_name; } + const PathExprSegment &get_method_name () const { return method_name; } + PathExprSegment &get_method_name () { return method_name; } protected: /* Use covariance to implement clone function as returning this object rather @@ -2462,6 +2470,18 @@ public: const std::vector &get_outer_attrs () const { return outer_attrs; } std::vector &get_outer_attrs () { return outer_attrs; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_pattern () { + rust_assert (pattern != nullptr); + return pattern; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (has_type_given ()); + return type; + } }; // Base closure definition expression AST node - abstract @@ -2756,6 +2776,12 @@ public: return expr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &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 */ @@ -3667,6 +3693,10 @@ public: return scrutinee; } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector > &get_patterns () const { return match_arm_patterns; } + std::vector > &get_patterns () { return match_arm_patterns; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3728,6 +3758,12 @@ public: return iterator_expr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_pattern () { + rust_assert (pattern != nullptr); + return pattern; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3959,7 +3995,6 @@ class IfLetExpr : public ExprWithBlock std::vector > match_arm_patterns; // inlined std::unique_ptr value; std::unique_ptr if_block; - Location locus; public: @@ -4043,6 +4078,10 @@ public: return if_block; } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector > &get_patterns () const { return match_arm_patterns; } + std::vector > &get_patterns () { return match_arm_patterns; } + protected: /* Use covariance to implement clone function as returning this object rather * than base (or rather this or any derived object) */ @@ -4366,6 +4405,9 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector &get_outer_attrs () const { return outer_attrs; } std::vector &get_outer_attrs () { return outer_attrs; } + + const std::vector > &get_patterns () const { return match_arm_patterns; } + std::vector > &get_patterns () { return match_arm_patterns; } }; /* diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 5891383..c47a6f5 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -123,6 +123,16 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (type != nullptr); + return type; + } + + // TODO: mutable getter seems kinda dodgy + std::vector > &get_type_param_bounds () { return type_param_bounds; } + const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + protected: // Clone function implementation as (not pure) virtual method TypeParam *clone_generic_param_impl () const override @@ -245,6 +255,16 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (bound_type != nullptr); + return bound_type; + } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector > &get_type_param_bounds () { return type_param_bounds; } + const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + protected: // Clone function implementation as (not pure) virtual method TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override @@ -299,6 +319,10 @@ public: bool is_empty () const { return where_clause_items.empty (); } std::string as_string () const; + + // TODO: this mutable getter seems kinda dodgy + std::vector > &get_items () { return where_clause_items; } + const std::vector > &get_items () const { return where_clause_items; } }; // A self parameter in a method @@ -322,6 +346,8 @@ private: {} // this is ok as no outside classes can ever call this + // TODO: self param can have outer attributes + public: // Returns whether the self-param has a type field. bool has_type () const { return type != nullptr; } @@ -332,21 +358,15 @@ public: // Returns whether the self-param is in an error state. bool is_error () const { - return has_type () && has_lifetime (); + return (has_type () && has_lifetime ()) || (has_lifetime () && !has_ref); // not having either is not an error } // Creates an error state self-param. static SelfParam create_error () { - /* HACK: creates a dummy type. Since it's a unique pointer, it should - * clean it up, but it still allocates memory, which is not ideal. */ - return SelfParam (Lifetime (Lifetime::STATIC), false, false, - new QualifiedPathInType ( - QualifiedPathInType::create_error ())); - /* FIXME: is there a reason why I didn't just create a null pointer? Is it - * due to error being having both a type and a lifetime? If it is, wouldn't - * something like "not has_ref and has lifetime" for error be better? */ + // cannot have no ref but have a lifetime at the same time + return SelfParam (Lifetime (Lifetime::STATIC), false, false, nullptr); } // Type-based self parameter (not ref, no lifetime) @@ -373,13 +393,16 @@ public: // Overload assignment operator to use clone SelfParam &operator= (SelfParam const &other) { - if (other.type != nullptr) - type = other.type->clone_type (); is_mut = other.is_mut; has_ref = other.has_ref; lifetime = other.lifetime; locus = other.locus; + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + return *this; } @@ -390,6 +413,12 @@ public: std::string as_string () const; Location get_locus () const { return locus; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (has_type ()); + return type; + } }; // Qualifiers for function, i.e. const, unsafe, extern etc. @@ -437,11 +466,10 @@ struct FunctionParam private: std::vector outer_attrs; Location locus; - -public: std::unique_ptr param_name; std::unique_ptr type; +public: FunctionParam (std::unique_ptr param_name, std::unique_ptr param_type, std::vector outer_attrs, Location locus) : outer_attrs (std::move (outer_attrs)), locus (locus), @@ -496,6 +524,18 @@ public: // TODO: seems kinda dodgy. Think of better way. std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_pattern () { + rust_assert (param_name != nullptr); + return param_name; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (type != nullptr); + return type; + } }; // Visibility of item - if the item has it, then it is some form of public @@ -740,12 +780,30 @@ public: std::vector &get_function_params () { return function_params; } const std::vector &get_function_params () const { return function_params; } + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + // TODO: is this better? Or is a "vis_block" better? std::unique_ptr &get_definition () { rust_assert (function_body != nullptr); return function_body; } + SelfParam &get_self_param () { return self_param; } + const SelfParam &get_self_param () const { return self_param; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_return_type () { + rust_assert (has_return_type ()); + return return_type; + } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () { + rust_assert (has_where_clause ()); + return where_clause; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1299,7 +1357,7 @@ public: bool has_function_params () const { return !function_params.empty (); } // Returns whether function has return type - if not, it is void. - bool has_function_return_type () const { return return_type != nullptr; } + bool has_return_type () const { return return_type != nullptr; } // Returns whether function has a where clause. bool has_where_clause () const { return !where_clause.is_empty (); } @@ -1390,6 +1448,9 @@ public: std::vector &get_function_params () { return function_params; } const std::vector &get_function_params () const { return function_params; } + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + // TODO: is this better? Or is a "vis_block" better? std::unique_ptr &get_definition () { rust_assert (function_body != nullptr); @@ -1408,7 +1469,7 @@ public: // TODO: is this better? Or is a "vis_block" better? std::unique_ptr &get_return_type () { - rust_assert (return_type != nullptr); + rust_assert (has_return_type ()); return return_type; } @@ -1518,6 +1579,21 @@ public: void mark_for_strip () override { existing_type = nullptr; } bool is_marked_for_strip () const override { return existing_type == nullptr; } + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + + // 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 &get_type_aliased () { + rust_assert (existing_type != nullptr); + return existing_type; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1563,6 +1639,15 @@ public: Identifier get_struct_name () const { return struct_name; } + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () { + rust_assert (has_where_clause ()); + return where_clause; + } + protected: Struct (Identifier struct_name, std::vector> generic_params, @@ -1819,6 +1904,12 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_field_type () { + rust_assert (field_type != nullptr); + return field_type; + } }; // Rust tuple declared using struct keyword AST node @@ -2112,6 +2203,15 @@ public: std::vector> &get_variants () { return items; } const std::vector> &get_variants () const { return items; } + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () { + rust_assert (has_where_clause ()); + return where_clause; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2197,6 +2297,15 @@ public: std::vector &get_variants () { return variants; } const std::vector &get_variants () const { return variants; } + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () { + rust_assert (has_where_clause ()); + return where_clause; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2282,6 +2391,12 @@ public: return const_expr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (type != nullptr); + return type; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2377,6 +2492,12 @@ public: return expr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (type != nullptr); + return type; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2488,6 +2609,21 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_function_params () { return function_params; } const std::vector &get_function_params () const { return function_params; } + + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_return_type () { + rust_assert (has_return_type ()); + return return_type; + } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () { + rust_assert (has_where_clause ()); + return where_clause; + } }; // Actual trait item function declaration within traits @@ -2552,15 +2688,18 @@ public: std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } - std::vector &get_function_params () { return decl.get_function_params (); } - const std::vector &get_function_params () const { return decl.get_function_params (); } - // TODO: is this better? Or is a "vis_block" better? std::unique_ptr &get_definition () { - rust_assert (has_definition()); + rust_assert (has_definition ()); return block_expr; } + // TODO: is this better? Or is a "vis_block" better? + TraitFunctionDecl &get_trait_function_decl () { + // TODO: maybe only allow access if not marked for strip? + return decl; + } + protected: // Clone function implementation as (not pure) virtual method TraitItemFunc *clone_trait_item_impl () const override @@ -2675,6 +2814,24 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_function_params () { return function_params; } const std::vector &get_function_params () const { return function_params; } + + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_return_type () { + rust_assert (has_return_type ()); + return return_type; + } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () { + rust_assert (has_where_clause ()); + return where_clause; + } + + SelfParam &get_self_param () { return self_param; } + const SelfParam &get_self_param () const { return self_param; } }; // Actual trait item method declaration within traits @@ -2740,8 +2897,11 @@ public: std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } - std::vector &get_function_params () { return decl.get_function_params (); } - const std::vector &get_function_params () const { return decl.get_function_params (); } + // TODO: is this better? Or is a "vis_block" better? + TraitMethodDecl &get_trait_method_decl () { + // TODO: maybe only allow access if not marked for strip? + return decl; + } // TODO: is this better? Or is a "vis_block" better? std::unique_ptr &get_definition () { @@ -2840,6 +3000,12 @@ public: return expr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (type != nullptr); + return type; + } + protected: // Clone function implementation as (not pure) virtual method TraitItemConst *clone_trait_item_impl () const override @@ -2916,6 +3082,10 @@ public: std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } + // TODO: mutable getter seems kinda dodgy + std::vector > &get_type_param_bounds () { return type_param_bounds; } + const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + protected: // Clone function implementation as (not pure) virtual method TraitItemType *clone_trait_item_impl () const override @@ -3044,6 +3214,18 @@ public: const std::vector>& get_trait_items () const { return trait_items; } std::vector>& get_trait_items () { return trait_items; } + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + + std::vector > &get_type_param_bounds () { return type_param_bounds; } + const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + + // TODO: is this better? Or is a "vis_block" better? + WhereClause &get_where_clause () { + rust_assert (has_where_clause ()); + return where_clause; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -3091,6 +3273,21 @@ public: const std::vector& get_inner_attrs () const { return inner_attrs; } std::vector& get_inner_attrs () { return inner_attrs; } + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + + // 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 &get_type () { + rust_assert (trait_type != nullptr); + return trait_type; + } + protected: // Mega-constructor Impl (std::vector> generic_params, @@ -3274,6 +3471,12 @@ public: const std::vector>& get_impl_items () const { return impl_items; } std::vector>& get_impl_items () { return impl_items; } + // TODO: is this better? Or is a "vis_block" better? + TypePath &get_trait_path () { + // TODO: assert that trait path is not empty? + return trait_path; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -3435,6 +3638,12 @@ public: std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (item_type != nullptr); + return item_type; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -3522,6 +3731,12 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr &get_type () { + rust_assert (param_type != nullptr); + return param_type; + } }; // A function item used in an extern block @@ -3652,6 +3867,21 @@ public: std::vector &get_function_params () { return function_params; } const std::vector &get_function_params () const { return function_params; } + std::vector > &get_generic_params () { return generic_params; } + const std::vector > &get_generic_params () const { return generic_params; } + + // 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 &get_return_type () { + rust_assert (has_return_type ()); + return return_type; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index c59e6bd..b5d7869 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -45,7 +45,6 @@ struct GenericArgsBinding private: Identifier identifier; std::unique_ptr type; - Location locus; public: @@ -100,6 +99,12 @@ public: GenericArgsBinding &operator= (GenericArgsBinding &&other) = default; std::string as_string () const; + + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr &get_type () { + rust_assert (type != nullptr); + return type; + } }; // Generic arguments allowed in each path expression segment - inline? @@ -166,6 +171,16 @@ public: } std::string as_string () const; + + // TODO: is this better? Or is a "vis_pattern" better? + std::vector> &get_type_args () { + return type_args; + } + + // TODO: is this better? Or is a "vis_pattern" better? + std::vector &get_binding_args () { + return binding_args; + } }; /* A segment of a path in expression, including an identifier aspect and maybe @@ -221,6 +236,12 @@ public: std::string as_string () const; Location get_locus () const { return locus; } + + // TODO: is this better? Or is a "vis_pattern" better? + GenericArgs &get_generic_args () { + rust_assert (has_generic_args ()); + return generic_args; + } }; // AST node representing a pattern that involves a "path" - abstract base class @@ -249,6 +270,10 @@ public: bool is_single_segment () const { return segments.size () == 1; } std::string as_string () const override; + + // TODO: this seems kinda dodgy + std::vector &get_segments () { return segments; } + const std::vector &get_segments () const { return segments; } }; /* AST node representing a path-in-expression pattern (path that allows generic @@ -416,6 +441,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_pattern" better? + GenericArgs &get_generic_args () { + rust_assert (has_generic_args ()); + return generic_args; + } + protected: // Use covariance to override base class method TypePathSegmentGeneric *clone_type_path_segment_impl () const override @@ -504,6 +535,16 @@ public: TypePathFunction &operator= (TypePathFunction &&other) = default; std::string as_string () const; + + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector> &get_params () const { return inputs; } + std::vector> &get_params () { return inputs; } + + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr &get_return_type () { + rust_assert (has_return_type ()); + return return_type; + } }; // Segment used in type path with a function argument @@ -536,6 +577,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_pattern" better? + TypePathFunction &get_type_path_function () { + rust_assert (!function_path.is_error ()); + return function_path; + } + protected: // Use covariance to override base class method TypePathSegmentFunction *clone_type_path_segment_impl () const override @@ -547,7 +594,6 @@ protected: // Path used inside types class TypePath : public TypeNoBounds { -public: bool has_opening_scope_resolution; std::vector> segments; Location locus; @@ -622,8 +668,13 @@ public: TraitBound *to_trait_bound (bool in_parens) const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: this seems kinda dodgy + std::vector> &get_segments () { return segments; } + const std::vector> &get_segments () const { return segments; } }; struct QualifiedPathType @@ -691,6 +742,18 @@ public: std::string as_string () const; Location get_locus () const { return locus; } + + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr &get_type () { + rust_assert (type_to_invoke_on != nullptr); + return type_to_invoke_on; + } + + // TODO: is this better? Or is a "vis_pattern" better? + TypePath &get_as_type_path () { + rust_assert (has_as_clause ()); + return trait_path; + } }; /* AST node representing a qualified path-in-expression pattern (path that @@ -735,6 +798,12 @@ public: void mark_for_strip () override { path_type = QualifiedPathType::create_error (); } bool is_marked_for_strip () const override { return is_error (); } + // TODO: is this better? Or is a "vis_pattern" better? + QualifiedPathType &get_qualified_path_type () { + rust_assert (!path_type.is_error ()); + return path_type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -819,6 +888,19 @@ public: std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; + + // TODO: is this better? Or is a "vis_pattern" better? + QualifiedPathType &get_qualified_path_type () { + rust_assert (!path_type.is_error ()); + return path_type; + } + + // TODO: this seems kinda dodgy + std::vector> &get_segments () { return segments; } + const std::vector> &get_segments () const { return segments; } + + Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } }; } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 63abe7a..5dd0429 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -34,6 +34,7 @@ public: {} Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; @@ -49,7 +50,6 @@ protected: // Identifier pattern AST node (bind value matched to a variable) class IdentifierPattern : public Pattern { -public: Identifier variable_ident; bool is_ref; bool is_mut; @@ -59,6 +59,7 @@ public: Location locus; +public: std::string as_string () const; // Returns whether the IdentifierPattern has a pattern to bind. @@ -104,9 +105,18 @@ public: IdentifierPattern &operator= (IdentifierPattern &&other) = default; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr &get_pattern_to_bind () { + rust_assert (has_pattern_to_bind ()); + return to_bind; + } + + Identifier get_ident() const { return variable_ident; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -127,6 +137,7 @@ public: WildcardPattern (Location locus) : locus (locus) {} Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; @@ -295,6 +306,7 @@ public: RangePattern &operator= (RangePattern &&other) = default; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; @@ -345,8 +357,17 @@ public: ReferencePattern (ReferencePattern &&other) = default; ReferencePattern &operator= (ReferencePattern &&other) = default; + Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } + void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr &get_referenced_pattern () { + rust_assert (pattern != nullptr); + return pattern; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -356,6 +377,7 @@ protected: } }; +#if 0 // aka StructPatternEtCetera; potential element in struct pattern struct StructPatternEtc { @@ -375,6 +397,7 @@ public: return StructPatternEtc (std::vector ()); } }; +#endif // Base class for a single field in a struct pattern - abstract class StructPatternField @@ -398,6 +421,13 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; + + // TODO: seems kinda dodgy. Think of better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + protected: StructPatternField (std::vector outer_attribs, Location locus) : outer_attrs (std::move (outer_attribs)), locus (locus) @@ -424,19 +454,27 @@ public: // Copy constructor requires clone StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other) - : StructPatternField (other), index (other.index), - tuple_pattern (other.tuple_pattern->clone_pattern ()) - {} + : StructPatternField (other), index (other.index) + { + // guard to prevent null dereference (only required if error state) + if (other.tuple_pattern != nullptr) + tuple_pattern = other.tuple_pattern->clone_pattern (); + } // Overload assignment operator to perform clone StructPatternFieldTuplePat & operator= (StructPatternFieldTuplePat const &other) { StructPatternField::operator= (other); - tuple_pattern = other.tuple_pattern->clone_pattern (); index = other.index; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.tuple_pattern != nullptr) + tuple_pattern = other.tuple_pattern->clone_pattern (); + else + tuple_pattern = nullptr; + return *this; } @@ -449,6 +487,16 @@ public: void accept_vis (ASTVisitor &vis) override; + // based on idea of tuple pattern no longer existing + void mark_for_strip () override { tuple_pattern = nullptr; } + bool is_marked_for_strip () const override { return tuple_pattern == nullptr; } + + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr &get_index_pattern () { + rust_assert (tuple_pattern != nullptr); + return tuple_pattern; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -475,9 +523,12 @@ public: // Copy constructor requires clone StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other) - : StructPatternField (other), ident (other.ident), - ident_pattern (other.ident_pattern->clone_pattern ()) - {} + : StructPatternField (other), ident (other.ident) + { + // guard to prevent null dereference (only required if error state) + if (other.ident_pattern != nullptr) + ident_pattern = other.ident_pattern->clone_pattern (); + } // Overload assignment operator to clone StructPatternFieldIdentPat & @@ -485,9 +536,14 @@ public: { StructPatternField::operator= (other); ident = other.ident; - ident_pattern = other.ident_pattern->clone_pattern (); // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.ident_pattern != nullptr) + ident_pattern = other.ident_pattern->clone_pattern (); + else + ident_pattern = nullptr; + return *this; } @@ -500,6 +556,16 @@ public: void accept_vis (ASTVisitor &vis) override; + // based on idea of identifier pattern no longer existing + void mark_for_strip () override { ident_pattern = nullptr; } + bool is_marked_for_strip () const override { return ident_pattern == nullptr; } + + // TODO: is this better? Or is a "vis_pattern" better? + std::unique_ptr &get_ident_pattern () { + rust_assert (ident_pattern != nullptr); + return ident_pattern; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -527,6 +593,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // based on idea of identifier no longer existing + void mark_for_strip () override { ident = {}; } + bool is_marked_for_strip () const override { return ident.empty (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -544,7 +614,8 @@ private: std::vector> fields; bool has_struct_pattern_etc; - StructPatternEtc etc; + std::vector struct_pattern_etc_attrs; + //StructPatternEtc etc; // must have at least one of the two and maybe both @@ -561,24 +632,26 @@ public: return !has_struct_pattern_fields () && !has_struct_pattern_etc; } + bool has_etc () const { return has_struct_pattern_etc; } + // Constructor for StructPatternElements with both (potentially) StructPatternElements ( std::vector> fields, - StructPatternEtc etc) + std::vector etc_attrs) : fields (std::move (fields)), has_struct_pattern_etc (true), - etc (std::move (etc)) + struct_pattern_etc_attrs (std::move (etc_attrs)) {} // Constructor for StructPatternElements with no StructPatternEtc StructPatternElements ( std::vector> fields) : fields (std::move (fields)), has_struct_pattern_etc (false), - etc (StructPatternEtc::create_empty ()) + struct_pattern_etc_attrs () {} // Copy constructor with vector clone StructPatternElements (StructPatternElements const &other) - : has_struct_pattern_etc (other.has_struct_pattern_etc), etc (other.etc) + : has_struct_pattern_etc (other.has_struct_pattern_etc), struct_pattern_etc_attrs (other.struct_pattern_etc_attrs) { fields.reserve (other.fields.size ()); for (const auto &e : other.fields) @@ -588,7 +661,7 @@ public: // Overloaded assignment operator with vector clone StructPatternElements &operator= (StructPatternElements const &other) { - etc = other.etc; + struct_pattern_etc_attrs = other.struct_pattern_etc_attrs; has_struct_pattern_etc = other.has_struct_pattern_etc; fields.reserve (other.fields.size ()); @@ -610,6 +683,20 @@ public: } std::string as_string () const; + + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_struct_pattern_fields () { return fields; } + const std::vector> &get_struct_pattern_fields () const { return fields; } + + std::vector &get_etc_outer_attrs () { return struct_pattern_etc_attrs; } + const std::vector &get_etc_outer_attrs () const { return struct_pattern_etc_attrs; } + + void strip_etc () + { + has_struct_pattern_etc = false; + struct_pattern_etc_attrs.clear (); + struct_pattern_etc_attrs.shrink_to_fit (); + } }; // Struct pattern AST node representation @@ -640,9 +727,14 @@ public: bool has_struct_pattern_elems () const { return !elems.is_empty (); } Location get_locus () const { return path.get_locus (); } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + // TODO: seems kinda dodgy. Think of better way. + StructPatternElements &get_struct_pattern_elems () { return elems; } + const StructPatternElements &get_struct_pattern_elems () const { return elems; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -712,6 +804,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_patterns () { return patterns; } + const std::vector> &get_patterns () const { return patterns; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -768,6 +864,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_lower_patterns () { return lower_patterns; } + const std::vector> &get_lower_patterns () const { return lower_patterns; } + + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_upper_patterns () { return upper_patterns; } + const std::vector> &get_upper_patterns () const { return upper_patterns; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -789,6 +893,9 @@ class TupleStructPattern : public Pattern public: std::string as_string () const override; + // Returns whether the pattern has tuple struct items. + bool has_items () const { return items != nullptr; } + TupleStructPattern (PathInExpression tuple_struct_path, std::unique_ptr items) : path (std::move (tuple_struct_path)), items (std::move (items)) @@ -796,14 +903,23 @@ public: // Copy constructor required to clone TupleStructPattern (TupleStructPattern const &other) - : path (other.path), items (other.items->clone_tuple_struct_items ()) - {} + : path (other.path) + { + // guard to protect from null dereference + if (other.items != nullptr) + items = other.items->clone_tuple_struct_items (); + } // Operator overload assignment operator to clone TupleStructPattern &operator= (TupleStructPattern const &other) { path = other.path; - items = other.items->clone_tuple_struct_items (); + + // guard to protect from null dereference + if (other.items != nullptr) + items = other.items->clone_tuple_struct_items (); + else + items = nullptr; return *this; } @@ -813,9 +929,17 @@ public: TupleStructPattern &operator= (TupleStructPattern &&other) = default; Location get_locus () const { return path.get_locus (); } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + // TODO: seems kinda dodgy. Think of better way. + std::unique_ptr &get_items () + { + rust_assert (has_items ()); + return items; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -921,6 +1045,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_patterns () { return patterns; } + const std::vector> &get_patterns () const { return patterns; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -979,6 +1107,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_lower_patterns () { return lower_patterns; } + const std::vector> &get_lower_patterns () const { return lower_patterns; } + + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_upper_patterns () { return upper_patterns; } + const std::vector> &get_upper_patterns () const { return upper_patterns; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -993,7 +1129,6 @@ class TuplePattern : public Pattern { // bool has_tuple_pattern_items; std::unique_ptr items; - Location locus; public: @@ -1030,9 +1165,17 @@ public: } Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + // TODO: seems kinda dodgy. Think of better way. + std::unique_ptr &get_items () + { + rust_assert (has_tuple_pattern_items ()); + return items; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1078,9 +1221,17 @@ public: GroupedPattern &operator= (GroupedPattern &&other) = default; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + // TODO: seems kinda dodgy. Think of better way. + std::unique_ptr &get_pattern_in_parens () + { + rust_assert (pattern_in_parens != nullptr); + return pattern_in_parens; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1128,9 +1279,14 @@ public: SlicePattern &operator= (SlicePattern &&other) = default; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + // TODO: seems kinda dodgy. Think of better way. + std::vector> &get_items () { return items; } + const std::vector> &get_items () const { return items; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 0bb1021..167828c 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -131,10 +131,15 @@ public: // TODO: is this better? Or is a "vis_block" better? std::unique_ptr &get_init_expr () { - rust_assert (init_expr != nullptr); + rust_assert (has_init_expr ()); return init_expr; } + std::unique_ptr &get_pattern () { + rust_assert (variables_pattern != nullptr); + return variables_pattern; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 78b57eb..d5953a5 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -106,6 +106,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; }; @@ -164,6 +165,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; }; @@ -212,7 +214,7 @@ public: } // Creates a trait bound (clone of this one's trait bound) - HACK - TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override + TraitBound *to_trait_bound (bool) const override { /* NOTE: obviously it is unknown whether the internal type is a trait bound * due to polymorphism, so just let the internal type handle it. As @@ -221,6 +223,7 @@ public: } Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; }; @@ -229,7 +232,6 @@ public: class ImplTraitTypeOneBound : public TypeNoBounds { TraitBound trait_bound; - Location locus; protected: @@ -248,6 +250,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; }; @@ -258,7 +261,6 @@ class TraitObjectTypeOneBound : public TypeNoBounds { bool has_dyn; TraitBound trait_bound; - Location locus; protected: @@ -279,14 +281,15 @@ public: std::string as_string () const override; // Creates a trait bound (clone of this one's trait bound) - HACK - TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override + TraitBound *to_trait_bound (bool) const override { /* NOTE: this assumes there is no dynamic dispatch specified- if there was, * this cloning would not be required as parsing is unambiguous. */ - return new AST::TraitBound (trait_bound); + return new TraitBound (trait_bound); } Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; }; @@ -335,6 +338,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; @@ -368,6 +372,7 @@ public: std::string as_string () const override { return "! (never type)"; } Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; }; @@ -420,6 +425,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; @@ -480,6 +486,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; @@ -528,6 +535,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; @@ -574,6 +582,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; @@ -607,6 +616,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; }; @@ -755,6 +765,7 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index eb01b12..d684c7d 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -100,11 +100,11 @@ Compilation::compileVarDecl (Bfunction *fndecl, AST::LetStmt *stmt, stmt->variables_pattern->accept_vis (*this); for (auto &pattern : patternBuffer) { - auto var = backend->local_variable (fndecl, pattern.variable_ident, + auto var = backend->local_variable (fndecl, pattern.get_ident (), translatedType, NULL /*decl_var*/, false /*address_taken*/, stmt->locus); vars.push_back (var); - scope.InsertVar (pattern.variable_ident, var); + scope.InsertVar (pattern.get_ident (), var); } patternBuffer.clear (); return true; @@ -219,7 +219,7 @@ Compilation::visit (AST::TypePathSegmentFunction &segment) void Compilation::visit (AST::TypePath &path) { - if (path.segments.size () > 1) + if (path.get_segments ().size () > 1) { rust_error_at (path.get_locus (), "unable to compile multi segment types yet"); return; @@ -953,7 +953,7 @@ Compilation::visit (AST::Function &function) { // translate the type translatedType = NULL; - param.type->accept_vis (*this); + param.get_type ()->accept_vis (*this); if (translatedType == NULL) { rust_error_at (param.get_locus (), "failed to generate type for parameter"); @@ -961,7 +961,7 @@ Compilation::visit (AST::Function &function) } auto before = patternBuffer.size (); - param.param_name->accept_vis (*this); + param.get_pattern ()->accept_vis (*this); if (patternBuffer.size () <= before) { rust_error_at (param.get_locus (), "failed to analyse parameter name"); @@ -974,13 +974,13 @@ Compilation::visit (AST::Function &function) auto paramName = patternBuffer.back (); patternBuffer.pop_back (); parameters.push_back ( - Backend::Btyped_identifier (paramName.variable_ident, + Backend::Btyped_identifier (paramName.get_ident (), translatedType, param.get_locus ())); } } Btype *returnType = NULL; - if (function.has_function_return_type ()) + if (function.has_return_type ()) { translatedType = NULL; function.get_return_type ()->accept_vis (*this); @@ -1051,7 +1051,7 @@ Compilation::visit (AST::Function &function) scope.PushBlock (code_block); Bvariable *retDecl = NULL; - if (function.has_function_return_type ()) + if (function.has_return_type ()) { bool address_is_taken = false; Bstatement *ret_var_stmt = NULL; @@ -1302,21 +1302,21 @@ Compilation::visit (AST::LetStmt &stmt) for (auto &pattern : patternBuffer) { Bvariable *var = NULL; - if (!scope.LookupVar (pattern.variable_ident, &var)) + if (!scope.LookupVar (pattern.get_ident (), &var)) { rust_error_at (stmt.get_locus (), "failed to find var decl for %s", - pattern.variable_ident.c_str ()); + pattern.get_ident ().c_str ()); return; } varBuffer.push_back (var); Bexpression *init = NULL; - VISIT_POP (stmt.init_expr->get_locus_slow (), stmt.init_expr, init, + VISIT_POP (stmt.get_init_expr ()->get_locus_slow (), stmt.get_init_expr (), init, exprs); if (init == NULL) { - rust_error_at (stmt.init_expr->get_locus_slow (), + rust_error_at (stmt.get_init_expr ()->get_locus_slow (), "failed to compile init statement"); return; } diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 7dd9750..2fe84cb 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -15,37 +15,197 @@ namespace Rust { void expand_struct_fields(std::vector& fields) { for (int i = 0; i < fields.size();) { - auto& field_attrs = fields[i].get_outer_attrs(); + auto& field = fields[i]; + + auto& field_attrs = field.get_outer_attrs(); expander.expand_cfg_attrs(field_attrs); - if (expander.fails_cfg(field_attrs)) + if (expander.fails_cfg(field_attrs)) { fields.erase(fields.begin() + i); - else - i++; + continue; + } + + // expand sub-types of type, but can't strip type itself + auto& type = field.get_field_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + // if nothing else happens, increment + i++; } } void expand_tuple_fields(std::vector& fields) { for (int i = 0; i < fields.size();) { - auto& field_attrs = fields[i].get_outer_attrs(); + auto& field = fields[i]; + + auto& field_attrs = field.get_outer_attrs(); expander.expand_cfg_attrs(field_attrs); - if (expander.fails_cfg(field_attrs)) + if (expander.fails_cfg(field_attrs)) { fields.erase(fields.begin() + i); - else - i++; + continue; + } + + // expand sub-types of type, but can't strip type itself + auto& type = field.get_field_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + // if nothing else happens, increment + i++; } } void expand_function_params(std::vector& params) { for (int i = 0; i < params.size();) { - auto& param_attrs = params[i].get_outer_attrs(); + auto& param = params[i]; + + auto& param_attrs = param.get_outer_attrs(); expander.expand_cfg_attrs(param_attrs); - if (expander.fails_cfg(param_attrs)) + if (expander.fails_cfg(param_attrs)) { params.erase(params.begin() + i); - else - i++; + continue; + } + + // TODO: should an unwanted strip lead to break out of loop? + auto& pattern = param.get_pattern(); + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + + auto& type = param.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + // increment + i++; + } + } + + void expand_generic_args(AST::GenericArgs& args) { + // lifetime args can't be expanded + + // expand type args - strip sub-types only + for (auto& type : args.get_type_args()) { + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + } + + // expand binding args - strip sub-types only + for (auto& binding : args.get_binding_args()) { + auto& type = binding.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + } + } + + void expand_qualified_path_type(AST::QualifiedPathType& path_type) { + auto& type = path_type.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + if (path_type.has_as_clause()) { + auto& type_path = path_type.get_as_type_path(); + visit(type_path); + if (type_path.is_marked_for_strip()) + rust_error_at(type_path.get_locus(), "cannot strip type path in this position"); + } + } + + void expand_closure_params(std::vector& params) { + for (int i = 0; i < params.size();) { + auto& param = params[i]; + + auto& param_attrs = param.get_outer_attrs(); + expander.expand_cfg_attrs(param_attrs); + if (expander.fails_cfg(param_attrs)) { + params.erase(params.begin() + i); + continue; + } + + auto& pattern = param.get_pattern(); + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + + if (param.has_type_given()) { + auto& type = param.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + } + + // increment if found nothing else so far + i++; } } + void expand_self_param(AST::SelfParam& self_param) { + if (self_param.has_type()) { + auto& type = self_param.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + } + // TODO: maybe check for invariants being violated - e.g. both type and lifetime? + } + + void expand_where_clause(AST::WhereClause& where_clause) { + // items cannot be stripped conceptually, so just accept visitor + for (auto& item : where_clause.get_items()) + item->accept_vis(*this); + } + + void expand_trait_function_decl(AST::TraitFunctionDecl& decl) { + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : decl.get_generic_params()) + param->accept_vis(*this); + + /* strip function parameters if required - this is specifically + * allowed by spec */ + expand_function_params(decl.get_function_params()); + + if (decl.has_return_type()) { + auto& return_type = decl.get_return_type(); + return_type->accept_vis(*this); + if (return_type->is_marked_for_strip()) + rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); + } + + if (decl.has_where_clause()) + expand_where_clause(decl.get_where_clause()); + } + + void expand_trait_method_decl(AST::TraitMethodDecl& decl) { + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : decl.get_generic_params()) + param->accept_vis(*this); + + /* assuming you can't strip self param - wouldn't be a method + * anymore. spec allows outer attrs on self param, but doesn't + * specify whether cfg is used. */ + expand_self_param(decl.get_self_param()); + + /* strip function parameters if required - this is specifically + * allowed by spec */ + expand_function_params(decl.get_function_params()); + + if (decl.has_return_type()) { + auto& return_type = decl.get_return_type(); + return_type->accept_vis(*this); + if (return_type->is_marked_for_strip()) + rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); + } + + if (decl.has_where_clause()) + expand_where_clause(decl.get_where_clause()); + } + void visit(AST::Token& tok) override { // shouldn't require? } @@ -77,7 +237,11 @@ namespace Rust { return; } + // can't strip simple path + // I don't think any macro token trees can be stripped in any way + + // TODO: maybe have cfg! macro stripping behaviour here? } void visit(AST::PathInExpression& path) override { @@ -87,18 +251,43 @@ namespace Rust { path.mark_for_strip(); return; } + + for (auto& segment : path.get_segments()) { + if (segment.has_generic_args()) + expand_generic_args(segment.get_generic_args()); + } } void visit(AST::TypePathSegment& segment) override { - // shouldn't require? + // shouldn't require } void visit(AST::TypePathSegmentGeneric& segment) override { - // shouldn't require? + // TODO: strip inside generic args + + if (!segment.has_generic_args()) + return; + + expand_generic_args(segment.get_generic_args()); } void visit(AST::TypePathSegmentFunction& segment) override { - // shouldn't require? + auto& type_path_function = segment.get_type_path_function(); + + for (auto& type : type_path_function.get_params()) { + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + } + + if (type_path_function.has_return_type()) { + auto& return_type = type_path_function.get_return_type(); + return_type->accept_vis(*this); + if (return_type->is_marked_for_strip()) + rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); + } } void visit(AST::TypePath& path) override { - // shouldn't require? + // this shouldn't strip any segments, but can strip inside them + for (auto& segment : path.get_segments()) + segment->accept_vis(*this); } void visit(AST::QualifiedPathInExpression& path) override { // initial strip test based on outer attrs @@ -107,9 +296,20 @@ namespace Rust { path.mark_for_strip(); return; } + + expand_qualified_path_type(path.get_qualified_path_type()); + + for (auto& segment : path.get_segments()) { + if (segment.has_generic_args()) + expand_generic_args(segment.get_generic_args()); + } } void visit(AST::QualifiedPathInType& path) override { - // shouldn't require? + expand_qualified_path_type(path.get_qualified_path_type()); + + // this shouldn't strip any segments, but can strip inside them + for (auto& segment : path.get_segments()) + segment->accept_vis(*this); } void visit(AST::LiteralExpr& expr) override { @@ -258,14 +458,21 @@ namespace Rust { /* outer attributes never allowed before these. while cannot strip * direct descendant expression, can strip ones below that */ + auto& casted_expr = expr.get_casted_expr(); /* should have no possibility for outer attrs as would be parsed * with outer expr */ - expr.get_casted_expr()->accept_vis(*this); + casted_expr->accept_vis(*this); // ensure that they are not marked for strip - if (expr.get_casted_expr()->is_marked_for_strip()) - rust_error_at(expr.get_casted_expr()->get_locus_slow(), + if (casted_expr->is_marked_for_strip()) + rust_error_at(casted_expr->get_locus_slow(), "cannot strip expression in this position - outer attributes are never allowed before cast exprs"); + + // TODO: strip sub-types of type + auto& type = expr.get_type_to_cast_to(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); } void visit(AST::AssignmentExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -478,6 +685,12 @@ namespace Rust { expr.mark_for_strip(); return; } + + // strip sub-exprs of path + auto& struct_name = expr.get_struct_name(); + visit(struct_name); + if (struct_name.is_marked_for_strip()) + rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); } void visit(AST::StructExprFieldIdentifier& field) override { // as no attrs (at moment, at least), no stripping possible @@ -514,7 +727,13 @@ namespace Rust { if (expander.fails_cfg(expr.get_inner_attrs())) { expr.mark_for_strip(); return; - } + } + + // strip sub-exprs of path + auto& struct_name = expr.get_struct_name(); + visit(struct_name); + if (struct_name.is_marked_for_strip()) + rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); /* spec does not specify whether expressions are allowed to be * stripped at top level of struct fields, but I wouldn't think @@ -551,6 +770,12 @@ namespace Rust { return; } + // strip sub-exprs of path + auto& struct_name = expr.get_struct_name(); + visit(struct_name); + if (struct_name.is_marked_for_strip()) + rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); + /* struct base presumably can't be stripped, as the '..' is before * the expression. as such, can only strip sub-expressions. */ rust_assert(!expr.get_struct_base().is_invalid()); @@ -576,6 +801,12 @@ namespace Rust { return; } + // strip sub-exprs of path + auto& struct_name = expr.get_struct_name(); + visit(struct_name); + if (struct_name.is_marked_for_strip()) + rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); + /* spec says outer attributes are specifically allowed for elements * of tuple-style struct expressions, so full stripping possible */ auto& values = expr.get_elems(); @@ -598,6 +829,12 @@ namespace Rust { expr.mark_for_strip(); return; } + + // strip sub-exprs of path + auto& struct_name = expr.get_struct_name(); + visit(struct_name); + if (struct_name.is_marked_for_strip()) + rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); } void visit(AST::EnumExprFieldIdentifier& field) override { // as no attrs (at moment, at least), no stripping possible @@ -630,6 +867,12 @@ namespace Rust { // supposedly spec doesn't allow inner attributes in enum exprs + // strip sub-exprs of path + auto& enum_path = expr.get_enum_variant_path(); + visit(enum_path); + if (enum_path.is_marked_for_strip()) + rust_error_at(enum_path.get_locus(), "cannot strip path in this position"); + /* spec does not specify whether expressions are allowed to be * stripped at top level of expression fields, but I wouldn't think * that they would be, so operating under the assumption that only @@ -649,6 +892,12 @@ namespace Rust { // supposedly spec doesn't allow inner attributes in enum exprs + // strip sub-exprs of path + auto& enum_path = expr.get_enum_variant_path(); + visit(enum_path); + if (enum_path.is_marked_for_strip()) + rust_error_at(enum_path.get_locus(), "cannot strip path in this position"); + /* spec says outer attributes are specifically allowed for elements * of tuple-style enum expressions, so full stripping possible */ auto& values = expr.get_elems(); @@ -666,6 +915,12 @@ namespace Rust { } void visit(AST::EnumExprFieldless& expr) override { // can't be stripped as no attrs + + // strip sub-exprs of path + auto& enum_path = expr.get_enum_variant_path(); + visit(enum_path); + if (enum_path.is_marked_for_strip()) + rust_error_at(enum_path.get_locus(), "cannot strip path in this position"); } void visit(AST::CallExpr& expr) override { // initial strip test based on outer attrs @@ -716,7 +971,9 @@ namespace Rust { rust_error_at(receiver->get_locus_slow(), "cannot strip expression in this position - outer attributes not allowed"); - // no outer attrs on paths possible + auto& method_name = expr.get_method_name(); + if (method_name.has_generic_args()) + expand_generic_args(method_name.get_generic_args()); /* spec says outer attributes are specifically allowed for elements * of method call expressions, so full stripping possible */ @@ -760,15 +1017,7 @@ namespace Rust { /* 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++; - } + expand_closure_params(expr.get_params()); // can't strip expression itself, but can strip sub-expressions auto& definition_expr = expr.get_definition_expr(); @@ -827,15 +1076,13 @@ namespace Rust { /* 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++; - } + expand_closure_params(expr.get_params()); + + // can't strip return type, but can strip sub-types + auto& type = expr.get_return_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); // can't strip expression itself, but can strip sub-expressions auto& definition_block = expr.get_definition_block(); @@ -1042,6 +1289,12 @@ namespace Rust { return; } + for (auto& pattern : expr.get_patterns()) { + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + // can't strip scrutinee expr itself, but can strip sub-expressions auto& scrutinee_expr = expr.get_scrutinee_expr(); scrutinee_expr->accept_vis(*this); @@ -1064,6 +1317,12 @@ namespace Rust { return; } + // TODO: strip sub-patterns of pattern + auto& pattern = expr.get_pattern(); + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + // can't strip scrutinee expr itself, but can strip sub-expressions auto& iterator_expr = expr.get_iterator_expr(); iterator_expr->accept_vis(*this); @@ -1195,6 +1454,12 @@ namespace Rust { return; } + for (auto& pattern : expr.get_patterns()) { + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + // can't strip value expr itself, but can strip sub-expressions auto& value_expr = expr.get_value_expr(); value_expr->accept_vis(*this); @@ -1217,6 +1482,12 @@ namespace Rust { return; } + for (auto& pattern : expr.get_patterns()) { + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + // can't strip value expr itself, but can strip sub-expressions auto& value_expr = expr.get_value_expr(); value_expr->accept_vis(*this); @@ -1246,6 +1517,12 @@ namespace Rust { return; } + for (auto& pattern : expr.get_patterns()) { + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + // can't strip value expr itself, but can strip sub-expressions auto& value_expr = expr.get_value_expr(); value_expr->accept_vis(*this); @@ -1275,6 +1552,12 @@ namespace Rust { return; } + for (auto& pattern : expr.get_patterns()) { + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + // can't strip value expr itself, but can strip sub-expressions auto& value_expr = expr.get_value_expr(); value_expr->accept_vis(*this); @@ -1332,6 +1615,12 @@ namespace Rust { continue; } + for (auto& pattern : match_arm.get_patterns()) { + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + /* assuming that guard expression cannot be stripped as * strictly speaking you would have to strip the whole guard to * make syntactical sense, which you can't do. as such, only @@ -1388,13 +1677,35 @@ namespace Rust { } void visit(AST::TypeParam& param) override { - // shouldn't require? + // outer attributes don't actually do anything, so ignore them + + if (param.has_type_param_bounds()) { + // don't strip directly, only components of bounds + for (auto& bound : param.get_type_param_bounds()) + bound->accept_vis(*this); + } + + if (param.has_type()) { + auto& type = param.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + } } void visit(AST::LifetimeWhereClauseItem& item) override { - // shouldn't require? + // shouldn't require } void visit(AST::TypeBoundWhereClauseItem& item) override { - // shouldn't require? + // for lifetimes shouldn't require + + auto& type = item.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + // don't strip directly, only components of bounds + for (auto& bound : item.get_type_param_bounds()) + bound->accept_vis(*this); } void visit(AST::Method& method) override { // initial test based on outer attrs @@ -1404,14 +1715,29 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : method.get_generic_params()) + param->accept_vis(*this); + /* assuming you can't strip self param - wouldn't be a method * anymore. spec allows outer attrs on self param, but doesn't * specify whether cfg is used. */ + expand_self_param(method.get_self_param()); /* strip method parameters if required - this is specifically * allowed by spec */ expand_function_params(method.get_function_params()); + if (method.has_return_type()) { + auto& return_type = method.get_return_type(); + return_type->accept_vis(*this); + if (return_type->is_marked_for_strip()) + rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); + } + + if (method.has_where_clause()) + expand_where_clause(method.get_where_clause()); + /* body should always exist - if error state, should have returned * before now */ // can't strip block itself, but can strip sub-expressions @@ -1491,10 +1817,24 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : function.get_generic_params()) + param->accept_vis(*this); + /* strip function parameters if required - this is specifically * allowed by spec */ expand_function_params(function.get_function_params()); + if (function.has_return_type()) { + auto& return_type = function.get_return_type(); + return_type->accept_vis(*this); + if (return_type->is_marked_for_strip()) + rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); + } + + if (function.has_where_clause()) + expand_where_clause(function.get_where_clause()); + /* body should always exist - if error state, should have returned * before now */ // can't strip block itself, but can strip sub-expressions @@ -1511,6 +1851,18 @@ namespace Rust { type_alias.mark_for_strip(); return; } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : type_alias.get_generic_params()) + param->accept_vis(*this); + + if (type_alias.has_where_clause()) + expand_where_clause(type_alias.get_where_clause()); + + auto& type = type_alias.get_type_aliased(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); } void visit(AST::StructStruct& struct_item) override { // initial test based on outer attrs @@ -1520,6 +1872,13 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : struct_item.get_generic_params()) + param->accept_vis(*this); + + if (struct_item.has_where_clause()) + expand_where_clause(struct_item.get_where_clause()); + /* strip struct fields if required - this is presumably * allowed by spec */ expand_struct_fields(struct_item.get_fields()); @@ -1532,9 +1891,16 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : tuple_struct.get_generic_params()) + param->accept_vis(*this); + /* strip struct fields if required - this is presumably * allowed by spec */ expand_tuple_fields(tuple_struct.get_fields()); + + if (tuple_struct.has_where_clause()) + expand_where_clause(tuple_struct.get_where_clause()); } void visit(AST::EnumItem& item) override { // initial test based on outer attrs @@ -1593,6 +1959,13 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : enum_item.get_generic_params()) + param->accept_vis(*this); + + if (enum_item.has_where_clause()) + expand_where_clause(enum_item.get_where_clause()); + /* strip enum fields if required - this is presumably * allowed by spec */ auto& variants = enum_item.get_variants(); @@ -1616,6 +1989,13 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : union_item.get_generic_params()) + param->accept_vis(*this); + + if (union_item.has_where_clause()) + expand_where_clause(union_item.get_where_clause()); + /* strip union fields if required - this is presumably * allowed by spec */ expand_struct_fields(union_item.get_variants()); @@ -1628,6 +2008,12 @@ namespace Rust { return; } + // strip any sub-types + auto& type = const_item.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ @@ -1645,6 +2031,12 @@ namespace Rust { return; } + // strip any sub-types + auto& type = static_item.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ @@ -1662,9 +2054,7 @@ namespace Rust { return; } - /* strip function parameters if required - this is specifically - * allowed by spec */ - expand_function_params(item.get_function_params()); + expand_trait_function_decl(item.get_trait_function_decl()); if (item.has_definition()) { /* strip any internal sub-expressions - expression itself isn't @@ -1685,13 +2075,7 @@ namespace Rust { return; } - /* assuming you can't strip self param - wouldn't be a method - * anymore. spec allows outer attrs on self param, but doesn't - * specify whether cfg is used. */ - - /* strip function parameters if required - this is specifically - * allowed by spec */ - expand_function_params(item.get_function_params()); + expand_trait_method_decl(item.get_trait_method_decl()); if (item.has_definition()) { /* strip any internal sub-expressions - expression itself isn't @@ -1712,6 +2096,12 @@ namespace Rust { return; } + // strip any sub-types + auto& type = item.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped */ @@ -1730,6 +2120,12 @@ namespace Rust { item.mark_for_strip(); return; } + + if (item.has_type_param_bounds()) { + // don't strip directly, only components of bounds + for (auto& bound : item.get_type_param_bounds()) + bound->accept_vis(*this); + } } void visit(AST::Trait& trait) override { // initial strip test based on outer attrs @@ -1746,6 +2142,19 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : trait.get_generic_params()) + param->accept_vis(*this); + + if (trait.has_type_param_bounds()) { + // don't strip directly, only components of bounds + for (auto& bound : trait.get_type_param_bounds()) + bound->accept_vis(*this); + } + + if (trait.has_where_clause()) + expand_where_clause(trait.get_where_clause()); + // strip trait items if required auto& trait_items = trait.get_trait_items(); for (int i = 0; i < trait_items.size();) { @@ -1775,6 +2184,18 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : impl.get_generic_params()) + param->accept_vis(*this); + + auto& type = impl.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + if (impl.has_where_clause()) + expand_where_clause(impl.get_where_clause()); + // strip inherent impl items if required auto& impl_items = impl.get_impl_items(); for (int i = 0; i < impl_items.size();) { @@ -1804,6 +2225,23 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : impl.get_generic_params()) + param->accept_vis(*this); + + auto& type = impl.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + auto& trait_path = impl.get_trait_path(); + visit(trait_path); + if (trait_path.is_marked_for_strip()) + rust_error_at(trait_path.get_locus(), "cannot strip typepath in this position"); + + if (impl.has_where_clause()) + expand_where_clause(impl.get_where_clause()); + // strip trait impl items if required auto& impl_items = impl.get_impl_items(); for (int i = 0; i < impl_items.size();) { @@ -1825,6 +2263,11 @@ namespace Rust { item.mark_for_strip(); return; } + + auto& type = item.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); } void visit(AST::ExternalFunctionItem& item) override { // strip test based on outer attrs @@ -1834,16 +2277,30 @@ namespace Rust { return; } + // just expand sub-stuff - can't actually strip generic params themselves + for (auto& param : item.get_generic_params()) + param->accept_vis(*this); + /* strip function parameters if required - this is specifically * allowed by spec */ auto& params = item.get_function_params(); for (int i = 0; i < params.size();) { - auto& param_attrs = params[i].get_outer_attrs(); + auto& param = params[i]; + + auto& param_attrs = param.get_outer_attrs(); expander.expand_cfg_attrs(param_attrs); - if (expander.fails_cfg(param_attrs)) + if (expander.fails_cfg(param_attrs)) { params.erase(params.begin() + i); - else - i++; + continue; + } + + auto& type = param.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + // increment if nothing else happens + i++; } /* NOTE: these are extern function params, which may have different * rules and restrictions to "normal" function params. So expansion @@ -1851,6 +2308,16 @@ namespace Rust { /* TODO: assuming that variadic nature cannot be stripped. If this * is not true, then have code here to do so. */ + + if (item.has_return_type()) { + auto& return_type = item.get_return_type(); + return_type->accept_vis(*this); + if (return_type->is_marked_for_strip()) + rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); + } + + if (item.has_where_clause()) + expand_where_clause(item.get_where_clause()); } void visit(AST::ExternBlock& block) override { // initial strip test based on outer attrs @@ -1904,6 +2371,8 @@ namespace Rust { } // I don't think any macro token trees can be stripped in any way + + // TODO: maybe have stripping behaviour for the cfg! macro here? } void visit(AST::MetaItemPath& meta_item) override {} void visit(AST::MetaItemSeq& meta_item) override {} @@ -1912,29 +2381,186 @@ namespace Rust { void visit(AST::MetaListPaths& meta_item) override {} void visit(AST::MetaListNameValueStr& meta_item) override {} - // stripping shouldn't be required or possible for patterns - void visit(AST::LiteralPattern& pattern) override {} - void visit(AST::IdentifierPattern& pattern) override {} - void visit(AST::WildcardPattern& pattern) override {} - void visit(AST::RangePatternBoundLiteral& bound) override {} - void visit(AST::RangePatternBoundPath& bound) override {} - void visit(AST::RangePatternBoundQualPath& bound) override {} - void visit(AST::RangePattern& pattern) override {} - void visit(AST::ReferencePattern& pattern) override {} - void visit(AST::StructPatternFieldTuplePat& field) override {} - void visit(AST::StructPatternFieldIdentPat& field) override {} - void visit(AST::StructPatternFieldIdent& field) override {} + void visit(AST::LiteralPattern& pattern) override { + // not possible + } + void visit(AST::IdentifierPattern& pattern) override { + // can only strip sub-patterns of the inner pattern to bind + if (!pattern.has_pattern_to_bind()) + return; + + auto& sub_pattern = pattern.get_pattern_to_bind(); + sub_pattern->accept_vis(*this); + if (sub_pattern->is_marked_for_strip()) + rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + void visit(AST::WildcardPattern& pattern) override { + // not possible + } + void visit(AST::RangePatternBoundLiteral& bound) override { + // not possible + } + void visit(AST::RangePatternBoundPath& bound) override { + // TODO: maybe possible if path is possible + } + void visit(AST::RangePatternBoundQualPath& bound) override { + // TODO: maybe possible if path is possible + } + void visit(AST::RangePattern& pattern) override { + // TODO: possible if any bounds are possible + } + void visit(AST::ReferencePattern& pattern) override { + auto& sub_pattern = pattern.get_referenced_pattern(); + sub_pattern->accept_vis(*this); + if (sub_pattern->is_marked_for_strip()) + rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + void visit(AST::StructPatternFieldTuplePat& field) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(field.get_outer_attrs()); + if (expander.fails_cfg(field.get_outer_attrs())) { + field.mark_for_strip(); + return; + } + + // strip sub-patterns (can't strip top-level pattern) + auto& sub_pattern = field.get_index_pattern(); + sub_pattern->accept_vis(*this); + if (sub_pattern->is_marked_for_strip()) + rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + void visit(AST::StructPatternFieldIdentPat& field) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(field.get_outer_attrs()); + if (expander.fails_cfg(field.get_outer_attrs())) { + field.mark_for_strip(); + return; + } + + // strip sub-patterns (can't strip top-level pattern) + auto& sub_pattern = field.get_ident_pattern(); + sub_pattern->accept_vis(*this); + if (sub_pattern->is_marked_for_strip()) + rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position"); + } + void visit(AST::StructPatternFieldIdent& field) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(field.get_outer_attrs()); + if (expander.fails_cfg(field.get_outer_attrs())) { + field.mark_for_strip(); + return; + } + } void visit(AST::StructPattern& pattern) override { // TODO: apparently struct pattern fields can have outer attrs. so can they be stripped? + if (!pattern.has_struct_pattern_elems()) + return; + + auto& elems = pattern.get_struct_pattern_elems(); + + // assuming you can strip struct pattern fields + auto& fields = elems.get_struct_pattern_fields(); + for (int i = 0; i < fields.size();) { + auto& field = fields[i]; + + field->accept_vis(*this); + + if (field->is_marked_for_strip()) + fields.erase(fields.begin() + i); + else + i++; + } + + // assuming you can strip the ".." part + if (elems.has_etc()) { + expander.expand_cfg_attrs(elems.get_etc_outer_attrs()); + if (expander.fails_cfg(elems.get_etc_outer_attrs())) + elems.strip_etc(); + } + } + void visit(AST::TupleStructItemsNoRange& tuple_items) override { + // can't strip individual patterns, only sub-patterns + for (auto& pattern : tuple_items.get_patterns()) { + pattern->accept_vis(*this); + + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + } + void visit(AST::TupleStructItemsRange& tuple_items) override { + // can't strip individual patterns, only sub-patterns + for (auto& lower_pattern : tuple_items.get_lower_patterns()) { + lower_pattern->accept_vis(*this); + + if (lower_pattern->is_marked_for_strip()) + rust_error_at(lower_pattern->get_locus_slow(), "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + for (auto& upper_pattern : tuple_items.get_upper_patterns()) { + upper_pattern->accept_vis(*this); + + if (upper_pattern->is_marked_for_strip()) + rust_error_at(upper_pattern->get_locus_slow(), "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + } + void visit(AST::TupleStructPattern& pattern) override { + // TODO: stripping of path? + + if (pattern.has_items()) + pattern.get_items()->accept_vis(*this); + } + void visit(AST::TuplePatternItemsMultiple& tuple_items) override { + // can't strip individual patterns, only sub-patterns + for (auto& pattern : tuple_items.get_patterns()) { + pattern->accept_vis(*this); + + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + } + void visit(AST::TuplePatternItemsRanged& tuple_items) override { + // can't strip individual patterns, only sub-patterns + for (auto& lower_pattern : tuple_items.get_lower_patterns()) { + lower_pattern->accept_vis(*this); + + if (lower_pattern->is_marked_for_strip()) + rust_error_at(lower_pattern->get_locus_slow(), "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + for (auto& upper_pattern : tuple_items.get_upper_patterns()) { + upper_pattern->accept_vis(*this); + + if (upper_pattern->is_marked_for_strip()) + rust_error_at(upper_pattern->get_locus_slow(), "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + } + void visit(AST::TuplePattern& pattern) override { + if (pattern.has_tuple_pattern_items()) + pattern.get_items()->accept_vis(*this); + } + void visit(AST::GroupedPattern& pattern) override { + // can't strip inner pattern, only sub-patterns + auto& pattern_in_parens = pattern.get_pattern_in_parens(); + + pattern_in_parens->accept_vis(*this); + + if (pattern_in_parens->is_marked_for_strip()) + rust_error_at(pattern_in_parens->get_locus_slow(), "cannot strip pattern in this position"); + } + void visit(AST::SlicePattern& pattern) override { + // can't strip individual patterns, only sub-patterns + for (auto& item : pattern.get_items()) { + item->accept_vis(*this); + + if (item->is_marked_for_strip()) + rust_error_at(item->get_locus_slow(), "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } } - void visit(AST::TupleStructItemsNoRange& tuple_items) override {} - void visit(AST::TupleStructItemsRange& tuple_items) override {} - void visit(AST::TupleStructPattern& pattern) override {} - void visit(AST::TuplePatternItemsMultiple& tuple_items) override {} - void visit(AST::TuplePatternItemsRanged& tuple_items) override {} - void visit(AST::TuplePattern& pattern) override {} - void visit(AST::GroupedPattern& pattern) override {} - void visit(AST::SlicePattern& pattern) override {} void visit(AST::EmptyStmt& stmt) override { // assuming no outer attributes, so nothing can happen @@ -1947,6 +2573,12 @@ namespace Rust { return; } + // can't strip pattern, but call for sub-patterns + auto& pattern = stmt.get_pattern(); + pattern->accept_vis(*this); + if (pattern->is_marked_for_strip()) + rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped */ diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 769cf41..88252ac 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -10150,6 +10150,14 @@ Parser::parse_pattern () // tuple struct lexer.skip_token (); + // check if empty tuple + if (lexer.peek_token ()->get_id () == RIGHT_PAREN) + { + lexer.skip_token (); + return std::unique_ptr ( + new AST::TupleStructPattern (std::move (path), nullptr)); + } + // parse items std::unique_ptr items = parse_tuple_struct_items (); @@ -10574,6 +10582,14 @@ Parser::parse_ident_leading_pattern () // DEBUG fprintf (stderr, "parsing tuple struct pattern\n"); + // check if empty tuple + if (lexer.peek_token ()->get_id () == RIGHT_PAREN) + { + lexer.skip_token (); + return std::unique_ptr ( + new AST::TupleStructPattern (std::move (path), nullptr)); + } + // parse items std::unique_ptr items = parse_tuple_struct_items (); @@ -10816,53 +10832,46 @@ Parser::parse_struct_pattern_elems () { std::vector > fields; + std::vector etc_attrs; + bool has_etc = false; + // try parsing struct pattern fields const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_CURLY && t->get_id () != DOT_DOT) + while (t->get_id () != RIGHT_CURLY) { + std::vector outer_attrs = parse_outer_attributes (); + + // parse etc (must be last in struct pattern, so breaks) + if (lexer.peek_token ()->get_id () == DOT_DOT) + { + lexer.skip_token (); + etc_attrs = std::move (outer_attrs); + has_etc = true; + break; + } + std::unique_ptr field - = parse_struct_pattern_field (); + = parse_struct_pattern_field_partial (std::move (outer_attrs)); if (field == nullptr) { - // TODO: should this be an error? - // assuming that this means that it is a struct pattern etc instead - - // DEBUG - fprintf ( - stderr, - "failed to parse struct pattern field - breaking from loop\n"); - - break; + rust_error_at (lexer.peek_token ()->get_locus (), "failed to parse struct pattern field"); + // skip after somewhere? + return AST::StructPatternElements::create_empty (); } - fields.push_back (std::move (field)); - // DEBUG - fprintf (stderr, "successfully pushed back a struct pattern field\n"); - if (lexer.peek_token ()->get_id () != COMMA) - { break; - } - lexer.skip_token (); - - t = lexer.peek_token (); - } - /* FIXME: this method of parsing prevents parsing any outer attributes on the - * .. - also there seems to be no distinction between having etc and not - * having etc. */ - if (lexer.peek_token ()->get_id () == DOT_DOT) - { + // skip comma lexer.skip_token (); - - // as no outer attributes - AST::StructPatternEtc etc = AST::StructPatternEtc::create_empty (); - - return AST::StructPatternElements (std::move (fields), std::move (etc)); + t = lexer.peek_token (); } - return AST::StructPatternElements (std::move (fields)); + if (has_etc) + return AST::StructPatternElements (std::move (fields), std::move (etc_attrs)); + else + return AST::StructPatternElements (std::move (fields)); } /* Parses a struct pattern field (tuple index/pattern, identifier/pattern, or @@ -10874,6 +10883,15 @@ Parser::parse_struct_pattern_field () // parse outer attributes (if they exist) std::vector outer_attrs = parse_outer_attributes (); + return parse_struct_pattern_field_partial (std::move (outer_attrs)); +} + +/* Parses a struct pattern field (tuple index/pattern, identifier/pattern, or + * identifier), with outer attributes passed in. */ +template +std::unique_ptr +Parser::parse_struct_pattern_field_partial (std::vector outer_attrs) +{ // branch based on next token const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 5202abf..a6de87b 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -575,6 +575,7 @@ private: std::unique_ptr parse_tuple_struct_items (); AST::StructPatternElements parse_struct_pattern_elems (); std::unique_ptr parse_struct_pattern_field (); + std::unique_ptr parse_struct_pattern_field_partial (std::vector outer_attrs); int left_binding_power (const_TokenPtr token); -- cgit v1.1 From c7080f178a637cad04e196a404d5d44bb33189af Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Mon, 7 Dec 2020 19:51:24 +0800 Subject: Added more cfg stripping code --- gcc/rust/analysis/rust-type-resolution.cc | 2 +- gcc/rust/ast/rust-item.h | 20 ++-- gcc/rust/ast/rust-pattern.h | 25 +++++ gcc/rust/ast/rust-stmt.h | 7 +- gcc/rust/ast/rust-type.h | 108 +++++++++++++++++-- gcc/rust/backend/rust-compile.cc | 10 +- gcc/rust/expand/rust-macro-expand.cc | 167 ++++++++++++++++++++++++++---- gcc/rust/parse/rust-parse-impl.h | 79 +++++++------- gcc/rust/parse/rust-parse.h | 2 +- 9 files changed, 336 insertions(+), 84 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 439543e..2c720c6 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -1038,7 +1038,7 @@ TypeResolution::visit (AST::LetStmt &stmt) if (stmt.has_type () && stmt.has_init_expr ()) { - if (!typesAreCompatible (stmt.type.get (), inferedType, + if (!typesAreCompatible (stmt.get_type ().get (), inferedType, stmt.get_init_expr ()->get_locus_slow ())) { return; diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index c47a6f5..455511c 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -90,8 +90,12 @@ public: TypeParam (TypeParam const &other) : outer_attr (other.outer_attr), type_representation (other.type_representation), - type (other.type->clone_type ()), locus (other.locus) + locus (other.locus) { + // guard to prevent null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -101,11 +105,15 @@ public: TypeParam &operator= (TypeParam const &other) { type_representation = other.type_representation; - // type_param_bounds = other.type_param_bounds; - type = other.type->clone_type (); outer_attr = other.outer_attr; locus = other.locus; + // guard to prevent null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + type_param_bounds.reserve (other.type_param_bounds.size ()); for (const auto &e : other.type_param_bounds) type_param_bounds.push_back (e->clone_type_param_bound ()); @@ -453,7 +461,7 @@ public: if (!this->extern_abi.empty ()) { // having extern is required; not having it is an implementation error - gcc_assert (has_extern); + rust_assert (has_extern); } } @@ -1101,7 +1109,7 @@ public: { // compiler implementation error if there is a path with a // non-path-prefixed use tree glob - gcc_assert (!has_path ()); + rust_assert (!has_path ()); } // TODO: do path-prefixed paths also have to have a path? If so, have an // assert for that too. @@ -1153,7 +1161,7 @@ public: { // compiler implementation error if there is a path with a // non-path-prefixed use tree glob - gcc_assert (!has_path ()); + rust_assert (!has_path ()); } // TODO: do path-prefixed paths also have to have a path? If so, have an // assert for that too. diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 5dd0429..5ae68ab 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -223,6 +223,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems kinda dodgy + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -251,6 +255,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems kinda dodgy + QualifiedPathInExpression &get_qualified_path () { return path; } + const QualifiedPathInExpression &get_qualified_path () const { return path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -310,6 +318,17 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? or is a "vis_bound" better? + std::unique_ptr& get_lower_bound () { + rust_assert (lower != nullptr); + return lower; + } + + std::unique_ptr& get_upper_bound () { + rust_assert (upper != nullptr); + return upper; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -735,6 +754,9 @@ public: StructPatternElements &get_struct_pattern_elems () { return elems; } const StructPatternElements &get_struct_pattern_elems () const { return elems; } + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -940,6 +962,9 @@ public: return items; } + PathInExpression &get_path () { return path; } + const PathInExpression &get_path () const { return path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 167828c..88be256 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -41,7 +41,6 @@ class LetStmt : public Stmt // bool has_outer_attrs; std::vector outer_attrs; -public: std::unique_ptr variables_pattern; // bool has_type; @@ -52,6 +51,7 @@ public: Location locus; +public: Type *inferedType; // Returns whether let statement has outer attributes. @@ -140,6 +140,11 @@ public: return variables_pattern; } + std::unique_ptr &get_type () { + rust_assert (has_type ()); + return type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index d5953a5..ea9a89c 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -43,6 +43,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems kinda dodgy + TypePath &get_type_path () { return type_path; } + const TypePath &get_type_path () const { return type_path; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -109,6 +113,10 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: mutable getter seems kinda dodgy + std::vector > &get_type_param_bounds () { return type_param_bounds; } + const std::vector > &get_type_param_bounds () const { return type_param_bounds; } }; // An opaque value of another type that implements a set of traits @@ -168,6 +176,10 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: mutable getter seems kinda dodgy + std::vector > &get_type_param_bounds () { return type_param_bounds; } + const std::vector > &get_type_param_bounds () const { return type_param_bounds; } }; // A type with parentheses around it, used to avoid ambiguity. @@ -226,6 +238,12 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: would a "vis_type" be better? + std::unique_ptr &get_type_in_parens () { + rust_assert (type_in_parens != nullptr); + return type_in_parens; + } }; // Impl trait with a single bound? Poor reference material here. @@ -253,6 +271,12 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: would a "vis_type" be better? + TraitBound &get_trait_bound () { + // TODO: check to ensure invariants are met? + return trait_bound; + } }; /* A trait object with a single trait bound. The "trait bound" is really just @@ -292,6 +316,12 @@ public: Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; + + // TODO: would a "vis_type" be better? + TraitBound &get_trait_bound () { + // TODO: check to ensure invariants are met? + return trait_bound; + } }; class TypePath; // definition moved to "rust-path.h" @@ -342,6 +372,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: mutable getter seems kinda dodgy + std::vector > &get_elems () { return elems; } + const std::vector > &get_elems () const { return elems; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -429,6 +463,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: would a "vis_type" be better? + std::unique_ptr &get_type_pointed_to () { + rust_assert (type != nullptr); + return type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -490,6 +530,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: would a "vis_type" be better? + std::unique_ptr &get_type_referenced () { + rust_assert (type != nullptr); + return type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -539,6 +585,18 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: would a "vis_type" be better? + std::unique_ptr &get_elem_type () { + rust_assert (elem_type != nullptr); + return elem_type; + } + + // TODO: would a "vis_expr" be better? + std::unique_ptr &get_size_expr () { + rust_assert (size != nullptr); + return size; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -586,6 +644,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: would a "vis_type" be better? + std::unique_ptr &get_elem_type () { + rust_assert (elem_type != nullptr); + return elem_type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -635,6 +699,8 @@ public: }; private: + std::vector outer_attrs; + std::unique_ptr param_type; ParamKind param_kind; @@ -644,14 +710,14 @@ private: public: MaybeNamedParam (Identifier name, ParamKind param_kind, - std::unique_ptr param_type, Location locus) - : param_type (std::move (param_type)), param_kind (param_kind), + std::unique_ptr param_type, std::vector outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), param_type (std::move (param_type)), param_kind (param_kind), name (std::move (name)), locus (locus) {} // Copy constructor with clone MaybeNamedParam (MaybeNamedParam const &other) - : param_kind (other.param_kind), name (other.name), locus (other.locus) + : outer_attrs (other.outer_attrs), param_kind (other.param_kind), name (other.name), locus (other.locus) { // guard to prevent null dereference if (other.param_type != nullptr) @@ -663,6 +729,7 @@ public: // Overloaded assignment operator with clone MaybeNamedParam &operator= (MaybeNamedParam const &other) { + outer_attrs = other.outer_attrs; name = other.name; param_kind = other.param_kind; locus = other.locus; @@ -688,10 +755,20 @@ public: // Creates an error state param. static MaybeNamedParam create_error () { - return MaybeNamedParam ("", UNNAMED, nullptr, Location ()); + return MaybeNamedParam ("", UNNAMED, nullptr, {}, Location ()); } Location get_locus () const { return locus; } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector &get_outer_attrs () { return outer_attrs; } + const std::vector &get_outer_attrs () const { return outer_attrs; } + + // TODO: would a "vis_type" be better? + std::unique_ptr &get_type () { + rust_assert (param_type != nullptr); + return param_type; + } }; /* A function pointer type - can be created via coercion from function items and @@ -705,6 +782,7 @@ class BareFunctionType : public TypeNoBounds FunctionQualifiers function_qualifiers; std::vector params; bool is_variadic; + std::vector variadic_attrs; // bool has_return_type; // BareFunctionReturnType return_type; @@ -721,19 +799,22 @@ public: BareFunctionType (std::vector lifetime_params, FunctionQualifiers qualifiers, - std::vector named_params, bool is_variadic, + std::vector named_params, bool is_variadic, std::vector variadic_attrs, std::unique_ptr type, Location locus) : for_lifetimes (std::move (lifetime_params)), function_qualifiers (std::move (qualifiers)), params (std::move (named_params)), is_variadic (is_variadic), - return_type (std::move (type)), locus (locus) - {} + variadic_attrs (std::move (variadic_attrs)), return_type (std::move (type)), locus (locus) + { + if (!variadic_attrs.empty()) + is_variadic = true; + } // Copy constructor with clone BareFunctionType (BareFunctionType const &other) : for_lifetimes (other.for_lifetimes), function_qualifiers (other.function_qualifiers), params (other.params), - is_variadic (other.is_variadic), locus (other.locus) + is_variadic (other.is_variadic), variadic_attrs (other.variadic_attrs), locus (other.locus) { // guard to prevent null dereference if (other.return_type != nullptr) @@ -747,6 +828,7 @@ public: function_qualifiers = other.function_qualifiers; params = other.params; is_variadic = other.is_variadic; + variadic_attrs = other.variadic_attrs; locus = other.locus; // guard to prevent null dereference @@ -769,6 +851,16 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems kinda dodgy + std::vector &get_function_params () { return params; } + const std::vector &get_function_params () const { return params; } + + // TODO: would a "vis_type" be better? + std::unique_ptr &get_return_type () { + rust_assert (has_return_type ()); + return return_type; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index d684c7d..3691f9e 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -88,21 +88,21 @@ bool Compilation::compileVarDecl (Bfunction *fndecl, AST::LetStmt *stmt, std::vector &vars) { - AST::Type *type = stmt->has_type () ? stmt->type.get () : stmt->inferedType; + AST::Type *type = stmt->has_type () ? stmt->get_type ().get () : stmt->inferedType; translatedType = NULL; type->accept_vis (*this); if (translatedType == NULL) { - rust_error_at (stmt->locus, "failed to compile type for var decl"); + rust_error_at (stmt->get_locus (), "failed to compile type for var decl"); return false; } - stmt->variables_pattern->accept_vis (*this); + stmt->get_pattern ()->accept_vis (*this); for (auto &pattern : patternBuffer) { auto var = backend->local_variable (fndecl, pattern.get_ident (), translatedType, NULL /*decl_var*/, - false /*address_taken*/, stmt->locus); + false /*address_taken*/, stmt->get_locus ()); vars.push_back (var); scope.InsertVar (pattern.get_ident (), var); } @@ -1298,7 +1298,7 @@ Compilation::visit (AST::LetStmt &stmt) if (!stmt.has_init_expr ()) return; - stmt.variables_pattern->accept_vis (*this); + stmt.get_pattern ()->accept_vis (*this); for (auto &pattern : patternBuffer) { Bvariable *var = NULL; diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 2fe84cb..95fb962 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -2349,6 +2349,7 @@ namespace Rust { } } + // I don't think it would be possible to strip macros without expansion void visit(AST::MacroMatchFragment& match) override {} void visit(AST::MacroMatchRepetition& match) override {} void visit(AST::MacroMatcher& matcher) override {} @@ -2401,13 +2402,23 @@ namespace Rust { // not possible } void visit(AST::RangePatternBoundPath& bound) override { - // TODO: maybe possible if path is possible + // can expand path, but not strip it directly + auto& path = bound.get_path(); + visit(path); + if (path.is_marked_for_strip()) + rust_error_at(path.get_locus(), "cannot strip path in this position"); } void visit(AST::RangePatternBoundQualPath& bound) override { - // TODO: maybe possible if path is possible + // can expand path, but not strip it directly + auto& path = bound.get_qualified_path(); + visit(path); + if (path.is_marked_for_strip()) + rust_error_at(path.get_locus(), "cannot strip path in this position"); } void visit(AST::RangePattern& pattern) override { - // TODO: possible if any bounds are possible + // should have no capability to strip lower or upper bounds, only expand + pattern.get_lower_bound()->accept_vis(*this); + pattern.get_upper_bound()->accept_vis(*this); } void visit(AST::ReferencePattern& pattern) override { auto& sub_pattern = pattern.get_referenced_pattern(); @@ -2452,6 +2463,12 @@ namespace Rust { } } void visit(AST::StructPattern& pattern) override { + // expand (but don't strip) path + auto& path = pattern.get_path(); + visit(path); + if (path.is_marked_for_strip()) + rust_error_at(path.get_locus(), "cannot strip path in this position"); + // TODO: apparently struct pattern fields can have outer attrs. so can they be stripped? if (!pattern.has_struct_pattern_elems()) return; @@ -2506,7 +2523,11 @@ namespace Rust { } } void visit(AST::TupleStructPattern& pattern) override { - // TODO: stripping of path? + // expand (but don't strip) path + auto& path = pattern.get_path(); + visit(path); + if (path.is_marked_for_strip()) + rust_error_at(path.get_locus(), "cannot strip path in this position"); if (pattern.has_items()) pattern.get_items()->accept_vis(*this); @@ -2578,6 +2599,14 @@ namespace Rust { pattern->accept_vis(*this); if (pattern->is_marked_for_strip()) rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); + + // similar for type + if (stmt.has_type()) { + auto& type = stmt.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + } /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be @@ -2621,25 +2650,123 @@ namespace Rust { } } - // stripping shouldn't be required or possible for types - void visit(AST::TraitBound& bound) override {} - void visit(AST::ImplTraitType& type) override {} - void visit(AST::TraitObjectType& type) override {} - void visit(AST::ParenthesisedType& type) override {} - void visit(AST::ImplTraitTypeOneBound& type) override {} - void visit(AST::TraitObjectTypeOneBound& type) override {} - void visit(AST::TupleType& type) override {} - void visit(AST::NeverType& type) override {} - void visit(AST::RawPointerType& type) override {} - void visit(AST::ReferenceType& type) override {} + void visit(AST::TraitBound& bound) override { + // nothing in for lifetimes to strip + + // expand but don't strip type path + auto& path = bound.get_type_path(); + visit(path); + if (path.is_marked_for_strip()) + rust_error_at(path.get_locus(), "cannot strip type path in this position"); + } + void visit(AST::ImplTraitType& type) override { + // don't strip directly, only components of bounds + for (auto& bound : type.get_type_param_bounds()) + bound->accept_vis(*this); + } + void visit(AST::TraitObjectType& type) override { + // don't strip directly, only components of bounds + for (auto& bound : type.get_type_param_bounds()) + bound->accept_vis(*this); + } + void visit(AST::ParenthesisedType& type) override { + // expand but don't strip inner type + auto& inner_type = type.get_type_in_parens(); + inner_type->accept_vis(*this); + if (inner_type->is_marked_for_strip()) + rust_error_at(inner_type->get_locus_slow(), "cannot strip type in this position"); + } + void visit(AST::ImplTraitTypeOneBound& type) override { + // no stripping possible + visit(type.get_trait_bound()); + } + void visit(AST::TraitObjectTypeOneBound& type) override { + // no stripping possible + visit(type.get_trait_bound()); + } + void visit(AST::TupleType& type) override { + // TODO: assuming that types can't be stripped as types don't have outer attributes + for (auto& elem_type : type.get_elems()) { + elem_type->accept_vis(*this); + if (elem_type->is_marked_for_strip()) + rust_error_at(elem_type->get_locus_slow(), "cannot strip type in this position"); + } + } + void visit(AST::NeverType& type) override { + // no stripping possible + } + void visit(AST::RawPointerType& type) override { + // expand but don't strip type pointed to + auto& pointed_type = type.get_type_pointed_to(); + pointed_type->accept_vis(*this); + if (pointed_type->is_marked_for_strip()) + rust_error_at(pointed_type->get_locus_slow(), "cannot strip type in this position"); + } + void visit(AST::ReferenceType& type) override { + // expand but don't strip type referenced + auto& referenced_type = type.get_type_referenced(); + referenced_type->accept_vis(*this); + if (referenced_type->is_marked_for_strip()) + rust_error_at(referenced_type->get_locus_slow(), "cannot strip type in this position"); + } void visit(AST::ArrayType& type) override { - // TODO: array type contains a "constant expression" - could this have strippable sub-exprs? + // expand but don't strip type referenced + auto& base_type = type.get_elem_type(); + base_type->accept_vis(*this); + if (base_type->is_marked_for_strip()) + rust_error_at(base_type->get_locus_slow(), "cannot strip type in this position"); + + // same for expression + auto& size_expr = type.get_size_expr(); + size_expr->accept_vis(*this); + if (size_expr->is_marked_for_strip()) + rust_error_at(size_expr->get_locus_slow(), "cannot strip expression in this position"); + } + void visit(AST::SliceType& type) override { + // expand but don't strip elem type + auto& elem_type = type.get_elem_type(); + elem_type->accept_vis(*this); + if (elem_type->is_marked_for_strip()) + rust_error_at(elem_type->get_locus_slow(), "cannot strip type in this position"); + } + void visit(AST::InferredType& type) override { + // none possible } - void visit(AST::SliceType& type) override {} - void visit(AST::InferredType& type) override {} void visit(AST::BareFunctionType& type) override { - // TODO: bare function type contains "maybe-named params" that have outer attributes - could this be strippable? - // apparently "attribute rules are same as on regular function params", so looks like a yes + // seem to be no generics + + // presumably function params can be stripped + auto& params = type.get_function_params(); + for (int i = 0; i < params.size();) { + auto& param = params[i]; + + auto& param_attrs = param.get_outer_attrs(); + expander.expand_cfg_attrs(param_attrs); + if (expander.fails_cfg(param_attrs)) { + params.erase(params.begin() + i); + continue; + } + + auto& type = param.get_type(); + type->accept_vis(*this); + if (type->is_marked_for_strip()) + rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); + + // increment if nothing else happens + i++; + } + + /* TODO: assuming that variadic nature cannot be stripped. If this + * is not true, then have code here to do so. */ + + if (type.has_return_type()) { + auto& return_type = type.get_return_type(); + return_type->accept_vis(*this); + if (return_type->is_marked_for_strip()) + rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); + } + + // no where clause, apparently } }; diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 88252ac..3315da3 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -9205,7 +9205,7 @@ Parser::parse_for_prefixed_type () // Parses a maybe named param used in bare function types. template AST::MaybeNamedParam -Parser::parse_maybe_named_param () +Parser::parse_maybe_named_param (std::vector outer_attrs) { /* Basically guess that param is named if first token is identifier or * underscore and second token is semicolon. This should probably have no @@ -9242,7 +9242,7 @@ Parser::parse_maybe_named_param () } return AST::MaybeNamedParam (std::move (name), kind, std::move (type), - current->get_locus ()); + std::move (outer_attrs), current->get_locus ()); } /* Parses a bare function type (with the given for lifetimes for convenience - @@ -9258,63 +9258,58 @@ Parser::parse_bare_function_type ( AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); if (!skip_token (FN_TOK)) - { return nullptr; - } if (!skip_token (LEFT_PAREN)) - { return nullptr; - } // parse function params, if they exist std::vector params; bool is_variadic = false; - const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_PAREN) - { - // handle ellipsis (only if next character is right paren) - if (t->get_id () == ELLIPSIS) - { - if (lexer.peek_token (1)->get_id () == RIGHT_PAREN) - { - lexer.skip_token (); - is_variadic = true; - break; - } - else - { - rust_error_at (t->get_locus (), - "ellipsis (for variadic) can only go at end of " - "bare function type"); - return nullptr; - } - } + std::vector variadic_attrs; - // parse required param - AST::MaybeNamedParam param = parse_maybe_named_param (); - if (param.is_error ()) - { - rust_error_at ( - t->get_locus (), - "failed to parse maybe named param in bare function type"); - return nullptr; - } - params.push_back (std::move (param)); + const_TokenPtr t = lexer.peek_token (); + while (t->get_id () != RIGHT_PAREN) + { + std::vector temp_attrs = parse_outer_attributes (); - if (lexer.peek_token ()->get_id () != COMMA) - { - break; - } + if (lexer.peek_token ()->get_id () == ELLIPSIS) + { lexer.skip_token (); + is_variadic = true; + variadic_attrs = std::move (temp_attrs); t = lexer.peek_token (); + + if (t->get_id() != RIGHT_PAREN) + { + rust_error_at (t->get_locus (), + "expected right parentheses after variadic in maybe named function " + "parameters, found %qs", + t->get_token_description ()); + return nullptr; + } + + break; } - if (!skip_token (RIGHT_PAREN)) + AST::MaybeNamedParam param = parse_maybe_named_param (std::move (temp_attrs)); + if (param.is_error ()) { + rust_error_at (lexer.peek_token ()->get_locus (), "failed to parse maybe named param in bare function type"); return nullptr; } + params.push_back (std::move (param)); + + if (lexer.peek_token ()->get_id () != COMMA) + break; + + lexer.skip_token (); + t = lexer.peek_token (); + } + + if (!skip_token (RIGHT_PAREN)) + return nullptr; // bare function return type, if exists std::unique_ptr return_type = nullptr; @@ -9335,7 +9330,7 @@ Parser::parse_bare_function_type ( return std::unique_ptr (new AST::BareFunctionType ( std::move (for_lifetimes), std::move (qualifiers), std::move (params), - is_variadic, std::move (return_type), best_try_locus)); + is_variadic, std::move (variadic_attrs), std::move (return_type), best_try_locus)); } // Parses a reference type (mutable or immutable, with given lifetime). diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index a6de87b..7218ebc 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -545,7 +545,7 @@ private: std::unique_ptr parse_paren_prefixed_type (); std::unique_ptr parse_paren_prefixed_type_no_bounds (); std::unique_ptr parse_for_prefixed_type (); - AST::MaybeNamedParam parse_maybe_named_param (); + AST::MaybeNamedParam parse_maybe_named_param (std::vector outer_attrs); // Statement-related std::unique_ptr parse_stmt (); -- cgit v1.1 From 0e5d54bcb0d9e540fdf063b8602610ec4cc9e155 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Wed, 9 Dec 2020 10:59:13 +0800 Subject: Changed compiled files in makefile to be identical with upstream - hopefully prevents compile error --- gcc/rust/Make-lang.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc/rust') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 3293f90..35d5758 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -69,7 +69,8 @@ GRS_OBJS = \ rust/rust-parse.o \ rust/rust-ast-full-test.o \ rust/rust-session-manager.o \ - rust/rust-resolution.o \ + rust/rust-name-resolution.o \ + rust/rust-type-resolution.o \ rust/rust-scan.o \ rust/rust-compile.o \ rust/rust-macro-expand.o \ -- cgit v1.1 From 815c9e8b0734d45a6e5b5a7d50f38d4af7120a8c Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Wed, 9 Dec 2020 14:07:05 +0800 Subject: Fixed rust-type-resolution.cc compile error --- gcc/rust/analysis/rust-type-resolution.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc/rust') diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 2c720c6..3e2db7f 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -1046,7 +1046,7 @@ TypeResolution::visit (AST::LetStmt &stmt) } else if (stmt.has_type () && !stmt.has_init_expr ()) { - inferedType = stmt.type.get (); + inferedType = stmt.get_type ().get (); } // TODO check we know what the type is in the scope requires the builtins to -- cgit v1.1 From b343d117f5cf7976d3c4c93d9595e2471d780acd Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Wed, 9 Dec 2020 16:01:35 +0800 Subject: Fixed rust-compile.cc compile error --- gcc/rust/backend/rust-compile.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index dd28759..300240f 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -550,7 +550,7 @@ Compilation::visit (AST::ArrayExpr &expr) translatedType = nullptr; auto before = arrayConsStack.size (); - expr.get_internal_elements ()->accept_vis (*this); + expr.get_array_elems ()->accept_vis (*this); if (arrayConsStack.size () <= before) { rust_error_at (expr.get_locus_slow (), @@ -1465,7 +1465,7 @@ Compilation::visit (AST::ArrayType &type) { Btype *elementType; translatedType = nullptr; - type.get_element_type ()->accept_vis (*this); + type.get_elem_type ()->accept_vis (*this); if (translatedType == nullptr) { rust_error_at (type.get_locus (), -- cgit v1.1 From 53ddea7a266c43f30702b0c24ce05e4d5dad0ecc Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Wed, 9 Dec 2020 17:42:16 +0800 Subject: Fixed formatting to fit gcc style --- gcc/rust/ast/rust-ast-full-test.cc | 265 +- gcc/rust/ast/rust-ast.h | 55 +- gcc/rust/ast/rust-expr.h | 492 ++- gcc/rust/ast/rust-item.h | 667 ++-- gcc/rust/ast/rust-macro.h | 7 +- gcc/rust/ast/rust-path.h | 101 +- gcc/rust/ast/rust-pattern.h | 191 +- gcc/rust/ast/rust-stmt.h | 34 +- gcc/rust/ast/rust-type.h | 102 +- gcc/rust/expand/rust-macro-expand.cc | 6238 ++++++++++++++++++---------------- gcc/rust/expand/rust-macro-expand.h | 7 +- gcc/rust/rust-session-manager.cc | 3 +- 12 files changed, 4622 insertions(+), 3540 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 26a3356..030b0b3 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -171,13 +171,14 @@ Attribute::as_string () const { std::string path_str = path.as_string (); if (attr_input == nullptr) - return path_str; + return path_str; else - return path_str + attr_input->as_string (); + return path_str + attr_input->as_string (); } // Copy constructor must deep copy attr_input as unique pointer -Attribute::Attribute (Attribute const &other) : path (other.path), locus (other.locus) +Attribute::Attribute (Attribute const &other) + : path (other.path), locus (other.locus) { // guard to protect from null pointer dereference if (other.attr_input != nullptr) @@ -185,7 +186,8 @@ Attribute::Attribute (Attribute const &other) : path (other.path), locus (other. } // overload assignment operator to use custom clone method -Attribute &Attribute::operator= (Attribute const &other) +Attribute & +Attribute::operator= (Attribute const &other) { path = other.path; locus = other.locus; @@ -330,7 +332,7 @@ VisItem::as_string () const if (!outer_attrs.empty ()) { for (const auto &attr : outer_attrs) - str += attr.as_string () + "\n"; + str += attr.as_string () + "\n"; } if (has_visibility ()) @@ -678,20 +680,20 @@ Method::as_string () const else { for (const auto ¶m : function_params) - str += "\n " + param.as_string (); + str += "\n " + param.as_string (); } str += "\n Return type: "; if (has_return_type ()) - str += return_type->as_string (); + str += return_type->as_string (); else - str += "none (void)"; + str += "none (void)"; str += "\n Where clause: "; if (has_where_clause ()) - str += where_clause.as_string (); + str += where_clause.as_string (); else - str += "none"; + str += "none"; str += "\n Block expr (body): \n "; str += function_body->as_string (); @@ -1168,7 +1170,7 @@ Function::as_string () const } if (has_where_clause ()) - str += " where " + where_clause.as_string (); + str += " where " + where_clause.as_string (); str += "\n"; @@ -1199,7 +1201,7 @@ WhereClause::as_string () const else { for (const auto &item : where_clause_items) - str += "\n " + item->as_string (); + str += "\n " + item->as_string (); } return str; @@ -1224,7 +1226,7 @@ BlockExpr::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 (); + str += "\n" + indent_spaces (stay) + attr.as_string (); } // statements @@ -1254,9 +1256,9 @@ BlockExpr::as_string () const // final expression str += "\n" + indent_spaces (stay) + "final expression: "; if (expr == nullptr) - str += "none"; + str += "none"; else - str += "\n" + expr->as_string (); + str += "\n" + expr->as_string (); str += "\n" + indent_spaces (out) + "}"; return str; @@ -1268,7 +1270,7 @@ TraitImpl::as_string () const std::string str = VisItem::as_string (); if (has_unsafe) - str += "unsafe "; + str += "unsafe "; str += "impl "; @@ -1281,14 +1283,14 @@ TraitImpl::as_string () const else { for (const auto ¶m : generic_params) - str += "\n " + param->as_string (); + str += "\n " + param->as_string (); } str += "\n Has exclam: "; if (has_exclam) - str += "true"; + str += "true"; else - str += "false"; + str += "false"; str += "\n TypePath (to trait): " + trait_path.as_string (); @@ -1296,9 +1298,9 @@ TraitImpl::as_string () const str += "\n Where clause: "; if (!has_where_clause ()) - str += "none"; + str += "none"; else - str += where_clause.as_string (); + str += where_clause.as_string (); // inner attributes str += "\n inner attributes: "; @@ -1311,7 +1313,7 @@ TraitImpl::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 (); + str += "\n " + attr.as_string (); } str += "\n trait impl items: "; @@ -1322,7 +1324,7 @@ TraitImpl::as_string () const else { for (const auto &item : impl_items) - str += "\n " + item->as_string (); + str += "\n " + item->as_string (); } return str; @@ -1378,7 +1380,7 @@ MacroInvocationSemi::as_string () const if (!outer_attrs.empty ()) { for (const auto &attr : outer_attrs) - str += attr.as_string () + "\n"; + str += attr.as_string () + "\n"; } str += "\n" + path.as_string () + "!"; @@ -1438,7 +1440,7 @@ ExternBlock::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 (); + str += "\n " + attr.as_string (); } str += "\n external items: "; @@ -1449,7 +1451,7 @@ ExternBlock::as_string () const else { for (const auto &item : extern_items) - str += "\n " + item->as_string (); + str += "\n " + item->as_string (); } return str; @@ -1478,7 +1480,7 @@ MacroRulesDefinition::as_string () const if (!outer_attrs.empty ()) { for (const auto &attr : outer_attrs) - str += attr.as_string () + "\n"; + str += attr.as_string () + "\n"; } str += "macro_rules!"; @@ -1493,7 +1495,7 @@ MacroRulesDefinition::as_string () const else { for (const auto &rule : rules) - str += "\n " + rule.as_string (); + str += "\n " + rule.as_string (); } str += "\n Delim type: "; @@ -1528,7 +1530,7 @@ PathInExpression::as_string () const std::string str; if (has_opening_scope_resolution) - str = "::"; + str = "::"; return str + PathPattern::as_string (); } @@ -1559,7 +1561,7 @@ ClosureParam::as_string () const std::string str (pattern->as_string ()); if (has_type_given ()) - str += " : " + type->as_string (); + str += " : " + type->as_string (); return str; } @@ -1569,9 +1571,9 @@ ClosureExpr::as_string () const { std::string str ("ClosureExpr:\n Has move: "); if (has_move) - str += "true"; + str += "true"; else - str += "false"; + str += "false"; str += "\n Params: "; if (params.empty ()) @@ -1581,7 +1583,7 @@ ClosureExpr::as_string () const else { for (const auto ¶m : params) - str += "\n " + param.as_string (); + str += "\n " + param.as_string (); } return str; @@ -1605,7 +1607,7 @@ PathPattern::as_string () const std::string str; for (const auto &segment : segments) - str += segment.as_string () + "::"; + str += segment.as_string () + "::"; // basically a hack - remove last two characters of string (remove final ::) str.erase (str.length () - 2); @@ -1620,7 +1622,7 @@ QualifiedPathType::as_string () const str += type_to_invoke_on->as_string (); if (has_as_clause ()) - str += " as " + trait_path.as_string (); + str += " as " + trait_path.as_string (); return str + ">"; } @@ -1637,10 +1639,10 @@ BorrowExpr::as_string () const std::string str ("&"); if (double_borrow) - str += "&"; + str += "&"; if (is_mut) - str += "mut "; + str += "mut "; str += main_or_left_expr->as_string (); @@ -1653,7 +1655,7 @@ ReturnExpr::as_string () const std::string str ("return "); if (has_returned_expr ()) - str += return_expr->as_string (); + str += return_expr->as_string (); return str; } @@ -1674,7 +1676,7 @@ GroupedExpr::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 (); + str += "\n " + attr.as_string (); } str += "\n Expr in parens: " + expr_in_parens->as_string (); @@ -1694,7 +1696,7 @@ ContinueExpr::as_string () const std::string str ("continue "); if (has_label ()) - str += label.as_string (); + str += label.as_string (); return str; } @@ -1829,7 +1831,7 @@ MethodCallExpr::as_string () const for (const auto ¶m : params) { if (param == nullptr) - return "ERROR_MARK_STRING - method call expr param is null"; + return "ERROR_MARK_STRING - method call expr param is null"; str += "\n " + param->as_string (); } @@ -1968,7 +1970,7 @@ IfLetExpr::as_string () const else { for (const auto &pattern : match_arm_patterns) - str += "\n " + pattern->as_string (); + str += "\n " + pattern->as_string (); } str += "\n Scrutinee expr: " + value->as_string (); @@ -2157,7 +2159,7 @@ CallExpr::as_string () const for (const auto ¶m : params) { if (param == nullptr) - return "ERROR_MARK_STRING - call expr param is null"; + return "ERROR_MARK_STRING - call expr param is null"; str += "\n " + param->as_string (); } @@ -2173,9 +2175,9 @@ WhileLoopExpr::as_string () const str += "\n Label: "; if (!has_loop_label ()) - str += "none"; + str += "none"; else - str += loop_label.as_string (); + str += loop_label.as_string (); str += "\n Conditional expr: " + condition->as_string (); @@ -2191,9 +2193,9 @@ WhileLetLoopExpr::as_string () const str += "\n Label: "; if (!has_loop_label ()) - str += "none"; + str += "none"; else - str += loop_label.as_string (); + str += loop_label.as_string (); str += "\n Match arm patterns: "; if (match_arm_patterns.empty ()) @@ -2203,7 +2205,7 @@ WhileLetLoopExpr::as_string () const else { for (const auto &pattern : match_arm_patterns) - str += "\n " + pattern->as_string (); + str += "\n " + pattern->as_string (); } str += "\n Scrutinee expr: " + scrutinee->as_string (); @@ -2220,9 +2222,9 @@ LoopExpr::as_string () const str += "\n Label: "; if (!has_loop_label ()) - str += "none"; + str += "none"; else - str += loop_label.as_string (); + str += loop_label.as_string (); str += "\n Loop block: " + loop_block->as_string (); @@ -2245,14 +2247,14 @@ ArrayExpr::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 (); + str += "\n " + attr.as_string (); } str += "\n Array elems: "; if (!has_array_elems ()) - str += "none"; + str += "none"; else - str += internal_elements->as_string (); + str += internal_elements->as_string (); return str; } @@ -2269,10 +2271,10 @@ BreakExpr::as_string () const std::string str ("break "); if (has_label ()) - str += label.as_string () + " "; + str += label.as_string () + " "; if (has_break_expr ()) - str += break_expr->as_string (); + str += break_expr->as_string (); return str; } @@ -2297,7 +2299,7 @@ MatchArm::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 " + attr.as_string (); } str += "\nPatterns: "; @@ -2308,14 +2310,14 @@ MatchArm::as_string () const else { for (const auto &pattern : match_arm_patterns) - str += "\n " + pattern->as_string (); + str += "\n " + pattern->as_string (); } str += "\nGuard expr: "; if (!has_match_arm_guard ()) - str += "none"; + str += "none"; else - str += guard_expr->as_string (); + str += guard_expr->as_string (); return str; } @@ -3629,7 +3631,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 (); + str += "\n" + indent_spaces (stay) + attr.as_string (); } indent_spaces (out); indent_spaces (out); @@ -3655,7 +3657,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 (); + str += "\n " + attr.as_string (); } return str; @@ -3665,9 +3667,9 @@ std::string StructBase::as_string () const { if (base_struct != nullptr) - return base_struct->as_string (); + return base_struct->as_string (); else - return "ERROR_MARK_STRING - invalid struct base had as string applied"; + return "ERROR_MARK_STRING - invalid struct base had as string applied"; } std::string @@ -3702,14 +3704,14 @@ StructExprStructFields::as_string () const else { for (const auto &field : fields) - str += "\n " + field->as_string (); + str += "\n " + field->as_string (); } str += "\n Struct base: "; if (!has_struct_base ()) - str += "none"; + str += "none"; else - str += struct_base.as_string (); + str += struct_base.as_string (); return str; } @@ -3729,7 +3731,7 @@ EnumExprStruct::as_string () const else { for (const auto &field : fields) - str += "\n " + field->as_string (); + str += "\n " + field->as_string (); } return str; @@ -3768,7 +3770,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 " + attr.as_string (); } str += "\n" + variant_name; @@ -3940,7 +3942,7 @@ ExternalStaticItem::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 " + attr.as_string (); } // start visibility on new line and with a space @@ -3949,7 +3951,7 @@ ExternalStaticItem::as_string () const str += "static "; if (has_mut) - str += "mut "; + str += "mut "; // add name str += item_name; @@ -3974,7 +3976,7 @@ ExternalFunctionItem::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 " + attr.as_string (); } // start visibility on new line and with a space @@ -4018,21 +4020,20 @@ ExternalFunctionItem::as_string () const else { for (const auto ¶m : function_params) - str += "\n " + param.as_string (); - + str += "\n " + param.as_string (); + if (has_variadics) { - 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 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)"; } } @@ -4043,9 +4044,9 @@ ExternalFunctionItem::as_string () const // where clause str += "\n Where clause: "; if (has_where_clause ()) - str += where_clause.as_string (); + str += where_clause.as_string (); else - str += "none"; + str += "none"; return str; } @@ -4055,14 +4056,14 @@ NamedFunctionParam::as_string () const { std::string str = "outer attributes: "; - if (!has_outer_attrs ()) + if (!has_outer_attrs ()) { str += "none"; - } - else + } + else { - for (const auto& attr : outer_attrs) - str += "\n " + attr.as_string (); + for (const auto &attr : outer_attrs) + str += "\n " + attr.as_string (); } str += "\n" + name; @@ -4735,7 +4736,8 @@ MacroParser::parse_meta_item_inner () std::vector meta_name_value_str_items; for (const auto &item : meta_items) { - std::unique_ptr converted_item = item->to_meta_name_value_str (); + std::unique_ptr converted_item + = item->to_meta_name_value_str (); if (converted_item == nullptr) { meta_name_value_str_items.clear (); @@ -5053,7 +5055,9 @@ MacroParser::parse_meta_item_lit () bool AttrInputMetaItemContainer::check_cfg_predicate (const Session &session) const { - /* NOTE: assuming that only first item must be true - cfg should only have one item, and cfg_attr only has first item as predicate. TODO ensure that this is correct. */ + /* NOTE: assuming that only first item must be true - cfg should only have one + * item, and cfg_attr only has first item as predicate. TODO ensure that this + * is correct. */ if (items.empty ()) return false; @@ -5352,52 +5356,61 @@ MetaItemPathLit::to_attribute () const new AttrInputLiteral (lit))); } -std::vector AttrInputMetaItemContainer::separate_cfg_attrs () const { - rust_assert (!items.empty ()); +std::vector +AttrInputMetaItemContainer::separate_cfg_attrs () const +{ + rust_assert (!items.empty ()); - if (items.size () == 1) - return {}; + if (items.size () == 1) + return {}; - std::vector attrs; - attrs.reserve (items.size () - 1); + std::vector attrs; + attrs.reserve (items.size () - 1); - for (auto it = items.begin () + 1; it != items.end (); ++it) { + for (auto it = items.begin () + 1; it != items.end (); ++it) + { Attribute attr = (*it)->to_attribute (); - if (attr.is_empty ()) { - // TODO should this be an error that causes us to chuck out everything? - continue; - } + if (attr.is_empty ()) + { + // TODO should this be an error that causes us to chuck out + // everything? + continue; + } attrs.push_back (std::move (attr)); } - attrs.shrink_to_fit (); - return attrs; - } + attrs.shrink_to_fit (); + return attrs; +} -bool Attribute::check_cfg_predicate (const Session &session) - { - /* assume that cfg predicate actually can exist, i.e. attribute has cfg or - * cfg_attr path */ - if (!has_attr_input () || (path.as_string () != "cfg" && path.as_string () != "cfg_attr")) - return false; +bool +Attribute::check_cfg_predicate (const Session &session) +{ + /* assume that cfg predicate actually can exist, i.e. attribute has cfg or + * cfg_attr path */ + if (!has_attr_input () + || (path.as_string () != "cfg" && path.as_string () != "cfg_attr")) + return false; - // TODO: maybe replace with storing a "has been parsed" variable? - parse_attr_to_meta_item (); - // can't be const because of this anyway + // TODO: maybe replace with storing a "has been parsed" variable? + parse_attr_to_meta_item (); + // can't be const because of this anyway - return attr_input->check_cfg_predicate (session); - } + return attr_input->check_cfg_predicate (session); +} -std::vector Attribute::separate_cfg_attrs () { - if (!has_attr_input () || path.as_string () != "cfg_attr") - return {}; +std::vector +Attribute::separate_cfg_attrs () +{ + if (!has_attr_input () || path.as_string () != "cfg_attr") + return {}; - // TODO: maybe replace with storing a "has been parsed" variable? - parse_attr_to_meta_item (); - // can't be const because of this anyway + // TODO: maybe replace with storing a "has been parsed" variable? + parse_attr_to_meta_item (); + // can't be const because of this anyway - return attr_input->separate_cfg_attrs (); - } + return attr_input->separate_cfg_attrs (); +} /* Visitor implementations - these are short but inlining can't happen anyway * due to virtual functions and I didn't want to make the ast header includes diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index b5e56ba..d23cb81 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -83,7 +83,7 @@ public: /* Converts token tree to a flat token stream. Tokens must be pointer to avoid * mutual dependency with Token. */ - virtual std::vector> to_token_stream () const = 0; + virtual std::vector > to_token_stream () const = 0; protected: // pure virtual clone implementation @@ -193,7 +193,7 @@ public: void accept_vis (ASTVisitor &vis) override; // Return copy of itself but in token stream form. - std::vector> to_token_stream () const override; + std::vector > to_token_stream () const override; TokenId get_id () const { return token_id; } @@ -526,7 +526,7 @@ protected: class DelimTokenTree : public TokenTree, public AttrInput { DelimType delim_type; - std::vector> token_trees; + std::vector > token_trees; Location locus; protected: @@ -551,8 +551,8 @@ protected: public: DelimTokenTree (DelimType delim_type, - std::vector> token_trees - = std::vector> (), + std::vector > token_trees + = std::vector > (), Location locus = Location ()) : delim_type (delim_type), token_trees (std::move (token_trees)), locus (locus) @@ -590,8 +590,7 @@ public: void accept_vis (ASTVisitor &vis) override; - bool - check_cfg_predicate (const Session&) const override + bool check_cfg_predicate (const Session &) const override { // this should never be called - should be converted first return false; @@ -599,7 +598,7 @@ public: AttrInput *parse_to_meta_item () const override; - std::vector> to_token_stream () const override; + std::vector > to_token_stream () const override; std::unique_ptr clone_delim_token_tree () const { @@ -636,7 +635,10 @@ public: /* HACK: used to simplify parsing - creates a copy of that type, or returns * null */ - virtual std::unique_ptr to_meta_name_value_str () const { return nullptr; } + virtual std::unique_ptr to_meta_name_value_str () const + { + return nullptr; + } // HACK: used to simplify parsing - same thing virtual SimplePath to_path_item () const @@ -644,7 +646,7 @@ public: return SimplePath::create_empty (); } - virtual Attribute to_attribute() const { return Attribute::create_empty (); } + virtual Attribute to_attribute () const { return Attribute::create_empty (); } virtual bool check_cfg_predicate (const Session &session) const = 0; }; @@ -652,11 +654,11 @@ public: // Container used to store MetaItems as AttrInput (bridge-ish kinda thing) class AttrInputMetaItemContainer : public AttrInput { - std::vector> items; + std::vector > items; public: AttrInputMetaItemContainer ( - std::vector> items) + std::vector > items) : items (std::move (items)) {} @@ -1001,10 +1003,7 @@ public: /* HACK: convert to trait bound. Virtual method overriden by classes that * enable this. */ - virtual TraitBound *to_trait_bound (bool) const - { - return nullptr; - } + virtual TraitBound *to_trait_bound (bool) const { return nullptr; } /* as pointer, shouldn't require definition beforehand, only forward * declaration. */ @@ -1220,7 +1219,7 @@ class MacroItem : public Item { /*public: std::string as_string() const;*/ - //std::vector outer_attrs; + // std::vector outer_attrs; protected: /*MacroItem (std::vector outer_attribs) @@ -1290,7 +1289,7 @@ protected: virtual TraitImplItem *clone_trait_impl_item_impl () const = 0; public: - virtual ~TraitImplItem () {}; + virtual ~TraitImplItem (){}; // Unique pointer custom clone function std::unique_ptr clone_trait_impl_item () const @@ -1335,20 +1334,21 @@ protected: class MacroInvocationSemi : public MacroItem, public TraitItem, public InherentImplItem, - public TraitImplItem, public ExternalItem + public TraitImplItem, + public ExternalItem { std::vector outer_attrs; SimplePath path; // all delim types except curly must have invocation end with a semicolon DelimType delim_type; - std::vector> token_trees; + std::vector > token_trees; Location locus; public: std::string as_string () const override; MacroInvocationSemi (SimplePath macro_path, DelimType delim_type, - std::vector> token_trees, + std::vector > token_trees, std::vector outer_attribs, Location locus) : outer_attrs (std::move (outer_attribs)), path (std::move (macro_path)), delim_type (delim_type), token_trees (std::move (token_trees)), @@ -1358,8 +1358,8 @@ public: // Copy constructor with vector clone MacroInvocationSemi (MacroInvocationSemi const &other) : MacroItem (other), TraitItem (other), InherentImplItem (other), - TraitImplItem (other), outer_attrs(other.outer_attrs), path (other.path), delim_type (other.delim_type), - locus (other.locus) + TraitImplItem (other), outer_attrs (other.outer_attrs), path (other.path), + delim_type (other.delim_type), locus (other.locus) { token_trees.reserve (other.token_trees.size ()); for (const auto &e : other.token_trees) @@ -1458,11 +1458,11 @@ struct Crate // dodgy spacing required here /* TODO: is it better to have a vector of items here or a module (implicit * top-level one)? */ - std::vector> items; + std::vector > items; public: // Constructor - Crate (std::vector> items, + Crate (std::vector > items, std::vector inner_attrs, bool has_utf8bom = false, bool has_shebang = false) : has_utf8bom (has_utf8bom), has_shebang (has_shebang), @@ -1503,13 +1503,14 @@ public: std::string as_string () const; // Delete all crate information, e.g. if fails cfg. - void strip_crate () { + void strip_crate () + { inner_attrs.clear (); inner_attrs.shrink_to_fit (); items.clear (); items.shrink_to_fit (); - // TODO: is this the best way to do this? + // TODO: is this the best way to do this? } }; diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index c7302fe..f129e8c 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -119,8 +119,7 @@ public: /* this can never be a cfg predicate - cfg and cfg_attr require a token-tree * cfg */ - bool - check_cfg_predicate (const Session&) const override { return false; } + bool check_cfg_predicate (const Session &) const override { return false; } protected: /* Use covariance to implement clone function as returning this object rather @@ -241,7 +240,10 @@ public: // Invalid if expr is null, so base stripping on that. void mark_for_strip () override { main_or_left_expr = nullptr; } - bool is_marked_for_strip () const override { return main_or_left_expr == nullptr; } + bool is_marked_for_strip () const override + { + return main_or_left_expr == nullptr; + } }; /* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be @@ -257,14 +259,16 @@ public: BorrowExpr (std::unique_ptr borrow_lvalue, bool is_mut_borrow, bool is_double_borrow, std::vector outer_attribs, Location locus) - : OperatorExpr (std::move (borrow_lvalue), std::move (outer_attribs), - locus), is_mut (is_mut_borrow), double_borrow (is_double_borrow) + : OperatorExpr (std::move (borrow_lvalue), std::move (outer_attribs), + locus), + is_mut (is_mut_borrow), double_borrow (is_double_borrow) {} void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_borrowed_expr () { + std::unique_ptr &get_borrowed_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } @@ -293,7 +297,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_dereferenced_expr () { + std::unique_ptr &get_dereferenced_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } @@ -323,7 +328,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_propagating_expr () { + std::unique_ptr &get_propagating_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } @@ -369,7 +375,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_negated_expr () { + std::unique_ptr &get_negated_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } @@ -446,13 +453,15 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_left_expr () { + std::unique_ptr &get_left_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_right_expr () { + std::unique_ptr &get_right_expr () + { rust_assert (right_expr != nullptr); return right_expr; } @@ -528,13 +537,15 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_left_expr () { + std::unique_ptr &get_left_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_right_expr () { + std::unique_ptr &get_right_expr () + { rust_assert (right_expr != nullptr); return right_expr; } @@ -604,13 +615,15 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_left_expr () { + std::unique_ptr &get_left_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_right_expr () { + std::unique_ptr &get_right_expr () + { rust_assert (right_expr != nullptr); return right_expr; } @@ -657,20 +670,22 @@ public: return *this; } - // move constructors + // move constructors TypeCastExpr (TypeCastExpr &&other) = default; TypeCastExpr &operator= (TypeCastExpr &&other) = default; void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_casted_expr () { + std::unique_ptr &get_casted_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type_to_cast_to () { + std::unique_ptr &get_type_to_cast_to () + { rust_assert (type_to_convert_to != nullptr); return type_to_convert_to; } @@ -727,13 +742,15 @@ public: void visit_rhs (ASTVisitor &vis) { right_expr->accept_vis (vis); } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_left_expr () { + std::unique_ptr &get_left_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_right_expr () { + std::unique_ptr &get_right_expr () + { rust_assert (right_expr != nullptr); return right_expr; } @@ -811,13 +828,15 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_left_expr () { + std::unique_ptr &get_left_expr () + { rust_assert (main_or_left_expr != nullptr); return main_or_left_expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_right_expr () { + std::unique_ptr &get_right_expr () + { rust_assert (right_expr != nullptr); return right_expr; } @@ -891,10 +910,14 @@ public: // Invalid if inner expr is null, so base stripping on that. void mark_for_strip () override { expr_in_parens = nullptr; } - bool is_marked_for_strip () const override { return expr_in_parens == nullptr; } + bool is_marked_for_strip () const override + { + return expr_in_parens == nullptr; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_expr_in_parens () { + std::unique_ptr &get_expr_in_parens () + { rust_assert (expr_in_parens != nullptr); return expr_in_parens; } @@ -969,7 +992,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_values () const { return values; } + const std::vector > &get_values () const + { + return values; + } std::vector > &get_values () { return values; } size_t get_num_values () const { return values.size (); } @@ -1030,13 +1056,15 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_elem_to_copy () { + std::unique_ptr &get_elem_to_copy () + { rust_assert (elem_to_copy != nullptr); return elem_to_copy; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_num_copies () { + std::unique_ptr &get_num_copies () + { rust_assert (num_copies != nullptr); return num_copies; } @@ -1055,7 +1083,7 @@ class ArrayExpr : public ExprWithoutBlock std::unique_ptr internal_elements; Location locus; - + // TODO: find another way to store this to save memory? bool marked_for_strip = false; @@ -1121,7 +1149,8 @@ public: bool is_marked_for_strip () const override { return marked_for_strip; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_array_elems () { + std::unique_ptr &get_array_elems () + { rust_assert (internal_elements != nullptr); return internal_elements; } @@ -1182,7 +1211,7 @@ public: // guard to prevent null dereference (only required if error state) if (other.array_expr != nullptr) array_expr = other.array_expr->clone_expr (); - else + else array_expr = nullptr; if (other.index_expr != nullptr) index_expr = other.index_expr->clone_expr (); @@ -1202,17 +1231,26 @@ public: void accept_vis (ASTVisitor &vis) override; // Invalid if either expr is null, so base stripping on that. - void mark_for_strip () override { array_expr = nullptr; index_expr = nullptr; } - bool is_marked_for_strip () const override { return array_expr == nullptr && index_expr == nullptr; } + void mark_for_strip () override + { + array_expr = nullptr; + index_expr = nullptr; + } + bool is_marked_for_strip () const override + { + return array_expr == nullptr && index_expr == nullptr; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_array_expr () { + std::unique_ptr &get_array_expr () + { rust_assert (array_expr != nullptr); return array_expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_index_expr () { + std::unique_ptr &get_index_expr () + { rust_assert (index_expr != nullptr); return index_expr; } @@ -1295,8 +1333,14 @@ public: bool is_marked_for_strip () const override { return marked_for_strip; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_tuple_elems () const { return tuple_elems; } - std::vector > &get_tuple_elems () { return tuple_elems; } + const std::vector > &get_tuple_elems () const + { + return tuple_elems; + } + std::vector > &get_tuple_elems () + { + return tuple_elems; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -1332,7 +1376,8 @@ public: // Copy constructor requires a clone for tuple_expr TupleIndexExpr (TupleIndexExpr const &other) - : ExprWithoutBlock (other), tuple_index (other.tuple_index), locus (other.locus) + : ExprWithoutBlock (other), tuple_index (other.tuple_index), + locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.tuple_expr != nullptr) @@ -1370,7 +1415,8 @@ public: bool is_marked_for_strip () const override { return tuple_expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_tuple_expr () { + std::unique_ptr &get_tuple_expr () + { rust_assert (tuple_expr != nullptr); return tuple_expr; } @@ -1404,7 +1450,10 @@ public: std::string as_string () const override; // Invalid if path is empty, so base stripping on that. - void mark_for_strip () override { struct_name = PathInExpression::create_error (); } + void mark_for_strip () override + { + struct_name = PathInExpression::create_error (); + } bool is_marked_for_strip () const override { return struct_name.is_error (); } }; @@ -1493,7 +1542,8 @@ public: std::string as_string () const; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_base_struct () { + std::unique_ptr &get_base_struct () + { rust_assert (base_struct != nullptr); return base_struct; } @@ -1577,7 +1627,8 @@ public: std::string as_string () const override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_value () { + std::unique_ptr &get_value () + { rust_assert (value != nullptr); return value; } @@ -1693,8 +1744,14 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector > &get_fields () { return fields; } - const std::vector > &get_fields () const { return fields; } + std::vector > &get_fields () + { + return fields; + } + const std::vector > &get_fields () const + { + return fields; + } StructBase &get_struct_base () { return struct_base; } const StructBase &get_struct_base () const { return struct_base; } @@ -1709,7 +1766,7 @@ protected: }; // AST node of the functional update struct creator -/* TODO: remove and replace with StructExprStructFields, except with empty +/* TODO: remove and replace with StructExprStructFields, except with empty * vector of fields? */ class StructExprStructBase : public StructExprStruct { @@ -1795,7 +1852,10 @@ public: void accept_vis (ASTVisitor &vis) override; - const std::vector > &get_elems () const { return exprs; } + const std::vector > &get_elems () const + { + return exprs; + } std::vector > &get_elems () { return exprs; } protected: @@ -1853,12 +1913,21 @@ protected: {} public: - const PathInExpression& get_enum_variant_path () const { return enum_variant_path; } - PathInExpression& get_enum_variant_path () { return enum_variant_path; } + const PathInExpression &get_enum_variant_path () const + { + return enum_variant_path; + } + PathInExpression &get_enum_variant_path () { return enum_variant_path; } // Invalid if path is in error state, so base stripping on that. - void mark_for_strip () override { enum_variant_path = PathInExpression::create_error (); } - bool is_marked_for_strip () const override { return enum_variant_path.is_error (); } + void mark_for_strip () override + { + enum_variant_path = PathInExpression::create_error (); + } + bool is_marked_for_strip () const override + { + return enum_variant_path.is_error (); + } }; /* Base AST node for a single enum expression field (in enum instance creation) @@ -1942,7 +2011,8 @@ public: std::string as_string () const override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_value () { + std::unique_ptr &get_value () + { rust_assert (value != nullptr); return value; } @@ -2054,7 +2124,10 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector > &get_fields () { return fields; } - const std::vector > &get_fields () const { return fields; } + const std::vector > &get_fields () const + { + return fields; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -2114,7 +2187,10 @@ public: void accept_vis (ASTVisitor &vis) override; - const std::vector > &get_elems () const { return values; } + const std::vector > &get_elems () const + { + return values; + } std::vector > &get_elems () { return values; } protected: @@ -2186,7 +2262,8 @@ public: // copy constructor requires clone CallExpr (CallExpr const &other) - : ExprWithoutBlock (other), locus (other.locus) { + : ExprWithoutBlock (other), locus (other.locus) + { // guard to prevent null dereference (only required if error state) if (other.function != nullptr) function = other.function->clone_expr (); @@ -2233,11 +2310,15 @@ public: bool is_marked_for_strip () const override { return function == nullptr; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_params () const { return params; } + const std::vector > &get_params () const + { + return params; + } std::vector > &get_params () { return params; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_function_expr () { + std::unique_ptr &get_function_expr () + { rust_assert (function != nullptr); return function; } @@ -2276,7 +2357,9 @@ public: // copy constructor required due to cloning MethodCallExpr (MethodCallExpr const &other) - : ExprWithoutBlock (other), method_name (other.method_name), locus (other.locus) { + : ExprWithoutBlock (other), method_name (other.method_name), + locus (other.locus) + { // guard to prevent null dereference (only required if error state) if (other.receiver != nullptr) receiver = other.receiver->clone_expr (); @@ -2321,11 +2404,15 @@ public: bool is_marked_for_strip () const override { return receiver == nullptr; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_params () const { return params; } + const std::vector > &get_params () const + { + return params; + } std::vector > &get_params () { return params; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_receiver_expr () { + std::unique_ptr &get_receiver_expr () + { rust_assert (receiver != nullptr); return receiver; } @@ -2402,7 +2489,8 @@ public: bool is_marked_for_strip () const override { return receiver == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_receiver_expr () { + std::unique_ptr &get_receiver_expr () + { rust_assert (receiver != nullptr); return receiver; } @@ -2438,14 +2526,14 @@ public: // Constructor for closure parameter ClosureParam (std::unique_ptr param_pattern, - std::unique_ptr param_type = nullptr, std::vector outer_attrs = {}) - : outer_attrs (std::move(outer_attrs)), pattern (std::move (param_pattern)), - type (std::move (param_type)) + std::unique_ptr param_type = nullptr, + std::vector 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) - : outer_attrs (other.outer_attrs) + ClosureParam (ClosureParam const &other) : outer_attrs (other.outer_attrs) { // guard to protect from null pointer dereference if (other.pattern != nullptr) @@ -2490,13 +2578,15 @@ public: std::vector &get_outer_attrs () { return outer_attrs; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_pattern () { + std::unique_ptr &get_pattern () + { rust_assert (pattern != nullptr); return pattern; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (has_type_given ()); return type; } @@ -2550,8 +2640,7 @@ public: {} // Copy constructor must be defined to allow copying via cloning of unique_ptr - ClosureExprInner (ClosureExprInner const &other) - : ClosureExpr (other) + ClosureExprInner (ClosureExprInner const &other) : ClosureExpr (other) { // guard to prevent null dereference (only required if error state) if (other.closure_inner != nullptr) @@ -2583,10 +2672,14 @@ public: // Invalid if inner expr is null, so base stripping on that. void mark_for_strip () override { closure_inner = nullptr; } - bool is_marked_for_strip () const override { return 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 &get_definition_expr () { + std::unique_ptr &get_definition_expr () + { rust_assert (closure_inner != nullptr); return closure_inner; } @@ -2633,7 +2726,8 @@ public: // Copy constructor with clone BlockExpr (BlockExpr const &other) - : ExprWithBlock (other), inner_attrs (other.inner_attrs), locus (other.locus) + : ExprWithBlock (other), inner_attrs (other.inner_attrs), + locus (other.locus) { // guard to protect from null pointer dereference if (other.expr != nullptr) @@ -2681,23 +2775,30 @@ public: void accept_vis (ASTVisitor &vis) override; // Invalid if has no statements or final expr, so base stripping on that. - void mark_for_strip () override - { - expr = nullptr; - statements.clear (); - statements.shrink_to_fit (); + void mark_for_strip () override + { + expr = nullptr; + statements.clear (); + statements.shrink_to_fit (); + } + bool is_marked_for_strip () const override + { + return expr == nullptr && statements.empty (); } - bool is_marked_for_strip () const override { return expr == nullptr && statements.empty (); } // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector &get_inner_attrs () const { return inner_attrs; } std::vector &get_inner_attrs () { return inner_attrs; } - const std::vector > &get_statements () const { return statements; } + const std::vector > &get_statements () const + { + return statements; + } std::vector > &get_statements () { return statements; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_tail_expr () { + std::unique_ptr &get_tail_expr () + { rust_assert (expr != nullptr); return expr; } @@ -2783,19 +2884,21 @@ public: void accept_vis (ASTVisitor &vis) override; - /* Invalid if inner expr is null, so base stripping on that. Technically, + /* Invalid if inner expr is null, so base stripping on that. Technically, * type should also not be null. */ void mark_for_strip () override { expr = nullptr; } bool is_marked_for_strip () const override { return expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_definition_block () { + std::unique_ptr &get_definition_block () + { rust_assert (expr != nullptr); return expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_return_type () { + std::unique_ptr &get_return_type () + { rust_assert (return_type != nullptr); return return_type; } @@ -2887,7 +2990,8 @@ public: // Copy constructor defined to use clone for unique pointer BreakExpr (BreakExpr const &other) - : ExprWithoutBlock (other), label (other.label), locus (other.locus), marked_for_strip (other.marked_for_strip) + : ExprWithoutBlock (other), label (other.label), locus (other.locus), + marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference if (other.break_expr != nullptr) @@ -2926,7 +3030,8 @@ public: bool is_marked_for_strip () const override { return marked_for_strip; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_break_expr () { + std::unique_ptr &get_break_expr () + { rust_assert (break_expr != nullptr); return break_expr; } @@ -2973,8 +3078,7 @@ public: {} // Copy constructor with cloning - RangeFromToExpr (RangeFromToExpr const &other) - : RangeExpr (other) + RangeFromToExpr (RangeFromToExpr const &other) : RangeExpr (other) { // guard to prevent null dereference (only required if error state) if (other.from != nullptr) @@ -3007,18 +3111,27 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if either expr is null, so base stripping on that. - void mark_for_strip () override { from = nullptr; to = nullptr; } - bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } + // Invalid if either expr is null, so base stripping on that. + void mark_for_strip () override + { + from = nullptr; + to = nullptr; + } + bool is_marked_for_strip () const override + { + return from == nullptr && to == nullptr; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_from_expr () { + std::unique_ptr &get_from_expr () + { rust_assert (from != nullptr); return from; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_to_expr () { + std::unique_ptr &get_to_expr () + { rust_assert (to != nullptr); return to; } @@ -3046,8 +3159,7 @@ public: {} // Copy constructor with clone - RangeFromExpr (RangeFromExpr const &other) - : RangeExpr (other) + RangeFromExpr (RangeFromExpr const &other) : RangeExpr (other) { // guard to prevent null dereference (only required if error state) if (other.from != nullptr) @@ -3058,7 +3170,7 @@ public: RangeFromExpr &operator= (RangeFromExpr const &other) { RangeExpr::operator= (other); - + // guard to prevent null dereference (only required if error state) if (other.from != nullptr) from = other.from->clone_expr (); @@ -3074,12 +3186,13 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if expr is null, so base stripping on that. + // Invalid if expr is null, so base stripping on that. void mark_for_strip () override { from = nullptr; } bool is_marked_for_strip () const override { return from == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_from_expr () { + std::unique_ptr &get_from_expr () + { rust_assert (from != nullptr); return from; } @@ -3108,8 +3221,7 @@ public: {} // Copy constructor with clone - RangeToExpr (RangeToExpr const &other) - : RangeExpr (other) + RangeToExpr (RangeToExpr const &other) : RangeExpr (other) { // guard to prevent null dereference (only required if error state) if (other.to != nullptr) @@ -3120,7 +3232,7 @@ public: RangeToExpr &operator= (RangeToExpr const &other) { RangeExpr::operator= (other); - + // guard to prevent null dereference (only required if error state) if (other.to != nullptr) to = other.to->clone_expr (); @@ -3136,12 +3248,13 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if expr is null, so base stripping on that. + // Invalid if expr is null, so base stripping on that. void mark_for_strip () override { to = nullptr; } bool is_marked_for_strip () const override { return to == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_to_expr () { + std::unique_ptr &get_to_expr () + { rust_assert (to != nullptr); return to; } @@ -3201,8 +3314,7 @@ public: // outer attributes not allowed // Copy constructor with clone - RangeFromToInclExpr (RangeFromToInclExpr const &other) - : RangeExpr (other) + RangeFromToInclExpr (RangeFromToInclExpr const &other) : RangeExpr (other) { // guard to prevent null dereference (only required if error state) if (other.from != nullptr) @@ -3215,7 +3327,7 @@ public: RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other) { RangeExpr::operator= (other); - + // guard to prevent null dereference (only required if error state) if (other.from != nullptr) from = other.from->clone_expr (); @@ -3235,18 +3347,27 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if either expr is null, so base stripping on that. - void mark_for_strip () override { from = nullptr; to = nullptr; } - bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } + // Invalid if either expr is null, so base stripping on that. + void mark_for_strip () override + { + from = nullptr; + to = nullptr; + } + bool is_marked_for_strip () const override + { + return from == nullptr && to == nullptr; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_from_expr () { + std::unique_ptr &get_from_expr () + { rust_assert (from != nullptr); return from; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_to_expr () { + std::unique_ptr &get_to_expr () + { rust_assert (to != nullptr); return to; } @@ -3275,8 +3396,7 @@ public: // outer attributes not allowed // Copy constructor with clone - RangeToInclExpr (RangeToInclExpr const &other) - : RangeExpr (other) + RangeToInclExpr (RangeToInclExpr const &other) : RangeExpr (other) { // guard to prevent null dereference (only required if error state) if (other.to != nullptr) @@ -3287,7 +3407,7 @@ public: RangeToInclExpr &operator= (RangeToInclExpr const &other) { RangeExpr::operator= (other); - + // guard to prevent null dereference (only required if error state) if (other.to != nullptr) to = other.to->clone_expr (); @@ -3303,12 +3423,13 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if expr is null, so base stripping on that. + // Invalid if expr is null, so base stripping on that. void mark_for_strip () override { to = nullptr; } bool is_marked_for_strip () const override { return to == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_to_expr () { + std::unique_ptr &get_to_expr () + { rust_assert (to != nullptr); return to; } @@ -3348,7 +3469,8 @@ public: // Copy constructor with clone ReturnExpr (ReturnExpr const &other) - : ExprWithoutBlock (other), locus (other.locus), marked_for_strip (other.marked_for_strip) + : ExprWithoutBlock (other), locus (other.locus), + marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference if (other.return_expr != nullptr) @@ -3386,7 +3508,8 @@ public: bool is_marked_for_strip () const override { return marked_for_strip; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_returned_expr () { + std::unique_ptr &get_returned_expr () + { rust_assert (return_expr != nullptr); return return_expr; } @@ -3453,12 +3576,13 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if block is null, so base stripping on that. + // Invalid if block is null, so base stripping on that. void mark_for_strip () override { expr = nullptr; } bool is_marked_for_strip () const override { return expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_block_expr () { + std::unique_ptr &get_block_expr () + { rust_assert (expr != nullptr); return expr; } @@ -3555,12 +3679,13 @@ public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } - // Invalid if loop block is null, so base stripping on that. + // Invalid if loop block is null, so base stripping on that. void mark_for_strip () override { loop_block = nullptr; } bool is_marked_for_strip () const override { return loop_block == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_loop_block () { + std::unique_ptr &get_loop_block () + { rust_assert (loop_block != nullptr); return loop_block; } @@ -3634,7 +3759,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_predicate_expr () { + std::unique_ptr &get_predicate_expr () + { rust_assert (condition != nullptr); return condition; } @@ -3706,14 +3832,21 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_scrutinee_expr () { + std::unique_ptr &get_scrutinee_expr () + { rust_assert (scrutinee != nullptr); return scrutinee; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_patterns () const { return match_arm_patterns; } - std::vector > &get_patterns () { return match_arm_patterns; } + const std::vector > &get_patterns () const + { + return match_arm_patterns; + } + std::vector > &get_patterns () + { + return match_arm_patterns; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -3771,13 +3904,15 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_iterator_expr () { + std::unique_ptr &get_iterator_expr () + { rust_assert (iterator_expr != nullptr); return iterator_expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_pattern () { + std::unique_ptr &get_pattern () + { rust_assert (pattern != nullptr); return pattern; } @@ -3814,8 +3949,7 @@ public: // outer attributes are never allowed on IfExprs // Copy constructor with clone - IfExpr (IfExpr const &other) - : ExprWithBlock (other), locus (other.locus) + IfExpr (IfExpr const &other) : ExprWithBlock (other), locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.condition != nullptr) @@ -3866,20 +4000,29 @@ public: void vis_if_block (ASTVisitor &vis) { if_block->accept_vis (vis); } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_condition_expr () { + std::unique_ptr &get_condition_expr () + { rust_assert (condition != nullptr); return condition; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_if_block () { + std::unique_ptr &get_if_block () + { rust_assert (if_block != nullptr); return if_block; } - // Invalid if if block or condition is null, so base stripping on that. - void mark_for_strip () override { if_block = nullptr; condition = nullptr; } - bool is_marked_for_strip () const override { return if_block == nullptr && condition == nullptr; } + // Invalid if if block or condition is null, so base stripping on that. + void mark_for_strip () override + { + if_block = nullptr; + condition = nullptr; + } + bool is_marked_for_strip () const override + { + return if_block == nullptr && condition == nullptr; + } protected: // Base clone function but still concrete as concrete base class @@ -3934,7 +4077,8 @@ public: void vis_else_block (ASTVisitor &vis) { else_block->accept_vis (vis); } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_else_block () { + std::unique_ptr &get_else_block () + { rust_assert (else_block != nullptr); return else_block; } @@ -3992,7 +4136,8 @@ public: } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_conseq_if_expr () { + std::unique_ptr &get_conseq_if_expr () + { rust_assert (conseq_if_expr != nullptr); return conseq_if_expr; } @@ -4080,25 +4225,40 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if block or value is null, so base stripping on that. - void mark_for_strip () override { if_block = nullptr; value = nullptr; } - bool is_marked_for_strip () const override { return if_block == nullptr && value == nullptr; } + // Invalid if block or value is null, so base stripping on that. + void mark_for_strip () override + { + if_block = nullptr; + value = nullptr; + } + bool is_marked_for_strip () const override + { + return if_block == nullptr && value == nullptr; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_value_expr () { + std::unique_ptr &get_value_expr () + { rust_assert (value != nullptr); return value; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_if_block () { + std::unique_ptr &get_if_block () + { rust_assert (if_block != nullptr); return if_block; } // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector > &get_patterns () const { return match_arm_patterns; } - std::vector > &get_patterns () { return match_arm_patterns; } + const std::vector > &get_patterns () const + { + return match_arm_patterns; + } + std::vector > &get_patterns () + { + return match_arm_patterns; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -4155,7 +4315,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_conseq_if_let_expr () { + std::unique_ptr &get_conseq_if_let_expr () + { rust_assert (if_let_expr != nullptr); return if_let_expr; } @@ -4213,7 +4374,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_else_block () { + std::unique_ptr &get_else_block () + { rust_assert (else_block != nullptr); return else_block; } @@ -4270,7 +4432,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_conseq_if_expr () { + std::unique_ptr &get_conseq_if_expr () + { rust_assert (if_expr != nullptr); return if_expr; } @@ -4327,7 +4490,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_conseq_if_let_expr () { + std::unique_ptr &get_conseq_if_let_expr () + { rust_assert (if_let_expr != nullptr); return if_let_expr; } @@ -4415,7 +4579,8 @@ public: std::string as_string () const; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_guard_expr () { + std::unique_ptr &get_guard_expr () + { rust_assert (has_match_arm_guard ()); return guard_expr; } @@ -4424,8 +4589,14 @@ public: const std::vector &get_outer_attrs () const { return outer_attrs; } std::vector &get_outer_attrs () { return outer_attrs; } - const std::vector > &get_patterns () const { return match_arm_patterns; } - std::vector > &get_patterns () { return match_arm_patterns; } + const std::vector > &get_patterns () const + { + return match_arm_patterns; + } + std::vector > &get_patterns () + { + return match_arm_patterns; + } }; /* @@ -4493,13 +4664,15 @@ public: std::string as_string () const; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_expr () { + std::unique_ptr &get_expr () + { rust_assert (expr != nullptr); return expr; } // TODO: is this better? Or is a "vis_block" better? - MatchArm &get_arm () { + MatchArm &get_arm () + { rust_assert (!arm.is_error ()); return arm; } @@ -4628,7 +4801,7 @@ public: // Copy constructor requires clone due to unique_ptr MatchExpr (MatchExpr const &other) - : ExprWithBlock (other), inner_attrs (other.inner_attrs), + : ExprWithBlock (other), inner_attrs (other.inner_attrs), match_arms (other.match_arms), locus (other.locus) { // guard to prevent null dereference (only required if error state) @@ -4671,7 +4844,7 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if branch value is null, so base stripping on that. + // Invalid if branch value is null, so base stripping on that. void mark_for_strip () override { branch_value = nullptr; } bool is_marked_for_strip () const override { return branch_value == nullptr; } @@ -4680,7 +4853,8 @@ public: std::vector &get_inner_attrs () { return inner_attrs; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_scrutinee_expr () { + std::unique_ptr &get_scrutinee_expr () + { rust_assert (branch_value != nullptr); return branch_value; } @@ -4746,12 +4920,13 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if awaited expr is null, so base stripping on that. + // Invalid if awaited expr is null, so base stripping on that. void mark_for_strip () override { awaited_expr = nullptr; } bool is_marked_for_strip () const override { return awaited_expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_awaited_expr () { + std::unique_ptr &get_awaited_expr () + { rust_assert (awaited_expr != nullptr); return awaited_expr; } @@ -4816,12 +4991,13 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if block is null, so base stripping on that. + // Invalid if block is null, so base stripping on that. void mark_for_strip () override { block_expr = nullptr; } bool is_marked_for_strip () const override { return block_expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_block_expr () { + std::unique_ptr &get_block_expr () + { rust_assert (block_expr != nullptr); return block_expr; } diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 455511c..f18124d 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -57,7 +57,7 @@ class TypeParam : public GenericParam // bool has_type_param_bounds; // TypeParamBounds type_param_bounds; - std::vector> + std::vector > type_param_bounds; // inlined form // bool has_type; @@ -76,8 +76,8 @@ public: bool has_outer_attribute () const { return !outer_attr.is_empty (); } TypeParam (Identifier type_representation, Location locus = Location (), - std::vector> type_param_bounds - = std::vector> (), + std::vector > type_param_bounds + = std::vector > (), std::unique_ptr type = nullptr, Attribute outer_attr = Attribute::create_empty ()) : outer_attr (std::move (outer_attr)), @@ -89,8 +89,7 @@ public: // Copy constructor uses clone TypeParam (TypeParam const &other) : outer_attr (other.outer_attr), - type_representation (other.type_representation), - locus (other.locus) + type_representation (other.type_representation), locus (other.locus) { // guard to prevent null pointer dereference if (other.type != nullptr) @@ -132,14 +131,22 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (type != nullptr); return type; } // TODO: mutable getter seems kinda dodgy - std::vector > &get_type_param_bounds () { return type_param_bounds; } - const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + std::vector > &get_type_param_bounds () + { + return type_param_bounds; + } + const std::vector > & + get_type_param_bounds () const + { + return type_param_bounds; + } protected: // Clone function implementation as (not pure) virtual method @@ -211,7 +218,7 @@ class TypeBoundWhereClauseItem : public WhereClauseItem // bool has_type_param_bounds; // TypeParamBounds type_param_bounds; - std::vector> + std::vector > type_param_bounds; // inlined form // should this store location info? @@ -225,7 +232,7 @@ public: TypeBoundWhereClauseItem ( std::vector for_lifetimes, std::unique_ptr bound_type, - std::vector> type_param_bounds) + std::vector > type_param_bounds) : for_lifetimes (std::move (for_lifetimes)), bound_type (std::move (bound_type)), type_param_bounds (std::move (type_param_bounds)) @@ -264,14 +271,22 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (bound_type != nullptr); return bound_type; } // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector > &get_type_param_bounds () { return type_param_bounds; } - const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + std::vector > &get_type_param_bounds () + { + return type_param_bounds; + } + const std::vector > & + get_type_param_bounds () const + { + return type_param_bounds; + } protected: // Clone function implementation as (not pure) virtual method @@ -285,13 +300,13 @@ protected: struct WhereClause { private: - std::vector> where_clause_items; + std::vector > where_clause_items; // should this store location info? public: WhereClause ( - std::vector> where_clause_items) + std::vector > where_clause_items) : where_clause_items (std::move (where_clause_items)) {} @@ -320,7 +335,7 @@ public: // Creates a WhereClause with no items. static WhereClause create_empty () { - return WhereClause (std::vector> ()); + return WhereClause (std::vector > ()); } // Returns whether the WhereClause has no items. @@ -329,8 +344,14 @@ public: std::string as_string () const; // TODO: this mutable getter seems kinda dodgy - std::vector > &get_items () { return where_clause_items; } - const std::vector > &get_items () const { return where_clause_items; } + std::vector > &get_items () + { + return where_clause_items; + } + const std::vector > &get_items () const + { + return where_clause_items; + } }; // A self parameter in a method @@ -423,7 +444,8 @@ public: Location get_locus () const { return locus; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (has_type ()); return type; } @@ -479,8 +501,9 @@ private: public: FunctionParam (std::unique_ptr param_name, - std::unique_ptr param_type, std::vector outer_attrs, Location locus) - : outer_attrs (std::move (outer_attrs)), locus (locus), + std::unique_ptr param_type, + std::vector outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), locus (locus), param_name (std::move (param_name)), type (std::move (param_type)) {} @@ -534,13 +557,15 @@ public: const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_pattern () { + std::unique_ptr &get_pattern () + { rust_assert (param_name != nullptr); return param_name; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (type != nullptr); return type; } @@ -647,7 +672,7 @@ class Method : public InherentImplItem, public TraitImplItem // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined SelfParam self_param; @@ -670,14 +695,15 @@ public: // Returns whether the method is in an error state. bool is_error () const { - return function_body == nullptr || method_name.empty () || self_param.is_error (); + return function_body == nullptr || method_name.empty () + || self_param.is_error (); } // Creates an error state method. static Method create_error () { return Method ("", FunctionQualifiers (FunctionQualifiers::NONE, true), - std::vector> (), + std::vector > (), SelfParam::create_error (), std::vector (), nullptr, WhereClause::create_empty (), nullptr, Visibility::create_error (), std::vector (), {}); @@ -700,7 +726,7 @@ public: // Mega-constructor with all possible fields Method (Identifier method_name, FunctionQualifiers qualifiers, - std::vector> generic_params, + std::vector > generic_params, SelfParam self_param, std::vector function_params, std::unique_ptr return_type, WhereClause where_clause, std::unique_ptr function_body, Visibility vis, @@ -712,8 +738,8 @@ public: self_param (std::move (self_param)), function_params (std::move (function_params)), return_type (std::move (return_type)), - where_clause (std::move (where_clause)), function_body (std::move (function_body)), - locus (locus) + where_clause (std::move (where_clause)), + function_body (std::move (function_body)), locus (locus) {} // TODO: add constructor with less fields @@ -728,7 +754,7 @@ public: // guard to prevent null dereference (always required) if (other.return_type != nullptr) return_type = other.return_type->clone_type (); - + // guard to prevent null dereference (only required if error state) if (other.function_body != nullptr) function_body = other.function_body->clone_block_expr (); @@ -779,20 +805,33 @@ public: // Invalid if block is null, so base stripping on that. void mark_for_strip () override { function_body = nullptr; } - bool is_marked_for_strip () const override { return function_body == nullptr; } + bool is_marked_for_strip () const override + { + return function_body == nullptr; + } // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } std::vector &get_function_params () { return function_params; } - const std::vector &get_function_params () const { return function_params; } + const std::vector &get_function_params () const + { + return function_params; + } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_definition () { + std::unique_ptr &get_definition () + { rust_assert (function_body != nullptr); return function_body; } @@ -801,13 +840,15 @@ public: const SelfParam &get_self_param () const { return self_param; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_return_type () { + std::unique_ptr &get_return_type () + { rust_assert (has_return_type ()); return return_type; } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + WhereClause &get_where_clause () + { rust_assert (has_where_clause ()); return where_clause; } @@ -838,11 +879,12 @@ protected: // Visibility constructor VisItem (Visibility visibility, std::vector outer_attrs = std::vector ()) - : visibility (std::move (visibility)), outer_attrs(std::move (outer_attrs)) + : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs)) {} // Visibility copy constructor - VisItem (VisItem const &other) : visibility (other.visibility), outer_attrs(other.outer_attrs) + VisItem (VisItem const &other) + : visibility (other.visibility), outer_attrs (other.outer_attrs) {} // Overload assignment operator to clone @@ -903,7 +945,7 @@ class ModuleBodied : public Module // bool has_inner_attrs; std::vector inner_attrs; // bool has_items; - std::vector> items; + std::vector > items; public: std::string as_string () const override; @@ -916,8 +958,8 @@ public: // Full constructor ModuleBodied (Identifier name, Location locus, - std::vector> items - = std::vector> (), + std::vector > items + = std::vector > (), Visibility visibility = Visibility::create_error (), std::vector inner_attrs = std::vector (), std::vector outer_attrs = std::vector ()) @@ -959,11 +1001,14 @@ public: void add_crate_name (std::vector &names) const override; // TODO: think of better way to do this - mutable getter seems dodgy - const std::vector& get_inner_attrs () const { return inner_attrs; } - std::vector& get_inner_attrs () { return inner_attrs; } + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } - const std::vector>& get_items () const { return items; } - std::vector>& get_items () { return items; } + const std::vector > &get_items () const + { + return items; + } + std::vector > &get_items () { return items; } protected: /* Use covariance to implement clone function as returning this object @@ -977,9 +1022,11 @@ protected: // Module without a body, loaded from external file class ModuleNoBody : public Module { - /* TODO: are modules loaded from file unique? As in, can you load the same file into two different - * other files? Because this may make the difference between simply replacing this with the module - * "definition" (as loaded from another file) vs this having to "reference" a module with body. */ + /* TODO: are modules loaded from file unique? As in, can you load the same + * file into two different other files? Because this may make the difference + * between simply replacing this with the module + * "definition" (as loaded from another file) vs this having to "reference" a + * module with body. */ public: std::string as_string () const override; @@ -1048,7 +1095,10 @@ public: // Invalid if crate name is empty, so base stripping on that. void mark_for_strip () override { referenced_crate = ""; } - bool is_marked_for_strip () const override { return referenced_crate.empty (); } + bool is_marked_for_strip () const override + { + return referenced_crate.empty (); + } protected: /* Use covariance to implement clone function as returning this object @@ -1149,11 +1199,11 @@ private: PathType path_type; SimplePath path; - std::vector> trees; + std::vector > trees; public: UseTreeList (PathType path_type, SimplePath path, - std::vector> trees, Location locus) + std::vector > trees, Location locus) : UseTree (locus), path_type (path_type), path (std::move (path)), trees (std::move (trees)) { @@ -1337,7 +1387,7 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined // bool has_function_params; // FunctionParams function_params; @@ -1372,7 +1422,7 @@ public: // Mega-constructor with all possible fields Function (Identifier function_name, FunctionQualifiers qualifiers, - std::vector> generic_params, + std::vector > generic_params, std::vector function_params, std::unique_ptr return_type, WhereClause where_clause, std::unique_ptr function_body, Visibility vis, @@ -1399,7 +1449,7 @@ public: // guard to prevent null dereference (always required) if (other.return_type != nullptr) return_type = other.return_type->clone_type (); - + // guard to prevent null dereference (only required if error state) if (other.function_body != nullptr) function_body = other.function_body->clone_block_expr (); @@ -1426,7 +1476,7 @@ public: return_type = other.return_type->clone_type (); else return_type = nullptr; - + // guard to prevent null dereference (only required if error state) if (other.function_body != nullptr) function_body = other.function_body->clone_block_expr (); @@ -1450,17 +1500,30 @@ public: // Invalid if block is null, so base stripping on that. void mark_for_strip () override { function_body = nullptr; } - bool is_marked_for_strip () const override { return function_body == nullptr; } + bool is_marked_for_strip () const override + { + return function_body == nullptr; + } // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_function_params () { return function_params; } - const std::vector &get_function_params () const { return function_params; } + const std::vector &get_function_params () const + { + return function_params; + } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_definition () { + std::unique_ptr &get_definition () + { rust_assert (function_body != nullptr); return function_body; } @@ -1470,13 +1533,15 @@ public: Identifier get_function_name () const { return function_name; } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + 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 &get_return_type () { + std::unique_ptr &get_return_type () + { rust_assert (has_return_type ()); return return_type; } @@ -1508,7 +1573,7 @@ class TypeAlias : public VisItem, public TraitImplItem // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined // bool has_where_clause; WhereClause where_clause; @@ -1528,7 +1593,7 @@ public: // Mega-constructor with all possible fields TypeAlias (Identifier new_type_name, - std::vector> generic_params, + std::vector > generic_params, WhereClause where_clause, std::unique_ptr existing_type, Visibility vis, std::vector outer_attrs, Location locus) : VisItem (std::move (vis), std::move (outer_attrs)), @@ -1585,19 +1650,30 @@ public: // Invalid if existing type is null, so base stripping on that. void mark_for_strip () override { existing_type = nullptr; } - bool is_marked_for_strip () const override { return existing_type == nullptr; } + bool is_marked_for_strip () const override + { + return existing_type == nullptr; + } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + 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 &get_type_aliased () { + std::unique_ptr &get_type_aliased () + { rust_assert (existing_type != nullptr); return existing_type; } @@ -1624,7 +1700,7 @@ protected: // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined // bool has_where_clause; WhereClause where_clause; @@ -1647,18 +1723,25 @@ public: Identifier get_struct_name () const { return struct_name; } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + WhereClause &get_where_clause () + { rust_assert (has_where_clause ()); return where_clause; } protected: Struct (Identifier struct_name, - std::vector> generic_params, + std::vector > generic_params, WhereClause where_clause, Visibility vis, Location locus, std::vector outer_attrs = std::vector ()) : VisItem (std::move (vis), std::move (outer_attrs)), @@ -1780,7 +1863,8 @@ public: Identifier get_field_name () const { return field_name; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_field_type () { + std::unique_ptr &get_field_type () + { rust_assert (field_type != nullptr); return field_type; } @@ -1799,7 +1883,7 @@ public: // Mega-constructor with all possible fields StructStruct (std::vector fields, Identifier struct_name, - std::vector> generic_params, + std::vector > generic_params, WhereClause where_clause, bool is_unit, Visibility vis, std::vector outer_attrs, Location locus) : Struct (std::move (struct_name), std::move (generic_params), @@ -1810,12 +1894,13 @@ public: // Unit struct constructor StructStruct (Identifier struct_name, - std::vector> generic_params, + std::vector > generic_params, WhereClause where_clause, Visibility vis, std::vector outer_attrs, Location locus) : Struct (std::move (struct_name), std::move (generic_params), std::move (where_clause), std::move (vis), locus, - std::move (outer_attrs)), is_unit (true) + std::move (outer_attrs)), + is_unit (true) {} // TODO: can a unit struct have generic fields? assuming yes for now. @@ -1914,7 +1999,8 @@ public: const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_field_type () { + std::unique_ptr &get_field_type () + { rust_assert (field_type != nullptr); return field_type; } @@ -1930,7 +2016,7 @@ public: // Mega-constructor with all possible fields TupleStruct (std::vector fields, Identifier struct_name, - std::vector> generic_params, + std::vector > generic_params, WhereClause where_clause, Visibility vis, std::vector outer_attrs, Location locus) : Struct (std::move (struct_name), std::move (generic_params), @@ -2026,7 +2112,10 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_tuple_fields () { return tuple_fields; } - const std::vector &get_tuple_fields () const { return tuple_fields; } + const std::vector &get_tuple_fields () const + { + return tuple_fields; + } protected: // Clone function implementation as (not pure) virtual method @@ -2059,7 +2148,10 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_struct_fields () { return struct_fields; } - const std::vector &get_struct_fields () const { return struct_fields; } + const std::vector &get_struct_fields () const + { + return struct_fields; + } protected: // Clone function implementation as (not pure) virtual method @@ -2106,7 +2198,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_expr () { + std::unique_ptr &get_expr () + { rust_assert (expression != nullptr); return expression; } @@ -2126,12 +2219,12 @@ class Enum : public VisItem // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined // bool has_where_clause; WhereClause where_clause; - std::vector> items; + std::vector > items; Location locus; @@ -2150,8 +2243,8 @@ public: // Mega-constructor Enum (Identifier enum_name, Visibility vis, - std::vector> generic_params, - WhereClause where_clause, std::vector> items, + std::vector > generic_params, + WhereClause where_clause, std::vector > items, std::vector outer_attrs, Location locus) : VisItem (std::move (vis), std::move (outer_attrs)), enum_name (std::move (enum_name)), @@ -2208,14 +2301,24 @@ public: bool is_marked_for_strip () const override { return enum_name.empty (); } // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector> &get_variants () { return items; } - const std::vector> &get_variants () const { return items; } + std::vector > &get_variants () { return items; } + const std::vector > &get_variants () const + { + return items; + } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + WhereClause &get_where_clause () + { rust_assert (has_where_clause ()); return where_clause; } @@ -2233,7 +2336,7 @@ class Union : public VisItem // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined // bool has_where_clause; WhereClause where_clause; @@ -2252,7 +2355,7 @@ public: bool has_where_clause () const { return !where_clause.is_empty (); } Union (Identifier union_name, Visibility vis, - std::vector> generic_params, + std::vector > generic_params, WhereClause where_clause, std::vector variants, std::vector outer_attrs, Location locus) : VisItem (std::move (vis), std::move (outer_attrs)), @@ -2305,11 +2408,18 @@ public: std::vector &get_variants () { return variants; } const std::vector &get_variants () const { return variants; } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + WhereClause &get_where_clause () + { rust_assert (has_where_clause ()); return where_clause; } @@ -2390,17 +2500,26 @@ public: void accept_vis (ASTVisitor &vis) override; // Invalid if type or expression are null, so base stripping on that. - void mark_for_strip () override { type = nullptr; const_expr = nullptr; } - bool is_marked_for_strip () const override { return type == nullptr && const_expr == nullptr; } + void mark_for_strip () override + { + type = nullptr; + const_expr = nullptr; + } + bool is_marked_for_strip () const override + { + return type == nullptr && const_expr == nullptr; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_expr () { + std::unique_ptr &get_expr () + { rust_assert (const_expr != nullptr); return const_expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (type != nullptr); return type; } @@ -2491,17 +2610,26 @@ public: void accept_vis (ASTVisitor &vis) override; // Invalid if type or expression are null, so base stripping on that. - void mark_for_strip () override { type = nullptr; expr = nullptr; } - bool is_marked_for_strip () const override { return type == nullptr && expr == nullptr; } + void mark_for_strip () override + { + type = nullptr; + expr = nullptr; + } + bool is_marked_for_strip () const override + { + return type == nullptr && expr == nullptr; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_expr () { + std::unique_ptr &get_expr () + { rust_assert (expr != nullptr); return expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (type != nullptr); return type; } @@ -2525,7 +2653,7 @@ private: // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined // bool has_params; // FunctionParams function_params; @@ -2554,7 +2682,7 @@ public: // Mega-constructor TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers, - std::vector> generic_params, + std::vector > generic_params, std::vector function_params, std::unique_ptr return_type, WhereClause where_clause) @@ -2569,8 +2697,7 @@ public: // Copy constructor with clone TraitFunctionDecl (TraitFunctionDecl const &other) : qualifiers (other.qualifiers), function_name (other.function_name), - function_params (other.function_params), - where_clause (other.where_clause) + function_params (other.function_params), where_clause (other.where_clause) { // guard to prevent nullptr dereference if (other.return_type != nullptr) @@ -2616,19 +2743,30 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_function_params () { return function_params; } - const std::vector &get_function_params () const { return function_params; } + const std::vector &get_function_params () const + { + return function_params; + } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_return_type () { + std::unique_ptr &get_return_type () + { rust_assert (has_return_type ()); return return_type; } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + WhereClause &get_where_clause () + { rust_assert (has_where_clause ()); return where_clause; } @@ -2690,20 +2828,25 @@ public: // Invalid if trait decl is empty, so base stripping on that. void mark_for_strip () override { decl.mark_for_strip (); } - bool is_marked_for_strip () const override { return decl.is_marked_for_strip (); } + bool is_marked_for_strip () const override + { + return decl.is_marked_for_strip (); + } // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_definition () { + std::unique_ptr &get_definition () + { rust_assert (has_definition ()); return block_expr; } // TODO: is this better? Or is a "vis_block" better? - TraitFunctionDecl &get_trait_function_decl () { + TraitFunctionDecl &get_trait_function_decl () + { // TODO: maybe only allow access if not marked for strip? return decl; } @@ -2726,7 +2869,7 @@ private: // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined SelfParam self_param; @@ -2757,7 +2900,7 @@ public: // Mega-constructor TraitMethodDecl (Identifier function_name, FunctionQualifiers qualifiers, - std::vector> generic_params, + std::vector > generic_params, SelfParam self_param, std::vector function_params, std::unique_ptr return_type, WhereClause where_clause) @@ -2821,19 +2964,30 @@ public: // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_function_params () { return function_params; } - const std::vector &get_function_params () const { return function_params; } + const std::vector &get_function_params () const + { + return function_params; + } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_return_type () { + std::unique_ptr &get_return_type () + { rust_assert (has_return_type ()); return return_type; } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + WhereClause &get_where_clause () + { rust_assert (has_where_clause ()); return where_clause; } @@ -2862,8 +3016,7 @@ public: // Copy constructor with clone TraitItemMethod (TraitItemMethod const &other) - : outer_attrs (other.outer_attrs), decl (other.decl), - locus (other.locus) + : outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus) { // guard to prevent null dereference if (other.block_expr != nullptr) @@ -2899,21 +3052,26 @@ public: // Invalid if trait decl is empty, so base stripping on that. void mark_for_strip () override { decl.mark_for_strip (); } - bool is_marked_for_strip () const override { return decl.is_marked_for_strip (); } + bool is_marked_for_strip () const override + { + return decl.is_marked_for_strip (); + } // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: is this better? Or is a "vis_block" better? - TraitMethodDecl &get_trait_method_decl () { + TraitMethodDecl &get_trait_method_decl () + { // TODO: maybe only allow access if not marked for strip? return decl; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_definition () { - rust_assert (has_definition()); + std::unique_ptr &get_definition () + { + rust_assert (has_definition ()); return block_expr; } @@ -2955,7 +3113,7 @@ public: // guard to prevent null dereference if (other.expr != nullptr) expr = other.expr->clone_expr (); - + // guard to prevent null dereference (only for error state) if (other.type != nullptr) type = other.type->clone_type (); @@ -3003,13 +3161,15 @@ public: const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_expr () { + std::unique_ptr &get_expr () + { rust_assert (expr != nullptr); return expr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (type != nullptr); return type; } @@ -3031,7 +3191,7 @@ class TraitItemType : public TraitItem // bool has_type_param_bounds; // TypeParamBounds type_param_bounds; - std::vector> + std::vector > type_param_bounds; // inlined form Location locus; @@ -3042,7 +3202,7 @@ public: TraitItemType ( Identifier name, - std::vector> type_param_bounds, + std::vector > type_param_bounds, std::vector outer_attrs, Location locus) : outer_attrs (std::move (outer_attrs)), name (std::move (name)), type_param_bounds (std::move (type_param_bounds)), locus (locus) @@ -3091,8 +3251,15 @@ public: const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: mutable getter seems kinda dodgy - std::vector > &get_type_param_bounds () { return type_param_bounds; } - const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + std::vector > &get_type_param_bounds () + { + return type_param_bounds; + } + const std::vector > & + get_type_param_bounds () const + { + return type_param_bounds; + } protected: // Clone function implementation as (not pure) virtual method @@ -3110,11 +3277,11 @@ class Trait : public VisItem // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined // bool has_type_param_bounds; // TypeParamBounds type_param_bounds; - std::vector> + std::vector > type_param_bounds; // inlined form // bool has_where_clause; @@ -3123,7 +3290,7 @@ class Trait : public VisItem std::vector inner_attrs; // bool has_trait_items; - std::vector> trait_items; + std::vector > trait_items; Location locus; @@ -3147,23 +3314,26 @@ public: // Mega-constructor Trait (Identifier name, bool is_unsafe, - std::vector> generic_params, - std::vector> type_param_bounds, + std::vector > generic_params, + std::vector > type_param_bounds, WhereClause where_clause, - std::vector> trait_items, Visibility vis, - std::vector outer_attrs, std::vector inner_attrs, Location locus) + std::vector > trait_items, Visibility vis, + std::vector outer_attrs, std::vector inner_attrs, + Location locus) : VisItem (std::move (vis), std::move (outer_attrs)), has_unsafe (is_unsafe), name (std::move (name)), generic_params (std::move (generic_params)), type_param_bounds (std::move (type_param_bounds)), - where_clause (std::move (where_clause)), inner_attrs (std::move (inner_attrs)), + where_clause (std::move (where_clause)), + inner_attrs (std::move (inner_attrs)), trait_items (std::move (trait_items)), locus (locus) {} // Copy constructor with vector clone Trait (Trait const &other) : VisItem (other), has_unsafe (other.has_unsafe), name (other.name), - where_clause (other.where_clause), inner_attrs (other.inner_attrs), locus (other.locus) + where_clause (other.where_clause), inner_attrs (other.inner_attrs), + locus (other.locus) { generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) @@ -3216,20 +3386,40 @@ public: bool is_marked_for_strip () const override { return name.empty (); } // TODO: think of better way to do this - const std::vector& get_inner_attrs () const { return inner_attrs; } - std::vector& get_inner_attrs () { return inner_attrs; } + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } - const std::vector>& get_trait_items () const { return trait_items; } - std::vector>& get_trait_items () { return trait_items; } + const std::vector > &get_trait_items () const + { + return trait_items; + } + std::vector > &get_trait_items () + { + return trait_items; + } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } - std::vector > &get_type_param_bounds () { return type_param_bounds; } - const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + std::vector > &get_type_param_bounds () + { + return type_param_bounds; + } + const std::vector > & + get_type_param_bounds () const + { + return type_param_bounds; + } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + WhereClause &get_where_clause () + { rust_assert (has_where_clause ()); return where_clause; } @@ -3247,7 +3437,7 @@ class Impl : public VisItem protected: // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined std::unique_ptr trait_type; @@ -3278,27 +3468,35 @@ public: bool is_marked_for_strip () const override { return trait_type == nullptr; } // TODO: think of better way to do this - const std::vector& get_inner_attrs () const { return inner_attrs; } - std::vector& get_inner_attrs () { return inner_attrs; } + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + 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 &get_type () { + std::unique_ptr &get_type () + { rust_assert (trait_type != nullptr); return trait_type; } protected: // Mega-constructor - Impl (std::vector> generic_params, + Impl (std::vector > generic_params, std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, std::vector inner_attrs, std::vector outer_attrs, Location locus) @@ -3311,7 +3509,7 @@ protected: // Copy constructor Impl (Impl const &other) - : VisItem (other), where_clause (other.where_clause), + : VisItem (other), where_clause (other.where_clause), inner_attrs (other.inner_attrs), locus (other.locus) { // guard to prevent null dereference (only required if error state) @@ -3353,7 +3551,7 @@ protected: class InherentImpl : public Impl { // bool has_impl_items; - std::vector> impl_items; + std::vector > impl_items; public: std::string as_string () const override; @@ -3362,8 +3560,8 @@ public: bool has_impl_items () const { return !impl_items.empty (); } // Mega-constructor - InherentImpl (std::vector> impl_items, - std::vector> generic_params, + InherentImpl (std::vector > impl_items, + std::vector > generic_params, std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, std::vector inner_attrs, std::vector outer_attrs, Location locus) @@ -3400,8 +3598,14 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: think of better way to do this - const std::vector>& get_impl_items () const { return impl_items; } - std::vector>& get_impl_items () { return impl_items; } + const std::vector > &get_impl_items () const + { + return impl_items; + } + std::vector > &get_impl_items () + { + return impl_items; + } protected: /* Use covariance to implement clone function as returning this object @@ -3420,7 +3624,7 @@ class TraitImpl : public Impl TypePath trait_path; // bool has_impl_items; - std::vector> impl_items; + std::vector > impl_items; public: std::string as_string () const override; @@ -3430,8 +3634,8 @@ public: // Mega-constructor TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam, - std::vector> impl_items, - std::vector> generic_params, + std::vector > impl_items, + std::vector > generic_params, std::unique_ptr trait_type, WhereClause where_clause, Visibility vis, std::vector inner_attrs, std::vector outer_attrs, Location locus) @@ -3476,11 +3680,18 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: think of better way to do this - const std::vector>& get_impl_items () const { return impl_items; } - std::vector>& get_impl_items () { return impl_items; } + const std::vector > &get_impl_items () const + { + return impl_items; + } + std::vector > &get_impl_items () + { + return impl_items; + } // TODO: is this better? Or is a "vis_block" better? - TypePath &get_trait_path () { + TypePath &get_trait_path () + { // TODO: assert that trait path is not empty? return trait_path; } @@ -3587,17 +3798,17 @@ class ExternalStaticItem : public ExternalItem public: ExternalStaticItem (Identifier item_name, std::unique_ptr item_type, - bool is_mut, Visibility vis, std::vector 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), + bool is_mut, Visibility vis, + std::vector 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) - : outer_attrs (other.outer_attrs), visibility (other.visibility), item_name (other.item_name), - locus (other.locus), has_mut (other.has_mut) + : 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) @@ -3647,7 +3858,8 @@ public: const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (item_type != nullptr); return item_type; } @@ -3666,14 +3878,14 @@ struct NamedFunctionParam { private: // bool has_name; // otherwise is _ - std::string name; + std::string name; std::unique_ptr param_type; // TODO: should this store location data? // seemingly new since writing this node - std::vector outer_attrs; + std::vector outer_attrs; public: /* Returns whether the named function parameter has a name (i.e. name is not @@ -3695,8 +3907,10 @@ public: return NamedFunctionParam ("", nullptr, {}); } - NamedFunctionParam (std::string name, std::unique_ptr param_type, std::vector outer_attrs) - : name (std::move (name)), param_type (std::move (param_type)), outer_attrs (std::move (outer_attrs)) + NamedFunctionParam (std::string name, std::unique_ptr param_type, + std::vector outer_attrs) + : name (std::move (name)), param_type (std::move (param_type)), + outer_attrs (std::move (outer_attrs)) {} // Copy constructor @@ -3741,7 +3955,8 @@ public: const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (param_type != nullptr); return param_type; } @@ -3761,7 +3976,7 @@ class ExternalFunctionItem : public ExternalItem // bool has_generics; // Generics generic_params; - std::vector> generic_params; // inlined + std::vector > generic_params; // inlined // bool has_return_type; // FunctionReturnType return_type; @@ -3794,33 +4009,41 @@ public: 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 (); } + bool has_variadic_outer_attrs () const + { + return !variadic_outer_attrs.empty (); + } Location get_locus () const { return locus; } ExternalFunctionItem ( Identifier item_name, - std::vector> generic_params, + std::vector > generic_params, std::unique_ptr return_type, WhereClause where_clause, - std::vector function_params, bool has_variadics, std::vector variadic_outer_attrs, - Visibility vis, std::vector outer_attrs, Location locus) - : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), + std::vector function_params, bool has_variadics, + std::vector variadic_outer_attrs, Visibility vis, + std::vector outer_attrs, Location 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), variadic_outer_attrs (std::move (variadic_outer_attrs)) + 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? + // TODO: assert that if has variadic outer attrs, then has_variadics is + // true? } // Copy constructor with clone ExternalFunctionItem (ExternalFunctionItem const &other) - : outer_attrs (other.outer_attrs), visibility (other.visibility), item_name (other.item_name), - locus (other.locus), 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), variadic_outer_attrs (other.variadic_outer_attrs) + has_variadics (other.has_variadics), + variadic_outer_attrs (other.variadic_outer_attrs) { // guard to prevent null pointer dereference if (other.return_type != nullptr) @@ -3872,20 +4095,34 @@ public: std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } - std::vector &get_function_params () { return function_params; } - const std::vector &get_function_params () const { return function_params; } + std::vector &get_function_params () + { + return function_params; + } + const std::vector &get_function_params () const + { + return function_params; + } - std::vector > &get_generic_params () { return generic_params; } - const std::vector > &get_generic_params () const { return generic_params; } + std::vector > &get_generic_params () + { + return generic_params; + } + const std::vector > &get_generic_params () const + { + return generic_params; + } // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { + 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 &get_return_type () { + std::unique_ptr &get_return_type () + { rust_assert (has_return_type ()); return return_type; } @@ -3909,10 +4146,10 @@ class ExternBlock : public VisItem std::vector inner_attrs; // bool has_extern_items; - std::vector> extern_items; + std::vector > extern_items; Location locus; - + // TODO: find another way to store this to save memory? bool marked_for_strip = false; @@ -3929,7 +4166,7 @@ public: bool has_abi () const { return !abi.empty (); } ExternBlock (std::string abi, - std::vector> extern_items, + std::vector > extern_items, Visibility vis, std::vector inner_attrs, std::vector outer_attrs, Location locus) : VisItem (std::move (vis), std::move (outer_attrs)), abi (std::move (abi)), @@ -3976,12 +4213,18 @@ public: bool is_marked_for_strip () const override { return marked_for_strip; } // TODO: think of better way to do this - const std::vector>& get_extern_items () const { return extern_items; } - std::vector>& get_extern_items () { return extern_items; } + const std::vector > &get_extern_items () const + { + return extern_items; + } + std::vector > &get_extern_items () + { + return extern_items; + } // TODO: think of better way to do this - const std::vector& get_inner_attrs () const { return inner_attrs; } - std::vector& get_inner_attrs () { return inner_attrs; } + const std::vector &get_inner_attrs () const { return inner_attrs; } + std::vector &get_inner_attrs () { return inner_attrs; } protected: /* Use covariance to implement clone function as returning this object diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 2a97854..5760392 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -132,8 +132,7 @@ public: {} // Copy constructor with clone - MacroMatchRepetition (MacroMatchRepetition const &other) - : op (other.op) + MacroMatchRepetition (MacroMatchRepetition const &other) : op (other.op) { // guard to protect from null pointer dereference if (other.sep != nullptr) @@ -291,7 +290,7 @@ class MacroRulesDefinition : public MacroItem { std::vector outer_attrs; Identifier rule_name; - // MacroRulesDef rules_def; + // MacroRulesDef rules_def; // only curly without required semicolon at end DelimType delim_type; // MacroRules rules; @@ -363,7 +362,7 @@ protected: { return new MacroInvocation (*this); } - + /* Use covariance to implement clone function as returning this object rather * than base */ MacroInvocation *clone_expr_without_block_impl () const override diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index b5d7869..392fc18 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -101,7 +101,8 @@ public: std::string as_string () const; // TODO: is this better? Or is a "vis_pattern" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (type != nullptr); return type; } @@ -111,7 +112,7 @@ public: struct GenericArgs { std::vector lifetime_args; - std::vector> type_args; + std::vector > type_args; std::vector binding_args; Location locus; @@ -124,7 +125,7 @@ public: } GenericArgs (std::vector lifetime_args, - std::vector> type_args, + std::vector > type_args, std::vector binding_args, Location locus = Location ()) : lifetime_args (std::move (lifetime_args)), @@ -166,21 +167,17 @@ public: static GenericArgs create_empty () { return GenericArgs (std::vector (), - std::vector> (), + std::vector > (), std::vector ()); } std::string as_string () const; // TODO: is this better? Or is a "vis_pattern" better? - std::vector> &get_type_args () { - return type_args; - } + std::vector > &get_type_args () { return type_args; } // TODO: is this better? Or is a "vis_pattern" better? - std::vector &get_binding_args () { - return binding_args; - } + std::vector &get_binding_args () { return binding_args; } }; /* A segment of a path in expression, including an identifier aspect and maybe @@ -213,8 +210,8 @@ public: PathExprSegment (std::string segment_name, Location locus, std::vector lifetime_args = std::vector (), - std::vector> type_args - = std::vector> (), + std::vector > type_args + = std::vector > (), std::vector binding_args = std::vector ()) : segment_name (PathIdentSegment (std::move (segment_name))), @@ -238,7 +235,8 @@ public: Location get_locus () const { return locus; } // TODO: is this better? Or is a "vis_pattern" better? - GenericArgs &get_generic_args () { + GenericArgs &get_generic_args () + { rust_assert (has_generic_args ()); return generic_args; } @@ -262,7 +260,11 @@ protected: SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const; // Removes all segments of the path. - void remove_all_segments () { segments.clear (); segments.shrink_to_fit (); } + void remove_all_segments () + { + segments.clear (); + segments.shrink_to_fit (); + } public: /* Returns whether the path is a single segment (excluding qualified path @@ -427,7 +429,7 @@ public: TypePathSegmentGeneric (std::string segment_name, bool has_separating_scope_resolution, std::vector lifetime_args, - std::vector> type_args, + std::vector > type_args, std::vector binding_args, Location locus) : TypePathSegment (std::move (segment_name), @@ -442,7 +444,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - GenericArgs &get_generic_args () { + GenericArgs &get_generic_args () + { rust_assert (has_generic_args ()); return generic_args; } @@ -463,7 +466,7 @@ private: /*bool has_inputs; TypePathFnInputs inputs;*/ // inlined from TypePathFnInputs - std::vector> inputs; + std::vector > inputs; // bool has_type; std::unique_ptr return_type; @@ -491,7 +494,7 @@ public: static TypePathFunction create_error () { return TypePathFunction (true); } // Constructor - TypePathFunction (std::vector> inputs, + TypePathFunction (std::vector > inputs, std::unique_ptr type = nullptr) : inputs (std::move (inputs)), return_type (std::move (type)), is_invalid (false) @@ -537,11 +540,15 @@ public: std::string as_string () const; // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector> &get_params () const { return inputs; } - std::vector> &get_params () { return inputs; } + const std::vector > &get_params () const + { + return inputs; + } + std::vector > &get_params () { return inputs; } // TODO: is this better? Or is a "vis_pattern" better? - std::unique_ptr &get_return_type () { + std::unique_ptr &get_return_type () + { rust_assert (has_return_type ()); return return_type; } @@ -578,7 +585,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - TypePathFunction &get_type_path_function () { + TypePathFunction &get_type_path_function () + { rust_assert (!function_path.is_error ()); return function_path; } @@ -595,7 +603,7 @@ protected: class TypePath : public TypeNoBounds { bool has_opening_scope_resolution; - std::vector> segments; + std::vector > segments; Location locus; protected: @@ -620,12 +628,12 @@ public: // Creates an error state TypePath. static TypePath create_error () { - return TypePath (std::vector> (), + return TypePath (std::vector > (), Location ()); } // Constructor - TypePath (std::vector> segments, + TypePath (std::vector > segments, Location locus, bool has_opening_scope_resolution = false) : has_opening_scope_resolution (has_opening_scope_resolution), segments (std::move (segments)), locus (locus) @@ -673,8 +681,14 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: this seems kinda dodgy - std::vector> &get_segments () { return segments; } - const std::vector> &get_segments () const { return segments; } + std::vector > &get_segments () + { + return segments; + } + const std::vector > &get_segments () const + { + return segments; + } }; struct QualifiedPathType @@ -744,13 +758,15 @@ public: Location get_locus () const { return locus; } // TODO: is this better? Or is a "vis_pattern" better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (type_to_invoke_on != nullptr); return type_to_invoke_on; } // TODO: is this better? Or is a "vis_pattern" better? - TypePath &get_as_type_path () { + TypePath &get_as_type_path () + { rust_assert (has_as_clause ()); return trait_path; } @@ -795,11 +811,15 @@ public: void accept_vis (ASTVisitor &vis) override; // Invalid if path_type is error, so base stripping on that. - void mark_for_strip () override { path_type = QualifiedPathType::create_error (); } + void mark_for_strip () override + { + path_type = QualifiedPathType::create_error (); + } bool is_marked_for_strip () const override { return is_error (); } // TODO: is this better? Or is a "vis_pattern" better? - QualifiedPathType &get_qualified_path_type () { + QualifiedPathType &get_qualified_path_type () + { rust_assert (!path_type.is_error ()); return path_type; } @@ -825,7 +845,7 @@ protected: class QualifiedPathInType : public TypeNoBounds { QualifiedPathType path_type; - std::vector> segments; + std::vector > segments; Location locus; protected: @@ -839,7 +859,7 @@ protected: public: QualifiedPathInType ( QualifiedPathType qual_path_type, - std::vector> path_segments, + std::vector > path_segments, Location locus = Location ()) : path_type (std::move (qual_path_type)), segments (std::move (path_segments)), locus (locus) @@ -882,7 +902,7 @@ public: { return QualifiedPathInType ( QualifiedPathType::create_error (), - std::vector> ()); + std::vector > ()); } std::string as_string () const override; @@ -890,14 +910,21 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - QualifiedPathType &get_qualified_path_type () { + QualifiedPathType &get_qualified_path_type () + { rust_assert (!path_type.is_error ()); return path_type; } // TODO: this seems kinda dodgy - std::vector> &get_segments () { return segments; } - const std::vector> &get_segments () const { return segments; } + std::vector > &get_segments () + { + return segments; + } + const std::vector > &get_segments () const + { + return segments; + } Location get_locus () const { return locus; } Location get_locus_slow () const final override { return get_locus (); } diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 5ae68ab..3a87a83 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -94,7 +94,7 @@ public: // fix to prevent null pointer dereference if (other.to_bind != nullptr) to_bind = other.to_bind->clone_pattern (); - else + else to_bind = nullptr; return *this; @@ -110,12 +110,13 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - std::unique_ptr &get_pattern_to_bind () { + std::unique_ptr &get_pattern_to_bind () + { rust_assert (has_pattern_to_bind ()); return to_bind; } - Identifier get_ident() const { return variable_ident; } + Identifier get_ident () const { return variable_ident; } protected: /* Use covariance to implement clone function as returning this object rather @@ -319,12 +320,14 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? or is a "vis_bound" better? - std::unique_ptr& get_lower_bound () { + std::unique_ptr &get_lower_bound () + { rust_assert (lower != nullptr); return lower; } - std::unique_ptr& get_upper_bound () { + std::unique_ptr &get_upper_bound () + { rust_assert (upper != nullptr); return upper; } @@ -382,7 +385,8 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - std::unique_ptr &get_referenced_pattern () { + std::unique_ptr &get_referenced_pattern () + { rust_assert (pattern != nullptr); return pattern; } @@ -508,10 +512,14 @@ public: // based on idea of tuple pattern no longer existing void mark_for_strip () override { tuple_pattern = nullptr; } - bool is_marked_for_strip () const override { return tuple_pattern == nullptr; } + bool is_marked_for_strip () const override + { + return tuple_pattern == nullptr; + } // TODO: is this better? Or is a "vis_pattern" better? - std::unique_ptr &get_index_pattern () { + std::unique_ptr &get_index_pattern () + { rust_assert (tuple_pattern != nullptr); return tuple_pattern; } @@ -577,10 +585,14 @@ public: // based on idea of identifier pattern no longer existing void mark_for_strip () override { ident_pattern = nullptr; } - bool is_marked_for_strip () const override { return ident_pattern == nullptr; } + bool is_marked_for_strip () const override + { + return ident_pattern == nullptr; + } // TODO: is this better? Or is a "vis_pattern" better? - std::unique_ptr &get_ident_pattern () { + std::unique_ptr &get_ident_pattern () + { rust_assert (ident_pattern != nullptr); return ident_pattern; } @@ -630,11 +642,11 @@ struct StructPatternElements { private: // bool has_struct_pattern_fields; - std::vector> fields; + std::vector > fields; bool has_struct_pattern_etc; std::vector struct_pattern_etc_attrs; - //StructPatternEtc etc; + // StructPatternEtc etc; // must have at least one of the two and maybe both @@ -655,7 +667,7 @@ public: // Constructor for StructPatternElements with both (potentially) StructPatternElements ( - std::vector> fields, + std::vector > fields, std::vector etc_attrs) : fields (std::move (fields)), has_struct_pattern_etc (true), struct_pattern_etc_attrs (std::move (etc_attrs)) @@ -663,14 +675,15 @@ public: // Constructor for StructPatternElements with no StructPatternEtc StructPatternElements ( - std::vector> fields) + std::vector > fields) : fields (std::move (fields)), has_struct_pattern_etc (false), struct_pattern_etc_attrs () {} // Copy constructor with vector clone StructPatternElements (StructPatternElements const &other) - : has_struct_pattern_etc (other.has_struct_pattern_etc), struct_pattern_etc_attrs (other.struct_pattern_etc_attrs) + : has_struct_pattern_etc (other.has_struct_pattern_etc), + struct_pattern_etc_attrs (other.struct_pattern_etc_attrs) { fields.reserve (other.fields.size ()); for (const auto &e : other.fields) @@ -698,21 +711,35 @@ public: static StructPatternElements create_empty () { return StructPatternElements ( - std::vector> ()); + std::vector > ()); } std::string as_string () const; // TODO: seems kinda dodgy. Think of better way. - std::vector> &get_struct_pattern_fields () { return fields; } - const std::vector> &get_struct_pattern_fields () const { return fields; } + std::vector > & + get_struct_pattern_fields () + { + return fields; + } + const std::vector > & + get_struct_pattern_fields () const + { + return fields; + } - std::vector &get_etc_outer_attrs () { return struct_pattern_etc_attrs; } - const std::vector &get_etc_outer_attrs () const { return struct_pattern_etc_attrs; } + std::vector &get_etc_outer_attrs () + { + return struct_pattern_etc_attrs; + } + const std::vector &get_etc_outer_attrs () const + { + return struct_pattern_etc_attrs; + } - void strip_etc () - { - has_struct_pattern_etc = false; + void strip_etc () + { + has_struct_pattern_etc = false; struct_pattern_etc_attrs.clear (); struct_pattern_etc_attrs.shrink_to_fit (); } @@ -752,7 +779,10 @@ public: // TODO: seems kinda dodgy. Think of better way. StructPatternElements &get_struct_pattern_elems () { return elems; } - const StructPatternElements &get_struct_pattern_elems () const { return elems; } + const StructPatternElements &get_struct_pattern_elems () const + { + return elems; + } PathInExpression &get_path () { return path; } const PathInExpression &get_path () const { return path; } @@ -792,10 +822,10 @@ protected: // Class for non-ranged tuple struct pattern patterns class TupleStructItemsNoRange : public TupleStructItems { - std::vector> patterns; + std::vector > patterns; public: - TupleStructItemsNoRange (std::vector> patterns) + TupleStructItemsNoRange (std::vector > patterns) : patterns (std::move (patterns)) {} @@ -827,8 +857,11 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::vector> &get_patterns () { return patterns; } - const std::vector> &get_patterns () const { return patterns; } + std::vector > &get_patterns () { return patterns; } + const std::vector > &get_patterns () const + { + return patterns; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -842,12 +875,12 @@ protected: // Class for ranged tuple struct pattern patterns class TupleStructItemsRange : public TupleStructItems { - std::vector> lower_patterns; - std::vector> upper_patterns; + std::vector > lower_patterns; + std::vector > upper_patterns; public: - TupleStructItemsRange (std::vector> lower_patterns, - std::vector> upper_patterns) + TupleStructItemsRange (std::vector > lower_patterns, + std::vector > upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} @@ -887,12 +920,24 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::vector> &get_lower_patterns () { return lower_patterns; } - const std::vector> &get_lower_patterns () const { return lower_patterns; } + std::vector > &get_lower_patterns () + { + return lower_patterns; + } + const std::vector > &get_lower_patterns () const + { + return lower_patterns; + } // TODO: seems kinda dodgy. Think of better way. - std::vector> &get_upper_patterns () { return upper_patterns; } - const std::vector> &get_upper_patterns () const { return upper_patterns; } + std::vector > &get_upper_patterns () + { + return upper_patterns; + } + const std::vector > &get_upper_patterns () const + { + return upper_patterns; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -924,8 +969,7 @@ public: {} // Copy constructor required to clone - TupleStructPattern (TupleStructPattern const &other) - : path (other.path) + TupleStructPattern (TupleStructPattern const &other) : path (other.path) { // guard to protect from null dereference if (other.items != nullptr) @@ -956,10 +1000,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::unique_ptr &get_items () - { + std::unique_ptr &get_items () + { rust_assert (has_items ()); - return items; + return items; } PathInExpression &get_path () { return path; } @@ -1036,10 +1080,10 @@ TuplePatternItemsSingle(*this); // Class representing TuplePattern patterns where there are multiple patterns class TuplePatternItemsMultiple : public TuplePatternItems { - std::vector> patterns; + std::vector > patterns; public: - TuplePatternItemsMultiple (std::vector> patterns) + TuplePatternItemsMultiple (std::vector > patterns) : patterns (std::move (patterns)) {} @@ -1071,8 +1115,11 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::vector> &get_patterns () { return patterns; } - const std::vector> &get_patterns () const { return patterns; } + std::vector > &get_patterns () { return patterns; } + const std::vector > &get_patterns () const + { + return patterns; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -1086,13 +1133,13 @@ protected: // Class representing TuplePattern patterns where there are a range of patterns class TuplePatternItemsRanged : public TuplePatternItems { - std::vector> lower_patterns; - std::vector> upper_patterns; + std::vector > lower_patterns; + std::vector > upper_patterns; public: TuplePatternItemsRanged ( - std::vector> lower_patterns, - std::vector> upper_patterns) + std::vector > lower_patterns, + std::vector > upper_patterns) : lower_patterns (std::move (lower_patterns)), upper_patterns (std::move (upper_patterns)) {} @@ -1133,12 +1180,24 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::vector> &get_lower_patterns () { return lower_patterns; } - const std::vector> &get_lower_patterns () const { return lower_patterns; } + std::vector > &get_lower_patterns () + { + return lower_patterns; + } + const std::vector > &get_lower_patterns () const + { + return lower_patterns; + } // TODO: seems kinda dodgy. Think of better way. - std::vector> &get_upper_patterns () { return upper_patterns; } - const std::vector> &get_upper_patterns () const { return upper_patterns; } + std::vector > &get_upper_patterns () + { + return upper_patterns; + } + const std::vector > &get_upper_patterns () const + { + return upper_patterns; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -1167,8 +1226,7 @@ public: {} // Copy constructor requires clone - TuplePattern (TuplePattern const &other) - : locus (other.locus) + TuplePattern (TuplePattern const &other) : locus (other.locus) { // guard to prevent null dereference if (other.items != nullptr) @@ -1195,10 +1253,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::unique_ptr &get_items () - { + std::unique_ptr &get_items () + { rust_assert (has_tuple_pattern_items ()); - return items; + return items; } protected: @@ -1251,10 +1309,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::unique_ptr &get_pattern_in_parens () - { + std::unique_ptr &get_pattern_in_parens () + { rust_assert (pattern_in_parens != nullptr); - return pattern_in_parens; + return pattern_in_parens; } protected: @@ -1269,13 +1327,13 @@ protected: // AST node representing patterns that can match slices and arrays class SlicePattern : public Pattern { - std::vector> items; + std::vector > items; Location locus; public: std::string as_string () const override; - SlicePattern (std::vector> items, Location locus) + SlicePattern (std::vector > items, Location locus) : items (std::move (items)), locus (locus) {} @@ -1309,8 +1367,11 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: seems kinda dodgy. Think of better way. - std::vector> &get_items () { return items; } - const std::vector> &get_items () const { return items; } + std::vector > &get_items () { return items; } + const std::vector > &get_items () const + { + return items; + } protected: /* Use covariance to implement clone function as returning this object rather diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 88be256..faea905 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -80,7 +80,7 @@ public: // guard to prevent null dereference (only required if error state) if (other.variables_pattern != nullptr) variables_pattern = other.variables_pattern->clone_pattern (); - + // guard to prevent null dereference (always required) if (other.init_expr != nullptr) init_expr = other.init_expr->clone_expr (); @@ -99,7 +99,7 @@ public: variables_pattern = other.variables_pattern->clone_pattern (); else variables_pattern = nullptr; - + // guard to prevent null dereference (always required) if (other.init_expr != nullptr) init_expr = other.init_expr->clone_expr (); @@ -123,24 +123,30 @@ public: // Invalid if pattern is null, so base stripping on that. void mark_for_strip () override { variables_pattern = nullptr; } - bool is_marked_for_strip () const override { return variables_pattern == nullptr; } + bool is_marked_for_strip () const override + { + return variables_pattern == nullptr; + } // TODO: this mutable getter seems really dodgy. Think up better way. std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_init_expr () { + std::unique_ptr &get_init_expr () + { rust_assert (has_init_expr ()); return init_expr; } - std::unique_ptr &get_pattern () { + std::unique_ptr &get_pattern () + { rust_assert (variables_pattern != nullptr); return variables_pattern; } - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (has_type ()); return type; } @@ -188,8 +194,7 @@ public: {}*/ // Copy constructor with clone - ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) - : ExprStmt (other) + ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) : ExprStmt (other) { // guard to prevent null dereference (only required if error state) if (other.expr != nullptr) @@ -203,7 +208,7 @@ public: ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other) { ExprStmt::operator= (other); - //expr = other.expr->clone_expr (); + // expr = other.expr->clone_expr (); // guard to prevent null dereference (only required if error state) if (other.expr != nullptr) @@ -225,7 +230,8 @@ public: bool is_marked_for_strip () const override { return expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_expr () { + std::unique_ptr &get_expr () + { rust_assert (expr != nullptr); return expr; } @@ -254,8 +260,7 @@ public: {} // Copy constructor with clone - ExprStmtWithBlock (ExprStmtWithBlock const &other) - : ExprStmt (other) + ExprStmtWithBlock (ExprStmtWithBlock const &other) : ExprStmt (other) { // guard to prevent null dereference (only required if error state) if (other.expr != nullptr) @@ -266,7 +271,7 @@ public: ExprStmtWithBlock &operator= (ExprStmtWithBlock const &other) { ExprStmt::operator= (other); - + // guard to prevent null dereference (only required if error state) if (other.expr != nullptr) expr = other.expr->clone_expr_with_block (); @@ -287,7 +292,8 @@ public: bool is_marked_for_strip () const override { return expr == nullptr; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr &get_expr () { + std::unique_ptr &get_expr () + { rust_assert (expr != nullptr); return expr; } diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 4351017..8c175d3 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -115,8 +115,15 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: mutable getter seems kinda dodgy - std::vector > &get_type_param_bounds () { return type_param_bounds; } - const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + std::vector > &get_type_param_bounds () + { + return type_param_bounds; + } + const std::vector > & + get_type_param_bounds () const + { + return type_param_bounds; + } }; // An opaque value of another type that implements a set of traits @@ -178,8 +185,15 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: mutable getter seems kinda dodgy - std::vector > &get_type_param_bounds () { return type_param_bounds; } - const std::vector > &get_type_param_bounds () const { return type_param_bounds; } + std::vector > &get_type_param_bounds () + { + return type_param_bounds; + } + const std::vector > & + get_type_param_bounds () const + { + return type_param_bounds; + } }; // A type with parentheses around it, used to avoid ambiguity. @@ -240,9 +254,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: would a "vis_type" be better? - std::unique_ptr &get_type_in_parens () { + std::unique_ptr &get_type_in_parens () + { rust_assert (type_in_parens != nullptr); - return type_in_parens; + return type_in_parens; } }; @@ -273,9 +288,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: would a "vis_type" be better? - TraitBound &get_trait_bound () { + TraitBound &get_trait_bound () + { // TODO: check to ensure invariants are met? - return trait_bound; + return trait_bound; } }; @@ -318,9 +334,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: would a "vis_type" be better? - TraitBound &get_trait_bound () { + TraitBound &get_trait_bound () + { // TODO: check to ensure invariants are met? - return trait_bound; + return trait_bound; } }; @@ -374,7 +391,10 @@ public: // TODO: mutable getter seems kinda dodgy std::vector > &get_elems () { return elems; } - const std::vector > &get_elems () const { return elems; } + const std::vector > &get_elems () const + { + return elems; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -464,9 +484,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: would a "vis_type" be better? - std::unique_ptr &get_type_pointed_to () { + std::unique_ptr &get_type_pointed_to () + { rust_assert (type != nullptr); - return type; + return type; } protected: @@ -531,9 +552,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: would a "vis_type" be better? - std::unique_ptr &get_type_referenced () { + std::unique_ptr &get_type_referenced () + { rust_assert (type != nullptr); - return type; + return type; } protected: @@ -586,15 +608,17 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: would a "vis_type" be better? - std::unique_ptr &get_elem_type () { + std::unique_ptr &get_elem_type () + { rust_assert (elem_type != nullptr); - return elem_type; + return elem_type; } // TODO: would a "vis_expr" be better? - std::unique_ptr &get_size_expr () { + std::unique_ptr &get_size_expr () + { rust_assert (size != nullptr); - return size; + return size; } protected: @@ -645,9 +669,10 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: would a "vis_type" be better? - std::unique_ptr &get_elem_type () { + std::unique_ptr &get_elem_type () + { rust_assert (elem_type != nullptr); - return elem_type; + return elem_type; } protected: @@ -710,14 +735,17 @@ private: public: MaybeNamedParam (Identifier name, ParamKind param_kind, - std::unique_ptr param_type, std::vector outer_attrs, Location locus) - : outer_attrs (std::move (outer_attrs)), param_type (std::move (param_type)), param_kind (param_kind), + std::unique_ptr param_type, + std::vector outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), + param_type (std::move (param_type)), param_kind (param_kind), name (std::move (name)), locus (locus) {} // Copy constructor with clone MaybeNamedParam (MaybeNamedParam const &other) - : outer_attrs (other.outer_attrs), param_kind (other.param_kind), name (other.name), locus (other.locus) + : outer_attrs (other.outer_attrs), param_kind (other.param_kind), + name (other.name), locus (other.locus) { // guard to prevent null dereference if (other.param_type != nullptr) @@ -765,9 +793,10 @@ public: const std::vector &get_outer_attrs () const { return outer_attrs; } // TODO: would a "vis_type" be better? - std::unique_ptr &get_type () { + std::unique_ptr &get_type () + { rust_assert (param_type != nullptr); - return param_type; + return param_type; } }; @@ -799,14 +828,16 @@ public: BareFunctionType (std::vector lifetime_params, FunctionQualifiers qualifiers, - std::vector named_params, bool is_variadic, std::vector variadic_attrs, + std::vector named_params, bool is_variadic, + std::vector variadic_attrs, std::unique_ptr type, Location locus) : for_lifetimes (std::move (lifetime_params)), function_qualifiers (std::move (qualifiers)), params (std::move (named_params)), is_variadic (is_variadic), - variadic_attrs (std::move (variadic_attrs)), return_type (std::move (type)), locus (locus) + variadic_attrs (std::move (variadic_attrs)), + return_type (std::move (type)), locus (locus) { - if (!variadic_attrs.empty()) + if (!variadic_attrs.empty ()) is_variadic = true; } @@ -814,7 +845,8 @@ public: BareFunctionType (BareFunctionType const &other) : for_lifetimes (other.for_lifetimes), function_qualifiers (other.function_qualifiers), params (other.params), - is_variadic (other.is_variadic), variadic_attrs (other.variadic_attrs), locus (other.locus) + is_variadic (other.is_variadic), variadic_attrs (other.variadic_attrs), + locus (other.locus) { // guard to prevent null dereference if (other.return_type != nullptr) @@ -853,12 +885,16 @@ public: // TODO: this mutable getter seems kinda dodgy std::vector &get_function_params () { return params; } - const std::vector &get_function_params () const { return params; } + const std::vector &get_function_params () const + { + return params; + } // TODO: would a "vis_type" be better? - std::unique_ptr &get_return_type () { + std::unique_ptr &get_return_type () + { rust_assert (has_return_type ()); - return return_type; + return return_type; } protected: diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 95fb962..82941c7 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -5,2870 +5,3388 @@ #include "rust-diagnostics.h" namespace Rust { - // Visitor used to expand attributes. - class AttrVisitor : public AST::ASTVisitor { - private: - MacroExpander& expander; - - public: - AttrVisitor(MacroExpander& expander) : expander(expander) {} - - void expand_struct_fields(std::vector& fields) { - for (int i = 0; i < fields.size();) { - auto& field = fields[i]; - - auto& field_attrs = field.get_outer_attrs(); - expander.expand_cfg_attrs(field_attrs); - if (expander.fails_cfg(field_attrs)) { - fields.erase(fields.begin() + i); - continue; - } - - // expand sub-types of type, but can't strip type itself - auto& type = field.get_field_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - // if nothing else happens, increment - i++; - } - } - - void expand_tuple_fields(std::vector& fields) { - for (int i = 0; i < fields.size();) { - auto& field = fields[i]; - - auto& field_attrs = field.get_outer_attrs(); - expander.expand_cfg_attrs(field_attrs); - if (expander.fails_cfg(field_attrs)) { - fields.erase(fields.begin() + i); - continue; - } - - // expand sub-types of type, but can't strip type itself - auto& type = field.get_field_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - // if nothing else happens, increment - i++; - } - } - - void expand_function_params(std::vector& params) { - for (int i = 0; i < params.size();) { - auto& param = params[i]; - - auto& param_attrs = param.get_outer_attrs(); - expander.expand_cfg_attrs(param_attrs); - if (expander.fails_cfg(param_attrs)) { - params.erase(params.begin() + i); - continue; - } - - // TODO: should an unwanted strip lead to break out of loop? - auto& pattern = param.get_pattern(); - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - - auto& type = param.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - // increment - i++; - } - } - - void expand_generic_args(AST::GenericArgs& args) { - // lifetime args can't be expanded - - // expand type args - strip sub-types only - for (auto& type : args.get_type_args()) { - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - - // expand binding args - strip sub-types only - for (auto& binding : args.get_binding_args()) { - auto& type = binding.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - } - - void expand_qualified_path_type(AST::QualifiedPathType& path_type) { - auto& type = path_type.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - if (path_type.has_as_clause()) { - auto& type_path = path_type.get_as_type_path(); - visit(type_path); - if (type_path.is_marked_for_strip()) - rust_error_at(type_path.get_locus(), "cannot strip type path in this position"); - } - } - - void expand_closure_params(std::vector& params) { - for (int i = 0; i < params.size();) { - auto& param = params[i]; - - auto& param_attrs = param.get_outer_attrs(); - expander.expand_cfg_attrs(param_attrs); - if (expander.fails_cfg(param_attrs)) { - params.erase(params.begin() + i); - continue; - } - - auto& pattern = param.get_pattern(); - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - - if (param.has_type_given()) { - auto& type = param.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - - // increment if found nothing else so far - i++; - } - } - - void expand_self_param(AST::SelfParam& self_param) { - if (self_param.has_type()) { - auto& type = self_param.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - // TODO: maybe check for invariants being violated - e.g. both type and lifetime? - } - - void expand_where_clause(AST::WhereClause& where_clause) { - // items cannot be stripped conceptually, so just accept visitor - for (auto& item : where_clause.get_items()) - item->accept_vis(*this); - } - - void expand_trait_function_decl(AST::TraitFunctionDecl& decl) { - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : decl.get_generic_params()) - param->accept_vis(*this); - - /* strip function parameters if required - this is specifically - * allowed by spec */ - expand_function_params(decl.get_function_params()); - - if (decl.has_return_type()) { - auto& return_type = decl.get_return_type(); - return_type->accept_vis(*this); - if (return_type->is_marked_for_strip()) - rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); - } - - if (decl.has_where_clause()) - expand_where_clause(decl.get_where_clause()); - } - - void expand_trait_method_decl(AST::TraitMethodDecl& decl) { - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : decl.get_generic_params()) - param->accept_vis(*this); - - /* assuming you can't strip self param - wouldn't be a method - * anymore. spec allows outer attrs on self param, but doesn't - * specify whether cfg is used. */ - expand_self_param(decl.get_self_param()); - - /* strip function parameters if required - this is specifically - * allowed by spec */ - expand_function_params(decl.get_function_params()); - - if (decl.has_return_type()) { - auto& return_type = decl.get_return_type(); - return_type->accept_vis(*this); - if (return_type->is_marked_for_strip()) - rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); - } - - if (decl.has_where_clause()) - expand_where_clause(decl.get_where_clause()); - } - - void visit(AST::Token& tok) override { - // shouldn't require? - } - void visit(AST::DelimTokenTree& delim_tok_tree) override { - // shouldn't require? - } - void visit(AST::AttrInputMetaItemContainer& input) override { - // shouldn't require? - } - void visit(AST::IdentifierExpr& ident_expr) override { - // strip test based on outer attrs - expander.expand_cfg_attrs(ident_expr.get_outer_attrs()); - if (expander.fails_cfg(ident_expr.get_outer_attrs())) { - ident_expr.mark_for_strip(); - return; - } - } - void visit(AST::Lifetime& lifetime) override { - // shouldn't require? - } - void visit(AST::LifetimeParam& lifetime_param) override { - // supposedly does not require - cfg does nothing - } - void visit(AST::MacroInvocationSemi& macro_invoc) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(macro_invoc.get_outer_attrs()); - if (expander.fails_cfg(macro_invoc.get_outer_attrs())) { - macro_invoc.mark_for_strip(); - return; - } - - // can't strip simple path - - // I don't think any macro token trees can be stripped in any way - - // TODO: maybe have cfg! macro stripping behaviour here? - } - - void visit(AST::PathInExpression& path) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(path.get_outer_attrs()); - if (expander.fails_cfg(path.get_outer_attrs())) { - path.mark_for_strip(); - return; - } - - for (auto& segment : path.get_segments()) { - if (segment.has_generic_args()) - expand_generic_args(segment.get_generic_args()); - } - } - void visit(AST::TypePathSegment& segment) override { - // shouldn't require - } - void visit(AST::TypePathSegmentGeneric& segment) override { - // TODO: strip inside generic args - - if (!segment.has_generic_args()) - return; - - expand_generic_args(segment.get_generic_args()); - } - void visit(AST::TypePathSegmentFunction& segment) override { - auto& type_path_function = segment.get_type_path_function(); - - for (auto& type : type_path_function.get_params()) { - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - - if (type_path_function.has_return_type()) { - auto& return_type = type_path_function.get_return_type(); - return_type->accept_vis(*this); - if (return_type->is_marked_for_strip()) - rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); - } - } - void visit(AST::TypePath& path) override { - // this shouldn't strip any segments, but can strip inside them - for (auto& segment : path.get_segments()) - segment->accept_vis(*this); - } - void visit(AST::QualifiedPathInExpression& path) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(path.get_outer_attrs()); - if (expander.fails_cfg(path.get_outer_attrs())) { - path.mark_for_strip(); - return; - } - - expand_qualified_path_type(path.get_qualified_path_type()); - - for (auto& segment : path.get_segments()) { - if (segment.has_generic_args()) - expand_generic_args(segment.get_generic_args()); - } - } - void visit(AST::QualifiedPathInType& path) override { - expand_qualified_path_type(path.get_qualified_path_type()); - - // this shouldn't strip any segments, but can strip inside them - for (auto& segment : path.get_segments()) - segment->accept_vis(*this); - } - - void visit(AST::LiteralExpr& 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; - } - } - void visit(AST::AttrInputLiteral& attr_input) override { - // shouldn't require? - } - void visit(AST::MetaItemLitExpr& meta_item) override { - // shouldn't require? - } - void visit(AST::MetaItemPathLit& meta_item) override { - // shouldn't require? - } - void visit(AST::BorrowExpr& 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 any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& borrowed_expr = expr.get_borrowed_expr(); - borrowed_expr->accept_vis(*this); - if (borrowed_expr->is_marked_for_strip()) - rust_error_at(borrowed_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::DereferenceExpr& 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 any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& dereferenced_expr = expr.get_dereferenced_expr(); - dereferenced_expr->accept_vis(*this); - if (dereferenced_expr->is_marked_for_strip()) - rust_error_at(dereferenced_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::ErrorPropagationExpr& 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 any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& propagating_expr = expr.get_propagating_expr(); - propagating_expr->accept_vis(*this); - if (propagating_expr->is_marked_for_strip()) - rust_error_at(propagating_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::NegationExpr& 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 any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& negated_expr = expr.get_negated_expr(); - negated_expr->accept_vis(*this); - if (negated_expr->is_marked_for_strip()) - rust_error_at(negated_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::ArithmeticOrLogicalExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - expr.get_left_expr()->accept_vis(*this); - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - expr.get_right_expr()->accept_vis(*this); - - // ensure that they are not marked for strip - if (expr.get_left_expr()->is_marked_for_strip()) - rust_error_at(expr.get_left_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); - if (expr.get_right_expr()->is_marked_for_strip()) - rust_error_at(expr.get_right_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::ComparisonExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - expr.get_left_expr()->accept_vis(*this); - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - expr.get_right_expr()->accept_vis(*this); - - // ensure that they are not marked for strip - if (expr.get_left_expr()->is_marked_for_strip()) - rust_error_at(expr.get_left_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); - if (expr.get_right_expr()->is_marked_for_strip()) - rust_error_at(expr.get_right_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::LazyBooleanExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - expr.get_left_expr()->accept_vis(*this); - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - expr.get_right_expr()->accept_vis(*this); - - // ensure that they are not marked for strip - if (expr.get_left_expr()->is_marked_for_strip()) - rust_error_at(expr.get_left_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); - if (expr.get_right_expr()->is_marked_for_strip()) - rust_error_at(expr.get_right_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::TypeCastExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * direct descendant expression, can strip ones below that */ - - auto& casted_expr = expr.get_casted_expr(); - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - casted_expr->accept_vis(*this); - - // ensure that they are not marked for strip - if (casted_expr->is_marked_for_strip()) - rust_error_at(casted_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes are never allowed before cast exprs"); - - // TODO: strip sub-types of type - auto& type = expr.get_type_to_cast_to(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - void visit(AST::AssignmentExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - expr.get_left_expr()->accept_vis(*this); - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - expr.get_right_expr()->accept_vis(*this); - - // ensure that they are not marked for strip - if (expr.get_left_expr()->is_marked_for_strip()) - rust_error_at(expr.get_left_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); - if (expr.get_right_expr()->is_marked_for_strip()) - rust_error_at(expr.get_right_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::CompoundAssignmentExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - expr.get_left_expr()->accept_vis(*this); - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - expr.get_right_expr()->accept_vis(*this); - - // ensure that they are not marked for strip - if (expr.get_left_expr()->is_marked_for_strip()) - rust_error_at(expr.get_left_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes are never allowed before binary op exprs"); - if (expr.get_right_expr()->is_marked_for_strip()) - rust_error_at(expr.get_right_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::GroupedExpr& 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 test based on inner attrs - spec says these are inner - * attributes, not outer attributes of inner expr */ - expander.expand_cfg_attrs(expr.get_inner_attrs()); - if (expander.fails_cfg(expr.get_inner_attrs())) { - expr.mark_for_strip(); - return; - } - - /* strip any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& inner_expr = expr.get_expr_in_parens(); - inner_expr->accept_vis(*this); - if (inner_expr->is_marked_for_strip()) - rust_error_at(inner_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::ArrayElemsValues& elems) override { - /* apparently outer attributes are allowed in "elements of array - * expressions" according to spec */ - auto& values = elems.get_values(); - 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::ArrayElemsCopied& elems) override { - /* apparently outer attributes are allowed in "elements of array - * expressions" according to spec. on the other hand, it would not - * make conceptual sense to be able to remove either expression. As - * such, not implementing. TODO clear up the ambiguity here */ - - // only intend stripping for internal sub-expressions - auto& copied_expr = elems.get_elem_to_copy(); - copied_expr->accept_vis(*this); - if (copied_expr->is_marked_for_strip()) - rust_error_at(copied_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - auto& copy_count = elems.get_num_copies(); - copy_count->accept_vis(*this); - if (copy_count->is_marked_for_strip()) - rust_error_at(copy_count->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::ArrayExpr& 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 test based on inner attrs - spec says there are separate - * inner attributes, not just outer attributes of inner exprs */ - expander.expand_cfg_attrs(expr.get_inner_attrs()); - if (expander.fails_cfg(expr.get_inner_attrs())) { - expr.mark_for_strip(); - return; - } - - /* assuming you can't strip away the ArrayElems type, but can strip - * internal expressions and whatever */ - if (expr.has_array_elems()) - expr.get_array_elems()->accept_vis(*this); - } - void visit(AST::ArrayIndexExpr& expr) override { - /* it is unclear whether outer attributes are supposed to be - * allowed, but conceptually it wouldn't make much sense, but - * having expansion code anyway. TODO */ - // 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 any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& array_expr = expr.get_array_expr(); - array_expr->accept_vis(*this); - if (array_expr->is_marked_for_strip()) - rust_error_at(array_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - auto& index_expr = expr.get_index_expr(); - index_expr->accept_vis(*this); - if (index_expr->is_marked_for_strip()) - rust_error_at(index_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::TupleExpr& expr) override { - /* according to spec, outer attributes are allowed on "elements of - * tuple expressions" */ - - // 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 test based on inner attrs - spec says these are inner - * attributes, not outer attributes of inner expr */ - expander.expand_cfg_attrs(expr.get_inner_attrs()); - if (expander.fails_cfg(expr.get_inner_attrs())) { - expr.mark_for_strip(); - return; - } - - /* apparently outer attributes are allowed in "elements of tuple - * expressions" according to spec */ - auto& values = expr.get_tuple_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::TupleIndexExpr& 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; - } - - /* wouldn't strip this directly (as outer attrs should be - * associated with this level), but any sub-expressions would be - * stripped. Thus, no need to erase when strip check called. */ - auto& tuple_expr = expr.get_tuple_expr(); - tuple_expr->accept_vis(*this); - if (tuple_expr->is_marked_for_strip()) - rust_error_at(tuple_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::StructExprStruct& 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 test based on inner attrs - spec says these are inner - * attributes, not outer attributes of inner expr */ - expander.expand_cfg_attrs(expr.get_inner_attrs()); - if (expander.fails_cfg(expr.get_inner_attrs())) { - expr.mark_for_strip(); - return; - } - - // strip sub-exprs of path - auto& struct_name = expr.get_struct_name(); - visit(struct_name); - if (struct_name.is_marked_for_strip()) - rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); - } - void visit(AST::StructExprFieldIdentifier& field) override { - // as no attrs (at moment, at least), no stripping possible - } - void visit(AST::StructExprFieldIdentifierValue& field) override { - /* as no attrs possible (at moment, at least), only sub-expression - * stripping is possible */ - auto& value = field.get_value(); - value->accept_vis(*this); - if (value->is_marked_for_strip()) - rust_error_at(value->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::StructExprFieldIndexValue& field) override { - /* as no attrs possible (at moment, at least), only sub-expression - * stripping is possible */ - auto& value = field.get_value(); - value->accept_vis(*this); - if (value->is_marked_for_strip()) - rust_error_at(value->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::StructExprStructFields& 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 test based on inner attrs - spec says these are inner - * attributes, not outer attributes of inner expr */ - expander.expand_cfg_attrs(expr.get_inner_attrs()); - if (expander.fails_cfg(expr.get_inner_attrs())) { - expr.mark_for_strip(); - return; - } - - // strip sub-exprs of path - auto& struct_name = expr.get_struct_name(); - visit(struct_name); - if (struct_name.is_marked_for_strip()) - rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); - - /* spec does not specify whether expressions are allowed to be - * stripped at top level of struct fields, but I wouldn't think - * that they would be, so operating under the assumption that only - * sub-expressions can be stripped. */ - for (auto& field : expr.get_fields()) { - field->accept_vis(*this); - // shouldn't strip in this - } - - /* struct base presumably can't be stripped, as the '..' is before - * the expression. as such, can only strip sub-expressions. */ - if (expr.has_struct_base()) { - auto& base_struct_expr = expr.get_struct_base().get_base_struct(); - base_struct_expr->accept_vis(*this); - if (base_struct_expr->is_marked_for_strip()) - rust_error_at(base_struct_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - } - void visit(AST::StructExprStructBase& 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 test based on inner attrs - spec says these are inner - * attributes, not outer attributes of inner expr */ - expander.expand_cfg_attrs(expr.get_inner_attrs()); - if (expander.fails_cfg(expr.get_inner_attrs())) { - expr.mark_for_strip(); - return; - } - - // strip sub-exprs of path - auto& struct_name = expr.get_struct_name(); - visit(struct_name); - if (struct_name.is_marked_for_strip()) - rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); - - /* struct base presumably can't be stripped, as the '..' is before - * the expression. as such, can only strip sub-expressions. */ - rust_assert(!expr.get_struct_base().is_invalid()); - auto& base_struct_expr = expr.get_struct_base().get_base_struct(); - base_struct_expr->accept_vis(*this); - if (base_struct_expr->is_marked_for_strip()) - rust_error_at(base_struct_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::StructExprTuple& 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 test based on inner attrs - spec says these are inner - * attributes, not outer attributes of inner expr */ - expander.expand_cfg_attrs(expr.get_inner_attrs()); - if (expander.fails_cfg(expr.get_inner_attrs())) { - expr.mark_for_strip(); - return; - } - - // strip sub-exprs of path - auto& struct_name = expr.get_struct_name(); - visit(struct_name); - if (struct_name.is_marked_for_strip()) - rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); - - /* spec says outer attributes are specifically allowed for elements - * of tuple-style struct 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::StructExprUnit& 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 sub-exprs of path - auto& struct_name = expr.get_struct_name(); - visit(struct_name); - if (struct_name.is_marked_for_strip()) - rust_error_at(struct_name.get_locus(), "cannot strip path in this position"); - } - 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 */ - auto& value = field.get_value(); - value->accept_vis(*this); - if (value->is_marked_for_strip()) - rust_error_at(value->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::EnumExprFieldIndexValue& field) override { - /* as no attrs possible (at moment, at least), only sub-expression - * stripping is possible */ - auto& value = field.get_value(); - value->accept_vis(*this); - if (value->is_marked_for_strip()) - rust_error_at(value->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::EnumExprStruct& 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 - - // strip sub-exprs of path - auto& enum_path = expr.get_enum_variant_path(); - visit(enum_path); - if (enum_path.is_marked_for_strip()) - rust_error_at(enum_path.get_locus(), "cannot strip path in this position"); - - /* spec does not specify whether expressions are allowed to be - * stripped at top level of expression fields, but I wouldn't think - * that they would be, so operating under the assumption that only - * sub-expressions can be stripped. */ - for (auto& field : expr.get_fields()) { - field->accept_vis(*this); - // shouldn't strip in this - } - } - 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 - - // strip sub-exprs of path - auto& enum_path = expr.get_enum_variant_path(); - visit(enum_path); - if (enum_path.is_marked_for_strip()) - rust_error_at(enum_path.get_locus(), "cannot strip path in this position"); - - /* 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 - - // strip sub-exprs of path - auto& enum_path = expr.get_enum_variant_path(); - visit(enum_path); - if (enum_path.is_marked_for_strip()) - rust_error_at(enum_path.get_locus(), "cannot strip path in this position"); - } - 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. */ - auto& function = expr.get_function_expr(); - function->accept_vis(*this); - if (function->is_marked_for_strip()) - rust_error_at(function->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - /* 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. */ - auto& receiver = expr.get_receiver_expr(); - receiver->accept_vis(*this); - if (receiver->is_marked_for_strip()) - rust_error_at(receiver->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - auto& method_name = expr.get_method_name(); - if (method_name.has_generic_args()) - expand_generic_args(method_name.get_generic_args()); - - /* 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 field expr as a whole. only sub-expr - * expansion is possible. */ - auto& receiver = expr.get_receiver_expr(); - receiver->accept_vis(*this); - if (receiver->is_marked_for_strip()) - rust_error_at(receiver->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - 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 */ - expand_closure_params(expr.get_params()); - - // can't strip expression itself, but can strip sub-expressions - auto& definition_expr = expr.get_definition_expr(); - definition_expr->accept_vis(*this); - if (definition_expr->is_marked_for_strip()) - rust_error_at(definition_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::BlockExpr& 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 test based on inner attrs - spec says there are inner - * attributes, not just outer attributes of inner stmts */ - expander.expand_cfg_attrs(expr.get_inner_attrs()); - if (expander.fails_cfg(expr.get_inner_attrs())) { - expr.mark_for_strip(); - return; - } - - // strip all statements - auto& stmts = expr.get_statements(); - for (int i = 0; i < stmts.size();) { - auto& stmt = stmts[i]; - - // mark for stripping if required - stmt->accept_vis(*this); - - if (stmt->is_marked_for_strip()) - stmts.erase(stmts.begin() + i); - else - i++; - } - - // strip tail expression if exists - can actually fully remove it - if (expr.has_tail_expr()) { - auto& tail_expr = expr.get_tail_expr(); - - tail_expr->accept_vis(*this); - - if (tail_expr->is_marked_for_strip()) - expr.strip_tail_expr(); - } - } - void visit(AST::ClosureExprInnerTyped& 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 */ - expand_closure_params(expr.get_params()); - - // can't strip return type, but can strip sub-types - auto& type = expr.get_return_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - // can't strip expression itself, but can strip sub-expressions - auto& definition_block = expr.get_definition_block(); - definition_block->accept_vis(*this); - if (definition_block->is_marked_for_strip()) - rust_error_at(definition_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::ContinueExpr& 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; - } - } - void visit(AST::BreakExpr& 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; - } - - /* spec does not say that you can have outer attributes on - * expression, so assuming you can't. stripping for sub-expressions - * is the only thing that can be done */ - if (expr.has_break_expr()) { - auto& break_expr = expr.get_break_expr(); - - break_expr->accept_vis(*this); - - if (break_expr->is_marked_for_strip()) - rust_error_at(break_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - } - void visit(AST::RangeFromToExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - expr.get_from_expr()->accept_vis(*this); - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - expr.get_to_expr()->accept_vis(*this); - - // ensure that they are not marked for strip - if (expr.get_from_expr()->is_marked_for_strip()) - rust_error_at(expr.get_from_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes are never allowed before range exprs"); - if (expr.get_to_expr()->is_marked_for_strip()) - rust_error_at(expr.get_to_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::RangeFromExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * direct descendant expression, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - auto& from_expr = expr.get_from_expr(); - - from_expr->accept_vis(*this); - - if (from_expr->is_marked_for_strip()) - rust_error_at(from_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes are never allowed before range exprs"); - } - void visit(AST::RangeToExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * direct descendant expression, can strip ones below that */ - - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - auto& to_expr = expr.get_to_expr(); - - to_expr->accept_vis(*this); - - if (to_expr->is_marked_for_strip()) - rust_error_at(to_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::RangeFullExpr& expr) override { - // outer attributes never allowed before these, so no stripping - } - void visit(AST::RangeFromToInclExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * two direct descendant expressions, can strip ones below that */ - - /* should have no possibility for outer attrs as would be parsed - * with outer expr */ - expr.get_from_expr()->accept_vis(*this); - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - expr.get_to_expr()->accept_vis(*this); - - // ensure that they are not marked for strip - if (expr.get_from_expr()->is_marked_for_strip()) - rust_error_at(expr.get_from_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes are never allowed before range exprs"); - if (expr.get_to_expr()->is_marked_for_strip()) - rust_error_at(expr.get_to_expr()->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::RangeToInclExpr& expr) override { - /* outer attributes never allowed before these. while cannot strip - * direct descendant expression, can strip ones below that */ - - /* should syntactically not have outer attributes, though this may - * not have worked in practice */ - auto& to_expr = expr.get_to_expr(); - - to_expr->accept_vis(*this); - - if (to_expr->is_marked_for_strip()) - rust_error_at(to_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::ReturnExpr& 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; - } - - /* spec does not say that you can have outer attributes on - * expression, so assuming you can't. stripping for sub-expressions - * is the only thing that can be done */ - if (expr.has_returned_expr()) { - auto& returned_expr = expr.get_returned_expr(); - - returned_expr->accept_vis(*this); - - if (returned_expr->is_marked_for_strip()) - rust_error_at(returned_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - /* TODO: conceptually, you would maybe be able to remove a returned - * expr - e.g. if you had conditional compilation returning void or - * returning a type. On the other hand, I think that function - * return type cannot be conditionally compiled, so I assumed you - * can't do this either. */ - } - void visit(AST::UnsafeBlockExpr& 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; - } - - // can't strip block itself, but can strip sub-expressions - auto& block_expr = expr.get_block_expr(); - block_expr->accept_vis(*this); - if (block_expr->is_marked_for_strip()) - rust_error_at(block_expr->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::LoopExpr& 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; - } - - // can't strip block itself, but can strip sub-expressions - auto& loop_block = expr.get_loop_block(); - loop_block->accept_vis(*this); - if (loop_block->is_marked_for_strip()) - rust_error_at(loop_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::WhileLoopExpr& 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; - } - - // can't strip predicate expr itself, but can strip sub-expressions - auto& predicate_expr = expr.get_predicate_expr(); - predicate_expr->accept_vis(*this); - if (predicate_expr->is_marked_for_strip()) - rust_error_at(predicate_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip block itself, but can strip sub-expressions - auto& loop_block = expr.get_loop_block(); - loop_block->accept_vis(*this); - if (loop_block->is_marked_for_strip()) - rust_error_at(loop_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::WhileLetLoopExpr& 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; - } - - for (auto& pattern : expr.get_patterns()) { - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - - // can't strip scrutinee expr itself, but can strip sub-expressions - auto& scrutinee_expr = expr.get_scrutinee_expr(); - scrutinee_expr->accept_vis(*this); - if (scrutinee_expr->is_marked_for_strip()) - rust_error_at(scrutinee_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip block itself, but can strip sub-expressions - auto& loop_block = expr.get_loop_block(); - loop_block->accept_vis(*this); - if (loop_block->is_marked_for_strip()) - rust_error_at(loop_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::ForLoopExpr& 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; - } - - // TODO: strip sub-patterns of pattern - auto& pattern = expr.get_pattern(); - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - - // can't strip scrutinee expr itself, but can strip sub-expressions - auto& iterator_expr = expr.get_iterator_expr(); - iterator_expr->accept_vis(*this); - if (iterator_expr->is_marked_for_strip()) - rust_error_at(iterator_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip block itself, but can strip sub-expressions - auto& loop_block = expr.get_loop_block(); - loop_block->accept_vis(*this); - if (loop_block->is_marked_for_strip()) - rust_error_at(loop_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::IfExpr& 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; - } - - // can't strip condition expr itself, but can strip sub-expressions - auto& condition_expr = expr.get_condition_expr(); - condition_expr->accept_vis(*this); - if (condition_expr->is_marked_for_strip()) - rust_error_at(condition_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip if block itself, but can strip sub-expressions - auto& if_block = expr.get_if_block(); - if_block->accept_vis(*this); - if (if_block->is_marked_for_strip()) - rust_error_at(if_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::IfExprConseqElse& 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; - } - - // can't strip condition expr itself, but can strip sub-expressions - auto& condition_expr = expr.get_condition_expr(); - condition_expr->accept_vis(*this); - if (condition_expr->is_marked_for_strip()) - rust_error_at(condition_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip if block itself, but can strip sub-expressions - auto& if_block = expr.get_if_block(); - if_block->accept_vis(*this); - if (if_block->is_marked_for_strip()) - rust_error_at(if_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - - // can't strip else block itself, but can strip sub-expressions - auto& else_block = expr.get_else_block(); - else_block->accept_vis(*this); - if (else_block->is_marked_for_strip()) - rust_error_at(else_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::IfExprConseqIf& 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; - } - - // can't strip condition expr itself, but can strip sub-expressions - auto& condition_expr = expr.get_condition_expr(); - condition_expr->accept_vis(*this); - if (condition_expr->is_marked_for_strip()) - rust_error_at(condition_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip if block itself, but can strip sub-expressions - auto& if_block = expr.get_if_block(); - if_block->accept_vis(*this); - if (if_block->is_marked_for_strip()) - rust_error_at(if_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - - // can't strip if expr itself, but can strip sub-expressions - auto& conseq_if_expr = expr.get_conseq_if_expr(); - conseq_if_expr->accept_vis(*this); - if (conseq_if_expr->is_marked_for_strip()) - rust_error_at(conseq_if_expr->get_locus_slow(), - "cannot strip consequent if expression in this position - outer attributes not allowed"); - } - void visit(AST::IfExprConseqIfLet& 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; - } - - // can't strip condition expr itself, but can strip sub-expressions - auto& condition_expr = expr.get_condition_expr(); - condition_expr->accept_vis(*this); - if (condition_expr->is_marked_for_strip()) - rust_error_at(condition_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip if block itself, but can strip sub-expressions - auto& if_block = expr.get_if_block(); - if_block->accept_vis(*this); - if (if_block->is_marked_for_strip()) - rust_error_at(if_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - - // can't strip if let expr itself, but can strip sub-expressions - auto& conseq_if_let_expr = expr.get_conseq_if_let_expr(); - conseq_if_let_expr->accept_vis(*this); - if (conseq_if_let_expr->is_marked_for_strip()) - rust_error_at(conseq_if_let_expr->get_locus_slow(), - "cannot strip consequent if let expression in this position - outer attributes not allowed"); - } - void visit(AST::IfLetExpr& 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; - } - - for (auto& pattern : expr.get_patterns()) { - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - - // can't strip value expr itself, but can strip sub-expressions - auto& value_expr = expr.get_value_expr(); - value_expr->accept_vis(*this); - if (value_expr->is_marked_for_strip()) - rust_error_at(value_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip if block itself, but can strip sub-expressions - auto& if_block = expr.get_if_block(); - if_block->accept_vis(*this); - if (if_block->is_marked_for_strip()) - rust_error_at(if_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::IfLetExprConseqElse& 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; - } - - for (auto& pattern : expr.get_patterns()) { - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - - // can't strip value expr itself, but can strip sub-expressions - auto& value_expr = expr.get_value_expr(); - value_expr->accept_vis(*this); - if (value_expr->is_marked_for_strip()) - rust_error_at(value_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip if block itself, but can strip sub-expressions - auto& if_block = expr.get_if_block(); - if_block->accept_vis(*this); - if (if_block->is_marked_for_strip()) - rust_error_at(if_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - - // can't strip else block itself, but can strip sub-expressions - auto& else_block = expr.get_else_block(); - else_block->accept_vis(*this); - if (else_block->is_marked_for_strip()) - rust_error_at(else_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::IfLetExprConseqIf& 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; - } - - for (auto& pattern : expr.get_patterns()) { - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - - // can't strip value expr itself, but can strip sub-expressions - auto& value_expr = expr.get_value_expr(); - value_expr->accept_vis(*this); - if (value_expr->is_marked_for_strip()) - rust_error_at(value_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip if block itself, but can strip sub-expressions - auto& if_block = expr.get_if_block(); - if_block->accept_vis(*this); - if (if_block->is_marked_for_strip()) - rust_error_at(if_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - - // can't strip if expr itself, but can strip sub-expressions - auto& conseq_if_expr = expr.get_conseq_if_expr(); - conseq_if_expr->accept_vis(*this); - if (conseq_if_expr->is_marked_for_strip()) - rust_error_at(conseq_if_expr->get_locus_slow(), - "cannot strip consequent if expression in this position - outer attributes not allowed"); - } - void visit(AST::IfLetExprConseqIfLet& 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; - } - - for (auto& pattern : expr.get_patterns()) { - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - - // can't strip value expr itself, but can strip sub-expressions - auto& value_expr = expr.get_value_expr(); - value_expr->accept_vis(*this); - if (value_expr->is_marked_for_strip()) - rust_error_at(value_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // can't strip if block itself, but can strip sub-expressions - auto& if_block = expr.get_if_block(); - if_block->accept_vis(*this); - if (if_block->is_marked_for_strip()) - rust_error_at(if_block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - - // can't strip if let expr itself, but can strip sub-expressions - auto& conseq_if_let_expr = expr.get_conseq_if_let_expr(); - conseq_if_let_expr->accept_vis(*this); - if (conseq_if_let_expr->is_marked_for_strip()) - rust_error_at(conseq_if_let_expr->get_locus_slow(), - "cannot strip consequent if let expression in this position - outer attributes not allowed"); - } - void visit(AST::MatchExpr& 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; - } - - // inner attr strip test - expander.expand_cfg_attrs(expr.get_inner_attrs()); - if (expander.fails_cfg(expr.get_inner_attrs())) { - expr.mark_for_strip(); - return; - } - - // can't strip scrutinee expr itself, but can strip sub-expressions - auto& scrutinee_expr = expr.get_scrutinee_expr(); - scrutinee_expr->accept_vis(*this); - if (scrutinee_expr->is_marked_for_strip()) - rust_error_at(scrutinee_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // strip match cases - auto& match_cases = expr.get_match_cases(); - for (int i = 0; i < match_cases.size(); ) { - auto& match_case = match_cases[i]; - - // strip match case based on outer attributes in match arm - auto& match_arm = match_case.get_arm(); - expander.expand_cfg_attrs(match_arm.get_outer_attrs()); - if (expander.fails_cfg(match_arm.get_outer_attrs())) { - // strip match case - match_cases.erase(match_cases.begin() + i); - continue; - } - - for (auto& pattern : match_arm.get_patterns()) { - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - - /* assuming that guard expression cannot be stripped as - * strictly speaking you would have to strip the whole guard to - * make syntactical sense, which you can't do. as such, only - * strip sub-expressions */ - if (match_arm.has_match_arm_guard()) { - auto& guard_expr = match_arm.get_guard_expr(); - guard_expr->accept_vis(*this); - if (guard_expr->is_marked_for_strip()) - rust_error_at(guard_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - - // strip sub-expressions from match cases - auto& case_expr = match_case.get_expr(); - case_expr->accept_vis(*this); - if (case_expr->is_marked_for_strip()) - rust_error_at(case_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - - // increment to next case if haven't continued - i++; - } - } - void visit(AST::AwaitExpr& 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; - } - - /* can't strip awaited expr itself, but can strip sub-expressions - * - this is because you can't have no expr to await */ - auto& awaited_expr = expr.get_awaited_expr(); - awaited_expr->accept_vis(*this); - if (awaited_expr->is_marked_for_strip()) - rust_error_at(awaited_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::AsyncBlockExpr& 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; - } - - // can't strip block itself, but can strip sub-expressions - auto& block_expr = expr.get_block_expr(); - block_expr->accept_vis(*this); - if (block_expr->is_marked_for_strip()) - rust_error_at(block_expr->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - - void visit(AST::TypeParam& param) override { - // outer attributes don't actually do anything, so ignore them - - if (param.has_type_param_bounds()) { - // don't strip directly, only components of bounds - for (auto& bound : param.get_type_param_bounds()) - bound->accept_vis(*this); - } - - if (param.has_type()) { - auto& type = param.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - } - void visit(AST::LifetimeWhereClauseItem& item) override { - // shouldn't require - } - void visit(AST::TypeBoundWhereClauseItem& item) override { - // for lifetimes shouldn't require - - auto& type = item.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - // don't strip directly, only components of bounds - for (auto& bound : item.get_type_param_bounds()) - bound->accept_vis(*this); - } - void visit(AST::Method& method) override { - // initial test based on outer attrs - expander.expand_cfg_attrs(method.get_outer_attrs()); - if (expander.fails_cfg(method.get_outer_attrs())) { - method.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : method.get_generic_params()) - param->accept_vis(*this); - - /* assuming you can't strip self param - wouldn't be a method - * anymore. spec allows outer attrs on self param, but doesn't - * specify whether cfg is used. */ - expand_self_param(method.get_self_param()); - - /* strip method parameters if required - this is specifically - * allowed by spec */ - expand_function_params(method.get_function_params()); - - if (method.has_return_type()) { - auto& return_type = method.get_return_type(); - return_type->accept_vis(*this); - if (return_type->is_marked_for_strip()) - rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); - } - - if (method.has_where_clause()) - expand_where_clause(method.get_where_clause()); - - /* body should always exist - if error state, should have returned - * before now */ - // can't strip block itself, but can strip sub-expressions - auto& block_expr = method.get_definition(); - block_expr->accept_vis(*this); - if (block_expr->is_marked_for_strip()) - rust_error_at(block_expr->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::ModuleBodied& module) override { - // strip test based on outer attrs - expander.expand_cfg_attrs(module.get_outer_attrs()); - if (expander.fails_cfg(module.get_outer_attrs())) { - module.mark_for_strip(); - return; - } - - // strip test based on inner attrs - expander.expand_cfg_attrs(module.get_inner_attrs()); - if (expander.fails_cfg(module.get_inner_attrs())) { - module.mark_for_strip(); - return; - } - - // strip items if required - auto& items = module.get_items(); - for (int i = 0; i < items.size();) { - auto& item = items[i]; - - // mark for stripping if required - item->accept_vis(*this); - - if (item->is_marked_for_strip()) - items.erase(items.begin() + i); - else - i++; - } - } - void visit(AST::ModuleNoBody& module) override { - // strip test based on outer attrs - expander.expand_cfg_attrs(module.get_outer_attrs()); - if (expander.fails_cfg(module.get_outer_attrs())) { - module.mark_for_strip(); - return; - } - } - void visit(AST::ExternCrate& crate) override { - // strip test based on outer attrs - expander.expand_cfg_attrs(crate.get_outer_attrs()); - if (expander.fails_cfg(crate.get_outer_attrs())) { - crate.mark_for_strip(); - return; - } - } - void visit(AST::UseTreeGlob& use_tree) override { - // shouldn't require? - } - void visit(AST::UseTreeList& use_tree) override { - // shouldn't require? - } - void visit(AST::UseTreeRebind& use_tree) override { - // shouldn't require? - } - void visit(AST::UseDeclaration& use_decl) override { - // strip test based on outer attrs - expander.expand_cfg_attrs(use_decl.get_outer_attrs()); - if (expander.fails_cfg(use_decl.get_outer_attrs())) { - use_decl.mark_for_strip(); - return; - } - } - void visit(AST::Function& function) override { - // initial test based on outer attrs - expander.expand_cfg_attrs(function.get_outer_attrs()); - if (expander.fails_cfg(function.get_outer_attrs())) { - function.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : function.get_generic_params()) - param->accept_vis(*this); - - /* strip function parameters if required - this is specifically - * allowed by spec */ - expand_function_params(function.get_function_params()); - - if (function.has_return_type()) { - auto& return_type = function.get_return_type(); - return_type->accept_vis(*this); - if (return_type->is_marked_for_strip()) - rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); - } - - if (function.has_where_clause()) - expand_where_clause(function.get_where_clause()); - - /* body should always exist - if error state, should have returned - * before now */ - // can't strip block itself, but can strip sub-expressions - auto& block_expr = function.get_definition(); - block_expr->accept_vis(*this); - if (block_expr->is_marked_for_strip()) - rust_error_at(block_expr->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - void visit(AST::TypeAlias& type_alias) override { - // initial test based on outer attrs - expander.expand_cfg_attrs(type_alias.get_outer_attrs()); - if (expander.fails_cfg(type_alias.get_outer_attrs())) { - type_alias.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : type_alias.get_generic_params()) - param->accept_vis(*this); - - if (type_alias.has_where_clause()) - expand_where_clause(type_alias.get_where_clause()); - - auto& type = type_alias.get_type_aliased(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - void visit(AST::StructStruct& struct_item) override { - // initial test based on outer attrs - expander.expand_cfg_attrs(struct_item.get_outer_attrs()); - if (expander.fails_cfg(struct_item.get_outer_attrs())) { - struct_item.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : struct_item.get_generic_params()) - param->accept_vis(*this); - - if (struct_item.has_where_clause()) - expand_where_clause(struct_item.get_where_clause()); - - /* strip struct fields if required - this is presumably - * allowed by spec */ - expand_struct_fields(struct_item.get_fields()); - } - void visit(AST::TupleStruct& tuple_struct) override { - // initial test based on outer attrs - expander.expand_cfg_attrs(tuple_struct.get_outer_attrs()); - if (expander.fails_cfg(tuple_struct.get_outer_attrs())) { - tuple_struct.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : tuple_struct.get_generic_params()) - param->accept_vis(*this); - - /* strip struct fields if required - this is presumably - * allowed by spec */ - expand_tuple_fields(tuple_struct.get_fields()); - - if (tuple_struct.has_where_clause()) - expand_where_clause(tuple_struct.get_where_clause()); - } - void visit(AST::EnumItem& item) override { - // initial 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::EnumItemTuple& item) override { - // initial 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 item fields if required - this is presumably - * allowed by spec */ - expand_tuple_fields(item.get_tuple_fields()); - } - void visit(AST::EnumItemStruct& item) override { - // initial 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 item fields if required - this is presumably - * allowed by spec */ - expand_struct_fields(item.get_struct_fields()); - } - void visit(AST::EnumItemDiscriminant& item) override { - // initial 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 any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& expr = item.get_expr(); - expr->accept_vis(*this); - if (expr->is_marked_for_strip()) - rust_error_at(expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::Enum& enum_item) override { - // initial test based on outer attrs - expander.expand_cfg_attrs(enum_item.get_outer_attrs()); - if (expander.fails_cfg(enum_item.get_outer_attrs())) { - enum_item.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : enum_item.get_generic_params()) - param->accept_vis(*this); - - if (enum_item.has_where_clause()) - expand_where_clause(enum_item.get_where_clause()); - - /* strip enum fields if required - this is presumably - * allowed by spec */ - auto& variants = enum_item.get_variants(); - for (int i = 0; i < variants.size();) { - auto& variant = variants[i]; - - // mark for stripping if required - variant->accept_vis(*this); - - if (variant->is_marked_for_strip()) - variants.erase(variants.begin() + i); - else - i++; - } - } - void visit(AST::Union& union_item) override { - // initial test based on outer attrs - expander.expand_cfg_attrs(union_item.get_outer_attrs()); - if (expander.fails_cfg(union_item.get_outer_attrs())) { - union_item.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : union_item.get_generic_params()) - param->accept_vis(*this); - - if (union_item.has_where_clause()) - expand_where_clause(union_item.get_where_clause()); - - /* strip union fields if required - this is presumably - * allowed by spec */ - expand_struct_fields(union_item.get_variants()); - } - void visit(AST::ConstantItem& const_item) override { - // initial test based on outer attrs - expander.expand_cfg_attrs(const_item.get_outer_attrs()); - if (expander.fails_cfg(const_item.get_outer_attrs())) { - const_item.mark_for_strip(); - return; - } - - // strip any sub-types - auto& type = const_item.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - /* strip any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& expr = const_item.get_expr(); - expr->accept_vis(*this); - if (expr->is_marked_for_strip()) - rust_error_at(expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::StaticItem& static_item) override { - // initial test based on outer attrs - expander.expand_cfg_attrs(static_item.get_outer_attrs()); - if (expander.fails_cfg(static_item.get_outer_attrs())) { - static_item.mark_for_strip(); - return; - } - - // strip any sub-types - auto& type = static_item.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - /* strip any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& expr = static_item.get_expr(); - expr->accept_vis(*this); - if (expr->is_marked_for_strip()) - rust_error_at(expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - void visit(AST::TraitItemFunc& item) override { - // initial 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; - } - - expand_trait_function_decl(item.get_trait_function_decl()); - - if (item.has_definition()) { - /* strip any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& block = item.get_definition(); - block->accept_vis(*this); - if (block->is_marked_for_strip()) - rust_error_at(block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - } - void visit(AST::TraitItemMethod& item) override { - // initial 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; - } - - expand_trait_method_decl(item.get_trait_method_decl()); - - if (item.has_definition()) { - /* strip any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped. */ - auto& block = item.get_definition(); - block->accept_vis(*this); - if (block->is_marked_for_strip()) - rust_error_at(block->get_locus_slow(), - "cannot strip block expression in this position - outer attributes not allowed"); - } - } - void visit(AST::TraitItemConst& item) override { - // initial 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 any sub-types - auto& type = item.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - /* strip any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped */ - if (item.has_expression()) { - auto& expr = item.get_expr(); - expr->accept_vis(*this); - if (expr->is_marked_for_strip()) - rust_error_at(expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - } - void visit(AST::TraitItemType& item) override { - // initial 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; - } - - if (item.has_type_param_bounds()) { - // don't strip directly, only components of bounds - for (auto& bound : item.get_type_param_bounds()) - bound->accept_vis(*this); - } - } - void visit(AST::Trait& trait) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(trait.get_outer_attrs()); - if (expander.fails_cfg(trait.get_outer_attrs())) { - trait.mark_for_strip(); - return; - } - - // strip test based on inner attrs - expander.expand_cfg_attrs(trait.get_inner_attrs()); - if (expander.fails_cfg(trait.get_inner_attrs())) { - trait.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : trait.get_generic_params()) - param->accept_vis(*this); - - if (trait.has_type_param_bounds()) { - // don't strip directly, only components of bounds - for (auto& bound : trait.get_type_param_bounds()) - bound->accept_vis(*this); - } - - if (trait.has_where_clause()) - expand_where_clause(trait.get_where_clause()); - - // strip trait items if required - auto& trait_items = trait.get_trait_items(); - for (int i = 0; i < trait_items.size();) { - auto& item = trait_items[i]; - - // mark for stripping if required - item->accept_vis(*this); - - if (item->is_marked_for_strip()) - trait_items.erase(trait_items.begin() + i); - else - i++; - } - } - void visit(AST::InherentImpl& impl) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(impl.get_outer_attrs()); - if (expander.fails_cfg(impl.get_outer_attrs())) { - impl.mark_for_strip(); - return; - } - - // strip test based on inner attrs - expander.expand_cfg_attrs(impl.get_inner_attrs()); - if (expander.fails_cfg(impl.get_inner_attrs())) { - impl.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : impl.get_generic_params()) - param->accept_vis(*this); - - auto& type = impl.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - if (impl.has_where_clause()) - expand_where_clause(impl.get_where_clause()); - - // strip inherent impl items if required - auto& impl_items = impl.get_impl_items(); - for (int i = 0; i < impl_items.size();) { - auto& item = impl_items[i]; - - // mark for stripping if required - item->accept_vis(*this); - - if (item->is_marked_for_strip()) - impl_items.erase(impl_items.begin() + i); - else - i++; - } - } - void visit(AST::TraitImpl& impl) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(impl.get_outer_attrs()); - if (expander.fails_cfg(impl.get_outer_attrs())) { - impl.mark_for_strip(); - return; - } - - // strip test based on inner attrs - expander.expand_cfg_attrs(impl.get_inner_attrs()); - if (expander.fails_cfg(impl.get_inner_attrs())) { - impl.mark_for_strip(); - return; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : impl.get_generic_params()) - param->accept_vis(*this); - - auto& type = impl.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - auto& trait_path = impl.get_trait_path(); - visit(trait_path); - if (trait_path.is_marked_for_strip()) - rust_error_at(trait_path.get_locus(), "cannot strip typepath in this position"); - - if (impl.has_where_clause()) - expand_where_clause(impl.get_where_clause()); - - // strip trait impl items if required - auto& impl_items = impl.get_impl_items(); - for (int i = 0; i < impl_items.size();) { - auto& item = impl_items[i]; - - // mark for stripping if required - item->accept_vis(*this); - - if (item->is_marked_for_strip()) - impl_items.erase(impl_items.begin() + i); - else - i++; - } - } - 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; - } - - auto& type = item.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - 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; - } - - // just expand sub-stuff - can't actually strip generic params themselves - for (auto& param : item.get_generic_params()) - param->accept_vis(*this); - - /* strip function parameters if required - this is specifically - * allowed by spec */ - auto& params = item.get_function_params(); - for (int i = 0; i < params.size();) { - auto& param = params[i]; - - auto& param_attrs = param.get_outer_attrs(); - expander.expand_cfg_attrs(param_attrs); - if (expander.fails_cfg(param_attrs)) { - params.erase(params.begin() + i); - continue; - } - - auto& type = param.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - // increment if nothing else happens - i++; - } - /* NOTE: these are extern function params, which may have different - * rules and restrictions to "normal" function params. So expansion - * handled separately. */ - - /* TODO: assuming that variadic nature cannot be stripped. If this - * is not true, then have code here to do so. */ - - if (item.has_return_type()) { - auto& return_type = item.get_return_type(); - return_type->accept_vis(*this); - if (return_type->is_marked_for_strip()) - rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); - } - - if (item.has_where_clause()) - expand_where_clause(item.get_where_clause()); - } - void visit(AST::ExternBlock& block) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(block.get_outer_attrs()); - if (expander.fails_cfg(block.get_outer_attrs())) { - block.mark_for_strip(); - return; - } - - // strip test based on inner attrs - expander.expand_cfg_attrs(block.get_inner_attrs()); - if (expander.fails_cfg(block.get_inner_attrs())) { - block.mark_for_strip(); - return; - } - - // strip external items if required - auto& extern_items = block.get_extern_items(); - for (int i = 0; i < extern_items.size();) { - auto& item = extern_items[i]; - - // mark for stripping if required - item->accept_vis(*this); - - if (item->is_marked_for_strip()) - extern_items.erase(extern_items.begin() + i); - else - i++; - } - } - - // I don't think it would be possible to strip macros without expansion - void visit(AST::MacroMatchFragment& match) override {} - void visit(AST::MacroMatchRepetition& match) override {} - void visit(AST::MacroMatcher& matcher) override {} - void visit(AST::MacroRulesDefinition& rules_def) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(rules_def.get_outer_attrs()); - if (expander.fails_cfg(rules_def.get_outer_attrs())) { - rules_def.mark_for_strip(); - return; - } - - // I don't think any macro rules can be stripped in any way - } - void visit(AST::MacroInvocation& macro_invoc) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(macro_invoc.get_outer_attrs()); - if (expander.fails_cfg(macro_invoc.get_outer_attrs())) { - macro_invoc.mark_for_strip(); - return; - } - - // I don't think any macro token trees can be stripped in any way - - // TODO: maybe have stripping behaviour for the cfg! macro here? - } - void visit(AST::MetaItemPath& meta_item) override {} - void visit(AST::MetaItemSeq& meta_item) override {} - void visit(AST::MetaWord& meta_item) override {} - void visit(AST::MetaNameValueStr& meta_item) override {} - void visit(AST::MetaListPaths& meta_item) override {} - void visit(AST::MetaListNameValueStr& meta_item) override {} - - void visit(AST::LiteralPattern& pattern) override { - // not possible - } - void visit(AST::IdentifierPattern& pattern) override { - // can only strip sub-patterns of the inner pattern to bind - if (!pattern.has_pattern_to_bind()) - return; - - auto& sub_pattern = pattern.get_pattern_to_bind(); - sub_pattern->accept_vis(*this); - if (sub_pattern->is_marked_for_strip()) - rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - void visit(AST::WildcardPattern& pattern) override { - // not possible - } - void visit(AST::RangePatternBoundLiteral& bound) override { - // not possible - } - void visit(AST::RangePatternBoundPath& bound) override { - // can expand path, but not strip it directly - auto& path = bound.get_path(); - visit(path); - if (path.is_marked_for_strip()) - rust_error_at(path.get_locus(), "cannot strip path in this position"); - } - void visit(AST::RangePatternBoundQualPath& bound) override { - // can expand path, but not strip it directly - auto& path = bound.get_qualified_path(); - visit(path); - if (path.is_marked_for_strip()) - rust_error_at(path.get_locus(), "cannot strip path in this position"); - } - void visit(AST::RangePattern& pattern) override { - // should have no capability to strip lower or upper bounds, only expand - pattern.get_lower_bound()->accept_vis(*this); - pattern.get_upper_bound()->accept_vis(*this); - } - void visit(AST::ReferencePattern& pattern) override { - auto& sub_pattern = pattern.get_referenced_pattern(); - sub_pattern->accept_vis(*this); - if (sub_pattern->is_marked_for_strip()) - rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - void visit(AST::StructPatternFieldTuplePat& field) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(field.get_outer_attrs()); - if (expander.fails_cfg(field.get_outer_attrs())) { - field.mark_for_strip(); - return; - } - - // strip sub-patterns (can't strip top-level pattern) - auto& sub_pattern = field.get_index_pattern(); - sub_pattern->accept_vis(*this); - if (sub_pattern->is_marked_for_strip()) - rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - void visit(AST::StructPatternFieldIdentPat& field) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(field.get_outer_attrs()); - if (expander.fails_cfg(field.get_outer_attrs())) { - field.mark_for_strip(); - return; - } - - // strip sub-patterns (can't strip top-level pattern) - auto& sub_pattern = field.get_ident_pattern(); - sub_pattern->accept_vis(*this); - if (sub_pattern->is_marked_for_strip()) - rust_error_at(sub_pattern->get_locus_slow(), "cannot strip pattern in this position"); - } - void visit(AST::StructPatternFieldIdent& field) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(field.get_outer_attrs()); - if (expander.fails_cfg(field.get_outer_attrs())) { - field.mark_for_strip(); - return; - } - } - void visit(AST::StructPattern& pattern) override { - // expand (but don't strip) path - auto& path = pattern.get_path(); - visit(path); - if (path.is_marked_for_strip()) - rust_error_at(path.get_locus(), "cannot strip path in this position"); - - // TODO: apparently struct pattern fields can have outer attrs. so can they be stripped? - if (!pattern.has_struct_pattern_elems()) - return; - - auto& elems = pattern.get_struct_pattern_elems(); - - // assuming you can strip struct pattern fields - auto& fields = elems.get_struct_pattern_fields(); - for (int i = 0; i < fields.size();) { - auto& field = fields[i]; - - field->accept_vis(*this); - - if (field->is_marked_for_strip()) - fields.erase(fields.begin() + i); - else - i++; - } - - // assuming you can strip the ".." part - if (elems.has_etc()) { - expander.expand_cfg_attrs(elems.get_etc_outer_attrs()); - if (expander.fails_cfg(elems.get_etc_outer_attrs())) - elems.strip_etc(); - } - } - void visit(AST::TupleStructItemsNoRange& tuple_items) override { - // can't strip individual patterns, only sub-patterns - for (auto& pattern : tuple_items.get_patterns()) { - pattern->accept_vis(*this); - - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - // TODO: quit stripping now? or keep going? - } - } - void visit(AST::TupleStructItemsRange& tuple_items) override { - // can't strip individual patterns, only sub-patterns - for (auto& lower_pattern : tuple_items.get_lower_patterns()) { - lower_pattern->accept_vis(*this); - - if (lower_pattern->is_marked_for_strip()) - rust_error_at(lower_pattern->get_locus_slow(), "cannot strip pattern in this position"); - // TODO: quit stripping now? or keep going? - } - for (auto& upper_pattern : tuple_items.get_upper_patterns()) { - upper_pattern->accept_vis(*this); - - if (upper_pattern->is_marked_for_strip()) - rust_error_at(upper_pattern->get_locus_slow(), "cannot strip pattern in this position"); - // TODO: quit stripping now? or keep going? - } - } - void visit(AST::TupleStructPattern& pattern) override { - // expand (but don't strip) path - auto& path = pattern.get_path(); - visit(path); - if (path.is_marked_for_strip()) - rust_error_at(path.get_locus(), "cannot strip path in this position"); - - if (pattern.has_items()) - pattern.get_items()->accept_vis(*this); - } - void visit(AST::TuplePatternItemsMultiple& tuple_items) override { - // can't strip individual patterns, only sub-patterns - for (auto& pattern : tuple_items.get_patterns()) { - pattern->accept_vis(*this); - - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - // TODO: quit stripping now? or keep going? - } - } - void visit(AST::TuplePatternItemsRanged& tuple_items) override { - // can't strip individual patterns, only sub-patterns - for (auto& lower_pattern : tuple_items.get_lower_patterns()) { - lower_pattern->accept_vis(*this); - - if (lower_pattern->is_marked_for_strip()) - rust_error_at(lower_pattern->get_locus_slow(), "cannot strip pattern in this position"); - // TODO: quit stripping now? or keep going? - } - for (auto& upper_pattern : tuple_items.get_upper_patterns()) { - upper_pattern->accept_vis(*this); - - if (upper_pattern->is_marked_for_strip()) - rust_error_at(upper_pattern->get_locus_slow(), "cannot strip pattern in this position"); - // TODO: quit stripping now? or keep going? - } - } - void visit(AST::TuplePattern& pattern) override { - if (pattern.has_tuple_pattern_items()) - pattern.get_items()->accept_vis(*this); - } - void visit(AST::GroupedPattern& pattern) override { - // can't strip inner pattern, only sub-patterns - auto& pattern_in_parens = pattern.get_pattern_in_parens(); - - pattern_in_parens->accept_vis(*this); - - if (pattern_in_parens->is_marked_for_strip()) - rust_error_at(pattern_in_parens->get_locus_slow(), "cannot strip pattern in this position"); - } - void visit(AST::SlicePattern& pattern) override { - // can't strip individual patterns, only sub-patterns - for (auto& item : pattern.get_items()) { - item->accept_vis(*this); - - if (item->is_marked_for_strip()) - rust_error_at(item->get_locus_slow(), "cannot strip pattern in this position"); - // TODO: quit stripping now? or keep going? - } - } - - void visit(AST::EmptyStmt& stmt) override { - // assuming no outer attributes, so nothing can happen - } - void visit(AST::LetStmt& stmt) override { - // initial strip test based on outer attrs - expander.expand_cfg_attrs(stmt.get_outer_attrs()); - if (expander.fails_cfg(stmt.get_outer_attrs())) { - stmt.mark_for_strip(); - return; - } - - // can't strip pattern, but call for sub-patterns - auto& pattern = stmt.get_pattern(); - pattern->accept_vis(*this); - if (pattern->is_marked_for_strip()) - rust_error_at(pattern->get_locus_slow(), "cannot strip pattern in this position"); - - // similar for type - if (stmt.has_type()) { - auto& type = stmt.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - } - - /* strip any internal sub-expressions - expression itself isn't - * allowed to have external attributes in this position so can't be - * stripped */ - if (stmt.has_init_expr()) { - auto& init_expr = stmt.get_init_expr(); - init_expr->accept_vis(*this); - if (init_expr->is_marked_for_strip()) - rust_error_at(init_expr->get_locus_slow(), - "cannot strip expression in this position - outer attributes not allowed"); - } - } - void visit(AST::ExprStmtWithoutBlock& stmt) override { - // outer attributes associated with expr, so rely on expr - - // guard - should prevent null pointer expr - if (stmt.is_marked_for_strip()) - return; - - // strip if expr is to be stripped - auto& expr = stmt.get_expr(); - expr->accept_vis(*this); - if (expr->is_marked_for_strip()) { - stmt.mark_for_strip(); - return; - } - } - void visit(AST::ExprStmtWithBlock& stmt) override { - // outer attributes associated with expr, so rely on expr - - // guard - should prevent null pointer expr - if (stmt.is_marked_for_strip()) - return; - - // strip if expr is to be stripped - auto& expr = stmt.get_expr(); - expr->accept_vis(*this); - if (expr->is_marked_for_strip()) { - stmt.mark_for_strip(); - return; - } - } - - void visit(AST::TraitBound& bound) override { - // nothing in for lifetimes to strip - - // expand but don't strip type path - auto& path = bound.get_type_path(); - visit(path); - if (path.is_marked_for_strip()) - rust_error_at(path.get_locus(), "cannot strip type path in this position"); - } - void visit(AST::ImplTraitType& type) override { - // don't strip directly, only components of bounds - for (auto& bound : type.get_type_param_bounds()) - bound->accept_vis(*this); - } - void visit(AST::TraitObjectType& type) override { - // don't strip directly, only components of bounds - for (auto& bound : type.get_type_param_bounds()) - bound->accept_vis(*this); - } - void visit(AST::ParenthesisedType& type) override { - // expand but don't strip inner type - auto& inner_type = type.get_type_in_parens(); - inner_type->accept_vis(*this); - if (inner_type->is_marked_for_strip()) - rust_error_at(inner_type->get_locus_slow(), "cannot strip type in this position"); - } - void visit(AST::ImplTraitTypeOneBound& type) override { - // no stripping possible - visit(type.get_trait_bound()); - } - void visit(AST::TraitObjectTypeOneBound& type) override { - // no stripping possible - visit(type.get_trait_bound()); - } - void visit(AST::TupleType& type) override { - // TODO: assuming that types can't be stripped as types don't have outer attributes - for (auto& elem_type : type.get_elems()) { - elem_type->accept_vis(*this); - if (elem_type->is_marked_for_strip()) - rust_error_at(elem_type->get_locus_slow(), "cannot strip type in this position"); - } - } - void visit(AST::NeverType& type) override { - // no stripping possible - } - void visit(AST::RawPointerType& type) override { - // expand but don't strip type pointed to - auto& pointed_type = type.get_type_pointed_to(); - pointed_type->accept_vis(*this); - if (pointed_type->is_marked_for_strip()) - rust_error_at(pointed_type->get_locus_slow(), "cannot strip type in this position"); - } - void visit(AST::ReferenceType& type) override { - // expand but don't strip type referenced - auto& referenced_type = type.get_type_referenced(); - referenced_type->accept_vis(*this); - if (referenced_type->is_marked_for_strip()) - rust_error_at(referenced_type->get_locus_slow(), "cannot strip type in this position"); - } - void visit(AST::ArrayType& type) override { - // expand but don't strip type referenced - auto& base_type = type.get_elem_type(); - base_type->accept_vis(*this); - if (base_type->is_marked_for_strip()) - rust_error_at(base_type->get_locus_slow(), "cannot strip type in this position"); - - // same for expression - auto& size_expr = type.get_size_expr(); - size_expr->accept_vis(*this); - if (size_expr->is_marked_for_strip()) - rust_error_at(size_expr->get_locus_slow(), "cannot strip expression in this position"); - } - void visit(AST::SliceType& type) override { - // expand but don't strip elem type - auto& elem_type = type.get_elem_type(); - elem_type->accept_vis(*this); - if (elem_type->is_marked_for_strip()) - rust_error_at(elem_type->get_locus_slow(), "cannot strip type in this position"); - } - void visit(AST::InferredType& type) override { - // none possible - } - void visit(AST::BareFunctionType& type) override { - // seem to be no generics - - // presumably function params can be stripped - auto& params = type.get_function_params(); - for (int i = 0; i < params.size();) { - auto& param = params[i]; - - auto& param_attrs = param.get_outer_attrs(); - expander.expand_cfg_attrs(param_attrs); - if (expander.fails_cfg(param_attrs)) { - params.erase(params.begin() + i); - continue; - } - - auto& type = param.get_type(); - type->accept_vis(*this); - if (type->is_marked_for_strip()) - rust_error_at(type->get_locus_slow(), "cannot strip type in this position"); - - // increment if nothing else happens - i++; - } - - /* TODO: assuming that variadic nature cannot be stripped. If this - * is not true, then have code here to do so. */ - - if (type.has_return_type()) { - auto& return_type = type.get_return_type(); - return_type->accept_vis(*this); - if (return_type->is_marked_for_strip()) - rust_error_at(return_type->get_locus_slow(), "cannot strip type in this position"); - } - - // no where clause, apparently - } - }; - - void MacroExpander::expand_invoc(std::unique_ptr& invoc) { - /* if current expansion depth > recursion limit, create an error (maybe fatal - * error) and return */ - - /* switch on type of macro: - - '!' syntax macro (inner switch) - - procedural macro - "A token-based function-like macro" - - 'macro_rules' (by example/pattern-match) macro? or not? "an - AST-based function-like macro" - - else is unreachable - - attribute syntax macro (inner switch) - - procedural macro attribute syntax - "A token-based attribute macro" - - legacy macro attribute syntax? - "an AST-based attribute macro" - - non-macro attribute: mark known - - else is unreachable - - derive macro (inner switch) - - derive or legacy derive - "token-based" vs "AST-based" - - else is unreachable - - derive container macro - unreachable*/ +// Visitor used to expand attributes. +class AttrVisitor : public AST::ASTVisitor +{ +private: + MacroExpander &expander; + +public: + AttrVisitor (MacroExpander &expander) : expander (expander) {} + + void expand_struct_fields (std::vector &fields) + { + for (int i = 0; i < fields.size ();) + { + auto &field = fields[i]; + + auto &field_attrs = field.get_outer_attrs (); + expander.expand_cfg_attrs (field_attrs); + if (expander.fails_cfg (field_attrs)) + { + fields.erase (fields.begin () + i); + continue; + } + + // expand sub-types of type, but can't strip type itself + auto &type = field.get_field_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + // if nothing else happens, increment + i++; + } + } + + void expand_tuple_fields (std::vector &fields) + { + for (int i = 0; i < fields.size ();) + { + auto &field = fields[i]; + + auto &field_attrs = field.get_outer_attrs (); + expander.expand_cfg_attrs (field_attrs); + if (expander.fails_cfg (field_attrs)) + { + fields.erase (fields.begin () + i); + continue; + } + + // expand sub-types of type, but can't strip type itself + auto &type = field.get_field_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + // if nothing else happens, increment + i++; + } + } + + void expand_function_params (std::vector ¶ms) + { + for (int i = 0; i < params.size ();) + { + auto ¶m = params[i]; + + auto ¶m_attrs = param.get_outer_attrs (); + expander.expand_cfg_attrs (param_attrs); + if (expander.fails_cfg (param_attrs)) + { + params.erase (params.begin () + i); + continue; + } + + // TODO: should an unwanted strip lead to break out of loop? + auto &pattern = param.get_pattern (); + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + + auto &type = param.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + // increment + i++; + } + } + + void expand_generic_args (AST::GenericArgs &args) + { + // lifetime args can't be expanded + + // expand type args - strip sub-types only + for (auto &type : args.get_type_args ()) + { + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + + // expand binding args - strip sub-types only + for (auto &binding : args.get_binding_args ()) + { + auto &type = binding.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + } + + void expand_qualified_path_type (AST::QualifiedPathType &path_type) + { + auto &type = path_type.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + if (path_type.has_as_clause ()) + { + auto &type_path = path_type.get_as_type_path (); + visit (type_path); + if (type_path.is_marked_for_strip ()) + rust_error_at (type_path.get_locus (), + "cannot strip type path in this position"); + } + } + + void expand_closure_params (std::vector ¶ms) + { + for (int i = 0; i < params.size ();) + { + auto ¶m = params[i]; + + auto ¶m_attrs = param.get_outer_attrs (); + expander.expand_cfg_attrs (param_attrs); + if (expander.fails_cfg (param_attrs)) + { + params.erase (params.begin () + i); + continue; + } + + auto &pattern = param.get_pattern (); + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + + if (param.has_type_given ()) + { + auto &type = param.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + + // increment if found nothing else so far + i++; + } + } + + void expand_self_param (AST::SelfParam &self_param) + { + if (self_param.has_type ()) + { + auto &type = self_param.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + // TODO: maybe check for invariants being violated - e.g. both type and + // lifetime? + } + + void expand_where_clause (AST::WhereClause &where_clause) + { + // items cannot be stripped conceptually, so just accept visitor + for (auto &item : where_clause.get_items ()) + item->accept_vis (*this); + } + + void expand_trait_function_decl (AST::TraitFunctionDecl &decl) + { + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : decl.get_generic_params ()) + param->accept_vis (*this); + + /* strip function parameters if required - this is specifically + * allowed by spec */ + expand_function_params (decl.get_function_params ()); + + if (decl.has_return_type ()) + { + auto &return_type = decl.get_return_type (); + return_type->accept_vis (*this); + if (return_type->is_marked_for_strip ()) + rust_error_at (return_type->get_locus_slow (), + "cannot strip type in this position"); + } + + if (decl.has_where_clause ()) + expand_where_clause (decl.get_where_clause ()); + } + + void expand_trait_method_decl (AST::TraitMethodDecl &decl) + { + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : decl.get_generic_params ()) + param->accept_vis (*this); + + /* assuming you can't strip self param - wouldn't be a method + * anymore. spec allows outer attrs on self param, but doesn't + * specify whether cfg is used. */ + expand_self_param (decl.get_self_param ()); + + /* strip function parameters if required - this is specifically + * allowed by spec */ + expand_function_params (decl.get_function_params ()); + + if (decl.has_return_type ()) + { + auto &return_type = decl.get_return_type (); + return_type->accept_vis (*this); + if (return_type->is_marked_for_strip ()) + rust_error_at (return_type->get_locus_slow (), + "cannot strip type in this position"); + } + + if (decl.has_where_clause ()) + expand_where_clause (decl.get_where_clause ()); + } + + void visit (AST::Token &tok) override + { + // shouldn't require? + } + void visit (AST::DelimTokenTree &delim_tok_tree) override + { + // shouldn't require? + } + void visit (AST::AttrInputMetaItemContainer &input) override + { + // shouldn't require? + } + void visit (AST::IdentifierExpr &ident_expr) override + { + // strip test based on outer attrs + expander.expand_cfg_attrs (ident_expr.get_outer_attrs ()); + if (expander.fails_cfg (ident_expr.get_outer_attrs ())) + { + ident_expr.mark_for_strip (); + return; + } + } + void visit (AST::Lifetime &lifetime) override + { + // shouldn't require? + } + void visit (AST::LifetimeParam &lifetime_param) override + { + // supposedly does not require - cfg does nothing + } + void visit (AST::MacroInvocationSemi ¯o_invoc) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (macro_invoc.get_outer_attrs ()); + if (expander.fails_cfg (macro_invoc.get_outer_attrs ())) + { + macro_invoc.mark_for_strip (); + return; + } + + // can't strip simple path + + // I don't think any macro token trees can be stripped in any way + + // TODO: maybe have cfg! macro stripping behaviour here? + } + + void visit (AST::PathInExpression &path) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (path.get_outer_attrs ()); + if (expander.fails_cfg (path.get_outer_attrs ())) + { + path.mark_for_strip (); + return; + } + + for (auto &segment : path.get_segments ()) + { + if (segment.has_generic_args ()) + expand_generic_args (segment.get_generic_args ()); + } + } + void visit (AST::TypePathSegment &segment) override + { + // shouldn't require + } + void visit (AST::TypePathSegmentGeneric &segment) override + { + // TODO: strip inside generic args + + if (!segment.has_generic_args ()) + return; + + expand_generic_args (segment.get_generic_args ()); + } + void visit (AST::TypePathSegmentFunction &segment) override + { + auto &type_path_function = segment.get_type_path_function (); + + for (auto &type : type_path_function.get_params ()) + { + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + + if (type_path_function.has_return_type ()) + { + auto &return_type = type_path_function.get_return_type (); + return_type->accept_vis (*this); + if (return_type->is_marked_for_strip ()) + rust_error_at (return_type->get_locus_slow (), + "cannot strip type in this position"); + } + } + void visit (AST::TypePath &path) override + { + // this shouldn't strip any segments, but can strip inside them + for (auto &segment : path.get_segments ()) + segment->accept_vis (*this); + } + void visit (AST::QualifiedPathInExpression &path) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (path.get_outer_attrs ()); + if (expander.fails_cfg (path.get_outer_attrs ())) + { + path.mark_for_strip (); + return; + } + + expand_qualified_path_type (path.get_qualified_path_type ()); + + for (auto &segment : path.get_segments ()) + { + if (segment.has_generic_args ()) + expand_generic_args (segment.get_generic_args ()); + } + } + void visit (AST::QualifiedPathInType &path) override + { + expand_qualified_path_type (path.get_qualified_path_type ()); + + // this shouldn't strip any segments, but can strip inside them + for (auto &segment : path.get_segments ()) + segment->accept_vis (*this); + } + + void visit (AST::LiteralExpr &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; + } + } + void visit (AST::AttrInputLiteral &attr_input) override + { + // shouldn't require? + } + void visit (AST::MetaItemLitExpr &meta_item) override + { + // shouldn't require? + } + void visit (AST::MetaItemPathLit &meta_item) override + { + // shouldn't require? + } + void visit (AST::BorrowExpr &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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &borrowed_expr = expr.get_borrowed_expr (); + borrowed_expr->accept_vis (*this); + if (borrowed_expr->is_marked_for_strip ()) + rust_error_at (borrowed_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::DereferenceExpr &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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &dereferenced_expr = expr.get_dereferenced_expr (); + dereferenced_expr->accept_vis (*this); + if (dereferenced_expr->is_marked_for_strip ()) + rust_error_at (dereferenced_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::ErrorPropagationExpr &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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &propagating_expr = expr.get_propagating_expr (); + propagating_expr->accept_vis (*this); + if (propagating_expr->is_marked_for_strip ()) + rust_error_at (propagating_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::NegationExpr &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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &negated_expr = expr.get_negated_expr (); + negated_expr->accept_vis (*this); + if (negated_expr->is_marked_for_strip ()) + rust_error_at (negated_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::ArithmeticOrLogicalExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr ()->accept_vis (*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr ()->accept_vis (*this); + + // ensure that they are not marked for strip + if (expr.get_left_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_left_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes are never allowed " + "before binary op exprs"); + if (expr.get_right_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_right_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::ComparisonExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr ()->accept_vis (*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr ()->accept_vis (*this); + + // ensure that they are not marked for strip + if (expr.get_left_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_left_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes are never allowed " + "before binary op exprs"); + if (expr.get_right_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_right_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::LazyBooleanExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr ()->accept_vis (*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr ()->accept_vis (*this); + + // ensure that they are not marked for strip + if (expr.get_left_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_left_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes are never allowed " + "before binary op exprs"); + if (expr.get_right_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_right_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::TypeCastExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * direct descendant expression, can strip ones below that */ + + auto &casted_expr = expr.get_casted_expr (); + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + casted_expr->accept_vis (*this); + + // ensure that they are not marked for strip + if (casted_expr->is_marked_for_strip ()) + rust_error_at (casted_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes are never allowed before cast exprs"); + + // TODO: strip sub-types of type + auto &type = expr.get_type_to_cast_to (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + void visit (AST::AssignmentExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr ()->accept_vis (*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr ()->accept_vis (*this); + + // ensure that they are not marked for strip + if (expr.get_left_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_left_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes are never allowed " + "before binary op exprs"); + if (expr.get_right_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_right_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::CompoundAssignmentExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_left_expr ()->accept_vis (*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_right_expr ()->accept_vis (*this); + + // ensure that they are not marked for strip + if (expr.get_left_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_left_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes are never allowed " + "before binary op exprs"); + if (expr.get_right_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_right_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::GroupedExpr &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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs (expr.get_inner_attrs ()); + if (expander.fails_cfg (expr.get_inner_attrs ())) + { + expr.mark_for_strip (); + return; + } + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &inner_expr = expr.get_expr_in_parens (); + inner_expr->accept_vis (*this); + if (inner_expr->is_marked_for_strip ()) + rust_error_at (inner_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::ArrayElemsValues &elems) override + { + /* apparently outer attributes are allowed in "elements of array + * expressions" according to spec */ + auto &values = elems.get_values (); + 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::ArrayElemsCopied &elems) override + { + /* apparently outer attributes are allowed in "elements of array + * expressions" according to spec. on the other hand, it would not + * make conceptual sense to be able to remove either expression. As + * such, not implementing. TODO clear up the ambiguity here */ + + // only intend stripping for internal sub-expressions + auto &copied_expr = elems.get_elem_to_copy (); + copied_expr->accept_vis (*this); + if (copied_expr->is_marked_for_strip ()) + rust_error_at (copied_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + auto ©_count = elems.get_num_copies (); + copy_count->accept_vis (*this); + if (copy_count->is_marked_for_strip ()) + rust_error_at (copy_count->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::ArrayExpr &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 test based on inner attrs - spec says there are separate + * inner attributes, not just outer attributes of inner exprs */ + expander.expand_cfg_attrs (expr.get_inner_attrs ()); + if (expander.fails_cfg (expr.get_inner_attrs ())) + { + expr.mark_for_strip (); + return; + } + + /* assuming you can't strip away the ArrayElems type, but can strip + * internal expressions and whatever */ + if (expr.has_array_elems ()) + expr.get_array_elems ()->accept_vis (*this); + } + void visit (AST::ArrayIndexExpr &expr) override + { + /* it is unclear whether outer attributes are supposed to be + * allowed, but conceptually it wouldn't make much sense, but + * having expansion code anyway. TODO */ + // 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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &array_expr = expr.get_array_expr (); + array_expr->accept_vis (*this); + if (array_expr->is_marked_for_strip ()) + rust_error_at (array_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + auto &index_expr = expr.get_index_expr (); + index_expr->accept_vis (*this); + if (index_expr->is_marked_for_strip ()) + rust_error_at (index_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::TupleExpr &expr) override + { + /* according to spec, outer attributes are allowed on "elements of + * tuple expressions" */ + + // 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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs (expr.get_inner_attrs ()); + if (expander.fails_cfg (expr.get_inner_attrs ())) + { + expr.mark_for_strip (); + return; + } + + /* apparently outer attributes are allowed in "elements of tuple + * expressions" according to spec */ + auto &values = expr.get_tuple_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::TupleIndexExpr &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; + } + + /* wouldn't strip this directly (as outer attrs should be + * associated with this level), but any sub-expressions would be + * stripped. Thus, no need to erase when strip check called. */ + auto &tuple_expr = expr.get_tuple_expr (); + tuple_expr->accept_vis (*this); + if (tuple_expr->is_marked_for_strip ()) + rust_error_at (tuple_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::StructExprStruct &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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs (expr.get_inner_attrs ()); + if (expander.fails_cfg (expr.get_inner_attrs ())) + { + expr.mark_for_strip (); + return; + } + + // strip sub-exprs of path + auto &struct_name = expr.get_struct_name (); + visit (struct_name); + if (struct_name.is_marked_for_strip ()) + rust_error_at (struct_name.get_locus (), + "cannot strip path in this position"); + } + void visit (AST::StructExprFieldIdentifier &field) override + { + // as no attrs (at moment, at least), no stripping possible + } + void visit (AST::StructExprFieldIdentifierValue &field) override + { + /* as no attrs possible (at moment, at least), only sub-expression + * stripping is possible */ + auto &value = field.get_value (); + value->accept_vis (*this); + if (value->is_marked_for_strip ()) + rust_error_at (value->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::StructExprFieldIndexValue &field) override + { + /* as no attrs possible (at moment, at least), only sub-expression + * stripping is possible */ + auto &value = field.get_value (); + value->accept_vis (*this); + if (value->is_marked_for_strip ()) + rust_error_at (value->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::StructExprStructFields &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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs (expr.get_inner_attrs ()); + if (expander.fails_cfg (expr.get_inner_attrs ())) + { + expr.mark_for_strip (); + return; + } + + // strip sub-exprs of path + auto &struct_name = expr.get_struct_name (); + visit (struct_name); + if (struct_name.is_marked_for_strip ()) + rust_error_at (struct_name.get_locus (), + "cannot strip path in this position"); + + /* spec does not specify whether expressions are allowed to be + * stripped at top level of struct fields, but I wouldn't think + * that they would be, so operating under the assumption that only + * sub-expressions can be stripped. */ + for (auto &field : expr.get_fields ()) + { + field->accept_vis (*this); + // shouldn't strip in this + } + + /* struct base presumably can't be stripped, as the '..' is before + * the expression. as such, can only strip sub-expressions. */ + if (expr.has_struct_base ()) + { + auto &base_struct_expr = expr.get_struct_base ().get_base_struct (); + base_struct_expr->accept_vis (*this); + if (base_struct_expr->is_marked_for_strip ()) + rust_error_at (base_struct_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + } + void visit (AST::StructExprStructBase &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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs (expr.get_inner_attrs ()); + if (expander.fails_cfg (expr.get_inner_attrs ())) + { + expr.mark_for_strip (); + return; + } + + // strip sub-exprs of path + auto &struct_name = expr.get_struct_name (); + visit (struct_name); + if (struct_name.is_marked_for_strip ()) + rust_error_at (struct_name.get_locus (), + "cannot strip path in this position"); + + /* struct base presumably can't be stripped, as the '..' is before + * the expression. as such, can only strip sub-expressions. */ + rust_assert (!expr.get_struct_base ().is_invalid ()); + auto &base_struct_expr = expr.get_struct_base ().get_base_struct (); + base_struct_expr->accept_vis (*this); + if (base_struct_expr->is_marked_for_strip ()) + rust_error_at (base_struct_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::StructExprTuple &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 test based on inner attrs - spec says these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs (expr.get_inner_attrs ()); + if (expander.fails_cfg (expr.get_inner_attrs ())) + { + expr.mark_for_strip (); + return; + } + + // strip sub-exprs of path + auto &struct_name = expr.get_struct_name (); + visit (struct_name); + if (struct_name.is_marked_for_strip ()) + rust_error_at (struct_name.get_locus (), + "cannot strip path in this position"); + + /* spec says outer attributes are specifically allowed for elements + * of tuple-style struct 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::StructExprUnit &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 sub-exprs of path + auto &struct_name = expr.get_struct_name (); + visit (struct_name); + if (struct_name.is_marked_for_strip ()) + rust_error_at (struct_name.get_locus (), + "cannot strip path in this position"); + } + 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 */ + auto &value = field.get_value (); + value->accept_vis (*this); + if (value->is_marked_for_strip ()) + rust_error_at (value->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::EnumExprFieldIndexValue &field) override + { + /* as no attrs possible (at moment, at least), only sub-expression + * stripping is possible */ + auto &value = field.get_value (); + value->accept_vis (*this); + if (value->is_marked_for_strip ()) + rust_error_at (value->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::EnumExprStruct &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 + + // strip sub-exprs of path + auto &enum_path = expr.get_enum_variant_path (); + visit (enum_path); + if (enum_path.is_marked_for_strip ()) + rust_error_at (enum_path.get_locus (), + "cannot strip path in this position"); + + /* spec does not specify whether expressions are allowed to be + * stripped at top level of expression fields, but I wouldn't think + * that they would be, so operating under the assumption that only + * sub-expressions can be stripped. */ + for (auto &field : expr.get_fields ()) + { + field->accept_vis (*this); + // shouldn't strip in this + } + } + 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 + + // strip sub-exprs of path + auto &enum_path = expr.get_enum_variant_path (); + visit (enum_path); + if (enum_path.is_marked_for_strip ()) + rust_error_at (enum_path.get_locus (), + "cannot strip path in this position"); + + /* 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 + + // strip sub-exprs of path + auto &enum_path = expr.get_enum_variant_path (); + visit (enum_path); + if (enum_path.is_marked_for_strip ()) + rust_error_at (enum_path.get_locus (), + "cannot strip path in this position"); + } + 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. */ + auto &function = expr.get_function_expr (); + function->accept_vis (*this); + if (function->is_marked_for_strip ()) + rust_error_at (function->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + /* spec says outer attributes are specifically allowed for elements + * of call expressions, so full stripping possible */ + auto ¶ms = expr.get_params (); + for (int i = 0; i < params.size ();) + { + auto ¶m = 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. */ + auto &receiver = expr.get_receiver_expr (); + receiver->accept_vis (*this); + if (receiver->is_marked_for_strip ()) + rust_error_at (receiver->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + auto &method_name = expr.get_method_name (); + if (method_name.has_generic_args ()) + expand_generic_args (method_name.get_generic_args ()); + + /* spec says outer attributes are specifically allowed for elements + * of method call expressions, so full stripping possible */ + auto ¶ms = expr.get_params (); + for (int i = 0; i < params.size ();) + { + auto ¶m = 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 field expr as a whole. only sub-expr + * expansion is possible. */ + auto &receiver = expr.get_receiver_expr (); + receiver->accept_vis (*this); + if (receiver->is_marked_for_strip ()) + rust_error_at (receiver->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + 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 */ + expand_closure_params (expr.get_params ()); + + // can't strip expression itself, but can strip sub-expressions + auto &definition_expr = expr.get_definition_expr (); + definition_expr->accept_vis (*this); + if (definition_expr->is_marked_for_strip ()) + rust_error_at (definition_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::BlockExpr &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 test based on inner attrs - spec says there are inner + * attributes, not just outer attributes of inner stmts */ + expander.expand_cfg_attrs (expr.get_inner_attrs ()); + if (expander.fails_cfg (expr.get_inner_attrs ())) + { + expr.mark_for_strip (); + return; + } + + // strip all statements + auto &stmts = expr.get_statements (); + for (int i = 0; i < stmts.size ();) + { + auto &stmt = stmts[i]; + + // mark for stripping if required + stmt->accept_vis (*this); + + if (stmt->is_marked_for_strip ()) + stmts.erase (stmts.begin () + i); + else + i++; + } + + // strip tail expression if exists - can actually fully remove it + if (expr.has_tail_expr ()) + { + auto &tail_expr = expr.get_tail_expr (); + + tail_expr->accept_vis (*this); + + if (tail_expr->is_marked_for_strip ()) + expr.strip_tail_expr (); + } + } + void visit (AST::ClosureExprInnerTyped &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 */ + expand_closure_params (expr.get_params ()); + + // can't strip return type, but can strip sub-types + auto &type = expr.get_return_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + // can't strip expression itself, but can strip sub-expressions + auto &definition_block = expr.get_definition_block (); + definition_block->accept_vis (*this); + if (definition_block->is_marked_for_strip ()) + rust_error_at (definition_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::ContinueExpr &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; + } + } + void visit (AST::BreakExpr &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; + } + + /* spec does not say that you can have outer attributes on + * expression, so assuming you can't. stripping for sub-expressions + * is the only thing that can be done */ + if (expr.has_break_expr ()) + { + auto &break_expr = expr.get_break_expr (); + + break_expr->accept_vis (*this); + + if (break_expr->is_marked_for_strip ()) + rust_error_at (break_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + } + void visit (AST::RangeFromToExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_from_expr ()->accept_vis (*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_to_expr ()->accept_vis (*this); + + // ensure that they are not marked for strip + if (expr.get_from_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_from_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes are never allowed " + "before range exprs"); + if (expr.get_to_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_to_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::RangeFromExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * direct descendant expression, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + auto &from_expr = expr.get_from_expr (); + + from_expr->accept_vis (*this); + + if (from_expr->is_marked_for_strip ()) + rust_error_at (from_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes are never allowed before range exprs"); + } + void visit (AST::RangeToExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * direct descendant expression, can strip ones below that */ + + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + auto &to_expr = expr.get_to_expr (); + + to_expr->accept_vis (*this); + + if (to_expr->is_marked_for_strip ()) + rust_error_at (to_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::RangeFullExpr &expr) override + { + // outer attributes never allowed before these, so no stripping + } + void visit (AST::RangeFromToInclExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * two direct descendant expressions, can strip ones below that */ + + /* should have no possibility for outer attrs as would be parsed + * with outer expr */ + expr.get_from_expr ()->accept_vis (*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + expr.get_to_expr ()->accept_vis (*this); + + // ensure that they are not marked for strip + if (expr.get_from_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_from_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes are never allowed " + "before range exprs"); + if (expr.get_to_expr ()->is_marked_for_strip ()) + rust_error_at (expr.get_to_expr ()->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::RangeToInclExpr &expr) override + { + /* outer attributes never allowed before these. while cannot strip + * direct descendant expression, can strip ones below that */ + + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + auto &to_expr = expr.get_to_expr (); + + to_expr->accept_vis (*this); + + if (to_expr->is_marked_for_strip ()) + rust_error_at (to_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::ReturnExpr &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; + } + + /* spec does not say that you can have outer attributes on + * expression, so assuming you can't. stripping for sub-expressions + * is the only thing that can be done */ + if (expr.has_returned_expr ()) + { + auto &returned_expr = expr.get_returned_expr (); + + returned_expr->accept_vis (*this); + + if (returned_expr->is_marked_for_strip ()) + rust_error_at (returned_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + /* TODO: conceptually, you would maybe be able to remove a returned + * expr - e.g. if you had conditional compilation returning void or + * returning a type. On the other hand, I think that function + * return type cannot be conditionally compiled, so I assumed you + * can't do this either. */ + } + void visit (AST::UnsafeBlockExpr &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; + } + + // can't strip block itself, but can strip sub-expressions + auto &block_expr = expr.get_block_expr (); + block_expr->accept_vis (*this); + if (block_expr->is_marked_for_strip ()) + rust_error_at (block_expr->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::LoopExpr &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; + } + + // can't strip block itself, but can strip sub-expressions + auto &loop_block = expr.get_loop_block (); + loop_block->accept_vis (*this); + if (loop_block->is_marked_for_strip ()) + rust_error_at (loop_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::WhileLoopExpr &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; + } + + // can't strip predicate expr itself, but can strip sub-expressions + auto &predicate_expr = expr.get_predicate_expr (); + predicate_expr->accept_vis (*this); + if (predicate_expr->is_marked_for_strip ()) + rust_error_at (predicate_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip block itself, but can strip sub-expressions + auto &loop_block = expr.get_loop_block (); + loop_block->accept_vis (*this); + if (loop_block->is_marked_for_strip ()) + rust_error_at (loop_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::WhileLetLoopExpr &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; + } + + for (auto &pattern : expr.get_patterns ()) + { + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + + // can't strip scrutinee expr itself, but can strip sub-expressions + auto &scrutinee_expr = expr.get_scrutinee_expr (); + scrutinee_expr->accept_vis (*this); + if (scrutinee_expr->is_marked_for_strip ()) + rust_error_at (scrutinee_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip block itself, but can strip sub-expressions + auto &loop_block = expr.get_loop_block (); + loop_block->accept_vis (*this); + if (loop_block->is_marked_for_strip ()) + rust_error_at (loop_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::ForLoopExpr &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; + } + + // TODO: strip sub-patterns of pattern + auto &pattern = expr.get_pattern (); + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + + // can't strip scrutinee expr itself, but can strip sub-expressions + auto &iterator_expr = expr.get_iterator_expr (); + iterator_expr->accept_vis (*this); + if (iterator_expr->is_marked_for_strip ()) + rust_error_at (iterator_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip block itself, but can strip sub-expressions + auto &loop_block = expr.get_loop_block (); + loop_block->accept_vis (*this); + if (loop_block->is_marked_for_strip ()) + rust_error_at (loop_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::IfExpr &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; + } + + // can't strip condition expr itself, but can strip sub-expressions + auto &condition_expr = expr.get_condition_expr (); + condition_expr->accept_vis (*this); + if (condition_expr->is_marked_for_strip ()) + rust_error_at (condition_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto &if_block = expr.get_if_block (); + if_block->accept_vis (*this); + if (if_block->is_marked_for_strip ()) + rust_error_at (if_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::IfExprConseqElse &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; + } + + // can't strip condition expr itself, but can strip sub-expressions + auto &condition_expr = expr.get_condition_expr (); + condition_expr->accept_vis (*this); + if (condition_expr->is_marked_for_strip ()) + rust_error_at (condition_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto &if_block = expr.get_if_block (); + if_block->accept_vis (*this); + if (if_block->is_marked_for_strip ()) + rust_error_at (if_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + + // can't strip else block itself, but can strip sub-expressions + auto &else_block = expr.get_else_block (); + else_block->accept_vis (*this); + if (else_block->is_marked_for_strip ()) + rust_error_at (else_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::IfExprConseqIf &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; + } + + // can't strip condition expr itself, but can strip sub-expressions + auto &condition_expr = expr.get_condition_expr (); + condition_expr->accept_vis (*this); + if (condition_expr->is_marked_for_strip ()) + rust_error_at (condition_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto &if_block = expr.get_if_block (); + if_block->accept_vis (*this); + if (if_block->is_marked_for_strip ()) + rust_error_at (if_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + + // can't strip if expr itself, but can strip sub-expressions + auto &conseq_if_expr = expr.get_conseq_if_expr (); + conseq_if_expr->accept_vis (*this); + if (conseq_if_expr->is_marked_for_strip ()) + rust_error_at (conseq_if_expr->get_locus_slow (), + "cannot strip consequent if expression in this " + "position - outer attributes not allowed"); + } + void visit (AST::IfExprConseqIfLet &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; + } + + // can't strip condition expr itself, but can strip sub-expressions + auto &condition_expr = expr.get_condition_expr (); + condition_expr->accept_vis (*this); + if (condition_expr->is_marked_for_strip ()) + rust_error_at (condition_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto &if_block = expr.get_if_block (); + if_block->accept_vis (*this); + if (if_block->is_marked_for_strip ()) + rust_error_at (if_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + + // can't strip if let expr itself, but can strip sub-expressions + auto &conseq_if_let_expr = expr.get_conseq_if_let_expr (); + conseq_if_let_expr->accept_vis (*this); + if (conseq_if_let_expr->is_marked_for_strip ()) + rust_error_at (conseq_if_let_expr->get_locus_slow (), + "cannot strip consequent if let expression in this " + "position - outer attributes not " + "allowed"); + } + void visit (AST::IfLetExpr &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; + } + + for (auto &pattern : expr.get_patterns ()) + { + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + + // can't strip value expr itself, but can strip sub-expressions + auto &value_expr = expr.get_value_expr (); + value_expr->accept_vis (*this); + if (value_expr->is_marked_for_strip ()) + rust_error_at (value_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto &if_block = expr.get_if_block (); + if_block->accept_vis (*this); + if (if_block->is_marked_for_strip ()) + rust_error_at (if_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::IfLetExprConseqElse &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; + } + + for (auto &pattern : expr.get_patterns ()) + { + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + + // can't strip value expr itself, but can strip sub-expressions + auto &value_expr = expr.get_value_expr (); + value_expr->accept_vis (*this); + if (value_expr->is_marked_for_strip ()) + rust_error_at (value_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto &if_block = expr.get_if_block (); + if_block->accept_vis (*this); + if (if_block->is_marked_for_strip ()) + rust_error_at (if_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + + // can't strip else block itself, but can strip sub-expressions + auto &else_block = expr.get_else_block (); + else_block->accept_vis (*this); + if (else_block->is_marked_for_strip ()) + rust_error_at (else_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::IfLetExprConseqIf &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; + } + + for (auto &pattern : expr.get_patterns ()) + { + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + + // can't strip value expr itself, but can strip sub-expressions + auto &value_expr = expr.get_value_expr (); + value_expr->accept_vis (*this); + if (value_expr->is_marked_for_strip ()) + rust_error_at (value_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto &if_block = expr.get_if_block (); + if_block->accept_vis (*this); + if (if_block->is_marked_for_strip ()) + rust_error_at (if_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + + // can't strip if expr itself, but can strip sub-expressions + auto &conseq_if_expr = expr.get_conseq_if_expr (); + conseq_if_expr->accept_vis (*this); + if (conseq_if_expr->is_marked_for_strip ()) + rust_error_at (conseq_if_expr->get_locus_slow (), + "cannot strip consequent if expression in this " + "position - outer attributes not allowed"); + } + void visit (AST::IfLetExprConseqIfLet &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; + } + + for (auto &pattern : expr.get_patterns ()) + { + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + + // can't strip value expr itself, but can strip sub-expressions + auto &value_expr = expr.get_value_expr (); + value_expr->accept_vis (*this); + if (value_expr->is_marked_for_strip ()) + rust_error_at (value_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // can't strip if block itself, but can strip sub-expressions + auto &if_block = expr.get_if_block (); + if_block->accept_vis (*this); + if (if_block->is_marked_for_strip ()) + rust_error_at (if_block->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + + // can't strip if let expr itself, but can strip sub-expressions + auto &conseq_if_let_expr = expr.get_conseq_if_let_expr (); + conseq_if_let_expr->accept_vis (*this); + if (conseq_if_let_expr->is_marked_for_strip ()) + rust_error_at (conseq_if_let_expr->get_locus_slow (), + "cannot strip consequent if let expression in this " + "position - outer attributes not " + "allowed"); + } + void visit (AST::MatchExpr &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; + } + + // inner attr strip test + expander.expand_cfg_attrs (expr.get_inner_attrs ()); + if (expander.fails_cfg (expr.get_inner_attrs ())) + { + expr.mark_for_strip (); + return; + } + + // can't strip scrutinee expr itself, but can strip sub-expressions + auto &scrutinee_expr = expr.get_scrutinee_expr (); + scrutinee_expr->accept_vis (*this); + if (scrutinee_expr->is_marked_for_strip ()) + rust_error_at (scrutinee_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // strip match cases + auto &match_cases = expr.get_match_cases (); + for (int i = 0; i < match_cases.size ();) + { + auto &match_case = match_cases[i]; + + // strip match case based on outer attributes in match arm + auto &match_arm = match_case.get_arm (); + expander.expand_cfg_attrs (match_arm.get_outer_attrs ()); + if (expander.fails_cfg (match_arm.get_outer_attrs ())) + { + // strip match case + match_cases.erase (match_cases.begin () + i); + continue; + } + + for (auto &pattern : match_arm.get_patterns ()) + { + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + + /* assuming that guard expression cannot be stripped as + * strictly speaking you would have to strip the whole guard to + * make syntactical sense, which you can't do. as such, only + * strip sub-expressions */ + if (match_arm.has_match_arm_guard ()) + { + auto &guard_expr = match_arm.get_guard_expr (); + guard_expr->accept_vis (*this); + if (guard_expr->is_marked_for_strip ()) + rust_error_at (guard_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + + // strip sub-expressions from match cases + auto &case_expr = match_case.get_expr (); + case_expr->accept_vis (*this); + if (case_expr->is_marked_for_strip ()) + rust_error_at (case_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + + // increment to next case if haven't continued + i++; + } + } + void visit (AST::AwaitExpr &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; + } + + /* can't strip awaited expr itself, but can strip sub-expressions + * - this is because you can't have no expr to await */ + auto &awaited_expr = expr.get_awaited_expr (); + awaited_expr->accept_vis (*this); + if (awaited_expr->is_marked_for_strip ()) + rust_error_at (awaited_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::AsyncBlockExpr &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; + } + + // can't strip block itself, but can strip sub-expressions + auto &block_expr = expr.get_block_expr (); + block_expr->accept_vis (*this); + if (block_expr->is_marked_for_strip ()) + rust_error_at (block_expr->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + + void visit (AST::TypeParam ¶m) override + { + // outer attributes don't actually do anything, so ignore them + + if (param.has_type_param_bounds ()) + { + // don't strip directly, only components of bounds + for (auto &bound : param.get_type_param_bounds ()) + bound->accept_vis (*this); + } + + if (param.has_type ()) + { + auto &type = param.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + } + void visit (AST::LifetimeWhereClauseItem &item) override + { + // shouldn't require + } + void visit (AST::TypeBoundWhereClauseItem &item) override + { + // for lifetimes shouldn't require + + auto &type = item.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + // don't strip directly, only components of bounds + for (auto &bound : item.get_type_param_bounds ()) + bound->accept_vis (*this); + } + void visit (AST::Method &method) override + { + // initial test based on outer attrs + expander.expand_cfg_attrs (method.get_outer_attrs ()); + if (expander.fails_cfg (method.get_outer_attrs ())) + { + method.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : method.get_generic_params ()) + param->accept_vis (*this); + + /* assuming you can't strip self param - wouldn't be a method + * anymore. spec allows outer attrs on self param, but doesn't + * specify whether cfg is used. */ + expand_self_param (method.get_self_param ()); + + /* strip method parameters if required - this is specifically + * allowed by spec */ + expand_function_params (method.get_function_params ()); + + if (method.has_return_type ()) + { + auto &return_type = method.get_return_type (); + return_type->accept_vis (*this); + if (return_type->is_marked_for_strip ()) + rust_error_at (return_type->get_locus_slow (), + "cannot strip type in this position"); + } + + if (method.has_where_clause ()) + expand_where_clause (method.get_where_clause ()); + + /* body should always exist - if error state, should have returned + * before now */ + // can't strip block itself, but can strip sub-expressions + auto &block_expr = method.get_definition (); + block_expr->accept_vis (*this); + if (block_expr->is_marked_for_strip ()) + rust_error_at (block_expr->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::ModuleBodied &module) override + { + // strip test based on outer attrs + expander.expand_cfg_attrs (module.get_outer_attrs ()); + if (expander.fails_cfg (module.get_outer_attrs ())) + { + module.mark_for_strip (); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs (module.get_inner_attrs ()); + if (expander.fails_cfg (module.get_inner_attrs ())) + { + module.mark_for_strip (); + return; + } + + // strip items if required + auto &items = module.get_items (); + for (int i = 0; i < items.size ();) + { + auto &item = items[i]; + + // mark for stripping if required + item->accept_vis (*this); + + if (item->is_marked_for_strip ()) + items.erase (items.begin () + i); + else + i++; + } + } + void visit (AST::ModuleNoBody &module) override + { + // strip test based on outer attrs + expander.expand_cfg_attrs (module.get_outer_attrs ()); + if (expander.fails_cfg (module.get_outer_attrs ())) + { + module.mark_for_strip (); + return; + } + } + void visit (AST::ExternCrate &crate) override + { + // strip test based on outer attrs + expander.expand_cfg_attrs (crate.get_outer_attrs ()); + if (expander.fails_cfg (crate.get_outer_attrs ())) + { + crate.mark_for_strip (); + return; + } + } + void visit (AST::UseTreeGlob &use_tree) override + { + // shouldn't require? + } + void visit (AST::UseTreeList &use_tree) override + { + // shouldn't require? + } + void visit (AST::UseTreeRebind &use_tree) override + { + // shouldn't require? + } + void visit (AST::UseDeclaration &use_decl) override + { + // strip test based on outer attrs + expander.expand_cfg_attrs (use_decl.get_outer_attrs ()); + if (expander.fails_cfg (use_decl.get_outer_attrs ())) + { + use_decl.mark_for_strip (); + return; + } + } + void visit (AST::Function &function) override + { + // initial test based on outer attrs + expander.expand_cfg_attrs (function.get_outer_attrs ()); + if (expander.fails_cfg (function.get_outer_attrs ())) + { + function.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : function.get_generic_params ()) + param->accept_vis (*this); + + /* strip function parameters if required - this is specifically + * allowed by spec */ + expand_function_params (function.get_function_params ()); + + if (function.has_return_type ()) + { + auto &return_type = function.get_return_type (); + return_type->accept_vis (*this); + if (return_type->is_marked_for_strip ()) + rust_error_at (return_type->get_locus_slow (), + "cannot strip type in this position"); + } + + if (function.has_where_clause ()) + expand_where_clause (function.get_where_clause ()); + + /* body should always exist - if error state, should have returned + * before now */ + // can't strip block itself, but can strip sub-expressions + auto &block_expr = function.get_definition (); + block_expr->accept_vis (*this); + if (block_expr->is_marked_for_strip ()) + rust_error_at (block_expr->get_locus_slow (), + "cannot strip block expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::TypeAlias &type_alias) override + { + // initial test based on outer attrs + expander.expand_cfg_attrs (type_alias.get_outer_attrs ()); + if (expander.fails_cfg (type_alias.get_outer_attrs ())) + { + type_alias.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : type_alias.get_generic_params ()) + param->accept_vis (*this); + + if (type_alias.has_where_clause ()) + expand_where_clause (type_alias.get_where_clause ()); + + auto &type = type_alias.get_type_aliased (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + void visit (AST::StructStruct &struct_item) override + { + // initial test based on outer attrs + expander.expand_cfg_attrs (struct_item.get_outer_attrs ()); + if (expander.fails_cfg (struct_item.get_outer_attrs ())) + { + struct_item.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : struct_item.get_generic_params ()) + param->accept_vis (*this); + + if (struct_item.has_where_clause ()) + expand_where_clause (struct_item.get_where_clause ()); + + /* strip struct fields if required - this is presumably + * allowed by spec */ + expand_struct_fields (struct_item.get_fields ()); + } + void visit (AST::TupleStruct &tuple_struct) override + { + // initial test based on outer attrs + expander.expand_cfg_attrs (tuple_struct.get_outer_attrs ()); + if (expander.fails_cfg (tuple_struct.get_outer_attrs ())) + { + tuple_struct.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : tuple_struct.get_generic_params ()) + param->accept_vis (*this); + + /* strip struct fields if required - this is presumably + * allowed by spec */ + expand_tuple_fields (tuple_struct.get_fields ()); + + if (tuple_struct.has_where_clause ()) + expand_where_clause (tuple_struct.get_where_clause ()); + } + void visit (AST::EnumItem &item) override + { + // initial 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::EnumItemTuple &item) override + { + // initial 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 item fields if required - this is presumably + * allowed by spec */ + expand_tuple_fields (item.get_tuple_fields ()); + } + void visit (AST::EnumItemStruct &item) override + { + // initial 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 item fields if required - this is presumably + * allowed by spec */ + expand_struct_fields (item.get_struct_fields ()); + } + void visit (AST::EnumItemDiscriminant &item) override + { + // initial 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 any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &expr = item.get_expr (); + expr->accept_vis (*this); + if (expr->is_marked_for_strip ()) + rust_error_at (expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::Enum &enum_item) override + { + // initial test based on outer attrs + expander.expand_cfg_attrs (enum_item.get_outer_attrs ()); + if (expander.fails_cfg (enum_item.get_outer_attrs ())) + { + enum_item.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : enum_item.get_generic_params ()) + param->accept_vis (*this); + + if (enum_item.has_where_clause ()) + expand_where_clause (enum_item.get_where_clause ()); + + /* strip enum fields if required - this is presumably + * allowed by spec */ + auto &variants = enum_item.get_variants (); + for (int i = 0; i < variants.size ();) + { + auto &variant = variants[i]; + + // mark for stripping if required + variant->accept_vis (*this); + + if (variant->is_marked_for_strip ()) + variants.erase (variants.begin () + i); + else + i++; + } + } + void visit (AST::Union &union_item) override + { + // initial test based on outer attrs + expander.expand_cfg_attrs (union_item.get_outer_attrs ()); + if (expander.fails_cfg (union_item.get_outer_attrs ())) + { + union_item.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : union_item.get_generic_params ()) + param->accept_vis (*this); + + if (union_item.has_where_clause ()) + expand_where_clause (union_item.get_where_clause ()); + + /* strip union fields if required - this is presumably + * allowed by spec */ + expand_struct_fields (union_item.get_variants ()); + } + void visit (AST::ConstantItem &const_item) override + { + // initial test based on outer attrs + expander.expand_cfg_attrs (const_item.get_outer_attrs ()); + if (expander.fails_cfg (const_item.get_outer_attrs ())) + { + const_item.mark_for_strip (); + return; + } + + // strip any sub-types + auto &type = const_item.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &expr = const_item.get_expr (); + expr->accept_vis (*this); + if (expr->is_marked_for_strip ()) + rust_error_at (expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::StaticItem &static_item) override + { + // initial test based on outer attrs + expander.expand_cfg_attrs (static_item.get_outer_attrs ()); + if (expander.fails_cfg (static_item.get_outer_attrs ())) + { + static_item.mark_for_strip (); + return; + } + + // strip any sub-types + auto &type = static_item.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &expr = static_item.get_expr (); + expr->accept_vis (*this); + if (expr->is_marked_for_strip ()) + rust_error_at (expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + void visit (AST::TraitItemFunc &item) override + { + // initial 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; + } + + expand_trait_function_decl (item.get_trait_function_decl ()); + + if (item.has_definition ()) + { + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &block = item.get_definition (); + block->accept_vis (*this); + if (block->is_marked_for_strip ()) + rust_error_at (block->get_locus_slow (), + "cannot strip block expression in this " + "position - outer attributes not allowed"); + } + } + void visit (AST::TraitItemMethod &item) override + { + // initial 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; + } + + expand_trait_method_decl (item.get_trait_method_decl ()); + + if (item.has_definition ()) + { + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + auto &block = item.get_definition (); + block->accept_vis (*this); + if (block->is_marked_for_strip ()) + rust_error_at (block->get_locus_slow (), + "cannot strip block expression in this " + "position - outer attributes not allowed"); + } + } + void visit (AST::TraitItemConst &item) override + { + // initial 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 any sub-types + auto &type = item.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped */ + if (item.has_expression ()) + { + auto &expr = item.get_expr (); + expr->accept_vis (*this); + if (expr->is_marked_for_strip ()) + rust_error_at (expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + } + void visit (AST::TraitItemType &item) override + { + // initial 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; + } + + if (item.has_type_param_bounds ()) + { + // don't strip directly, only components of bounds + for (auto &bound : item.get_type_param_bounds ()) + bound->accept_vis (*this); + } + } + void visit (AST::Trait &trait) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (trait.get_outer_attrs ()); + if (expander.fails_cfg (trait.get_outer_attrs ())) + { + trait.mark_for_strip (); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs (trait.get_inner_attrs ()); + if (expander.fails_cfg (trait.get_inner_attrs ())) + { + trait.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : trait.get_generic_params ()) + param->accept_vis (*this); + + if (trait.has_type_param_bounds ()) + { + // don't strip directly, only components of bounds + for (auto &bound : trait.get_type_param_bounds ()) + bound->accept_vis (*this); + } + + if (trait.has_where_clause ()) + expand_where_clause (trait.get_where_clause ()); + + // strip trait items if required + auto &trait_items = trait.get_trait_items (); + for (int i = 0; i < trait_items.size ();) + { + auto &item = trait_items[i]; + + // mark for stripping if required + item->accept_vis (*this); + + if (item->is_marked_for_strip ()) + trait_items.erase (trait_items.begin () + i); + else + i++; + } + } + void visit (AST::InherentImpl &impl) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (impl.get_outer_attrs ()); + if (expander.fails_cfg (impl.get_outer_attrs ())) + { + impl.mark_for_strip (); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs (impl.get_inner_attrs ()); + if (expander.fails_cfg (impl.get_inner_attrs ())) + { + impl.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : impl.get_generic_params ()) + param->accept_vis (*this); + + auto &type = impl.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + if (impl.has_where_clause ()) + expand_where_clause (impl.get_where_clause ()); + + // strip inherent impl items if required + auto &impl_items = impl.get_impl_items (); + for (int i = 0; i < impl_items.size ();) + { + auto &item = impl_items[i]; + + // mark for stripping if required + item->accept_vis (*this); + + if (item->is_marked_for_strip ()) + impl_items.erase (impl_items.begin () + i); + else + i++; + } + } + void visit (AST::TraitImpl &impl) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (impl.get_outer_attrs ()); + if (expander.fails_cfg (impl.get_outer_attrs ())) + { + impl.mark_for_strip (); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs (impl.get_inner_attrs ()); + if (expander.fails_cfg (impl.get_inner_attrs ())) + { + impl.mark_for_strip (); + return; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : impl.get_generic_params ()) + param->accept_vis (*this); + + auto &type = impl.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + auto &trait_path = impl.get_trait_path (); + visit (trait_path); + if (trait_path.is_marked_for_strip ()) + rust_error_at (trait_path.get_locus (), + "cannot strip typepath in this position"); + + if (impl.has_where_clause ()) + expand_where_clause (impl.get_where_clause ()); + + // strip trait impl items if required + auto &impl_items = impl.get_impl_items (); + for (int i = 0; i < impl_items.size ();) + { + auto &item = impl_items[i]; + + // mark for stripping if required + item->accept_vis (*this); + + if (item->is_marked_for_strip ()) + impl_items.erase (impl_items.begin () + i); + else + i++; + } + } + 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; + } + + auto &type = item.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + 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; + } + + // just expand sub-stuff - can't actually strip generic params themselves + for (auto ¶m : item.get_generic_params ()) + param->accept_vis (*this); + + /* strip function parameters if required - this is specifically + * allowed by spec */ + auto ¶ms = item.get_function_params (); + for (int i = 0; i < params.size ();) + { + auto ¶m = params[i]; + + auto ¶m_attrs = param.get_outer_attrs (); + expander.expand_cfg_attrs (param_attrs); + if (expander.fails_cfg (param_attrs)) + { + params.erase (params.begin () + i); + continue; + } + + auto &type = param.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + // increment if nothing else happens + i++; + } + /* NOTE: these are extern function params, which may have different + * rules and restrictions to "normal" function params. So expansion + * handled separately. */ + + /* TODO: assuming that variadic nature cannot be stripped. If this + * is not true, then have code here to do so. */ + + if (item.has_return_type ()) + { + auto &return_type = item.get_return_type (); + return_type->accept_vis (*this); + if (return_type->is_marked_for_strip ()) + rust_error_at (return_type->get_locus_slow (), + "cannot strip type in this position"); + } + + if (item.has_where_clause ()) + expand_where_clause (item.get_where_clause ()); + } + void visit (AST::ExternBlock &block) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (block.get_outer_attrs ()); + if (expander.fails_cfg (block.get_outer_attrs ())) + { + block.mark_for_strip (); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs (block.get_inner_attrs ()); + if (expander.fails_cfg (block.get_inner_attrs ())) + { + block.mark_for_strip (); + return; + } + + // strip external items if required + auto &extern_items = block.get_extern_items (); + for (int i = 0; i < extern_items.size ();) + { + auto &item = extern_items[i]; + + // mark for stripping if required + item->accept_vis (*this); + + if (item->is_marked_for_strip ()) + extern_items.erase (extern_items.begin () + i); + else + i++; + } + } + + // I don't think it would be possible to strip macros without expansion + void visit (AST::MacroMatchFragment &match) override {} + void visit (AST::MacroMatchRepetition &match) override {} + void visit (AST::MacroMatcher &matcher) override {} + void visit (AST::MacroRulesDefinition &rules_def) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (rules_def.get_outer_attrs ()); + if (expander.fails_cfg (rules_def.get_outer_attrs ())) + { + rules_def.mark_for_strip (); + return; + } + + // I don't think any macro rules can be stripped in any way + } + void visit (AST::MacroInvocation ¯o_invoc) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (macro_invoc.get_outer_attrs ()); + if (expander.fails_cfg (macro_invoc.get_outer_attrs ())) + { + macro_invoc.mark_for_strip (); + return; + } + + // I don't think any macro token trees can be stripped in any way + + // TODO: maybe have stripping behaviour for the cfg! macro here? + } + void visit (AST::MetaItemPath &meta_item) override {} + void visit (AST::MetaItemSeq &meta_item) override {} + void visit (AST::MetaWord &meta_item) override {} + void visit (AST::MetaNameValueStr &meta_item) override {} + void visit (AST::MetaListPaths &meta_item) override {} + void visit (AST::MetaListNameValueStr &meta_item) override {} + + void visit (AST::LiteralPattern &pattern) override + { + // not possible + } + void visit (AST::IdentifierPattern &pattern) override + { + // can only strip sub-patterns of the inner pattern to bind + if (!pattern.has_pattern_to_bind ()) + return; + + auto &sub_pattern = pattern.get_pattern_to_bind (); + sub_pattern->accept_vis (*this); + if (sub_pattern->is_marked_for_strip ()) + rust_error_at (sub_pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + void visit (AST::WildcardPattern &pattern) override + { + // not possible + } + void visit (AST::RangePatternBoundLiteral &bound) override + { + // not possible + } + void visit (AST::RangePatternBoundPath &bound) override + { + // can expand path, but not strip it directly + auto &path = bound.get_path (); + visit (path); + if (path.is_marked_for_strip ()) + rust_error_at (path.get_locus (), "cannot strip path in this position"); + } + void visit (AST::RangePatternBoundQualPath &bound) override + { + // can expand path, but not strip it directly + auto &path = bound.get_qualified_path (); + visit (path); + if (path.is_marked_for_strip ()) + rust_error_at (path.get_locus (), "cannot strip path in this position"); + } + void visit (AST::RangePattern &pattern) override + { + // should have no capability to strip lower or upper bounds, only expand + pattern.get_lower_bound ()->accept_vis (*this); + pattern.get_upper_bound ()->accept_vis (*this); + } + void visit (AST::ReferencePattern &pattern) override + { + auto &sub_pattern = pattern.get_referenced_pattern (); + sub_pattern->accept_vis (*this); + if (sub_pattern->is_marked_for_strip ()) + rust_error_at (sub_pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + void visit (AST::StructPatternFieldTuplePat &field) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (field.get_outer_attrs ()); + if (expander.fails_cfg (field.get_outer_attrs ())) + { + field.mark_for_strip (); + return; + } + + // strip sub-patterns (can't strip top-level pattern) + auto &sub_pattern = field.get_index_pattern (); + sub_pattern->accept_vis (*this); + if (sub_pattern->is_marked_for_strip ()) + rust_error_at (sub_pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + void visit (AST::StructPatternFieldIdentPat &field) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (field.get_outer_attrs ()); + if (expander.fails_cfg (field.get_outer_attrs ())) + { + field.mark_for_strip (); + return; + } + + // strip sub-patterns (can't strip top-level pattern) + auto &sub_pattern = field.get_ident_pattern (); + sub_pattern->accept_vis (*this); + if (sub_pattern->is_marked_for_strip ()) + rust_error_at (sub_pattern->get_locus_slow (), + "cannot strip pattern in this position"); + } + void visit (AST::StructPatternFieldIdent &field) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (field.get_outer_attrs ()); + if (expander.fails_cfg (field.get_outer_attrs ())) + { + field.mark_for_strip (); + return; + } + } + void visit (AST::StructPattern &pattern) override + { + // expand (but don't strip) path + auto &path = pattern.get_path (); + visit (path); + if (path.is_marked_for_strip ()) + rust_error_at (path.get_locus (), "cannot strip path in this position"); + + // TODO: apparently struct pattern fields can have outer attrs. so can they + // be stripped? + if (!pattern.has_struct_pattern_elems ()) + return; + + auto &elems = pattern.get_struct_pattern_elems (); + + // assuming you can strip struct pattern fields + auto &fields = elems.get_struct_pattern_fields (); + for (int i = 0; i < fields.size ();) + { + auto &field = fields[i]; + + field->accept_vis (*this); + + if (field->is_marked_for_strip ()) + fields.erase (fields.begin () + i); + else + i++; + } + + // assuming you can strip the ".." part + if (elems.has_etc ()) + { + expander.expand_cfg_attrs (elems.get_etc_outer_attrs ()); + if (expander.fails_cfg (elems.get_etc_outer_attrs ())) + elems.strip_etc (); + } + } + void visit (AST::TupleStructItemsNoRange &tuple_items) override + { + // can't strip individual patterns, only sub-patterns + for (auto &pattern : tuple_items.get_patterns ()) + { + pattern->accept_vis (*this); + + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + } + void visit (AST::TupleStructItemsRange &tuple_items) override + { + // can't strip individual patterns, only sub-patterns + for (auto &lower_pattern : tuple_items.get_lower_patterns ()) + { + lower_pattern->accept_vis (*this); + + if (lower_pattern->is_marked_for_strip ()) + rust_error_at (lower_pattern->get_locus_slow (), + "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + for (auto &upper_pattern : tuple_items.get_upper_patterns ()) + { + upper_pattern->accept_vis (*this); + + if (upper_pattern->is_marked_for_strip ()) + rust_error_at (upper_pattern->get_locus_slow (), + "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + } + void visit (AST::TupleStructPattern &pattern) override + { + // expand (but don't strip) path + auto &path = pattern.get_path (); + visit (path); + if (path.is_marked_for_strip ()) + rust_error_at (path.get_locus (), "cannot strip path in this position"); + + if (pattern.has_items ()) + pattern.get_items ()->accept_vis (*this); + } + void visit (AST::TuplePatternItemsMultiple &tuple_items) override + { + // can't strip individual patterns, only sub-patterns + for (auto &pattern : tuple_items.get_patterns ()) + { + pattern->accept_vis (*this); + + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + } + void visit (AST::TuplePatternItemsRanged &tuple_items) override + { + // can't strip individual patterns, only sub-patterns + for (auto &lower_pattern : tuple_items.get_lower_patterns ()) + { + lower_pattern->accept_vis (*this); + + if (lower_pattern->is_marked_for_strip ()) + rust_error_at (lower_pattern->get_locus_slow (), + "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + for (auto &upper_pattern : tuple_items.get_upper_patterns ()) + { + upper_pattern->accept_vis (*this); + + if (upper_pattern->is_marked_for_strip ()) + rust_error_at (upper_pattern->get_locus_slow (), + "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + } + void visit (AST::TuplePattern &pattern) override + { + if (pattern.has_tuple_pattern_items ()) + pattern.get_items ()->accept_vis (*this); + } + void visit (AST::GroupedPattern &pattern) override + { + // can't strip inner pattern, only sub-patterns + auto &pattern_in_parens = pattern.get_pattern_in_parens (); + + pattern_in_parens->accept_vis (*this); + + if (pattern_in_parens->is_marked_for_strip ()) + rust_error_at (pattern_in_parens->get_locus_slow (), + "cannot strip pattern in this position"); + } + void visit (AST::SlicePattern &pattern) override + { + // can't strip individual patterns, only sub-patterns + for (auto &item : pattern.get_items ()) + { + item->accept_vis (*this); + + if (item->is_marked_for_strip ()) + rust_error_at (item->get_locus_slow (), + "cannot strip pattern in this position"); + // TODO: quit stripping now? or keep going? + } + } + + void visit (AST::EmptyStmt &stmt) override + { + // assuming no outer attributes, so nothing can happen + } + void visit (AST::LetStmt &stmt) override + { + // initial strip test based on outer attrs + expander.expand_cfg_attrs (stmt.get_outer_attrs ()); + if (expander.fails_cfg (stmt.get_outer_attrs ())) + { + stmt.mark_for_strip (); + return; + } + + // can't strip pattern, but call for sub-patterns + auto &pattern = stmt.get_pattern (); + pattern->accept_vis (*this); + if (pattern->is_marked_for_strip ()) + rust_error_at (pattern->get_locus_slow (), + "cannot strip pattern in this position"); + + // similar for type + if (stmt.has_type ()) + { + auto &type = stmt.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + } + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped */ + if (stmt.has_init_expr ()) + { + auto &init_expr = stmt.get_init_expr (); + init_expr->accept_vis (*this); + if (init_expr->is_marked_for_strip ()) + rust_error_at (init_expr->get_locus_slow (), + "cannot strip expression in this position - outer " + "attributes not allowed"); + } + } + void visit (AST::ExprStmtWithoutBlock &stmt) override + { + // outer attributes associated with expr, so rely on expr + + // guard - should prevent null pointer expr + if (stmt.is_marked_for_strip ()) + return; + + // strip if expr is to be stripped + auto &expr = stmt.get_expr (); + expr->accept_vis (*this); + if (expr->is_marked_for_strip ()) + { + stmt.mark_for_strip (); + return; + } + } + void visit (AST::ExprStmtWithBlock &stmt) override + { + // outer attributes associated with expr, so rely on expr + + // guard - should prevent null pointer expr + if (stmt.is_marked_for_strip ()) + return; + + // strip if expr is to be stripped + auto &expr = stmt.get_expr (); + expr->accept_vis (*this); + if (expr->is_marked_for_strip ()) + { + stmt.mark_for_strip (); + return; + } + } + + void visit (AST::TraitBound &bound) override + { + // nothing in for lifetimes to strip + + // expand but don't strip type path + auto &path = bound.get_type_path (); + visit (path); + if (path.is_marked_for_strip ()) + rust_error_at (path.get_locus (), + "cannot strip type path in this position"); + } + void visit (AST::ImplTraitType &type) override + { + // don't strip directly, only components of bounds + for (auto &bound : type.get_type_param_bounds ()) + bound->accept_vis (*this); + } + void visit (AST::TraitObjectType &type) override + { + // don't strip directly, only components of bounds + for (auto &bound : type.get_type_param_bounds ()) + bound->accept_vis (*this); + } + void visit (AST::ParenthesisedType &type) override + { + // expand but don't strip inner type + auto &inner_type = type.get_type_in_parens (); + inner_type->accept_vis (*this); + if (inner_type->is_marked_for_strip ()) + rust_error_at (inner_type->get_locus_slow (), + "cannot strip type in this position"); + } + void visit (AST::ImplTraitTypeOneBound &type) override + { + // no stripping possible + visit (type.get_trait_bound ()); + } + void visit (AST::TraitObjectTypeOneBound &type) override + { + // no stripping possible + visit (type.get_trait_bound ()); + } + void visit (AST::TupleType &type) override + { + // TODO: assuming that types can't be stripped as types don't have outer + // attributes + for (auto &elem_type : type.get_elems ()) + { + elem_type->accept_vis (*this); + if (elem_type->is_marked_for_strip ()) + rust_error_at (elem_type->get_locus_slow (), + "cannot strip type in this position"); + } + } + void visit (AST::NeverType &type) override + { + // no stripping possible + } + void visit (AST::RawPointerType &type) override + { + // expand but don't strip type pointed to + auto &pointed_type = type.get_type_pointed_to (); + pointed_type->accept_vis (*this); + if (pointed_type->is_marked_for_strip ()) + rust_error_at (pointed_type->get_locus_slow (), + "cannot strip type in this position"); + } + void visit (AST::ReferenceType &type) override + { + // expand but don't strip type referenced + auto &referenced_type = type.get_type_referenced (); + referenced_type->accept_vis (*this); + if (referenced_type->is_marked_for_strip ()) + rust_error_at (referenced_type->get_locus_slow (), + "cannot strip type in this position"); + } + void visit (AST::ArrayType &type) override + { + // expand but don't strip type referenced + auto &base_type = type.get_elem_type (); + base_type->accept_vis (*this); + if (base_type->is_marked_for_strip ()) + rust_error_at (base_type->get_locus_slow (), + "cannot strip type in this position"); + + // same for expression + auto &size_expr = type.get_size_expr (); + size_expr->accept_vis (*this); + if (size_expr->is_marked_for_strip ()) + rust_error_at (size_expr->get_locus_slow (), + "cannot strip expression in this position"); + } + void visit (AST::SliceType &type) override + { + // expand but don't strip elem type + auto &elem_type = type.get_elem_type (); + elem_type->accept_vis (*this); + if (elem_type->is_marked_for_strip ()) + rust_error_at (elem_type->get_locus_slow (), + "cannot strip type in this position"); + } + void visit (AST::InferredType &type) override + { + // none possible + } + void visit (AST::BareFunctionType &type) override + { + // seem to be no generics + + // presumably function params can be stripped + auto ¶ms = type.get_function_params (); + for (int i = 0; i < params.size ();) + { + auto ¶m = params[i]; + + auto ¶m_attrs = param.get_outer_attrs (); + expander.expand_cfg_attrs (param_attrs); + if (expander.fails_cfg (param_attrs)) + { + params.erase (params.begin () + i); + continue; + } + + auto &type = param.get_type (); + type->accept_vis (*this); + if (type->is_marked_for_strip ()) + rust_error_at (type->get_locus_slow (), + "cannot strip type in this position"); + + // increment if nothing else happens + i++; + } + + /* TODO: assuming that variadic nature cannot be stripped. If this + * is not true, then have code here to do so. */ + + if (type.has_return_type ()) + { + auto &return_type = type.get_return_type (); + return_type->accept_vis (*this); + if (return_type->is_marked_for_strip ()) + rust_error_at (return_type->get_locus_slow (), + "cannot strip type in this position"); + } + + // no where clause, apparently + } +}; + +void +MacroExpander::expand_invoc (std::unique_ptr &invoc) +{ + /* if current expansion depth > recursion limit, create an error (maybe fatal + * error) and return */ + + /* switch on type of macro: + - '!' syntax macro (inner switch) + - procedural macro - "A token-based function-like macro" + - 'macro_rules' (by example/pattern-match) macro? or not? "an + AST-based function-like macro" + - else is unreachable + - attribute syntax macro (inner switch) + - procedural macro attribute syntax - "A token-based attribute macro" + - legacy macro attribute syntax? - "an AST-based attribute macro" + - non-macro attribute: mark known + - else is unreachable + - derive macro (inner switch) + - derive or legacy derive - "token-based" vs "AST-based" + - else is unreachable + - derive container macro - unreachable*/ +} + +/* Determines whether any cfg predicate is false and hence item with attributes + * should be stripped. */ +bool +MacroExpander::fails_cfg (std::vector &attrs) +{ + for (auto &attr : attrs) + { + if (attr.get_path () == "cfg" && !attr.check_cfg_predicate (session)) + return true; } - - /* Determines whether any cfg predicate is false and hence item with attributes should - * be stripped. */ - bool MacroExpander::fails_cfg(std::vector& attrs) { - for (auto& attr : attrs) { - if (attr.get_path() == "cfg" && !attr.check_cfg_predicate(session)) - return true; - } - return false; + return false; +} + +// Expands cfg_attr attributes. +void +MacroExpander::expand_cfg_attrs (std::vector &attrs) +{ + for (int i = 0; i < attrs.size ();) + { + auto &attr = attrs[i]; + if (attr.get_path () == "cfg_attr") + { + if (attr.check_cfg_predicate (session)) + { + // split off cfg_attr + std::vector new_attrs + = attr.separate_cfg_attrs (); + + // remove attr from vector + attrs.erase (attrs.begin () + i); + + // add new attrs to vector + attrs.insert (attrs.begin () + i, + std::make_move_iterator (new_attrs.begin ()), + std::make_move_iterator (new_attrs.end ())); + } + + /* do something - if feature (first token in tree) is in fact enabled, + * make tokens listed afterwards into attributes. i.e.: for + * [cfg_attr(feature = "wow", wow1, wow2)], if "wow" is true, then add + * attributes [wow1] and [wow2] to attribute list. This can also be + * recursive, so check for expanded attributes being recursive and + * possibly recursively call the expand_attrs? */ + } + else + { + i++; + } } - - // Expands cfg_attr attributes. - void MacroExpander::expand_cfg_attrs(std::vector& attrs) { - for (int i = 0; i < attrs.size();) { - auto& attr = attrs[i]; - if (attr.get_path() == "cfg_attr") { - if (attr.check_cfg_predicate(session)) { - // split off cfg_attr - std::vector new_attrs = attr.separate_cfg_attrs(); - - // remove attr from vector - attrs.erase(attrs.begin() + i); - - // add new attrs to vector - attrs.insert(attrs.begin() + i, std::make_move_iterator(new_attrs.begin()), - std::make_move_iterator(new_attrs.end())); - } - - /* do something - if feature (first token in tree) is in fact enabled, - * make tokens listed afterwards into attributes. i.e.: for - * [cfg_attr(feature = "wow", wow1, wow2)], if "wow" is true, then add - * attributes [wow1] and [wow2] to attribute list. This can also be - * recursive, so check for expanded attributes being recursive and - * possibly recursively call the expand_attrs? */ - } else { - i++; - } - } - attrs.shrink_to_fit(); + attrs.shrink_to_fit (); +} + +void +MacroExpander::expand_crate () +{ + /* fill macro/decorator map from init list? not sure where init list comes + * from? */ + + // TODO: does cfg apply for inner attributes? research. + // the apparent answer (from playground test) is yes + + // expand crate cfg_attr attributes + expand_cfg_attrs (crate.inner_attrs); + + if (fails_cfg (crate.inner_attrs)) + { + // basically, delete whole crate + crate.strip_crate (); + // TODO: maybe create warning here? probably not desired behaviour } + // expand module attributes? + + // expand attributes recursively and strip items if required + AttrVisitor attr_visitor (*this); + auto &items = crate.items; + for (int i = 0; i < items.size ();) + { + auto &item = items[i]; + + // mark for stripping if required + item->accept_vis (attr_visitor); + + if (item->is_marked_for_strip ()) + items.erase (items.begin () + i); + else + i++; + } + // TODO: should recursive attribute and macro expansion be done in the same + // transversal? Or in separate ones like currently? - void MacroExpander::expand_crate() { - /* fill macro/decorator map from init list? not sure where init list comes - * from? */ - - // TODO: does cfg apply for inner attributes? research. - // the apparent answer (from playground test) is yes - - // expand crate cfg_attr attributes - expand_cfg_attrs(crate.inner_attrs); - - if (fails_cfg(crate.inner_attrs)) { - // basically, delete whole crate - crate.strip_crate(); - // TODO: maybe create warning here? probably not desired behaviour - } - // expand module attributes? - - // expand attributes recursively and strip items if required - AttrVisitor attr_visitor(*this); - auto& items = crate.items; - for (int i = 0; i < items.size();) { - auto& item = items[i]; - - // mark for stripping if required - item->accept_vis(attr_visitor); - - if (item->is_marked_for_strip()) - items.erase(items.begin() + i); - else - i++; - } - // TODO: should recursive attribute and macro expansion be done in the same transversal? Or in - // separate ones like currently? - - // expand module tree recursively + // expand module tree recursively - // post-process + // post-process - // extract exported macros? - } + // extract exported macros? +} } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index a7fe076..c8c7f35 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -27,7 +27,8 @@ struct MacroExpander ExpansionCfg cfg; unsigned int expansion_depth = 0; - MacroExpander (AST::Crate &crate, ExpansionCfg cfg, Session &session) : cfg (cfg), crate (crate), session (session) + MacroExpander (AST::Crate &crate, ExpansionCfg cfg, Session &session) + : cfg (cfg), crate (crate), session (session) {} ~MacroExpander () = default; @@ -40,8 +41,8 @@ struct MacroExpander // should this be public or private? void expand_invoc (std::unique_ptr &invoc); - void expand_cfg_attrs(std::vector& attrs); - bool fails_cfg(std::vector& attr); + void expand_cfg_attrs (std::vector &attrs); + bool fails_cfg (std::vector &attr); /* TODO: make it extend ASTVisitor so that individual items can be accessed * properly? */ diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 5da2764..3e573a6 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -630,7 +630,8 @@ Session::injection (AST::Crate &crate) * rustc also has a "quote" macro that is defined differently and is * supposedly not stable so eh. */ /* TODO: actually implement injection of these macros. In particular, derive - * macros, cfg, and test should be prioritised since they seem to be used the most. */ + * macros, cfg, and test should be prioritised since they seem to be used the + * most. */ // crate injection std::vector names; -- cgit v1.1 From 4232e46d87feb91749edb944681d0d4b93475c3a Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Thu, 10 Dec 2020 18:32:07 +0800 Subject: Fixed BlockExpr not being allowed to be empty --- gcc/rust/ast/rust-expr.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index f129e8c..a3c94aa 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -2704,6 +2704,7 @@ class BlockExpr : public ExprWithBlock std::unique_ptr expr; // inlined from Statements Location locus; + bool marked_for_strip = false; public: std::string as_string () const override; @@ -2727,7 +2728,7 @@ public: // Copy constructor with clone BlockExpr (BlockExpr const &other) : ExprWithBlock (other), inner_attrs (other.inner_attrs), - locus (other.locus) + locus (other.locus), marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference if (other.expr != nullptr) @@ -2744,6 +2745,7 @@ public: ExprWithBlock::operator= (other); inner_attrs = other.inner_attrs; locus = other.locus; + marked_for_strip = other.marked_for_strip; // outer_attrs = other.outer_attrs; // guard to protect from null pointer dereference @@ -2770,20 +2772,18 @@ public: } Location get_locus () const { return locus; } - Location get_locus_slow () const override { return get_locus (); } + Location get_locus_slow () const final override { return get_locus (); } void accept_vis (ASTVisitor &vis) override; - // Invalid if has no statements or final expr, so base stripping on that. + // Can be completely empty, so have to have a separate flag. void mark_for_strip () override { - expr = nullptr; - statements.clear (); - statements.shrink_to_fit (); + marked_for_strip = true; } bool is_marked_for_strip () const override { - return expr == nullptr && statements.empty (); + return marked_for_strip; } // TODO: this mutable getter seems really dodgy. Think up better way. @@ -2799,7 +2799,7 @@ public: // TODO: is this better? Or is a "vis_block" better? std::unique_ptr &get_tail_expr () { - rust_assert (expr != nullptr); + rust_assert (has_tail_expr ()); return expr; } -- cgit v1.1 From e21c9fe1657303605efeacd4890430e7d40c4c3c Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Thu, 10 Dec 2020 20:53:26 +0800 Subject: Enhanced dumping of expansion --- gcc/rust/rust-session-manager.cc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 3e573a6..da50948 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -344,8 +344,8 @@ Session::enable_dump (std::string arg) if (arg == "all") { rust_error_at (Location (), - "dumping all is not supported as of now. choose %, " - "%, or %"); + "dumping all is not supported as of now. choose %, %, " + "or %"); return false; } else if (arg == "lex") @@ -390,8 +390,8 @@ Session::enable_dump (std::string arg) else { rust_error_at (Location (), - "dump option %qs was unrecognised. choose %, " - "%, or %", + "dump option %qs was unrecognised. choose %, %, or " + "%", arg.c_str ()); return false; } @@ -472,7 +472,6 @@ Session::parse_file (const char *filename) if (options.dump_option == CompileOptions::REGISTER_PLUGINS_DUMP) { // TODO: what do I dump here? - return; } // injection pipeline stage @@ -482,7 +481,6 @@ Session::parse_file (const char *filename) if (options.dump_option == CompileOptions::INJECTION_DUMP) { // TODO: what do I dump here? injected crate names? - return; } // expansion pipeline stage @@ -491,8 +489,10 @@ Session::parse_file (const char *filename) if (options.dump_option == CompileOptions::EXPANSION_DUMP) { - // TODO: what do I dump here? expanded macros? AST with expanded macros? - return; + // dump AST with expanded stuff + fprintf (stderr, "BEGIN POST-EXPANSION AST DUMP\n"); + parser.debug_dump_ast_output (parsed_crate); + fprintf (stderr, "END POST-EXPANSION AST DUMP\n"); } // resolution pipeline stage @@ -502,7 +502,6 @@ Session::parse_file (const char *filename) if (options.dump_option == CompileOptions::RESOLUTION_DUMP) { // TODO: what do I dump here? resolved names? AST with resolved names? - return; } if (saw_errors ()) -- cgit v1.1 From 6ee2c06c47a905b11ee5b674710df187126203bc Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sun, 13 Dec 2020 15:47:32 +0800 Subject: Attempt to fix array parsing errors --- gcc/rust/ast/rust-ast.h | 6 +++--- gcc/rust/ast/rust-macro.h | 6 ++++++ gcc/rust/expand/rust-macro-expand.cc | 19 +++++++++++++++++++ gcc/rust/parse/rust-parse-impl.h | 8 ++++++-- 4 files changed, 34 insertions(+), 5 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index d23cb81..1ad0cf9 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -473,9 +473,9 @@ public: std::string as_string () const; // TODO: does this require visitor pattern as not polymorphic? - - // Maybe change to const-reference in future - SimplePath get_path () const { return path; } + + const SimplePath &get_path () const { return path; } + SimplePath &get_path () { return path; } // Call to parse attribute body to meta item syntax. void parse_attr_to_meta_item (); diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 5760392..2cae0f9 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -318,6 +318,9 @@ public: std::vector &get_outer_attrs () { return outer_attrs; } const std::vector &get_outer_attrs () const { return outer_attrs; } + std::vector &get_macro_rules () { return rules; } + const std::vector &get_macro_rules () const { return rules; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -355,6 +358,9 @@ public: void mark_for_strip () override { path = SimplePath::create_empty (); } bool is_marked_for_strip () const override { return path.is_empty (); } + const SimplePath &get_path () const { return path; } + SimplePath &get_path () { return path; } + 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 82941c7..4f28836 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -3291,6 +3291,25 @@ MacroExpander::expand_invoc (std::unique_ptr &invoc) - derive or legacy derive - "token-based" vs "AST-based" - else is unreachable - derive container macro - unreachable*/ + +#if 0 + // macro_rules macro test code + auto rule_def = find_rules_def(invoc->get_path()); + if (rule_def != nullptr) { + ASTFrag expanded = expand_decl_macro(invoc, rule_def); + /* could make this a data structure containing vectors of exprs, patterns and types (for regular), + * and then stmts and items (for semi). Except what about having an expr, then a type? Hmm. Might + * have to do the "unified base type" thing OR just have a simulated union, and then have AST frag + * be a vector of these simulated unions. */ + + // how would errors be signalled? null fragment? something else? + // what about error vs just not having stuff in rules definition yet? + + /* replace macro invocation with ast frag. actually, don't have any context here. maybe attach ast + * frag to macro invocation, and then have a method above get it? Or just return the ast frag from + * this method. */ + } +#endif } /* Determines whether any cfg predicate is false and hence item with attributes diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 3315da3..bade40c 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -8431,6 +8431,8 @@ Parser::parse_array_expr ( return nullptr; } + skip_token (RIGHT_SQUARE); + std::unique_ptr copied_array_elems ( new AST::ArrayElemsCopied (std::move (initial_expr), std::move (copy_amount))); @@ -8447,6 +8449,8 @@ Parser::parse_array_expr ( exprs.push_back (std::move (initial_expr)); exprs.shrink_to_fit (); + skip_token (RIGHT_SQUARE); + std::unique_ptr array_elems ( new AST::ArrayElemsValues (std::move (exprs))); return std::unique_ptr ( @@ -13709,8 +13713,8 @@ Parser::parse_field_access_expr ( std::vector outer_attrs, ParseRestrictions restrictions ATTRIBUTE_UNUSED) { - // get field name identifier (assume that this is a field access expr and not - // say await) + /* get field name identifier (assume that this is a field access expr and not + * await, for instance) */ const_TokenPtr ident_tok = expect_token (IDENTIFIER); Identifier ident = ident_tok->get_str (); -- cgit v1.1 From 4490d49331a092775ebd3d38bec14b2eb7d98998 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sun, 13 Dec 2020 16:20:57 +0800 Subject: Fixed SimplePath's operator == not being const --- gcc/rust/ast/rust-ast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 1ad0cf9..bdc1f12 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -327,7 +327,7 @@ public: // does this need visitor if not polymorphic? probably not // path-to-string comparison operator - bool operator== (const std::string &rhs) + bool operator== (const std::string &rhs) const { return !has_opening_scope_resolution && segments.size () == 1 && segments[0].as_string () == rhs; -- cgit v1.1 From a697962166a9c72e568814e09658a896fc92fef5 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sun, 13 Dec 2020 17:21:38 +0800 Subject: Modified binding power used when parsing expression inside index expr --- gcc/rust/parse/rust-parse-impl.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index bade40c..74b6510 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -13681,12 +13681,14 @@ Parser::parse_tuple_index_expr ( template std::unique_ptr Parser::parse_index_expr ( - const_TokenPtr tok ATTRIBUTE_UNUSED, std::unique_ptr array_expr, - std::vector outer_attrs, ParseRestrictions restrictions) + const_TokenPtr, std::unique_ptr array_expr, + std::vector outer_attrs, ParseRestrictions) { // parse RHS (as tok has already been consumed in parse_expression) - std::unique_ptr index_expr - = parse_expr (LBP_ARRAY_REF, std::vector (), restrictions); + /*std::unique_ptr index_expr + = parse_expr (LBP_ARRAY_REF, std::vector (), restrictions);*/ + // TODO: conceptually, should treat [] as brackets, so just parse all expr + std::unique_ptr index_expr = parse_expr (); if (index_expr == nullptr) return nullptr; -- cgit v1.1 From 6d9b6db945ec25b51bff8b04e151973788149f3d Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Sun, 13 Dec 2020 18:18:37 +0800 Subject: Added location storage for struct expr fields Fixed typo in an enum expr field class --- gcc/rust/ast/rust-expr.h | 62 +++++++++++++++++++++++++--------------- gcc/rust/parse/rust-parse-impl.h | 10 +++---- 2 files changed, 44 insertions(+), 28 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index a3c94aa..cfffb38 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1566,6 +1566,8 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + virtual Location get_locus_slow () const = 0; + protected: // pure virtual clone implementation virtual StructExprField *clone_struct_expr_field_impl () const = 0; @@ -1575,15 +1577,18 @@ protected: class StructExprFieldIdentifier : public StructExprField { Identifier field_name; + Location locus; - // TODO: should this store location data? public: - StructExprFieldIdentifier (Identifier field_identifier) - : field_name (std::move (field_identifier)) + StructExprFieldIdentifier (Identifier field_identifier, Location locus) + : field_name (std::move (field_identifier)), locus (locus) {} std::string as_string () const override { return field_name; } + Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } + void accept_vis (ASTVisitor &vis) override; protected: @@ -1638,13 +1643,13 @@ public: class StructExprFieldIdentifierValue : public StructExprFieldWithVal { Identifier field_name; + Location locus; - // TODO: should this store location data? public: StructExprFieldIdentifierValue (Identifier field_identifier, - std::unique_ptr field_value) + std::unique_ptr field_value, Location locus) : StructExprFieldWithVal (std::move (field_value)), - field_name (std::move (field_identifier)) + field_name (std::move (field_identifier)), locus (locus) {} std::string as_string () const override; @@ -1653,6 +1658,9 @@ public: std::string get_field_name () const { return field_name; } + Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1666,12 +1674,12 @@ protected: class StructExprFieldIndexValue : public StructExprFieldWithVal { TupleIndex index; + Location locus; - // TODO: should this store location data? public: StructExprFieldIndexValue (TupleIndex tuple_index, - std::unique_ptr field_value) - : StructExprFieldWithVal (std::move (field_value)), index (tuple_index) + std::unique_ptr field_value, Location locus) + : StructExprFieldWithVal (std::move (field_value)), index (tuple_index), locus (locus) {} std::string as_string () const override; @@ -1680,6 +1688,9 @@ public: TupleIndex get_index () const { return index; } + Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1947,6 +1958,8 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + virtual Location get_locus_slow () const = 0; + protected: // Clone function implementation as pure virtual method virtual EnumExprField *clone_enum_expr_field_impl () const = 0; @@ -1956,18 +1969,20 @@ protected: class EnumExprFieldIdentifier : public EnumExprField { Identifier field_name; - - // TODO: should this store location data? + Location locus; public: EnumExprFieldIdentifier (Identifier field_identifier) - : field_name (std::move (field_identifier)) + : field_name (std::move (field_identifier)), locus (locus) {} void accept_vis (ASTVisitor &vis) override; std::string as_string () const override { return field_name; } + Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1983,8 +1998,6 @@ class EnumExprFieldWithVal : public EnumExprField { std::unique_ptr value; - // TODO: should this store location data? - protected: EnumExprFieldWithVal (std::unique_ptr field_value) : value (std::move (field_value)) @@ -2022,20 +2035,22 @@ public: class EnumExprFieldIdentifierValue : public EnumExprFieldWithVal { Identifier field_name; - - // TODO: should this store location data? + Location locus; public: EnumExprFieldIdentifierValue (Identifier field_name, - std::unique_ptr field_value) + std::unique_ptr field_value, Location locus) : EnumExprFieldWithVal (std::move (field_value)), - field_name (std::move (field_name)) + field_name (std::move (field_name)), locus (locus) {} std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; + Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2051,18 +2066,21 @@ class EnumExprFieldIndexValue : public EnumExprFieldWithVal TupleIndex index; // TODO: implement "with val" as a template with EnumExprField as type param? - // TODO: should this store location data? + Location locus; public: EnumExprFieldIndexValue (TupleIndex field_index, - std::unique_ptr field_value) - : EnumExprFieldWithVal (std::move (field_value)), index (field_index) + std::unique_ptr field_value, Location locus) + : EnumExprFieldWithVal (std::move (field_value)), index (field_index), locus (locus) {} std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; + Location get_locus () const { return locus; } + Location get_locus_slow () const final override { return get_locus (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2075,9 +2093,7 @@ protected: // Struct-like syntax enum variant instance creation AST node class EnumExprStruct : public EnumVariantExpr { - // std::vector fields; std::vector > fields; - Location locus; public: diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 74b6510..02c32b2 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -11509,7 +11509,7 @@ Parser::parse_struct_expr_field () return std::unique_ptr ( new AST::StructExprFieldIdentifierValue (std::move (ident), - std::move (expr))); + std::move (expr), t->get_locus ())); } else { @@ -11518,7 +11518,7 @@ Parser::parse_struct_expr_field () lexer.skip_token (); return std::unique_ptr ( - new AST::StructExprFieldIdentifier (std::move (ident))); + new AST::StructExprFieldIdentifier (std::move (ident), t->get_locus ())); } case INT_LITERAL: { // parse tuple index field @@ -11542,7 +11542,7 @@ Parser::parse_struct_expr_field () } return std::unique_ptr ( - new AST::StructExprFieldIndexValue (index, std::move (expr))); + new AST::StructExprFieldIndexValue (index, std::move (expr), t->get_locus ())); } case DOT_DOT: /* this is a struct base and can't be parsed here, so just return nothing @@ -11551,8 +11551,8 @@ Parser::parse_struct_expr_field () return nullptr; default: rust_error_at (t->get_locus (), - "unrecognised token %qs as first token of struct expr " - "field - expected identifier or int literal", + "unrecognised token %qs as first token of struct expr field - " + "expected identifier or int literal", t->get_token_description ()); return nullptr; } -- cgit v1.1 From 296916261846a9eaab03335d5e12a31271f2cf76 Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Mon, 14 Dec 2020 15:09:08 +0800 Subject: Improved use tree parsing --- gcc/rust/parse/rust-parse-impl.h | 427 ++++++++++++++++++++++----------------- 1 file changed, 245 insertions(+), 182 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 02c32b2..187f821 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -523,7 +523,27 @@ Parser::parse_attribute_body () return AST::Attribute (std::move (attr_path), std::move (attr_input), locus); } -// Parses a SimplePath AST node +/* Determines whether token is a valid simple path segment. This does not + * include scope resolution operators. */ +inline bool +is_simple_path_segment (TokenId id) +{ + switch (id) + { + case IDENTIFIER: + case SUPER: + case SELF: + case CRATE: + return true; + case DOLLAR_SIGN: + // assume that dollar sign leads to $crate + return true; + default: + return false; + } +} + +// Parses a SimplePath AST node, if it exists. Does nothing otherwise. template AST::SimplePath Parser::parse_simple_path () @@ -531,6 +551,11 @@ Parser::parse_simple_path () bool has_opening_scope_resolution = false; Location locus = Linemap::unknown_location (); + // don't parse anything if not a path upfront + if (!is_simple_path_segment (lexer.peek_token ()->get_id ()) + && !is_simple_path_segment (lexer.peek_token (1)->get_id ())) + return AST::SimplePath::create_empty (); + /* Checks for opening scope resolution (i.e. global scope fully-qualified * path) */ if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION) @@ -586,6 +611,8 @@ Parser::parse_simple_path () return AST::SimplePath (std::move (segments), has_opening_scope_resolution, locus); + /* TODO: now that is_simple_path_segment exists, could probably start + * actually making errors upon parse failure of segments and whatever */ } /* Parses a single SimplePathSegment (does not handle the scope resolution @@ -604,22 +631,21 @@ Parser::parse_simple_path_segment () case SUPER: lexer.skip_token (); - return AST::SimplePathSegment (std::string ("super"), t->get_locus ()); + return AST::SimplePathSegment ("super", t->get_locus ()); case SELF: lexer.skip_token (); - return AST::SimplePathSegment (std::string ("self"), t->get_locus ()); + return AST::SimplePathSegment ("self", t->get_locus ()); case CRATE: lexer.skip_token (); - return AST::SimplePathSegment (std::string ("crate"), t->get_locus ()); + return AST::SimplePathSegment ("crate", t->get_locus ()); case DOLLAR_SIGN: if (lexer.peek_token (1)->get_id () == CRATE) { lexer.skip_token (1); - return AST::SimplePathSegment (std::string ("$crate"), - t->get_locus ()); + return AST::SimplePathSegment ("$crate", t->get_locus ()); } gcc_fallthrough (); default: @@ -653,25 +679,25 @@ Parser::parse_path_ident_segment () case SUPER: lexer.skip_token (); - return AST::PathIdentSegment (std::string ("super")); + return AST::PathIdentSegment ("super"); case SELF: lexer.skip_token (); - return AST::PathIdentSegment (std::string ("self")); + return AST::PathIdentSegment ("self"); case SELF_ALIAS: lexer.skip_token (); - return AST::PathIdentSegment (std::string ("Self")); + return AST::PathIdentSegment ("Self"); case CRATE: lexer.skip_token (); - return AST::PathIdentSegment (std::string ("crate")); + return AST::PathIdentSegment ("crate"); case DOLLAR_SIGN: if (lexer.peek_token (1)->get_id () == CRATE) { lexer.skip_token (1); - return AST::PathIdentSegment (std::string ("$crate")); + return AST::PathIdentSegment ("$crate"); } gcc_fallthrough (); default: @@ -1265,8 +1291,7 @@ Parser::parse_macro_item ( /* dodgy way of detecting macro due to weird context-dependence thing. * probably can be improved */ // TODO: ensure that string compare works properly - if (t->get_id () == IDENTIFIER - && t->get_str () == std::string ("macro_rules")) + if (t->get_id () == IDENTIFIER && t->get_str () == "macro_rules") { return parse_macro_rules_def (std::move (outer_attrs)); } @@ -2081,7 +2106,7 @@ Parser::parse_extern_crate ( lexer.skip_token (); break; case SELF: - crate_name = std::string ("self"); + crate_name = "self"; lexer.skip_token (); break; default: @@ -2120,7 +2145,7 @@ Parser::parse_extern_crate ( lexer.skip_token (); break; case UNDERSCORE: - as_name = std::string ("_"); + as_name = "_"; lexer.skip_token (); break; default: @@ -2216,17 +2241,14 @@ Parser::parse_use_tree () { // has no path, so must be glob or nested tree UseTree type - /* due to implementation issues, parsing simple path removes any trailing - * scope resolutions (or any, actually, if the use tree has no path - * given), so we'll just assume that there's one there. */ - // Check anyway, but optional. + bool is_global = false; + + // check for global scope resolution operator if (lexer.peek_token ()->get_id () == SCOPE_RESOLUTION) { lexer.skip_token (); + is_global = true; } - /* Note that this implementation issue also makes it impossible to - * determine at the moment whether the tree has GLOBAL or NO_PATH path - * type. */ const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) @@ -2235,11 +2257,14 @@ Parser::parse_use_tree () // glob UseTree type lexer.skip_token (); - // TODO: find way to determine whether GLOBAL or NO_PATH path type - - // placeholder - return std::unique_ptr ( - new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH, - AST::SimplePath::create_empty (), locus)); + if (is_global) + return std::unique_ptr ( + new AST::UseTreeGlob (AST::UseTreeGlob::GLOBAL, + AST::SimplePath::create_empty (), locus)); + else + return std::unique_ptr ( + new AST::UseTreeGlob (AST::UseTreeGlob::NO_PATH, + AST::SimplePath::create_empty (), locus)); case LEFT_CURLY: { // nested tree UseTree type lexer.skip_token (); @@ -2258,11 +2283,9 @@ Parser::parse_use_tree () use_trees.push_back (std::move (use_tree)); if (lexer.peek_token ()->get_id () != COMMA) - { - break; - } - lexer.skip_token (); + break; + lexer.skip_token (); t = lexer.peek_token (); } @@ -2273,24 +2296,30 @@ Parser::parse_use_tree () return nullptr; } - /* TODO: find way to determine whether GLOBAL or NO_PATH path type - - * placeholder */ - return std::unique_ptr ( - new AST::UseTreeList (AST::UseTreeList::NO_PATH, - AST::SimplePath::create_empty (), - std::move (use_trees), locus)); + if (is_global) + return std::unique_ptr ( + new AST::UseTreeList (AST::UseTreeList::GLOBAL, + AST::SimplePath::create_empty (), + std::move (use_trees), locus)); + else + return std::unique_ptr ( + new AST::UseTreeList (AST::UseTreeList::NO_PATH, + AST::SimplePath::create_empty (), + std::move (use_trees), locus)); } case AS: // this is not allowed - rust_error_at (t->get_locus (), - "use declaration with rebind % requires a valid " - "simple path - none found"); + rust_error_at ( + t->get_locus (), + "use declaration with rebind % requires a valid simple path - " + "none found"); skip_after_semicolon (); return nullptr; default: rust_error_at (t->get_locus (), "unexpected token %qs in use tree with no valid " - "simple path (i.e. list or glob use tree)", + "simple path (i.e. list" + " or glob use tree)", t->get_token_description ()); skip_after_semicolon (); return nullptr; @@ -2299,7 +2328,8 @@ Parser::parse_use_tree () else { /* Due to aforementioned implementation issues, the trailing :: token is - * consumed by the path, so it can not be used as a disambiguator. */ + * consumed by the path, so it can not be used as a disambiguator. + * NOPE, not true anymore - TODO what are the consequences of this? */ const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) @@ -2330,11 +2360,9 @@ Parser::parse_use_tree () use_trees.push_back (std::move (use_tree)); if (lexer.peek_token ()->get_id () != COMMA) - { - break; - } - lexer.skip_token (); + break; + lexer.skip_token (); t = lexer.peek_token (); } @@ -2371,14 +2399,13 @@ Parser::parse_use_tree () return std::unique_ptr ( new AST::UseTreeRebind (AST::UseTreeRebind::WILDCARD, - std::move (path), locus, - std::string ("_"))); + std::move (path), locus, "_")); default: - rust_error_at (t->get_locus (), - "unexpected token %qs in use tree with as " - "clause - expected " - "identifier or %<_%>", - t->get_token_description ()); + rust_error_at ( + t->get_locus (), + "unexpected token %qs in use tree with as clause - expected " + "identifier or %<_%>", + t->get_token_description ()); skip_after_semicolon (); return nullptr; } @@ -2445,7 +2472,8 @@ Parser::parse_function ( // parse function parameters (only if next token isn't right paren) std::vector function_params; if (lexer.peek_token ()->get_id () != RIGHT_PAREN) - function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); + function_params + = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -3241,7 +3269,7 @@ Parser::parse_type_param () std::move (outer_attr))); } -/* Parses regular (i.e. non-generic) parameters in functions or methods. Also +/* Parses regular (i.e. non-generic) parameters in functions or methods. Also * has end token handling. */ template template @@ -3251,12 +3279,12 @@ Parser::parse_function_params (EndTokenPred is_end_token) std::vector params; if (is_end_token (lexer.peek_token ()->get_id ())) - return params; + return params; AST::FunctionParam initial_param = parse_function_param (); // Return empty parameter list if no parameter there - if (initial_param.is_error ()) + if (initial_param.is_error ()) { // TODO: is this an error? return params; @@ -3275,7 +3303,7 @@ Parser::parse_function_params (EndTokenPred is_end_token) // TODO: strictly speaking, shouldn't there be no trailing comma? if (is_end_token (lexer.peek_token ()->get_id ())) - break; + break; // now, as right paren would break, function param is required AST::FunctionParam param = parse_function_param (); @@ -3340,7 +3368,7 @@ std::unique_ptr Parser::parse_function_return_type () { if (lexer.peek_token ()->get_id () != RETURN_TYPE) - return nullptr; + return nullptr; // skip return type, as it now obviously exists lexer.skip_token (); @@ -4639,12 +4667,13 @@ Parser::parse_trait_item () /* skip comma so function and method regular params can be parsed in * same way */ if (lexer.peek_token ()->get_id () == COMMA) - lexer.skip_token (); + lexer.skip_token (); } // parse trait function params std::vector function_params - = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); + = parse_function_params ( + [] (TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -5164,11 +5193,12 @@ Parser::parse_inherent_impl_function_or_method ( /* skip comma so function and method regular params can be parsed in same * way */ if (lexer.peek_token ()->get_id () == COMMA) - lexer.skip_token (); + lexer.skip_token (); } // parse trait function params - std::vector function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); + std::vector function_params + = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -5413,7 +5443,8 @@ Parser::parse_trait_impl_function_or_method ( std::vector function_params; if (lexer.peek_token ()->get_id () != RIGHT_PAREN) { - function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); + function_params + = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); if (function_params.empty ()) { @@ -5547,7 +5578,7 @@ Parser::parse_extern_block ( // skip somewhere return nullptr; } - + extern_items.shrink_to_fit (); return std::unique_ptr ( @@ -5647,51 +5678,60 @@ Parser::parse_external_item () // parse parameters std::vector function_params; bool is_variadic = false; - std::vector variadic_attrs; + std::vector variadic_attrs; const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_PAREN) { - std::vector 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; - } - - break; - } + while (t->get_id () != RIGHT_PAREN) + { + std::vector 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 (); - AST::NamedFunctionParam param = parse_named_function_param (std::move (maybe_variadic_attrs)); - if (param.is_error ()) { + if (t->get_id () != RIGHT_PAREN) + { rust_error_at (t->get_locus (), - "could not parse named function parameter in external function"); + "expected right parentheses after variadic " + "in named function " + "parameters, found %qs", + t->get_token_description ()); 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)); - if (lexer.peek_token ()->get_id () != COMMA) - break; - + if (lexer.peek_token ()->get_id () != COMMA) + break; + // skip comma lexer.skip_token (); 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 return_type = parse_function_return_type (); @@ -5704,14 +5744,15 @@ Parser::parse_external_item () // skip somewhere? return nullptr; } - - function_params.shrink_to_fit (); + + function_params.shrink_to_fit (); return std::unique_ptr ( 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 (variadic_attrs), std::move (vis), + std::move (function_params), is_variadic, + std::move (variadic_attrs), std::move (vis), std::move (outer_attrs), locus)); } default: @@ -5728,7 +5769,8 @@ Parser::parse_external_item () * identifier). */ template AST::NamedFunctionParam -Parser::parse_named_function_param (std::vector outer_attrs) +Parser::parse_named_function_param ( + std::vector outer_attrs) { // parse identifier/_ std::string name; @@ -5766,7 +5808,8 @@ Parser::parse_named_function_param (std::vector::parse_method () lexer.skip_token (); // parse function parameters - std::vector function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); + std::vector function_params + = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -7294,12 +7338,12 @@ Parser::parse_literal_expr ( // use true and false keywords rather than "bool literal" Rust terminology case TRUE_LITERAL: type = AST::Literal::BOOL; - literal_value = std::string ("true"); + literal_value = "true"; lexer.skip_token (); break; case FALSE_LITERAL: type = AST::Literal::BOOL; - literal_value = std::string ("false"); + literal_value = "false"; lexer.skip_token (); break; default: @@ -8431,7 +8475,7 @@ Parser::parse_array_expr ( return nullptr; } - skip_token (RIGHT_SQUARE); + skip_token (RIGHT_SQUARE); std::unique_ptr copied_array_elems ( new AST::ArrayElemsCopied (std::move (initial_expr), @@ -8449,7 +8493,7 @@ Parser::parse_array_expr ( exprs.push_back (std::move (initial_expr)); exprs.shrink_to_fit (); - skip_token (RIGHT_SQUARE); + skip_token (RIGHT_SQUARE); std::unique_ptr array_elems ( new AST::ArrayElemsValues (std::move (exprs))); @@ -8543,7 +8587,8 @@ Parser::parse_closure_param () } } - return AST::ClosureParam (std::move (pattern), std::move (type), std::move (outer_attrs)); + return AST::ClosureParam (std::move (pattern), std::move (type), + std::move (outer_attrs)); } // Parses a grouped or tuple expression (disambiguates). @@ -9209,7 +9254,8 @@ Parser::parse_for_prefixed_type () // Parses a maybe named param used in bare function types. template AST::MaybeNamedParam -Parser::parse_maybe_named_param (std::vector outer_attrs) +Parser::parse_maybe_named_param ( + std::vector outer_attrs) { /* Basically guess that param is named if first token is identifier or * underscore and second token is semicolon. This should probably have no @@ -9262,10 +9308,10 @@ Parser::parse_bare_function_type ( AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); if (!skip_token (FN_TOK)) - return nullptr; + return nullptr; if (!skip_token (LEFT_PAREN)) - return nullptr; + return nullptr; // parse function params, if they exist std::vector params; @@ -9273,47 +9319,51 @@ Parser::parse_bare_function_type ( std::vector variadic_attrs; const_TokenPtr t = lexer.peek_token (); - while (t->get_id () != RIGHT_PAREN) - { - std::vector temp_attrs = parse_outer_attributes (); - - if (lexer.peek_token ()->get_id () == ELLIPSIS) + while (t->get_id () != RIGHT_PAREN) { - lexer.skip_token (); - is_variadic = true; - variadic_attrs = std::move (temp_attrs); + std::vector temp_attrs = parse_outer_attributes (); - t = lexer.peek_token (); + if (lexer.peek_token ()->get_id () == ELLIPSIS) + { + lexer.skip_token (); + is_variadic = true; + variadic_attrs = std::move (temp_attrs); - if (t->get_id() != RIGHT_PAREN) - { - rust_error_at (t->get_locus (), - "expected right parentheses after variadic in maybe named function " - "parameters, found %qs", - t->get_token_description ()); - return nullptr; - } + t = lexer.peek_token (); - break; - } + if (t->get_id () != RIGHT_PAREN) + { + rust_error_at (t->get_locus (), + "expected right parentheses after variadic in " + "maybe named function " + "parameters, found %qs", + t->get_token_description ()); + return nullptr; + } - AST::MaybeNamedParam param = parse_maybe_named_param (std::move (temp_attrs)); - if (param.is_error ()) - { - rust_error_at (lexer.peek_token ()->get_locus (), "failed to parse maybe named param in bare function type"); - return nullptr; - } - params.push_back (std::move (param)); + break; + } - if (lexer.peek_token ()->get_id () != COMMA) - break; + AST::MaybeNamedParam param + = parse_maybe_named_param (std::move (temp_attrs)); + if (param.is_error ()) + { + rust_error_at ( + lexer.peek_token ()->get_locus (), + "failed to parse maybe named param in bare function type"); + return nullptr; + } + params.push_back (std::move (param)); - lexer.skip_token (); - t = lexer.peek_token (); - } + if (lexer.peek_token ()->get_id () != COMMA) + break; + + lexer.skip_token (); + t = lexer.peek_token (); + } if (!skip_token (RIGHT_PAREN)) - return nullptr; + return nullptr; // bare function return type, if exists std::unique_ptr return_type = nullptr; @@ -9332,9 +9382,11 @@ Parser::parse_bare_function_type ( } } - return std::unique_ptr (new AST::BareFunctionType ( - std::move (for_lifetimes), std::move (qualifiers), std::move (params), - is_variadic, std::move (variadic_attrs), std::move (return_type), best_try_locus)); + return std::unique_ptr ( + new AST::BareFunctionType (std::move (for_lifetimes), + std::move (qualifiers), std::move (params), + is_variadic, std::move (variadic_attrs), + std::move (return_type), best_try_locus)); } // Parses a reference type (mutable or immutable, with given lifetime). @@ -10149,13 +10201,13 @@ Parser::parse_pattern () // tuple struct lexer.skip_token (); - // check if empty tuple - if (lexer.peek_token ()->get_id () == RIGHT_PAREN) - { - lexer.skip_token (); - return std::unique_ptr ( - new AST::TupleStructPattern (std::move (path), nullptr)); - } + // check if empty tuple + if (lexer.peek_token ()->get_id () == RIGHT_PAREN) + { + lexer.skip_token (); + return std::unique_ptr ( + new AST::TupleStructPattern (std::move (path), nullptr)); + } // parse items std::unique_ptr items @@ -10581,13 +10633,13 @@ Parser::parse_ident_leading_pattern () // DEBUG fprintf (stderr, "parsing tuple struct pattern\n"); - // check if empty tuple - if (lexer.peek_token ()->get_id () == RIGHT_PAREN) - { - lexer.skip_token (); - return std::unique_ptr ( - new AST::TupleStructPattern (std::move (path), nullptr)); - } + // check if empty tuple + if (lexer.peek_token ()->get_id () == RIGHT_PAREN) + { + lexer.skip_token (); + return std::unique_ptr ( + new AST::TupleStructPattern (std::move (path), nullptr)); + } // parse items std::unique_ptr items @@ -10841,26 +10893,27 @@ Parser::parse_struct_pattern_elems () std::vector outer_attrs = parse_outer_attributes (); // parse etc (must be last in struct pattern, so breaks) - if (lexer.peek_token ()->get_id () == DOT_DOT) - { - lexer.skip_token (); - etc_attrs = std::move (outer_attrs); - has_etc = true; - break; - } + if (lexer.peek_token ()->get_id () == DOT_DOT) + { + lexer.skip_token (); + etc_attrs = std::move (outer_attrs); + has_etc = true; + break; + } std::unique_ptr field = parse_struct_pattern_field_partial (std::move (outer_attrs)); if (field == nullptr) { - rust_error_at (lexer.peek_token ()->get_locus (), "failed to parse struct pattern field"); - // skip after somewhere? - return AST::StructPatternElements::create_empty (); + rust_error_at (lexer.peek_token ()->get_locus (), + "failed to parse struct pattern field"); + // skip after somewhere? + return AST::StructPatternElements::create_empty (); } fields.push_back (std::move (field)); if (lexer.peek_token ()->get_id () != COMMA) - break; + break; // skip comma lexer.skip_token (); @@ -10868,7 +10921,8 @@ Parser::parse_struct_pattern_elems () } if (has_etc) - return AST::StructPatternElements (std::move (fields), std::move (etc_attrs)); + return AST::StructPatternElements (std::move (fields), + std::move (etc_attrs)); else return AST::StructPatternElements (std::move (fields)); } @@ -10889,7 +10943,8 @@ Parser::parse_struct_pattern_field () * identifier), with outer attributes passed in. */ template std::unique_ptr -Parser::parse_struct_pattern_field_partial (std::vector outer_attrs) +Parser::parse_struct_pattern_field_partial ( + std::vector outer_attrs) { // branch based on next token const_TokenPtr t = lexer.peek_token (); @@ -11509,7 +11564,8 @@ Parser::parse_struct_expr_field () return std::unique_ptr ( new AST::StructExprFieldIdentifierValue (std::move (ident), - std::move (expr), t->get_locus ())); + std::move (expr), + t->get_locus ())); } else { @@ -11518,7 +11574,8 @@ Parser::parse_struct_expr_field () lexer.skip_token (); return std::unique_ptr ( - new AST::StructExprFieldIdentifier (std::move (ident), t->get_locus ())); + new AST::StructExprFieldIdentifier (std::move (ident), + t->get_locus ())); } case INT_LITERAL: { // parse tuple index field @@ -11542,7 +11599,8 @@ Parser::parse_struct_expr_field () } return std::unique_ptr ( - new AST::StructExprFieldIndexValue (index, std::move (expr), t->get_locus ())); + new AST::StructExprFieldIndexValue (index, std::move (expr), + t->get_locus ())); } case DOT_DOT: /* this is a struct base and can't be parsed here, so just return nothing @@ -11550,10 +11608,11 @@ Parser::parse_struct_expr_field () return nullptr; default: - rust_error_at (t->get_locus (), - "unrecognised token %qs as first token of struct expr field - " - "expected identifier or int literal", - t->get_token_description ()); + rust_error_at ( + t->get_locus (), + "unrecognised token %qs as first token of struct expr field - " + "expected identifier or int literal", + t->get_token_description ()); return nullptr; } } @@ -13686,7 +13745,8 @@ Parser::parse_index_expr ( { // parse RHS (as tok has already been consumed in parse_expression) /*std::unique_ptr index_expr - = parse_expr (LBP_ARRAY_REF, std::vector (), restrictions);*/ + = parse_expr (LBP_ARRAY_REF, std::vector (), + restrictions);*/ // TODO: conceptually, should treat [] as brackets, so just parse all expr std::unique_ptr index_expr = parse_expr (); if (index_expr == nullptr) @@ -14000,7 +14060,10 @@ Parser::parse_struct_expr_struct_partial ( } /* Parses a struct expr tuple with a path in expression already parsed (but not - * '(' token). */ + * '(' token). + * FIXME: this currently outputs a call expr, as they cannot be disambiguated. + * A better solution would be to just get this to call that function directly. + * */ template std::unique_ptr Parser::parse_struct_expr_tuple_partial ( @@ -14294,7 +14357,7 @@ Parser::parse_tuple_index_expr_float ( { // only works on float literals if (tok->get_id () != FLOAT_LITERAL) - return nullptr; + return nullptr; // DEBUG: fprintf (stderr, "exact string form of float: '%s'\n", -- cgit v1.1 From 52cc571b308d3d0103dd498fd277859e2116791a Mon Sep 17 00:00:00 2001 From: SimplyTheOther Date: Mon, 14 Dec 2020 15:41:48 +0800 Subject: Prevented several warnings about unused parameters --- gcc/rust/ast/rust-expr.h | 2 +- gcc/rust/expand/rust-macro-expand.cc | 62 ++++++++++++++++++------------------ gcc/rust/expand/rust-macro-expand.h | 2 +- 3 files changed, 33 insertions(+), 33 deletions(-) (limited to 'gcc/rust') diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index cfffb38..f86aa54 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1972,7 +1972,7 @@ class EnumExprFieldIdentifier : public EnumExprField Location locus; public: - EnumExprFieldIdentifier (Identifier field_identifier) + EnumExprFieldIdentifier (Identifier field_identifier, Location locus) : field_name (std::move (field_identifier)), locus (locus) {} diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 4f28836..79e74ac 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -246,15 +246,15 @@ public: expand_where_clause (decl.get_where_clause ()); } - void visit (AST::Token &tok) override + void visit (AST::Token &) override { // shouldn't require? } - void visit (AST::DelimTokenTree &delim_tok_tree) override + void visit (AST::DelimTokenTree &) override { // shouldn't require? } - void visit (AST::AttrInputMetaItemContainer &input) override + void visit (AST::AttrInputMetaItemContainer &) override { // shouldn't require? } @@ -268,11 +268,11 @@ public: return; } } - void visit (AST::Lifetime &lifetime) override + void visit (AST::Lifetime &) override { // shouldn't require? } - void visit (AST::LifetimeParam &lifetime_param) override + void visit (AST::LifetimeParam &) override { // supposedly does not require - cfg does nothing } @@ -309,7 +309,7 @@ public: expand_generic_args (segment.get_generic_args ()); } } - void visit (AST::TypePathSegment &segment) override + void visit (AST::TypePathSegment &) override { // shouldn't require } @@ -386,15 +386,15 @@ public: return; } } - void visit (AST::AttrInputLiteral &attr_input) override + void visit (AST::AttrInputLiteral &) override { // shouldn't require? } - void visit (AST::MetaItemLitExpr &meta_item) override + void visit (AST::MetaItemLitExpr &) override { // shouldn't require? } - void visit (AST::MetaItemPathLit &meta_item) override + void visit (AST::MetaItemPathLit &) override { // shouldn't require? } @@ -823,7 +823,7 @@ public: rust_error_at (struct_name.get_locus (), "cannot strip path in this position"); } - void visit (AST::StructExprFieldIdentifier &field) override + void visit (AST::StructExprFieldIdentifier &) override { // as no attrs (at moment, at least), no stripping possible } @@ -992,7 +992,7 @@ public: rust_error_at (struct_name.get_locus (), "cannot strip path in this position"); } - void visit (AST::EnumExprFieldIdentifier &field) override + void visit (AST::EnumExprFieldIdentifier &) override { // as no attrs (at moment, at least), no stripping possible } @@ -1375,7 +1375,7 @@ public: "cannot strip expression in this position - outer " "attributes not allowed"); } - void visit (AST::RangeFullExpr &expr) override + void visit (AST::RangeFullExpr &) override { // outer attributes never allowed before these, so no stripping } @@ -2001,7 +2001,7 @@ public: "cannot strip type in this position"); } } - void visit (AST::LifetimeWhereClauseItem &item) override + void visit (AST::LifetimeWhereClauseItem &) override { // shouldn't require } @@ -2117,15 +2117,15 @@ public: return; } } - void visit (AST::UseTreeGlob &use_tree) override + void visit (AST::UseTreeGlob &) override { // shouldn't require? } - void visit (AST::UseTreeList &use_tree) override + void visit (AST::UseTreeList &) override { // shouldn't require? } - void visit (AST::UseTreeRebind &use_tree) override + void visit (AST::UseTreeRebind &) override { // shouldn't require? } @@ -2760,9 +2760,9 @@ public: } // I don't think it would be possible to strip macros without expansion - void visit (AST::MacroMatchFragment &match) override {} - void visit (AST::MacroMatchRepetition &match) override {} - void visit (AST::MacroMatcher &matcher) override {} + void visit (AST::MacroMatchFragment &) override {} + void visit (AST::MacroMatchRepetition &) override {} + void visit (AST::MacroMatcher &) override {} void visit (AST::MacroRulesDefinition &rules_def) override { // initial strip test based on outer attrs @@ -2789,14 +2789,14 @@ public: // TODO: maybe have stripping behaviour for the cfg! macro here? } - void visit (AST::MetaItemPath &meta_item) override {} - void visit (AST::MetaItemSeq &meta_item) override {} - void visit (AST::MetaWord &meta_item) override {} - void visit (AST::MetaNameValueStr &meta_item) override {} - void visit (AST::MetaListPaths &meta_item) override {} - void visit (AST::MetaListNameValueStr &meta_item) override {} + void visit (AST::MetaItemPath &) override {} + void visit (AST::MetaItemSeq &) override {} + void visit (AST::MetaWord &) override {} + void visit (AST::MetaNameValueStr &) override {} + void visit (AST::MetaListPaths &) override {} + void visit (AST::MetaListNameValueStr &) override {} - void visit (AST::LiteralPattern &pattern) override + void visit (AST::LiteralPattern &) override { // not possible } @@ -2812,11 +2812,11 @@ public: rust_error_at (sub_pattern->get_locus_slow (), "cannot strip pattern in this position"); } - void visit (AST::WildcardPattern &pattern) override + void visit (AST::WildcardPattern &) override { // not possible } - void visit (AST::RangePatternBoundLiteral &bound) override + void visit (AST::RangePatternBoundLiteral &) override { // not possible } @@ -3042,7 +3042,7 @@ public: } } - void visit (AST::EmptyStmt &stmt) override + void visit (AST::EmptyStmt &) override { // assuming no outer attributes, so nothing can happen } @@ -3175,7 +3175,7 @@ public: "cannot strip type in this position"); } } - void visit (AST::NeverType &type) override + void visit (AST::NeverType &) override { // no stripping possible } @@ -3222,7 +3222,7 @@ public: rust_error_at (elem_type->get_locus_slow (), "cannot strip type in this position"); } - void visit (AST::InferredType &type) override + void visit (AST::InferredType &) override { // none possible } diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index c8c7f35..a0c1a076 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -15,7 +15,7 @@ class MacroInvocation; struct ExpansionCfg { // features? - unsigned int recursion_limit; // TODO: determine default recursion limit + unsigned int recursion_limit = 50; // TODO: determine default recursion limit // trace macros? // should test? // more default stuff? -- cgit v1.1