1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 // This file is part of GCC.
5 // GCC is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 3, or (at your option) any later
10 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // You should have received a copy of the GNU General Public License
16 // along with GCC; see the file COPYING3. If not see
17 // <http://www.gnu.org/licenses/>.
19 #ifndef RUST_EXPAND_VISITOR_H
20 #define RUST_EXPAND_VISITOR_H
22 #include "rust-ast-visitor.h"
23 #include "rust-macro-expand.h"
24 #include "rust-proc-macro.h"
29 * Whether or not an attribute is a derive attribute
32 is_derive (AST::Attribute
&attr
);
35 * Whether or not an attribute is builtin
38 is_builtin (AST::Attribute
&attr
);
40 class ExpandVisitor
: public AST::DefaultASTVisitor
43 ExpandVisitor (MacroExpander
&expander
) : expander (expander
) {}
45 /* Expand all of the macro invocations currently contained in a crate */
46 void go (AST::Crate
&crate
);
48 using AST::DefaultASTVisitor::visit
;
51 Maybe expand a macro invocation in lieu of an expression
52 expr : Core guidelines R33, this function reseat the pointer.
54 void maybe_expand_expr (std::unique_ptr
<AST::Expr
> &expr
);
57 Maybe expand a macro invocation in lieu of a type
58 type : Core guidelines R33, this function reseat the pointer.
60 void maybe_expand_type (std::unique_ptr
<AST::Type
> &type
);
63 * Expand all macro invocations in lieu of types within a vector of struct
66 void expand_struct_fields (std::vector
<AST::StructField
> &fields
);
69 * Expand all macro invocations in lieu of types within a vector of tuple
72 void expand_tuple_fields (std::vector
<AST::TupleField
> &fields
);
75 * Expand all macro invocations in lieu of types within a list of function
79 expand_function_params (std::vector
<std::unique_ptr
<AST::Param
>> ¶ms
);
82 * Expand all macro invocations in lieu of types within a list of generic
85 void expand_generic_args (AST::GenericArgs
&args
);
88 * Expand a macro invocation in lieu of a qualified path type
90 void expand_qualified_path_type (AST::QualifiedPathType
&path_type
);
92 // FIXME: Add documentation
93 void expand_closure_params (std::vector
<AST::ClosureParam
> ¶ms
);
94 void expand_where_clause (AST::WhereClause
&where_clause
);
97 * Expand a set of values, erasing them if they are marked for strip, and
98 * replacing them with expanded macro nodes if necessary.
99 * This function is slightly different from `expand_pointer_allow_strip` as
100 * it can only be called in certain expansion contexts - where macro
101 * invocations are allowed.
103 * @param ctx Context to use for macro expansion
104 * @param values Iterable reference over values to replace or erase
105 * @param extractor Function to call when replacing values with the content
106 * of an expanded AST node
108 template <typename T
, typename U
>
109 void expand_macro_children (MacroExpander::ContextType ctx
, T
&values
,
110 std::function
<U (AST::SingleASTNode
)> extractor
)
112 expander
.push_context (ctx
);
114 expand_macro_children (values
, extractor
);
116 expander
.pop_context ();
120 * Same as `expand_macro_children`, but does not push a context. This is
121 * useful if you're already pushing the context manually anyway for proc macro
122 * expansion, like in `expand_inner_{items, stmts}`
124 template <typename T
, typename U
>
125 void expand_macro_children (T
&values
,
126 std::function
<U (AST::SingleASTNode
)> extractor
)
128 for (auto it
= values
.begin (); it
!= values
.end ();)
133 value
->accept_vis (*this);
135 auto final_fragment
= expander
.take_expanded_fragment ();
137 // FIXME: Is that correct? It seems *extremely* dodgy
138 if (final_fragment
.should_expand ())
140 it
= values
.erase (it
);
141 for (auto &node
: final_fragment
.get_nodes ())
143 auto new_node
= extractor (node
);
144 if (new_node
!= nullptr)
146 it
= values
.insert (it
, std::move (new_node
));
159 * Perform in-place expansion of procedural macros and macro invocations for
160 * an item container or statement container, such as `AST::Crate`,
161 * `AST::Module` or `AST::BlockExpr`. This function will insert the expanded
162 * nodes in place, and replace macro invocations with their expanded nodes.
164 * @param values Vector of values to mutate in-place and append into
166 void expand_inner_items (std::vector
<std::unique_ptr
<AST::Item
>> &values
);
167 void expand_inner_stmts (AST::BlockExpr
&expr
);
169 // TODO: See if possible to make more specialization for Impl items, Block
170 // stmts etc? This could allow us to remove expand_macro_children or at least
171 // its extractor parameter
173 * These functions allow to easily visit `std::unique_ptr`s as well as
174 * _replace_ them when necessary, e.g when expanding macro invocations in a
175 * list of expressions or types. The most generic version of the function will
176 * simply call the visitor again on the pointer, but there are two
177 * specializations for `std::unique_ptr<Expr>` and `std::unique_ptr<Type>` to
178 * enable replacing as well.
180 template <typename T
> void visit (std::unique_ptr
<T
> &value
)
182 value
->accept_vis (*this);
185 template <typename T
> void visit (std::unique_ptr
<AST::Expr
> &expr
)
187 maybe_expand_expr (expr
);
190 template <typename T
> void visit (std::unique_ptr
<AST::Type
> &type
)
192 maybe_expand_type (type
);
195 void visit (AST::Crate
&crate
) override
;
196 void visit (AST::DelimTokenTree
&) override
;
197 void visit (AST::AttrInputMetaItemContainer
&) override
;
198 void visit (AST::IdentifierExpr
&ident_expr
) override
;
199 void visit (AST::LifetimeParam
&) override
;
200 void visit (AST::ConstGenericParam
&) override
;
202 void visit (AST::MacroInvocation
¯o_invoc
) override
;
204 void visit (AST::PathInExpression
&path
) override
;
205 void visit (AST::TypePathSegmentGeneric
&segment
) override
;
206 void visit (AST::TypePathSegmentFunction
&segment
) override
;
207 void visit (AST::QualifiedPathInExpression
&path
) override
;
208 void visit (AST::QualifiedPathInType
&path
) override
;
210 void visit (AST::LiteralExpr
&expr
) override
;
211 void visit (AST::AttrInputLiteral
&) override
;
212 void visit (AST::AttrInputMacro
&) override
;
213 void visit (AST::MetaItemLitExpr
&) override
;
214 void visit (AST::MetaItemPathLit
&) override
;
215 void visit (AST::ErrorPropagationExpr
&expr
) override
;
216 void visit (AST::ArithmeticOrLogicalExpr
&expr
) override
;
217 void visit (AST::ComparisonExpr
&expr
) override
;
218 void visit (AST::LazyBooleanExpr
&expr
) override
;
219 void visit (AST::AssignmentExpr
&expr
) override
;
220 void visit (AST::CompoundAssignmentExpr
&expr
) override
;
221 void visit (AST::GroupedExpr
&expr
) override
;
222 void visit (AST::StructExprStruct
&expr
) override
;
224 void visit (AST::CallExpr
&expr
) override
;
225 void visit (AST::MethodCallExpr
&expr
) override
;
226 void visit (AST::ClosureExprInner
&expr
) override
;
228 void visit (AST::BlockExpr
&expr
) override
;
230 void visit (AST::ClosureExprInnerTyped
&expr
) override
;
231 void visit (AST::ContinueExpr
&expr
) override
;
232 void visit (AST::IfExpr
&expr
) override
;
233 void visit (AST::IfExprConseqElse
&expr
) override
;
234 void visit (AST::IfLetExpr
&expr
) override
;
235 void visit (AST::IfLetExprConseqElse
&expr
) override
;
236 void visit (AST::MatchExpr
&expr
) override
;
237 void visit (AST::TypeParam
¶m
) override
;
238 void visit (AST::LifetimeWhereClauseItem
&) override
;
239 void visit (AST::TypeBoundWhereClauseItem
&item
) override
;
240 void visit (AST::ExternCrate
&crate
) override
;
241 void visit (AST::UseTreeGlob
&) override
;
242 void visit (AST::UseTreeList
&) override
;
243 void visit (AST::UseTreeRebind
&) override
;
244 void visit (AST::UseDeclaration
&use_decl
) override
;
245 void visit (AST::Function
&function
) override
;
246 void visit (AST::StructStruct
&struct_item
) override
;
247 void visit (AST::TupleStruct
&tuple_struct
) override
;
248 void visit (AST::EnumItem
&item
) override
;
249 void visit (AST::EnumItemTuple
&item
) override
;
250 void visit (AST::EnumItemStruct
&item
) override
;
251 void visit (AST::EnumItemDiscriminant
&item
) override
;
252 void visit (AST::Union
&union_item
) override
;
253 void visit (AST::ConstantItem
&const_item
) override
;
254 void visit (AST::StaticItem
&static_item
) override
;
255 void visit (AST::TraitItemConst
&item
) override
;
256 void visit (AST::Trait
&trait
) override
;
257 void visit (AST::InherentImpl
&impl
) override
;
258 void visit (AST::TraitImpl
&impl
) override
;
259 void visit (AST::ExternalTypeItem
&item
) override
;
260 void visit (AST::ExternalStaticItem
&item
) override
;
261 void visit (AST::ExternBlock
&block
) override
;
263 // I don't think it would be possible to strip macros without expansion
264 void visit (AST::MacroMatchRepetition
&) override
;
265 void visit (AST::MacroMatcher
&) override
;
266 void visit (AST::MacroRulesDefinition
&rules_def
) override
;
267 void visit (AST::MetaItemPath
&) override
;
268 void visit (AST::MetaItemSeq
&) override
;
269 void visit (AST::MetaListPaths
&) override
;
270 void visit (AST::MetaListNameValueStr
&) override
;
271 void visit (AST::StructPatternFieldIdent
&field
) override
;
272 void visit (AST::GroupedPattern
&pattern
) override
;
274 void visit (AST::LetStmt
&stmt
) override
;
275 void visit (AST::ExprStmt
&stmt
) override
;
277 void visit (AST::BareFunctionType
&type
) override
;
278 void visit (AST::FunctionParam
&type
) override
;
279 void visit (AST::SelfParam
&type
) override
;
281 template <typename T
>
282 void expand_inner_attribute (T
&item
, AST::SimplePath
&Path
);
284 template <typename T
>
285 void visit_inner_using_attrs (T
&item
, std::vector
<AST::Attribute
> &attrs
);
287 template <typename T
> void visit_inner_attrs (T
&item
);
290 MacroExpander
&expander
;
295 #endif // RUST_EXPAND_VISITOR_H