aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2022-03-28 10:52:47 +0200
committerArthur Cohen <arthur.cohen@embecosm.com>2022-03-31 09:42:26 +0200
commit6bf428379d138f0efe7e72bff11bffa348eb8932 (patch)
treecb555416a721400eafa49db930bc38bac72c5ead /gcc
parent3413f632ec84dca6489fe1ca47545b5543c2a1d5 (diff)
downloadgcc-6bf428379d138f0efe7e72bff11bffa348eb8932.zip
gcc-6bf428379d138f0efe7e72bff11bffa348eb8932.tar.gz
gcc-6bf428379d138f0efe7e72bff11bffa348eb8932.tar.bz2
macros: Expand macro invocation properly in type contexts
Macro invocations can be present where the language expects types. Thus, we need to add a new type of parsing context, a new transcriber, as well as a new way to extract types from the AST Fragments. This adds a lot of "expansion places" in the attribute visitor, as types can be present in a wide variety of constructs
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.cc219
-rw-r--r--gcc/testsuite/rust/compile/macro40.rs48
-rw-r--r--gcc/testsuite/rust/execute/torture/macros28.rs13
3 files changed, 280 insertions, 0 deletions
diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc
index 8f2a6c7..859ae7e 100644
--- a/gcc/rust/expand/rust-attribute-visitor.cc
+++ b/gcc/rust/expand/rust-attribute-visitor.cc
@@ -35,13 +35,22 @@ AttrVisitor::expand_struct_fields (std::vector<AST::StructField> &fields)
continue;
}
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
// expand sub-types of type, but can't strip type itself
auto &type = field.get_field_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
+ expander.pop_context ();
+
// if nothing else happens, increment
++it;
}
@@ -77,6 +86,8 @@ AttrVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields)
void
AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> &params)
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
for (auto it = params.begin (); it != params.end ();)
{
auto &param = *it;
@@ -98,6 +109,11 @@ AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> &params)
auto &type = param.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
@@ -105,27 +121,40 @@ AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> &params)
// increment
++it;
}
+
+ expander.pop_context ();
}
void
AttrVisitor::expand_generic_args (AST::GenericArgs &args)
{
// lifetime args can't be expanded
+ // FIXME: Can we have macro invocations for lifetimes?
+
+ expander.push_context (MacroExpander::ContextType::TYPE);
// expand type args - strip sub-types only
for (auto &type : args.get_type_args ())
{
type->accept_vis (*this);
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
}
+ expander.pop_context ();
+
+ // FIXME: Can we have macro invocations in generic type bindings?
// expand binding args - strip sub-types only
for (auto &binding : args.get_binding_args ())
{
auto &type = binding.get_type ();
type->accept_vis (*this);
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
@@ -135,8 +164,17 @@ AttrVisitor::expand_generic_args (AST::GenericArgs &args)
void
AttrVisitor::expand_qualified_path_type (AST::QualifiedPathType &path_type)
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &type = path_type.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
+ expander.pop_context ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
@@ -174,11 +212,19 @@ AttrVisitor::AttrVisitor::expand_closure_params (
if (param.has_type_given ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
auto &type = param.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
// increment if found nothing else so far
@@ -191,11 +237,19 @@ AttrVisitor::expand_self_param (AST::SelfParam &self_param)
{
if (self_param.has_type ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
auto &type = self_param.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
/* TODO: maybe check for invariants being violated - e.g. both type and
* lifetime? */
@@ -222,11 +276,20 @@ AttrVisitor::expand_trait_function_decl (AST::TraitFunctionDecl &decl)
if (decl.has_return_type ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &return_type = decl.get_return_type ();
return_type->accept_vis (*this);
+
+ auto r_fragment = expander.take_expanded_fragment (*this);
+ if (r_fragment.should_expand ())
+ return_type = r_fragment.take_type_fragment ();
+
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
if (decl.has_where_clause ())
@@ -251,11 +314,20 @@ AttrVisitor::expand_trait_method_decl (AST::TraitMethodDecl &decl)
if (decl.has_return_type ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &return_type = decl.get_return_type ();
return_type->accept_vis (*this);
+
+ auto r_fragment = expander.take_expanded_fragment (*this);
+ if (r_fragment.should_expand ())
+ return_type = r_fragment.take_type_fragment ();
+
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
if (decl.has_where_clause ())
@@ -368,11 +440,20 @@ AttrVisitor::visit (AST::TypePathSegmentFunction &segment)
if (type_path_function.has_return_type ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &return_type = type_path_function.get_return_type ();
return_type->accept_vis (*this);
+
+ auto r_fragment = expander.take_expanded_fragment (*this);
+ if (r_fragment.should_expand ())
+ return_type = r_fragment.take_type_fragment ();
+
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
}
void
@@ -1176,12 +1257,21 @@ AttrVisitor::visit (AST::ClosureExprInnerTyped &expr)
* allowed by spec */
expand_closure_params (expr.get_params ());
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
// can't strip return type, but can strip sub-types
auto &type = expr.get_return_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
+ expander.pop_context ();
+
// can't strip expression itself, but can strip sub-expressions
auto &definition_block = expr.get_definition_block ();
definition_block->accept_vis (*this);
@@ -1928,11 +2018,19 @@ AttrVisitor::visit (AST::TypeParam &param)
if (param.has_type ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
auto &type = param.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
}
void
@@ -1945,11 +2043,20 @@ AttrVisitor::visit (AST::TypeBoundWhereClauseItem &item)
{
// for lifetimes shouldn't require
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &type = item.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
+ expander.pop_context ();
+
// don't strip directly, only components of bounds
for (auto &bound : item.get_type_param_bounds ())
bound->accept_vis (*this);
@@ -1980,11 +2087,20 @@ AttrVisitor::visit (AST::Method &method)
if (method.has_return_type ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &return_type = method.get_return_type ();
return_type->accept_vis (*this);
+
+ auto r_fragment = expander.take_expanded_fragment (*this);
+ if (r_fragment.should_expand ())
+ return_type = r_fragment.take_type_fragment ();
+
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
if (method.has_where_clause ())
@@ -2093,11 +2209,20 @@ AttrVisitor::visit (AST::Function &function)
if (function.has_return_type ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &return_type = function.get_return_type ();
return_type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ return_type = t_fragment.take_type_fragment ();
+
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
if (function.has_where_clause ())
@@ -2297,12 +2422,21 @@ AttrVisitor::visit (AST::ConstantItem &const_item)
return;
}
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
// strip any sub-types
auto &type = const_item.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
+ expander.pop_context ();
+
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped. */
@@ -2324,12 +2458,21 @@ AttrVisitor::visit (AST::StaticItem &static_item)
return;
}
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
// strip any sub-types
auto &type = static_item.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
+ expander.pop_context ();
+
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped. */
@@ -2403,12 +2546,21 @@ AttrVisitor::visit (AST::TraitItemConst &item)
return;
}
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
// strip any sub-types
auto &type = item.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
+ expander.pop_context ();
+
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped */
@@ -2502,11 +2654,20 @@ AttrVisitor::visit (AST::InherentImpl &impl)
for (auto &param : impl.get_generic_params ())
param->accept_vis (*this);
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &type = impl.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
+ expander.pop_context ();
+
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
@@ -2539,11 +2700,20 @@ AttrVisitor::visit (AST::TraitImpl &impl)
for (auto &param : impl.get_generic_params ())
param->accept_vis (*this);
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &type = impl.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
+ expander.pop_context ();
+
auto &trait_path = impl.get_trait_path ();
visit (trait_path);
if (trait_path.is_marked_for_strip ())
@@ -2571,10 +2741,19 @@ AttrVisitor::visit (AST::ExternalStaticItem &item)
return;
}
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &type = item.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
+
+ expander.pop_context ();
}
void
AttrVisitor::visit (AST::ExternalFunctionItem &item)
@@ -2606,12 +2785,21 @@ AttrVisitor::visit (AST::ExternalFunctionItem &item)
continue;
}
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &type = param.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
+ expander.pop_context ();
+
// increment if nothing else happens
++it;
}
@@ -2624,16 +2812,26 @@ AttrVisitor::visit (AST::ExternalFunctionItem &item)
if (item.has_return_type ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &return_type = item.get_return_type ();
return_type->accept_vis (*this);
+
+ auto r_fragment = expander.take_expanded_fragment (*this);
+ if (r_fragment.should_expand ())
+ return_type = r_fragment.take_type_fragment ();
+
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
if (item.has_where_clause ())
expand_where_clause (item.get_where_clause ());
}
+
void
AttrVisitor::visit (AST::ExternBlock &block)
{
@@ -2991,11 +3189,20 @@ AttrVisitor::visit (AST::LetStmt &stmt)
// similar for type
if (stmt.has_type ())
{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &type = stmt.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
+
+ expander.pop_context ();
}
/* strip any internal sub-expressions - expression itself isn't
@@ -3190,12 +3397,21 @@ AttrVisitor::visit (AST::BareFunctionType &type)
continue;
}
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
auto &type = param.get_type ();
type->accept_vis (*this);
+
+ auto t_fragment = expander.take_expanded_fragment (*this);
+ if (t_fragment.should_expand ())
+ type = t_fragment.take_type_fragment ();
+
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
+ expander.pop_context ();
+
// increment if nothing else happens
++it;
}
@@ -3205,6 +3421,9 @@ AttrVisitor::visit (AST::BareFunctionType &type)
if (type.has_return_type ())
{
+ // FIXME: Can we have type expansion in this position?
+ // In that case, we need to handle AST::TypeNoBounds on top of just
+ // AST::Types
auto &return_type = type.get_return_type ();
return_type->accept_vis (*this);
if (return_type->is_marked_for_strip ())
diff --git a/gcc/testsuite/rust/compile/macro40.rs b/gcc/testsuite/rust/compile/macro40.rs
new file mode 100644
index 0000000..7151f3a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro40.rs
@@ -0,0 +1,48 @@
+// { dg-additional-options "-w" }
+
+macro_rules! t {
+ () => {
+ i32
+ };
+}
+
+macro_rules! s {
+ () => {
+ *const i8
+ };
+}
+
+extern "C" {
+ fn printf(s: s!(), ...);
+}
+
+fn square(arg: t!()) -> t!() {
+ let input: t!() = arg;
+
+ input * input
+}
+
+trait Trait {
+ fn f() -> t!();
+ fn g(arg: t!());
+}
+
+struct Wrapper {
+ inner: t!(),
+}
+
+impl Trait for Wrapper {
+ fn f() -> t!() {
+ 1
+ }
+
+ fn g(arg: t!()) {}
+}
+
+fn id<T>(arg: T) -> T {
+ arg
+}
+
+fn main() {
+ id::<t!()>(15);
+}
diff --git a/gcc/testsuite/rust/execute/torture/macros28.rs b/gcc/testsuite/rust/execute/torture/macros28.rs
new file mode 100644
index 0000000..b011f92
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/macros28.rs
@@ -0,0 +1,13 @@
+macro_rules! t {
+ () => {
+ i32
+ };
+}
+
+fn id<T>(arg: T) -> T {
+ arg
+}
+
+fn main() -> i32 {
+ id::<t!()>(15) - 15
+}