aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-10-21 13:05:18 +0000
committerGitHub <noreply@github.com>2022-10-21 13:05:18 +0000
commit60b21d2f58f46c93fc33f6192682abfed62d8dd9 (patch)
tree2f8fd5e728e601f5fa74d71afe1579a5fd3ba440 /gcc
parentdfb5921b76589c09e7794f5f8010427b93616e9d (diff)
parent89490980726d298311107a452bdebeb43a2ff7e6 (diff)
downloadgcc-60b21d2f58f46c93fc33f6192682abfed62d8dd9.zip
gcc-60b21d2f58f46c93fc33f6192682abfed62d8dd9.tar.gz
gcc-60b21d2f58f46c93fc33f6192682abfed62d8dd9.tar.bz2
Merge #1607
1607: Improve AST Fragment class r=CohenArthur a=CohenArthur This changes the APIs around creating AST fragments and refactors the class into its own header and source file, hopefully making it easier to use. This will also help creating "unexpanded" AST fragments for proper builtin macro expansion with the new fixed-point algorithm introduced by #1606 `@liushuyu` pinging you since you've worked extensively with the macro system. Would love your review! Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/ast/rust-ast-fragment.cc171
-rw-r--r--gcc/rust/ast/rust-ast-fragment.h118
-rw-r--r--gcc/rust/ast/rust-ast.h132
-rw-r--r--gcc/rust/ast/rust-macro.h18
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.h4
-rw-r--r--gcc/rust/expand/rust-macro-builtins.cc72
-rw-r--r--gcc/rust/expand/rust-macro-builtins.h40
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc42
-rw-r--r--gcc/rust/expand/rust-macro-expand.h23
-rw-r--r--gcc/rust/util/rust-hir-map.cc4
11 files changed, 390 insertions, 235 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index d7d6e880..5499e8c 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -69,6 +69,7 @@ GRS_OBJS = \
rust/rust-cfg-parser.o \
rust/rust-parse.o \
rust/rust-ast-full-test.o \
+ rust/rust-ast-fragment.o \
rust/rust-ast-dump.o \
rust/rust-hir-dump.o \
rust/rust-session-manager.o \
diff --git a/gcc/rust/ast/rust-ast-fragment.cc b/gcc/rust/ast/rust-ast-fragment.cc
new file mode 100644
index 0000000..c491609
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-fragment.cc
@@ -0,0 +1,171 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-ast-fragment.h"
+
+namespace Rust {
+namespace AST {
+
+Fragment::Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes)
+ : kind (kind), nodes (std::move (nodes))
+{}
+
+Fragment::Fragment (Fragment const &other) : kind (other.get_kind ())
+{
+ *this = other;
+}
+
+Fragment &
+Fragment::operator= (Fragment const &other)
+{
+ nodes.clear ();
+ nodes.reserve (other.nodes.size ());
+ kind = other.get_kind ();
+ for (auto &n : other.nodes)
+ {
+ nodes.push_back (n);
+ }
+
+ return *this;
+}
+
+Fragment
+Fragment::create_error ()
+{
+ return Fragment (FragmentKind::Error, {});
+}
+
+Fragment
+Fragment::complete (std::vector<AST::SingleASTNode> nodes)
+{
+ return Fragment (FragmentKind::Complete, std::move (nodes));
+}
+
+Fragment
+Fragment::unexpanded ()
+{
+ return Fragment (FragmentKind::Unexpanded, {});
+}
+
+std::vector<SingleASTNode> &
+Fragment::get_nodes ()
+{
+ return nodes;
+}
+
+FragmentKind
+Fragment::get_kind () const
+{
+ return kind;
+}
+
+bool
+Fragment::is_error () const
+{
+ return get_kind () == FragmentKind::Error;
+}
+
+bool
+Fragment::should_expand () const
+{
+ return !is_error ();
+}
+
+bool
+Fragment::is_expression_fragment () const
+{
+ return is_single_fragment_of_kind (SingleASTNode::NodeType::EXPRESSION);
+}
+
+bool
+Fragment::is_type_fragment () const
+{
+ return is_single_fragment_of_kind (SingleASTNode::NodeType::TYPE);
+}
+
+std::unique_ptr<Expr>
+Fragment::take_expression_fragment ()
+{
+ assert_single_fragment (SingleASTNode::NodeType::EXPRESSION);
+ return nodes[0].take_expr ();
+}
+
+std::unique_ptr<Type>
+Fragment::take_type_fragment ()
+{
+ assert_single_fragment (SingleASTNode::NodeType::TYPE);
+ return nodes[0].take_type ();
+}
+
+void
+Fragment::accept_vis (ASTVisitor &vis)
+{
+ for (auto &node : nodes)
+ node.accept_vis (vis);
+}
+
+bool
+Fragment::is_single_fragment () const
+{
+ return nodes.size () == 1;
+}
+
+bool
+Fragment::is_single_fragment_of_kind (SingleASTNode::NodeType expected) const
+{
+ return is_single_fragment () && nodes[0].get_kind () == expected;
+}
+
+void
+Fragment::assert_single_fragment (SingleASTNode::NodeType expected) const
+{
+ static const std::map<SingleASTNode::NodeType, const char *> str_map = {
+ {SingleASTNode::NodeType::IMPL, "impl"},
+ {SingleASTNode::NodeType::ITEM, "item"},
+ {SingleASTNode::NodeType::TYPE, "type"},
+ {SingleASTNode::NodeType::EXPRESSION, "expr"},
+ {SingleASTNode::NodeType::STMT, "stmt"},
+ {SingleASTNode::NodeType::EXTERN, "extern"},
+ {SingleASTNode::NodeType::TRAIT, "trait"},
+ {SingleASTNode::NodeType::TRAIT_IMPL, "trait impl"},
+ };
+
+ auto actual = nodes[0].get_kind ();
+ auto fail = false;
+
+ if (!is_single_fragment ())
+ {
+ rust_error_at (Location (), "fragment is not single");
+ fail = true;
+ }
+
+ if (actual != expected)
+ {
+ rust_error_at (
+ Location (),
+ "invalid fragment operation: expected %qs node, got %qs node",
+ str_map.find (expected)->second,
+ str_map.find (nodes[0].get_kind ())->second);
+ fail = true;
+ }
+
+ rust_assert (!fail);
+}
+
+} // namespace AST
+} // namespace Rust
diff --git a/gcc/rust/ast/rust-ast-fragment.h b/gcc/rust/ast/rust-ast-fragment.h
new file mode 100644
index 0000000..3ef4ba1
--- /dev/null
+++ b/gcc/rust/ast/rust-ast-fragment.h
@@ -0,0 +1,118 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_AST_FRAGMENT_H
+#define RUST_AST_FRAGMENT_H
+
+#include "rust-ast.h"
+#include "rust-system.h"
+
+namespace Rust {
+namespace AST {
+
+enum class FragmentKind
+{
+ /**
+ * If an AST Fragment still contains unexpanded tokens - this should only be
+ * used in the case of builtin macros which need to be expanded eagerly.
+ */
+ Unexpanded,
+ /**
+ * A completely expanded AST Fragment. This signifies that all
+ * `SingleASTNode`s in the `nodes` vector are valid.
+ *
+ * Note that this doesn't imply that the expansion is "done". One of the
+ * expanded nodes could very well be another macro invocation
+ */
+ Complete,
+ /**
+ * An error fragment.
+ */
+ Error,
+};
+
+/**
+ * An AST Fragment. Previously named `ASTFragment`.
+ *
+ * Basically, a "fragment" that can be incorporated into the AST, created as
+ * a result of macro expansion. Really annoying to work with due to the fact
+ * that macros can really expand to anything. As such, horrible representation
+ * at the moment.
+ */
+class Fragment
+{
+public:
+ Fragment (Fragment const &other);
+ Fragment &operator= (Fragment const &other);
+
+ /**
+ * Create an error fragment
+ */
+ static Fragment create_error ();
+
+ /**
+ * Create a complete AST fragment
+ */
+ static Fragment complete (std::vector<AST::SingleASTNode> nodes);
+
+ /**
+ * Create a fragment which contains unexpanded nodes
+ */
+ static Fragment unexpanded ();
+
+ FragmentKind get_kind () const;
+ std::vector<SingleASTNode> &get_nodes ();
+
+ bool is_error () const;
+ bool should_expand () const;
+
+ bool is_expression_fragment () const;
+ bool is_type_fragment () const;
+
+ std::unique_ptr<Expr> take_expression_fragment ();
+ std::unique_ptr<Type> take_type_fragment ();
+
+ void accept_vis (ASTVisitor &vis);
+
+private:
+ Fragment (FragmentKind kind, std::vector<SingleASTNode> nodes);
+
+ FragmentKind kind;
+
+ /**
+ * Basic idea: essentially, a vector of tagged unions of different AST node
+ * types. Now, this could actually be stored without a tagged union if the
+ * different AST node types had a unified parent, but that would create
+ * issues with the diamond problem or significant performance penalties. So
+ * a tagged union had to be used instead. A vector is used to represent the
+ * ability for a macro to expand to two statements, for instance.
+ */
+ std::vector<SingleASTNode> nodes;
+
+ /**
+ * We need to make a special case for Expression and Type fragments as only
+ * one Node will be extracted from the `nodes` vector
+ */
+ bool is_single_fragment () const;
+ bool is_single_fragment_of_kind (SingleASTNode::NodeType expected) const;
+ void assert_single_fragment (SingleASTNode::NodeType expected) const;
+};
+} // namespace AST
+} // namespace Rust
+
+#endif // !RUST_AST_FRAGMENT_H
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 492faea..e0e10dc 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1858,138 +1858,6 @@ public:
}
};
-/* Basically, a "fragment" that can be incorporated into the AST, created as
- * a result of macro expansion. Really annoying to work with due to the fact
- * that macros can really expand to anything. As such, horrible representation
- * at the moment. */
-class ASTFragment
-{
-private:
- /* basic idea: essentially, a vector of tagged unions of different AST node
- * types. Now, this could actually be stored without a tagged union if the
- * different AST node types had a unified parent, but that would create
- * issues with the diamond problem or significant performance penalties. So
- * a tagged union had to be used instead. A vector is used to represent the
- * ability for a macro to expand to two statements, for instance. */
-
- std::vector<SingleASTNode> nodes;
- bool fragment_is_error;
-
- /**
- * We need to make a special case for Expression and Type fragments as only
- * one Node will be extracted from the `nodes` vector
- */
-
- bool is_single_fragment () const { return nodes.size () == 1; }
-
- bool is_single_fragment_of_kind (SingleASTNode::NodeType expected) const
- {
- return is_single_fragment () && nodes[0].get_kind () == expected;
- }
-
- void assert_single_fragment (SingleASTNode::NodeType expected) const
- {
- static const std::map<SingleASTNode::NodeType, const char *> str_map = {
- {SingleASTNode::NodeType::IMPL, "impl"},
- {SingleASTNode::NodeType::ITEM, "item"},
- {SingleASTNode::NodeType::TYPE, "type"},
- {SingleASTNode::NodeType::EXPRESSION, "expr"},
- {SingleASTNode::NodeType::STMT, "stmt"},
- {SingleASTNode::NodeType::EXTERN, "extern"},
- {SingleASTNode::NodeType::TRAIT, "trait"},
- {SingleASTNode::NodeType::TRAIT_IMPL, "trait impl"},
- };
-
- auto actual = nodes[0].get_kind ();
- auto fail = false;
-
- if (!is_single_fragment ())
- {
- rust_error_at (Location (), "fragment is not single");
- fail = true;
- }
-
- if (actual != expected)
- {
- rust_error_at (
- Location (),
- "invalid fragment operation: expected %qs node, got %qs node",
- str_map.find (expected)->second,
- str_map.find (nodes[0].get_kind ())->second);
- fail = true;
- }
-
- rust_assert (!fail);
- }
-
-public:
- ASTFragment (std::vector<SingleASTNode> nodes, bool fragment_is_error = false)
- : nodes (std::move (nodes)), fragment_is_error (fragment_is_error)
- {
- if (fragment_is_error)
- rust_assert (nodes.empty ());
- }
-
- ASTFragment (ASTFragment const &other)
- : fragment_is_error (other.fragment_is_error)
- {
- nodes.clear ();
- nodes.reserve (other.nodes.size ());
- for (auto &n : other.nodes)
- {
- nodes.push_back (n);
- }
- }
-
- ASTFragment &operator= (ASTFragment const &other)
- {
- fragment_is_error = other.fragment_is_error;
- nodes.clear ();
- nodes.reserve (other.nodes.size ());
- for (auto &n : other.nodes)
- {
- nodes.push_back (n);
- }
-
- return *this;
- }
-
- static ASTFragment create_error () { return ASTFragment ({}, true); }
-
- std::vector<SingleASTNode> &get_nodes () { return nodes; }
- bool is_error () const { return fragment_is_error; }
-
- bool should_expand () const { return !is_error (); }
-
- bool is_expression_fragment () const
- {
- return is_single_fragment_of_kind (SingleASTNode::NodeType::EXPRESSION);
- }
-
- bool is_type_fragment () const
- {
- return is_single_fragment_of_kind (SingleASTNode::NodeType::TYPE);
- }
-
- std::unique_ptr<Expr> take_expression_fragment ()
- {
- assert_single_fragment (SingleASTNode::NodeType::EXPRESSION);
- return nodes[0].take_expr ();
- }
-
- std::unique_ptr<Type> take_type_fragment ()
- {
- assert_single_fragment (SingleASTNode::NodeType::TYPE);
- return nodes[0].take_type ();
- }
-
- void accept_vis (ASTVisitor &vis)
- {
- for (auto &node : nodes)
- node.accept_vis (vis);
- }
-};
-
// A crate AST object - holds all the data for a single compilation unit
struct Crate
{
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 276f441..a02c216 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -20,6 +20,7 @@
#define RUST_AST_MACRO_H
#include "rust-ast.h"
+#include "rust-ast-fragment.h"
#include "rust-location.h"
#include <string>
@@ -456,8 +457,7 @@ class MacroRulesDefinition : public MacroItem
std::vector<MacroRule> rules; // inlined form
Location locus;
- std::function<ASTFragment (Location, MacroInvocData &)>
- associated_transcriber;
+ std::function<Fragment (Location, MacroInvocData &)> associated_transcriber;
// Since we can't compare std::functions, we need to use an extra boolean
bool is_builtin_rule;
@@ -468,10 +468,10 @@ class MacroRulesDefinition : public MacroItem
* should make use of the actual rules. If the macro is builtin, then another
* associated transcriber should be used
*/
- static ASTFragment dummy_builtin (Location, MacroInvocData &)
+ static Fragment dummy_builtin (Location, MacroInvocData &)
{
gcc_unreachable ();
- return ASTFragment::create_error ();
+ return Fragment::create_error ();
}
/* NOTE: in rustc, macro definitions are considered (and parsed as) a type
@@ -491,9 +491,9 @@ public:
associated_transcriber (dummy_builtin), is_builtin_rule (false)
{}
- MacroRulesDefinition (Identifier builtin_name, DelimType delim_type,
- std::function<ASTFragment (Location, MacroInvocData &)>
- associated_transcriber)
+ MacroRulesDefinition (
+ Identifier builtin_name, DelimType delim_type,
+ std::function<Fragment (Location, MacroInvocData &)> associated_transcriber)
: outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
delim_type (delim_type), rules (std::vector<MacroRule> ()),
locus (Location ()), associated_transcriber (associated_transcriber),
@@ -521,14 +521,14 @@ public:
const std::vector<MacroRule> &get_rules () const { return rules; }
bool is_builtin () const { return is_builtin_rule; }
- const std::function<ASTFragment (Location, MacroInvocData &)> &
+ const std::function<Fragment (Location, MacroInvocData &)> &
get_builtin_transcriber () const
{
rust_assert (is_builtin ());
return associated_transcriber;
}
void set_builtin_transcriber (
- std::function<ASTFragment (Location, MacroInvocData &)> transcriber)
+ std::function<Fragment (Location, MacroInvocData &)> transcriber)
{
associated_transcriber = transcriber;
is_builtin_rule = true;
diff --git a/gcc/rust/expand/rust-attribute-visitor.h b/gcc/rust/expand/rust-attribute-visitor.h
index 0f9d106..c2e25df 100644
--- a/gcc/rust/expand/rust-attribute-visitor.h
+++ b/gcc/rust/expand/rust-attribute-visitor.h
@@ -56,11 +56,11 @@ public:
* @return Either the expanded fragment or an empty errored-out fragment
* indicating an expansion failure.
*/
- AST::ASTFragment expand_macro_fragment_recursive ()
+ AST::Fragment expand_macro_fragment_recursive ()
{
auto fragment = expander.take_expanded_fragment (*this);
unsigned int original_depth = expander.expansion_depth;
- auto final_fragment = AST::ASTFragment ({}, true);
+ auto final_fragment = AST::Fragment::create_error ();
while (fragment.should_expand ())
{
diff --git a/gcc/rust/expand/rust-macro-builtins.cc b/gcc/rust/expand/rust-macro-builtins.cc
index 706b5d4..14322d0 100644
--- a/gcc/rust/expand/rust-macro-builtins.cc
+++ b/gcc/rust/expand/rust-macro-builtins.cc
@@ -66,7 +66,7 @@ macro_end_token (AST::DelimTokenTree &invoc_token_tree,
/* Expand and extract an expression from the macro */
-static inline AST::ASTFragment
+static inline AST::Fragment
try_expand_macro_expression (AST::Expr *expr, MacroExpander *expander)
{
rust_assert (expander);
@@ -264,25 +264,25 @@ load_file_bytes (const char *filename)
}
} // namespace
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::assert (Location invoc_locus, AST::MacroInvocData &invoc)
{
rust_debug ("assert!() called");
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::file (Location invoc_locus, AST::MacroInvocData &invoc)
{
auto current_file
= Session::get_instance ().linemap->location_file (invoc_locus);
auto file_str = AST::SingleASTNode (make_string (invoc_locus, current_file));
- return AST::ASTFragment ({file_str});
+ return AST::Fragment::complete ({file_str});
}
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::column (Location invoc_locus, AST::MacroInvocData &invoc)
{
auto current_column
@@ -292,14 +292,14 @@ MacroBuiltin::column (Location invoc_locus, AST::MacroInvocData &invoc)
new AST::LiteralExpr (std::to_string (current_column), AST::Literal::INT,
PrimitiveCoreType::CORETYPE_U32, {}, invoc_locus)));
- return AST::ASTFragment ({column_no});
+ return AST::Fragment::complete ({column_no});
}
/* Expand builtin macro include_bytes!("filename"), which includes the contents
of the given file as reference to a byte array. Yields an expression of type
&'static [u8; N]. */
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::include_bytes (Location invoc_locus, AST::MacroInvocData &invoc)
{
/* Get target filename from the macro invocation, which is treated as a path
@@ -308,7 +308,7 @@ MacroBuiltin::include_bytes (Location invoc_locus, AST::MacroInvocData &invoc)
= parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus,
invoc.get_expander ());
if (lit_expr == nullptr)
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
std::string target_filename
= source_relative_path (lit_expr->as_string (), invoc_locus);
@@ -335,14 +335,14 @@ MacroBuiltin::include_bytes (Location invoc_locus, AST::MacroInvocData &invoc)
new AST::BorrowExpr (std::move (array), false, false, {}, invoc_locus));
auto node = AST::SingleASTNode (std::move (borrow));
- return AST::ASTFragment ({node});
+ return AST::Fragment::complete ({node});
}
/* Expand builtin macro include_str!("filename"), which includes the contents
of the given file as a string. The file must be UTF-8 encoded. Yields an
expression of type &'static str. */
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::include_str (Location invoc_locus, AST::MacroInvocData &invoc)
{
/* Get target filename from the macro invocation, which is treated as a path
@@ -351,7 +351,7 @@ MacroBuiltin::include_str (Location invoc_locus, AST::MacroInvocData &invoc)
= parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus,
invoc.get_expander ());
if (lit_expr == nullptr)
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
std::string target_filename
= source_relative_path (lit_expr->as_string (), invoc_locus);
@@ -362,30 +362,30 @@ MacroBuiltin::include_str (Location invoc_locus, AST::MacroInvocData &invoc)
std::string str ((const char *) &bytes[0], bytes.size ());
auto node = AST::SingleASTNode (make_string (invoc_locus, str));
- return AST::ASTFragment ({node});
+ return AST::Fragment::complete ({node});
}
/* Expand builtin macro compile_error!("error"), which forces a compile error
during the compile time. */
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::compile_error (Location invoc_locus, AST::MacroInvocData &invoc)
{
auto lit_expr
= parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus,
invoc.get_expander ());
if (lit_expr == nullptr)
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
std::string error_string = lit_expr->as_string ();
rust_error_at (invoc_locus, "%s", error_string.c_str ());
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
/* Expand builtin macro concat!(), which joins all the literal parameters
into a string with no delimiter. */
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::concat (Location invoc_locus, AST::MacroInvocData &invoc)
{
auto invoc_token_tree = invoc.get_delim_tok_tree ();
@@ -427,16 +427,16 @@ MacroBuiltin::concat (Location invoc_locus, AST::MacroInvocData &invoc)
parser.skip_token (last_token_id);
if (has_error)
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
auto node = AST::SingleASTNode (make_string (invoc_locus, str));
- return AST::ASTFragment ({node});
+ return AST::Fragment::complete ({node});
}
/* Expand builtin macro env!(), which inspects an environment variable at
compile time. */
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::env (Location invoc_locus, AST::MacroInvocData &invoc)
{
auto invoc_token_tree = invoc.get_delim_tok_tree ();
@@ -451,11 +451,11 @@ MacroBuiltin::env (Location invoc_locus, AST::MacroInvocData &invoc)
auto expanded_expr = try_expand_many_expr (parser, invoc_locus, last_token_id,
invoc.get_expander (), has_error);
if (has_error)
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
if (expanded_expr.size () < 1 || expanded_expr.size () > 2)
{
rust_error_at (invoc_locus, "env! takes 1 or 2 arguments");
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
if (expanded_expr.size () > 0)
{
@@ -463,7 +463,7 @@ MacroBuiltin::env (Location invoc_locus, AST::MacroInvocData &invoc)
= try_extract_string_literal_from_fragment (invoc_locus,
expanded_expr[0])))
{
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
}
if (expanded_expr.size () > 1)
@@ -472,7 +472,7 @@ MacroBuiltin::env (Location invoc_locus, AST::MacroInvocData &invoc)
= try_extract_string_literal_from_fragment (invoc_locus,
expanded_expr[1])))
{
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
}
@@ -487,14 +487,14 @@ MacroBuiltin::env (Location invoc_locus, AST::MacroInvocData &invoc)
lit_expr->as_string ().c_str ());
else
rust_error_at (invoc_locus, "%s", error_expr->as_string ().c_str ());
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
auto node = AST::SingleASTNode (make_string (invoc_locus, env_value));
- return AST::ASTFragment ({node});
+ return AST::Fragment::complete ({node});
}
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::cfg (Location invoc_locus, AST::MacroInvocData &invoc)
{
// only parse if not already parsed
@@ -519,7 +519,7 @@ MacroBuiltin::cfg (Location invoc_locus, AST::MacroInvocData &invoc)
/* TODO: assuming that cfg! macros can only have one meta item inner, like cfg
* attributes */
if (invoc.get_meta_items ().size () != 1)
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
bool result = invoc.get_meta_items ()[0]->check_cfg_predicate (
Session::get_instance ());
@@ -527,13 +527,13 @@ MacroBuiltin::cfg (Location invoc_locus, AST::MacroInvocData &invoc)
new AST::LiteralExpr (result ? "true" : "false", AST::Literal::BOOL,
PrimitiveCoreType::CORETYPE_BOOL, {}, invoc_locus)));
- return AST::ASTFragment ({literal_exp});
+ return AST::Fragment::complete ({literal_exp});
}
/* Expand builtin macro include!(), which includes a source file at the current
scope compile time. */
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::include (Location invoc_locus, AST::MacroInvocData &invoc)
{
/* Get target filename from the macro invocation, which is treated as a path
@@ -542,7 +542,7 @@ MacroBuiltin::include (Location invoc_locus, AST::MacroInvocData &invoc)
= parse_single_string_literal (invoc.get_delim_tok_tree (), invoc_locus,
invoc.get_expander ());
if (lit_expr == nullptr)
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
std::string filename
= source_relative_path (lit_expr->as_string (), invoc_locus);
@@ -556,7 +556,7 @@ MacroBuiltin::include (Location invoc_locus, AST::MacroInvocData &invoc)
{
rust_error_at (lit_expr->get_locus (),
"cannot open included file %qs: %m", target_filename);
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
rust_debug ("Attempting to parse included file %s", target_filename);
@@ -574,7 +574,7 @@ MacroBuiltin::include (Location invoc_locus, AST::MacroInvocData &invoc)
{
// inform the user that the errors above are from a included file
rust_inform (invoc_locus, "included from here");
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
std::vector<AST::SingleASTNode> nodes{};
@@ -584,10 +584,10 @@ MacroBuiltin::include (Location invoc_locus, AST::MacroInvocData &invoc)
nodes.push_back (node);
}
- return AST::ASTFragment (nodes);
+ return AST::Fragment::complete (nodes);
}
-AST::ASTFragment
+AST::Fragment
MacroBuiltin::line (Location invoc_locus, AST::MacroInvocData &invoc)
{
auto current_line
@@ -597,7 +597,7 @@ MacroBuiltin::line (Location invoc_locus, AST::MacroInvocData &invoc)
new AST::LiteralExpr (std::to_string (current_line), AST::Literal::INT,
PrimitiveCoreType::CORETYPE_U32, {}, invoc_locus)));
- return AST::ASTFragment ({line_no});
+ return AST::Fragment::complete ({line_no});
}
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-builtins.h b/gcc/rust/expand/rust-macro-builtins.h
index 91f3727..79305e4 100644
--- a/gcc/rust/expand/rust-macro-builtins.h
+++ b/gcc/rust/expand/rust-macro-builtins.h
@@ -20,6 +20,7 @@
#define RUST_MACRO_BUILTINS_H
#include "rust-ast.h"
+#include "rust-ast-fragment.h"
#include "rust-location.h"
/**
@@ -61,6 +62,7 @@
/* If assert is defined as a macro this file will not parse, so undefine this
before continuing. */
+// TODO: Rename all functions here `*_handler`
#ifdef assert
#undef assert
#endif
@@ -69,38 +71,34 @@ namespace Rust {
class MacroBuiltin
{
public:
- static AST::ASTFragment assert (Location invoc_locus,
- AST::MacroInvocData &invoc);
-
- static AST::ASTFragment file (Location invoc_locus,
- AST::MacroInvocData &invoc);
+ static AST::Fragment assert (Location invoc_locus,
+ AST::MacroInvocData &invoc);
- static AST::ASTFragment column (Location invoc_locus,
- AST::MacroInvocData &invoc);
+ static AST::Fragment file (Location invoc_locus, AST::MacroInvocData &invoc);
- static AST::ASTFragment include_bytes (Location invoc_locus,
- AST::MacroInvocData &invoc);
+ static AST::Fragment column (Location invoc_locus,
+ AST::MacroInvocData &invoc);
- static AST::ASTFragment include_str (Location invoc_locus,
- AST::MacroInvocData &invoc);
+ static AST::Fragment include_bytes (Location invoc_locus,
+ AST::MacroInvocData &invoc);
- static AST::ASTFragment compile_error (Location invoc_locus,
- AST::MacroInvocData &invoc);
+ static AST::Fragment include_str (Location invoc_locus,
+ AST::MacroInvocData &invoc);
- static AST::ASTFragment concat (Location invoc_locus,
- AST::MacroInvocData &invoc);
+ static AST::Fragment compile_error (Location invoc_locus,
+ AST::MacroInvocData &invoc);
- static AST::ASTFragment env (Location invoc_locus,
+ static AST::Fragment concat (Location invoc_locus,
AST::MacroInvocData &invoc);
- static AST::ASTFragment cfg (Location invoc_locus,
- AST::MacroInvocData &invoc);
+ static AST::Fragment env (Location invoc_locus, AST::MacroInvocData &invoc);
- static AST::ASTFragment include (Location invoc_locus,
- AST::MacroInvocData &invoc);
+ static AST::Fragment cfg (Location invoc_locus, AST::MacroInvocData &invoc);
- static AST::ASTFragment line (Location invoc_locus,
+ static AST::Fragment include (Location invoc_locus,
AST::MacroInvocData &invoc);
+
+ static AST::Fragment line (Location invoc_locus, AST::MacroInvocData &invoc);
};
} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 96b74da..5894434 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -26,7 +26,7 @@
#include "rust-early-name-resolver.h"
namespace Rust {
-AST::ASTFragment
+AST::Fragment
MacroExpander::expand_decl_macro (Location invoc_locus,
AST::MacroInvocData &invoc,
AST::MacroRulesDefinition &rules_def,
@@ -103,7 +103,7 @@ MacroExpander::expand_decl_macro (Location invoc_locus,
RichLocation r (invoc_locus);
r.add_range (rules_def.get_locus ());
rust_error_at (r, "Failed to match any rule within macro");
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
return transcribe_rule (*matched_rule, invoc_token_tree, matched_fragments,
@@ -139,7 +139,7 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon)
// - else is unreachable
// - derive container macro - unreachable
- auto fragment = AST::ASTFragment::create_error ();
+ auto fragment = AST::Fragment::create_error ();
invoc_data.set_expander (this);
// lookup the rules
@@ -707,7 +707,7 @@ MacroExpander::match_repetition (Parser<MacroInvocLexer> &parser,
/**
* Helper function to refactor calling a parsing function 0 or more times
*/
-static AST::ASTFragment
+static AST::Fragment
parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
std::function<AST::SingleASTNode ()> parse_fn)
{
@@ -723,13 +723,13 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
for (auto err : parser.get_errors ())
err.emit_error ();
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
nodes.emplace_back (std::move (node));
}
- return AST::ASTFragment (std::move (nodes));
+ return AST::Fragment::complete (std::move (nodes));
}
/**
@@ -738,7 +738,7 @@ parse_many (Parser<MacroInvocLexer> &parser, TokenId &delimiter,
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
-static AST::ASTFragment
+static AST::Fragment
transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
{
return parse_many (parser, delimiter, [&parser] () {
@@ -753,7 +753,7 @@ transcribe_many_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
-static AST::ASTFragment
+static AST::Fragment
transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
{
return parse_many (parser, delimiter, [&parser] () {
@@ -768,7 +768,7 @@ transcribe_many_ext (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
-static AST::ASTFragment
+static AST::Fragment
transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
TokenId &delimiter)
{
@@ -784,7 +784,7 @@ transcribe_many_trait_items (Parser<MacroInvocLexer> &parser,
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
-static AST::ASTFragment
+static AST::Fragment
transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
{
return parse_many (parser, delimiter, [&parser] () {
@@ -799,7 +799,7 @@ transcribe_many_impl_items (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
* @param parser Parser to extract items from
* @param delimiter Id of the token on which parsing should stop
*/
-static AST::ASTFragment
+static AST::Fragment
transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
TokenId &delimiter)
{
@@ -815,7 +815,7 @@ transcribe_many_trait_impl_items (Parser<MacroInvocLexer> &parser,
* @param parser Parser to extract statements from
* @param delimiter Id of the token on which parsing should stop
*/
-static AST::ASTFragment
+static AST::Fragment
transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
{
auto restrictions = ParseRestrictions ();
@@ -835,12 +835,12 @@ transcribe_many_stmts (Parser<MacroInvocLexer> &parser, TokenId &delimiter)
*
* @param parser Parser to extract statements from
*/
-static AST::ASTFragment
+static AST::Fragment
transcribe_expression (Parser<MacroInvocLexer> &parser)
{
auto expr = parser.parse_expr ();
- return AST::ASTFragment ({std::move (expr)});
+ return AST::Fragment::complete ({std::move (expr)});
}
/**
@@ -848,17 +848,17 @@ transcribe_expression (Parser<MacroInvocLexer> &parser)
*
* @param parser Parser to extract statements from
*/
-static AST::ASTFragment
+static AST::Fragment
transcribe_type (Parser<MacroInvocLexer> &parser)
{
auto type = parser.parse_type (true);
for (auto err : parser.get_errors ())
err.emit_error ();
- return AST::ASTFragment ({std::move (type)});
+ return AST::Fragment::complete ({std::move (type)});
}
-static AST::ASTFragment
+static AST::Fragment
transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
AST::DelimType delimiter, TokenId last_token_id)
{
@@ -868,7 +868,7 @@ transcribe_on_delimiter (Parser<MacroInvocLexer> &parser, bool semicolon,
return transcribe_expression (parser);
} // namespace Rust
-static AST::ASTFragment
+static AST::Fragment
transcribe_context (MacroExpander::ContextType ctx,
Parser<MacroInvocLexer> &parser, bool semicolon,
AST::DelimType delimiter, TokenId last_token_id)
@@ -929,7 +929,7 @@ tokens_to_str (std::vector<std::unique_ptr<AST::Token>> &tokens)
return str;
}
-AST::ASTFragment
+AST::Fragment
MacroExpander::transcribe_rule (
AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree,
std::map<std::string, MatchedFragmentContainer> &matched_fragments,
@@ -951,7 +951,7 @@ MacroExpander::transcribe_rule (
rust_debug ("substituted tokens: %s",
tokens_to_str (substituted_tokens).c_str ());
- // parse it to an ASTFragment
+ // parse it to an Fragment
MacroInvocLexer lex (std::move (substituted_tokens));
Parser<MacroInvocLexer> parser (lex);
@@ -994,7 +994,7 @@ MacroExpander::transcribe_rule (
{
for (auto &err : parser.get_errors ())
rust_error_at (err.locus, "%s", err.message.c_str ());
- return AST::ASTFragment::create_error ();
+ return AST::Fragment::create_error ();
}
// are all the tokens used?
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index c45a3bc..6253a4e 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -230,7 +230,7 @@ struct MacroExpander
MacroExpander (AST::Crate &crate, ExpansionCfg cfg, Session &session)
: cfg (cfg), crate (crate), session (session),
sub_stack (SubstitutionScope ()),
- expanded_fragment (AST::ASTFragment::create_error ()),
+ expanded_fragment (AST::Fragment::create_error ()),
resolver (Resolver::Resolver::get ()),
mappings (Analysis::Mappings::get ())
{}
@@ -246,10 +246,9 @@ struct MacroExpander
void expand_invoc (AST::MacroInvocation &invoc, bool has_semicolon);
// Expands a single declarative macro.
- AST::ASTFragment expand_decl_macro (Location locus,
- AST::MacroInvocData &invoc,
- AST::MacroRulesDefinition &rules_def,
- bool semicolon);
+ AST::Fragment expand_decl_macro (Location locus, AST::MacroInvocData &invoc,
+ AST::MacroRulesDefinition &rules_def,
+ bool semicolon);
void expand_cfg_attrs (AST::AttrVec &attrs);
bool fails_cfg (const AST::AttrVec &attr) const;
@@ -260,7 +259,7 @@ struct MacroExpander
bool try_match_rule (AST::MacroRule &match_rule,
AST::DelimTokenTree &invoc_token_tree);
- AST::ASTFragment transcribe_rule (
+ AST::Fragment transcribe_rule (
AST::MacroRule &match_rule, AST::DelimTokenTree &invoc_token_tree,
std::map<std::string, MatchedFragmentContainer> &matched_fragments,
bool semicolon, ContextType ctx);
@@ -314,16 +313,16 @@ struct MacroExpander
ContextType peek_context () { return context.back (); }
- void set_expanded_fragment (AST::ASTFragment &&fragment)
+ void set_expanded_fragment (AST::Fragment &&fragment)
{
expanded_fragment = std::move (fragment);
}
- AST::ASTFragment take_expanded_fragment (AST::ASTVisitor &vis)
+ AST::Fragment take_expanded_fragment (AST::ASTVisitor &vis)
{
- AST::ASTFragment old_fragment = std::move (expanded_fragment);
+ AST::Fragment old_fragment = std::move (expanded_fragment);
auto accumulator = std::vector<AST::SingleASTNode> ();
- expanded_fragment = AST::ASTFragment::create_error ();
+ expanded_fragment = AST::Fragment::create_error ();
auto early_name_resolver = Resolver::EarlyNameResolver ();
for (auto &node : old_fragment.get_nodes ())
@@ -345,7 +344,7 @@ struct MacroExpander
auto new_nodes = expanded_fragment.get_nodes ();
std::move (new_nodes.begin (), new_nodes.end (),
std::back_inserter (accumulator));
- expanded_fragment = AST::ASTFragment (accumulator);
+ expanded_fragment = AST::Fragment::complete (accumulator);
}
expansion_depth--;
}
@@ -358,7 +357,7 @@ private:
Session &session;
SubstitutionScope sub_stack;
std::vector<ContextType> context;
- AST::ASTFragment expanded_fragment;
+ AST::Fragment expanded_fragment;
public:
Resolver::Resolver *resolver;
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index cb540cd..a3073c0 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -840,8 +840,8 @@ Mappings::iterate_trait_items (
void
Mappings::insert_macro_def (AST::MacroRulesDefinition *macro)
{
- static std::map<std::string, std::function<AST::ASTFragment (
- Location, AST::MacroInvocData &)>>
+ static std::map<
+ std::string, std::function<AST::Fragment (Location, AST::MacroInvocData &)>>
builtin_macros = {
{"assert", MacroBuiltin::assert},
{"file", MacroBuiltin::file},