diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-03-06 20:50:55 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-03-06 20:50:55 +0000 |
commit | e2bccf43ed1bf33d5f454eab39a7a4a1f115b0bd (patch) | |
tree | 6e9e933267fd6c651c59607668e2fa08641b8b9d /gcc/rust | |
parent | d89c8ccf3237e66029125c0fe007297bb86eca74 (diff) | |
parent | 58d1721529e99c7c633615e7491b777a6198ed00 (diff) | |
download | gcc-e2bccf43ed1bf33d5f454eab39a7a4a1f115b0bd.zip gcc-e2bccf43ed1bf33d5f454eab39a7a4a1f115b0bd.tar.gz gcc-e2bccf43ed1bf33d5f454eab39a7a4a1f115b0bd.tar.bz2 |
Merge #985
985: Parse macro!(); as MacroInvocation with semicolon r=CohenArthur a=CohenArthur
When parsing a macro invocation as a statement, the parser would parse
an expression and then try parsing a semicolon. Since no actual
lookahead was done (which is a good thing), we couldn't convert a
`MacroInvocation` to a `MacroInvocationSemi` after the fact.
Since, unlike function calls, macro invocations can act differently
based on whether or not they are followed by a semicolon, we actually
need to differentiate between the two up until expansion.
This commits adds a new virtual method for ExprWithoutBlock when
converting to ExprStmtWithoutBlock so that classes inheriting
ExprWithoutBlock can specify a new behavior. In the case of our
MacroInvocation class, it simply means toggling a boolean: If we're
converting a macro from an expression to a statement, it must mean that
it should contain a semicolon.
Closes #941
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Diffstat (limited to 'gcc/rust')
-rw-r--r-- | gcc/rust/ast/rust-ast-full-decls.h | 1 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 21 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-visitor.h | 1 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 104 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 2 | ||||
-rw-r--r-- | gcc/rust/ast/rust-macro.h | 52 | ||||
-rw-r--r-- | gcc/rust/ast/rust-stmt.h | 6 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 35 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 4 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-base.h | 1 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-implitem.h | 10 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-item.h | 5 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-stmt.h | 5 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 61 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse.h | 13 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-base.h | 1 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-implitem.h | 15 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-item.h | 10 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-stmt.h | 5 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-toplevel.h | 2 |
20 files changed, 154 insertions, 200 deletions
diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 0d033ef1..f3af42e 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -54,7 +54,6 @@ class MacroItem; class TraitItem; class InherentImplItem; class TraitImplItem; -class MacroInvocationSemi; struct Crate; class PathExpr; diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 5244501..826d41a 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -1276,18 +1276,6 @@ TypeAlias::as_string () const } std::string -MacroInvocationSemi::as_string () const -{ - std::string str = "MacroInvocationSemi: "; - - str += append_attributes (outer_attrs, OUTER); - - str += "\n" + invoc_data.as_string (); - - return str; -} - -std::string ExternBlock::as_string () const { std::string str = VisItem::as_string (); @@ -1377,6 +1365,9 @@ MacroInvocation::as_string () const str += "\n " + invoc_data.as_string (); + str += "\n has semicolon: "; + str += has_semicolon () ? "true" : "false"; + return str; } @@ -4922,12 +4913,6 @@ LifetimeParam::accept_vis (ASTVisitor &vis) } void -MacroInvocationSemi::accept_vis (ASTVisitor &vis) -{ - vis.visit (*this); -} - -void PathInExpression::accept_vis (ASTVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index c8d3728..d3383b4 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -52,7 +52,6 @@ public: // virtual void visit(TraitItem& trait_item) = 0; // virtual void visit(InherentImplItem& inherent_impl_item) = 0; // virtual void visit(TraitImplItem& trait_impl_item) = 0; - virtual void visit (MacroInvocationSemi ¯o) = 0; // rust-path.h virtual void visit (PathInExpression &path) = 0; diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index dfd0b3e..08ecd18 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -861,7 +861,9 @@ public: add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const {} - bool is_item () const override final { return true; } + // FIXME: ARTHUR: Is it okay to have removed that final? Is it *required* + // behavior that we have items that can also be expressions? + bool is_item () const override { return true; } protected: // Clone function implementation as pure virtual method @@ -957,6 +959,8 @@ public: { return clone_expr_without_block_impl (); } + + virtual ExprWithoutBlock *to_stmt () const { return clone_expr_impl (); } }; /* HACK: IdentifierExpr, delete when figure out identifier vs expr problem in @@ -1630,104 +1634,6 @@ public: std::vector<SingleASTNode> &get_nodes () { return nodes; } }; -/* 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 ExternalItem -{ - std::vector<Attribute> outer_attrs; - MacroInvocData invoc_data; - Location locus; - NodeId node_id; - - // this is the expanded macro - ASTFragment fragment; - -public: - std::string as_string () const override; - - MacroInvocationSemi (MacroInvocData invoc_data, - std::vector<Attribute> outer_attrs, Location locus) - : outer_attrs (std::move (outer_attrs)), - invoc_data (std::move (invoc_data)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()), - fragment (ASTFragment::create_empty ()) - {} - - void accept_vis (ASTVisitor &vis) override; - - // Clones this macro invocation semi. - std::unique_ptr<MacroInvocationSemi> clone_macro_invocation_semi () const - { - return std::unique_ptr<MacroInvocationSemi> ( - clone_macro_invocation_semi_impl ()); - } - - void mark_for_strip () override { invoc_data.mark_for_strip (); } - bool is_marked_for_strip () const override - { - return invoc_data.is_marked_for_strip (); - } - - // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } - std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - - Location get_locus () const override final { return locus; } - - MacroInvocData &get_invoc_data () { return invoc_data; } - - ASTFragment &get_fragment () { return fragment; } - - void set_fragment (ASTFragment &&f) { fragment = std::move (f); } - - NodeId get_macro_node_id () const { return node_id; } - -protected: - MacroInvocationSemi *clone_macro_invocation_semi_impl () const - { - return new MacroInvocationSemi (*this); - } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - MacroInvocationSemi *clone_item_impl () const final override - { - return clone_macro_invocation_semi_impl (); - } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - MacroInvocationSemi *clone_inherent_impl_item_impl () const final override - { - return clone_macro_invocation_semi_impl (); - } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - MacroInvocationSemi *clone_trait_impl_item_impl () const final 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 final override - { - 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 final override - { - return clone_macro_invocation_semi_impl (); - } -}; - // A crate AST object - holds all the data for a single compilation unit struct Crate { diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 94e5cbd..567da0c 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -28,7 +28,6 @@ namespace AST { // forward decls class BlockExpr; class TypePath; -class MacroInvocationSemi; // TODO: inline? /*struct AbiName { @@ -4306,7 +4305,6 @@ protected: // Replaced with forward decls - defined in "rust-macro.h" class MacroItem; -class MacroInvocationSemi; class MacroRulesDefinition; } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 9f8f19c..2b39624 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -27,7 +27,6 @@ namespace AST { // Decls as definitions moved to rust-ast.h class MacroItem; -class MacroInvocationSemi; enum MacroFragSpec { @@ -454,6 +453,10 @@ protected: * compile time */ class MacroInvocation : public TypeNoBounds, public Pattern, + public MacroItem, + public TraitItem, + public TraitImplItem, + public InherentImplItem, public ExprWithoutBlock { std::vector<Attribute> outer_attrs; @@ -463,14 +466,22 @@ class MacroInvocation : public TypeNoBounds, // this is the expanded macro ASTFragment fragment; + // Important for when we actually expand the macro + bool is_semi_coloned; + + NodeId node_id; + public: std::string as_string () const override; MacroInvocation (MacroInvocData invoc_data, - std::vector<Attribute> outer_attrs, Location locus) + std::vector<Attribute> outer_attrs, Location locus, + bool is_semi_coloned = false) : outer_attrs (std::move (outer_attrs)), invoc_data (std::move (invoc_data)), locus (locus), - fragment (ASTFragment::create_empty ()) + fragment (ASTFragment::create_empty ()), + is_semi_coloned (is_semi_coloned), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} Location get_locus () const override final { return locus; } @@ -497,12 +508,16 @@ public: return ExprWithoutBlock::get_node_id (); } + NodeId get_macro_node_id () const { return node_id; } + MacroInvocData &get_invoc_data () { return invoc_data; } ASTFragment &get_fragment () { return fragment; } void set_fragment (ASTFragment &&f) { fragment = std::move (f); } + bool has_semicolon () const { return is_semi_coloned; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -529,6 +544,37 @@ protected: { return new MacroInvocation (*this); } + + Item *clone_item_impl () const override + { + return clone_macro_invocation_impl (); + } + + bool is_item () const override { return !has_semicolon (); } + + TraitItem *clone_trait_item_impl () const override + { + return clone_macro_invocation_impl (); + }; + + TraitImplItem *clone_trait_impl_item_impl () const override + { + return clone_macro_invocation_impl (); + }; + + InherentImplItem *clone_inherent_impl_item_impl () const override + { + return clone_macro_invocation_impl (); + } + + ExprWithoutBlock *to_stmt () const override + + { + auto new_impl = clone_macro_invocation_impl (); + new_impl->is_semi_coloned = true; + + return new_impl; + } }; // more generic meta item path-only form diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 61bce4a..942da7f 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -211,8 +211,9 @@ public: std::string as_string () const override; ExprStmtWithoutBlock (std::unique_ptr<ExprWithoutBlock> expr, Location locus) - : ExprStmt (locus), expr (std::move (expr)) + : ExprStmt (locus), expr (std::move (expr->to_stmt ())) {} + /*ExprStmtWithoutBlock (std::unique_ptr<Expr> expr, Location locus) : ExprStmt (locus), expr (std::move (expr)) {}*/ @@ -336,9 +337,6 @@ protected: } }; -/* Replaced definition of MacroInvocationSemi with forward decl - defined in - * rust-macro.h */ -class MacroInvocationSemi; } // namespace AST } // namespace Rust diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index a4ed36b..26f584d 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -310,7 +310,8 @@ public: { // supposedly does not require - cfg does nothing } - void visit (AST::MacroInvocationSemi ¯o_invoc) override + + void visit (AST::MacroInvocation ¯o_invoc) override { // initial strip test based on outer attrs expander.expand_cfg_attrs (macro_invoc.get_outer_attrs ()); @@ -326,9 +327,13 @@ public: // TODO: maybe have cfg! macro stripping behaviour here? - expander.expand_invoc_semi (macro_invoc); + if (macro_invoc.has_semicolon ()) + expander.expand_invoc_semi (macro_invoc); + else + expander.expand_invoc (macro_invoc); - // we need to visit the expanded fragments since it may need cfg expansion + // we need to visit the expanded fragments since it may need cfg + // expansion // and it may be recursive for (auto &node : macro_invoc.get_fragment ().get_nodes ()) node.accept_vis (*this); @@ -2534,28 +2539,6 @@ public: expander.mappings->insert_macro_def (&rules_def); } - void visit (AST::MacroInvocation ¯o_invoc) override - { - // FIXME - // we probably need another recurision check here - - // initial strip test based on outer attrs - expander.expand_cfg_attrs (macro_invoc.get_outer_attrs ()); - if (expander.fails_cfg_with_expand (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 - expander.expand_invoc (macro_invoc); - - // we need to visit the expanded fragments since it may need cfg expansion - // and it may be recursive - for (auto &node : macro_invoc.get_fragment ().get_nodes ()) - node.accept_vis (*this); - } - void visit (AST::MetaItemPath &) override {} void visit (AST::MetaItemSeq &) override {} void visit (AST::MetaWord &) override {} @@ -3209,7 +3192,7 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc) } void -MacroExpander::expand_invoc_semi (AST::MacroInvocationSemi &invoc) +MacroExpander::expand_invoc_semi (AST::MacroInvocation &invoc) { if (depth_exceeds_recursion_limit ()) { diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index 9309323..c56ece6 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -146,11 +146,11 @@ struct MacroExpander // Expands all macros in the crate passed in. void expand_crate (); - /* Expands a macro invocation (not macro invocation semi) - possibly make both + /* Expands a macro invocation - possibly make both * have similar duck-typed interface and use templates?*/ // should this be public or private? void expand_invoc (AST::MacroInvocation &invoc); - void expand_invoc_semi (AST::MacroInvocationSemi &invoc); + void expand_invoc_semi (AST::MacroInvocation &invoc); // Expands a single declarative macro. AST::ASTFragment expand_decl_macro (Location locus, diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h index 9eb9300..738ed58 100644 --- a/gcc/rust/hir/rust-ast-lower-base.h +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -56,7 +56,6 @@ public: // virtual void visit(TraitItem& trait_item) {} // virtual void visit(InherentImplItem& inherent_impl_item) {} // virtual void visit(TraitImplItem& trait_impl_item) {} - virtual void visit (AST::MacroInvocationSemi ¯o) {} // rust-path.h virtual void visit (AST::PathInExpression &path) {} diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h index 3d10b70..3b901f6 100644 --- a/gcc/rust/hir/rust-ast-lower-implitem.h +++ b/gcc/rust/hir/rust-ast-lower-implitem.h @@ -52,8 +52,11 @@ public: return resolver.translated; } - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); // FIXME @@ -318,8 +321,11 @@ public: return resolver.translated; } - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); // FIXME diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 55c8e8a..660a30c 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -51,8 +51,11 @@ public: return resolver.translated; } - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); // FIXME diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h index b25246a..484c638 100644 --- a/gcc/rust/hir/rust-ast-lower-stmt.h +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -45,8 +45,11 @@ public: return resolver.translated; } - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); // FIXME diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index af8f625..8559c3b 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1529,7 +1529,7 @@ Parser<ManagedTokenSource>::parse_macro_rules_def (AST::AttrVec outer_attrs) // Parses a semi-coloned (except for full block) macro invocation item. template <typename ManagedTokenSource> -std::unique_ptr<AST::MacroInvocationSemi> +std::unique_ptr<AST::MacroInvocation> Parser<ManagedTokenSource>::parse_macro_invocation_semi ( AST::AttrVec outer_attrs) { @@ -1618,10 +1618,10 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi ( { // as this is the end, allow recovery (probably) - may change - return std::unique_ptr<AST::MacroInvocationSemi> ( - new AST::MacroInvocationSemi (std::move (invoc_data), - std::move (outer_attrs), - macro_locus)); + return std::unique_ptr<AST::MacroInvocation> ( + new AST::MacroInvocation (std::move (invoc_data), + std::move (outer_attrs), macro_locus, + true)); } } @@ -1630,9 +1630,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_semi ( t->get_token_description (), lexer.peek_token ()->get_token_description ()); - return std::unique_ptr<AST::MacroInvocationSemi> ( - new AST::MacroInvocationSemi (std::move (invoc_data), - std::move (outer_attrs), macro_locus)); + return std::unique_ptr<AST::MacroInvocation> ( + new AST::MacroInvocation (std::move (invoc_data), + std::move (outer_attrs), macro_locus, true)); } else { @@ -7200,7 +7200,11 @@ Parser<ManagedTokenSource>::parse_expr_stmt_without_block ( // attempt to parse via parse_expr_without_block - seems to work std::unique_ptr<AST::ExprWithoutBlock> expr = nullptr; Location locus = lexer.peek_token ()->get_locus (); - expr = parse_expr_without_block (std::move (outer_attrs)); + + auto restrictions = ParseRestrictions (); + restrictions.expr_can_be_stmt = true; + + expr = parse_expr_without_block (std::move (outer_attrs), restrictions); if (expr == nullptr) { // expr is required, error @@ -7227,7 +7231,8 @@ Parser<ManagedTokenSource>::parse_expr_stmt_without_block ( * disambiguates). */ template <typename ManagedTokenSource> std::unique_ptr<AST::ExprWithoutBlock> -Parser<ManagedTokenSource>::parse_expr_without_block (AST::AttrVec outer_attrs) +Parser<ManagedTokenSource>::parse_expr_without_block ( + AST::AttrVec outer_attrs, ParseRestrictions restrictions) { /* Notes on types of expr without block: * - literal expr tokens that are literals @@ -7298,7 +7303,8 @@ Parser<ManagedTokenSource>::parse_expr_without_block (AST::AttrVec outer_attrs) /* HACK: piggyback on pratt parsed expr and abuse polymorphism to * essentially downcast */ - std::unique_ptr<AST::Expr> expr = parse_expr (std::move (outer_attrs)); + std::unique_ptr<AST::Expr> expr + = parse_expr (std::move (outer_attrs), restrictions); if (expr == nullptr) { @@ -11825,10 +11831,11 @@ Parser<ManagedTokenSource>::parse_path_based_stmt_or_expr ( { lexer.skip_token (); - std::unique_ptr<AST::MacroInvocationSemi> stmt ( - new AST::MacroInvocationSemi (std::move (invoc_data), - std::move (outer_attrs), - stmt_or_expr_loc)); + std::unique_ptr<AST::MacroInvocation> stmt ( + new AST::MacroInvocation (std::move (invoc_data), + std::move (outer_attrs), + stmt_or_expr_loc), + true); return ExprOrStmt (std::move (stmt)); } @@ -11836,7 +11843,8 @@ Parser<ManagedTokenSource>::parse_path_based_stmt_or_expr ( std::unique_ptr<AST::MacroInvocation> expr ( new AST::MacroInvocation (std::move (invoc_data), std::move (outer_attrs), - stmt_or_expr_loc)); + stmt_or_expr_loc), + false); return ExprOrStmt (std::move (expr)); } else @@ -12145,10 +12153,10 @@ Parser<ManagedTokenSource>::parse_macro_invocation_maybe_semi ( { lexer.skip_token (); - std::unique_ptr<AST::MacroInvocationSemi> stmt ( - new AST::MacroInvocationSemi (std::move (invoc_data), - std::move (outer_attrs), - macro_locus)); + std::unique_ptr<AST::MacroInvocation> stmt ( + new AST::MacroInvocation (std::move (invoc_data), + std::move (outer_attrs), macro_locus), + true); return ExprOrStmt (std::move (stmt)); } @@ -12430,7 +12438,8 @@ Parser<ManagedTokenSource>::null_denotation (const_TokenPtr tok, case EXCLAM: // macro return parse_macro_invocation_partial (std::move (path), - std::move (outer_attrs)); + std::move (outer_attrs), + restrictions); case LEFT_CURLY: { bool not_a_block = lexer.peek_token (1)->get_id () == IDENTIFIER @@ -14331,7 +14340,8 @@ Parser<ManagedTokenSource>::parse_function_call_expr ( template <typename ManagedTokenSource> std::unique_ptr<AST::MacroInvocation> Parser<ManagedTokenSource>::parse_macro_invocation_partial ( - AST::PathInExpression path, AST::AttrVec outer_attrs) + AST::PathInExpression path, AST::AttrVec outer_attrs, + ParseRestrictions restrictions) { // macro invocation if (!skip_token (EXCLAM)) @@ -14356,10 +14366,9 @@ Parser<ManagedTokenSource>::parse_macro_invocation_partial ( Location macro_locus = converted_path.get_locus (); - return std::unique_ptr<AST::MacroInvocation> ( - new AST::MacroInvocation (AST::MacroInvocData (std::move (converted_path), - std::move (tok_tree)), - std::move (outer_attrs), macro_locus)); + return std::unique_ptr<AST::MacroInvocation> (new AST::MacroInvocation ( + AST::MacroInvocData (std::move (converted_path), std::move (tok_tree)), + std::move (outer_attrs), macro_locus, restrictions.expr_can_be_stmt)); } /* Parses a struct expr struct with a path in expression already parsed (but not diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 438ab41..b283197 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -80,6 +80,7 @@ struct ParseRestrictions * like struct exprs being parsed from a dereference. */ bool entered_from_unary = false; bool expr_can_be_null = false; + bool expr_can_be_stmt = false; }; // Parser implementation for gccrs. @@ -157,7 +158,7 @@ private: std::unique_ptr<AST::TokenTree> parse_token_tree (); std::unique_ptr<AST::MacroRulesDefinition> parse_macro_rules_def (AST::AttrVec outer_attrs); - std::unique_ptr<AST::MacroInvocationSemi> + std::unique_ptr<AST::MacroInvocation> parse_macro_invocation_semi (AST::AttrVec outer_attrs); std::unique_ptr<AST::MacroInvocation> parse_macro_invocation (AST::AttrVec outer_attrs); @@ -468,9 +469,9 @@ private: parse_index_expr (const_TokenPtr tok, std::unique_ptr<AST::Expr> array_expr, AST::AttrVec outer_attrs, ParseRestrictions restrictions = ParseRestrictions ()); - std::unique_ptr<AST::MacroInvocation> - parse_macro_invocation_partial (AST::PathInExpression path, - AST::AttrVec outer_attrs); + std::unique_ptr<AST::MacroInvocation> parse_macro_invocation_partial ( + AST::PathInExpression path, AST::AttrVec outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); std::unique_ptr<AST::StructExprStruct> parse_struct_expr_struct_partial (AST::PathInExpression path, AST::AttrVec outer_attrs); @@ -490,7 +491,9 @@ private: std::unique_ptr<AST::ExprWithBlock> parse_expr_with_block (AST::AttrVec outer_attrs); std::unique_ptr<AST::ExprWithoutBlock> - parse_expr_without_block (AST::AttrVec outer_attrs = AST::AttrVec ()); + parse_expr_without_block (AST::AttrVec outer_attrs = AST::AttrVec (), + ParseRestrictions restrictions + = ParseRestrictions ()); // When given a pratt_parsed_loc, use it as the location of the // first token parsed in the expression (the parsing of that first // token should be skipped). diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h index 6ee5f3d..eca9694 100644 --- a/gcc/rust/resolve/rust-ast-resolve-base.h +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -38,7 +38,6 @@ public: void visit (AST::IdentifierExpr &) {} void visit (AST::Lifetime &) {} void visit (AST::LifetimeParam &) {} - void visit (AST::MacroInvocationSemi &) {} void visit (AST::PathInExpression &) {} void visit (AST::TypePathSegment &) {} void visit (AST::TypePathSegmentGeneric &) {} diff --git a/gcc/rust/resolve/rust-ast-resolve-implitem.h b/gcc/rust/resolve/rust-ast-resolve-implitem.h index ce7234c..7393393 100644 --- a/gcc/rust/resolve/rust-ast-resolve-implitem.h +++ b/gcc/rust/resolve/rust-ast-resolve-implitem.h @@ -49,8 +49,11 @@ public: item->accept_vis (resolver); } - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); for (auto &node : fragment.get_nodes ()) node.accept_vis (*this); @@ -144,8 +147,11 @@ public: item->accept_vis (resolver); }; - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); for (auto &node : fragment.get_nodes ()) node.accept_vis (*this); @@ -254,8 +260,11 @@ public: item->accept_vis (resolver); }; - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); for (auto &node : fragment.get_nodes ()) node.accept_vis (*this); diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 48f93e5..2cb0006 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -45,8 +45,11 @@ public: item->accept_vis (resolver); }; - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); for (auto &node : fragment.get_nodes ()) node.accept_vis (*this); @@ -234,8 +237,11 @@ public: item->accept_vis (resolver); }; - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); for (auto &node : fragment.get_nodes ()) node.accept_vis (*this); diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 7521739..785f3de 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -44,8 +44,11 @@ public: stmt->accept_vis (resolver); }; - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { + if (!invoc.has_semicolon ()) + return; + AST::ASTFragment &fragment = invoc.get_fragment (); for (auto &node : fragment.get_nodes ()) diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h index 39d6818..1f528fe 100644 --- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -43,7 +43,7 @@ public: item->accept_vis (resolver); }; - void visit (AST::MacroInvocationSemi &invoc) override + void visit (AST::MacroInvocation &invoc) override { AST::ASTFragment &fragment = invoc.get_fragment (); for (auto &node : fragment.get_nodes ()) |