diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-10-11 22:11:02 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-08 21:10:15 +0800 |
commit | eb644945a4f1bcac234a099f904812dcbbafcc93 (patch) | |
tree | 5343707ddba956043cd3cf3a69ecbde605399625 | |
parent | 423462fb6785896c8031319d50ac38fbca3afb51 (diff) | |
download | gcc-eb644945a4f1bcac234a099f904812dcbbafcc93.zip gcc-eb644945a4f1bcac234a099f904812dcbbafcc93.tar.gz gcc-eb644945a4f1bcac234a099f904812dcbbafcc93.tar.bz2 |
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
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 24 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 259 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 33 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 2 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.cc | 2 |
5 files changed, 184 insertions, 136 deletions
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<AttrInput> clone_attr_input () const - { - return std::unique_ptr<AttrInput> (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<Attribute> 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<std::unique_ptr<TokenTree>> 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<std::unique_ptr<TokenTree>> token_trees - = std::vector<std::unique_ptr<TokenTree>> (), - 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<std::unique_ptr<Token>> to_token_stream () const override; - - std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const - { - return std::unique_ptr<DelimTokenTree> (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<AttrInput> clone_attr_input () const + { + return std::unique_ptr<AttrInput> (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<Attribute> 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<std::unique_ptr<TokenTree>> 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<std::unique_ptr<TokenTree>> token_trees + = std::vector<std::unique_ptr<TokenTree>> (), + 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<std::unique_ptr<Token>> to_token_stream () const override; + + std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const + { + return std::unique_ptr<DelimTokenTree> (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<AST::Attribute>& 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<AST::Attribute>& 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<AST::Attribute> new_attrs = attr.separate_cfg_attrs (); + std::vector<AST::Attribute> 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<AST::MacroInvocation> &invoc); void expand_cfg_attrs(std::vector<AST::Attribute>& attrs); - bool check_cfg(AST::Attribute& attr); + bool fails_cfg(std::vector<AST::Attribute>& 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 |