diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 62 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 19 | ||||
-rw-r--r-- | gcc/rust/ast/rust-macro.h | 2 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 31 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 6 |
5 files changed, 86 insertions, 34 deletions
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<Attribute> AttrInputMetaItemContainer::separate_cfg_attrs () const { + rust_assert (!items.empty ()); + + if (items.size () == 1) + return {}; + + std::vector<Attribute> 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> 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<Attribute> 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<Attribute> 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<Attribute> 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<AST::Attribute>& attrs) { - for (auto it = attrs.begin(); it != attrs.end();) { - auto& attr = *it; + void MacroExpander::expand_cfg_attrs(std::vector<AST::Attribute>& 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<AST::Attribute> 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<AST::MacroInvocation> &invoc); + void expand_cfg_attrs(std::vector<AST::Attribute>& 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 |