aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/ast/rust-macro.h45
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc20
-rw-r--r--gcc/rust/util/rust-hir-map.cc11
3 files changed, 70 insertions, 6 deletions
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 995b255..9f8f19c 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -361,9 +361,26 @@ class MacroRulesDefinition : public MacroItem
DelimType delim_type;
// MacroRules rules;
std::vector<MacroRule> rules; // inlined form
-
Location locus;
+ std::function<ASTFragment (Location, MacroInvocData &)>
+ associated_transcriber;
+ // Since we can't compare std::functions, we need to use an extra boolean
+ bool is_builtin_rule;
+
+ /**
+ * Default function to use as an associated transcriber. This function should
+ * never be called, hence the gcc_unreachable().
+ * If this function is used, then the macro is not builtin and the compiler
+ * 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 &)
+ {
+ gcc_unreachable ();
+ return ASTFragment::create_empty ();
+ }
+
/* NOTE: in rustc, macro definitions are considered (and parsed as) a type
* of macro, whereas here they are considered part of the language itself.
* I am not aware of the implications of this decision. The rustc spec does
@@ -377,7 +394,17 @@ public:
std::vector<MacroRule> rules,
std::vector<Attribute> outer_attrs, Location locus)
: outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
- delim_type (delim_type), rules (std::move (rules)), locus (locus)
+ delim_type (delim_type), rules (std::move (rules)), locus (locus),
+ associated_transcriber (dummy_builtin), is_builtin_rule (false)
+ {}
+
+ MacroRulesDefinition (Identifier builtin_name, DelimType delim_type,
+ std::function<ASTFragment (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),
+ is_builtin_rule (true)
{}
void accept_vis (ASTVisitor &vis) override;
@@ -400,6 +427,20 @@ public:
std::vector<MacroRule> &get_rules () { return rules; }
const std::vector<MacroRule> &get_rules () const { return rules; }
+ bool is_builtin () const { return is_builtin_rule; }
+ const std::function<ASTFragment (Location, MacroInvocData &)> &
+ get_builtin_transcriber () const
+ {
+ rust_assert (is_builtin ());
+ return associated_transcriber;
+ }
+ void set_builtin_transcriber (
+ std::function<ASTFragment (Location, MacroInvocData &)> transcriber)
+ {
+ associated_transcriber = transcriber;
+ is_builtin_rule = true;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index b54aa01..7552e82 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -3194,8 +3194,14 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc)
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
rust_assert (ok);
- auto fragment
- = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, false);
+ auto fragment = AST::ASTFragment::create_empty ();
+
+ if (rules_def->is_builtin ())
+ fragment
+ = rules_def->get_builtin_transcriber () (invoc.get_locus (), invoc_data);
+ else
+ fragment
+ = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, false);
// lets attach this fragment to the invocation
invoc.set_fragment (std::move (fragment));
@@ -3229,8 +3235,14 @@ MacroExpander::expand_invoc_semi (AST::MacroInvocationSemi &invoc)
bool ok = mappings->lookup_macro_def (resolved_node, &rules_def);
rust_assert (ok);
- auto fragment
- = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, true);
+ auto fragment = AST::ASTFragment::create_empty ();
+
+ if (rules_def->is_builtin ())
+ fragment
+ = rules_def->get_builtin_transcriber () (invoc.get_locus (), invoc_data);
+ else
+ fragment
+ = expand_decl_macro (invoc.get_locus (), invoc_data, *rules_def, true);
// lets attach this fragment to the invocation
invoc.set_fragment (std::move (fragment));
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 1348e29..1c0e8fc 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -19,6 +19,7 @@
#include "rust-hir-map.h"
#include "rust-ast-full.h"
#include "rust-hir-full.h"
+#include "rust-macro-builtins.h"
namespace Rust {
namespace Analysis {
@@ -741,6 +742,16 @@ Mappings::iterate_trait_items (
void
Mappings::insert_macro_def (AST::MacroRulesDefinition *macro)
{
+ static std::map<std::string, std::function<AST::ASTFragment (
+ Location, AST::MacroInvocData &)>>
+ builtin_macros = {
+ {"assert", MacroBuiltin::assert},
+ };
+
+ auto builtin = builtin_macros.find (macro->get_rule_name ());
+ if (builtin != builtin_macros.end ())
+ macro->set_builtin_transcriber (builtin->second);
+
auto it = macroMappings.find (macro->get_node_id ());
rust_assert (it == macroMappings.end ());