aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-ast-full-test.cc62
-rw-r--r--gcc/rust/ast/rust-ast.h19
-rw-r--r--gcc/rust/ast/rust-macro.h2
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc31
-rw-r--r--gcc/rust/expand/rust-macro-expand.h6
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