Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
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
8 : : // version.
9 : :
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
13 : : // for more details.
14 : :
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/>.
18 : :
19 : : #ifndef RUST_EXPAND_VISITOR_H
20 : : #define RUST_EXPAND_VISITOR_H
21 : :
22 : : #include "rust-ast-visitor.h"
23 : : #include "rust-macro-expand.h"
24 : : #include "rust-proc-macro.h"
25 : :
26 : : namespace Rust {
27 : :
28 : : /**
29 : : * Whether or not an attribute is a derive attribute
30 : : */
31 : : bool is_derive (AST::Attribute &attr);
32 : :
33 : : /**
34 : : * Whether or not an attribute is builtin
35 : : */
36 : : bool is_builtin (AST::Attribute &attr);
37 : :
38 : : class ExpandVisitor : public AST::DefaultASTVisitor
39 : : {
40 : : public:
41 : 9953 : ExpandVisitor (MacroExpander &expander) : expander (expander) {}
42 : :
43 : : /* Expand all of the macro invocations currently contained in a crate */
44 : : void go (AST::Crate &crate);
45 : :
46 : : using AST::DefaultASTVisitor::visit;
47 : :
48 : : /*
49 : : Maybe expand a macro invocation in lieu of an expression
50 : : expr : Core guidelines R33, this function reseat the pointer.
51 : : */
52 : : void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr);
53 : :
54 : : /*
55 : : Maybe expand a macro invocation in lieu of a type
56 : : type : Core guidelines R33, this function reseat the pointer.
57 : : */
58 : : void maybe_expand_type (std::unique_ptr<AST::Type> &type);
59 : :
60 : : /**
61 : : * Expand all macro invocations in lieu of types within a vector of struct
62 : : * fields
63 : : */
64 : : void expand_struct_fields (std::vector<AST::StructField> &fields);
65 : :
66 : : /**
67 : : * Expand all macro invocations in lieu of types within a vector of tuple
68 : : * fields
69 : : */
70 : : void expand_tuple_fields (std::vector<AST::TupleField> &fields);
71 : :
72 : : /**
73 : : * Expand all macro invocations in lieu of types within a list of function
74 : : * parameters
75 : : */
76 : : void
77 : : expand_function_params (std::vector<std::unique_ptr<AST::Param>> ¶ms);
78 : :
79 : : /**
80 : : * Expand all macro invocations in lieu of types within a list of generic
81 : : * arguments
82 : : */
83 : : void expand_generic_args (AST::GenericArgs &args);
84 : :
85 : : /**
86 : : * Expand a macro invocation in lieu of a qualified path type
87 : : */
88 : : void expand_qualified_path_type (AST::QualifiedPathType &path_type);
89 : :
90 : : // FIXME: Add documentation
91 : : void expand_closure_params (std::vector<AST::ClosureParam> ¶ms);
92 : : void expand_where_clause (AST::WhereClause &where_clause);
93 : :
94 : : /**
95 : : * Expand a set of values, erasing them if they are marked for strip, and
96 : : * replacing them with expanded macro nodes if necessary.
97 : : * This function is slightly different from `expand_pointer_allow_strip` as
98 : : * it can only be called in certain expansion contexts - where macro
99 : : * invocations are allowed.
100 : : *
101 : : * @param ctx Context to use for macro expansion
102 : : * @param values Iterable reference over values to replace or erase
103 : : * @param extractor Function to call when replacing values with the content
104 : : * of an expanded AST node
105 : : */
106 : : template <typename T, typename U>
107 : 25284 : void expand_macro_children (MacroExpander::ContextType ctx, T &values,
108 : : U (AST::SingleASTNode::*extractor) (void))
109 : : {
110 : 25284 : expander.push_context (ctx);
111 : :
112 : 25284 : expand_macro_children (values, extractor);
113 : :
114 : 25284 : expander.pop_context ();
115 : 25284 : }
116 : :
117 : : /**
118 : : * Same as `expand_macro_children`, but does not push a context. This is
119 : : * useful if you're already pushing the context manually anyway for proc macro
120 : : * expansion, like in `expand_inner_{items, stmts}`
121 : : */
122 : : template <typename T, typename U>
123 : 89949 : void expand_macro_children (T &values,
124 : : U (AST::SingleASTNode::*extractor) (void))
125 : : {
126 : 226969 : for (auto it = values.begin (); it != values.end ();)
127 : : {
128 : 137020 : auto &value = *it;
129 : :
130 : : // Perform expansion
131 : 137020 : value->accept_vis (*this);
132 : :
133 : 137020 : auto final_fragment = expander.take_expanded_fragment ();
134 : :
135 : : // FIXME: Is that correct? It seems *extremely* dodgy
136 : 137020 : if (final_fragment.should_expand ())
137 : : {
138 : 783 : it = values.erase (it);
139 : 3953 : for (auto &node : final_fragment.get_nodes ())
140 : : {
141 : 3170 : U new_node = (node.*extractor) ();
142 : 3170 : if (new_node != nullptr)
143 : : {
144 : 3153 : it = values.insert (it, std::move (new_node));
145 : 3153 : it++;
146 : : }
147 : : }
148 : : }
149 : : else
150 : : {
151 : 136237 : ++it;
152 : : }
153 : : }
154 : 89949 : }
155 : :
156 : : /**
157 : : * Perform in-place expansion of procedural macros and macro invocations for
158 : : * an item container or statement container, such as `AST::Crate`,
159 : : * `AST::Module` or `AST::BlockExpr`. This function will insert the expanded
160 : : * nodes in place, and replace macro invocations with their expanded nodes.
161 : : *
162 : : * @param values Vector of values to mutate in-place and append into
163 : : */
164 : : void expand_inner_items (std::vector<std::unique_ptr<AST::Item>> &values);
165 : : void expand_inner_stmts (AST::BlockExpr &expr);
166 : :
167 : : // TODO: See if possible to make more specialization for Impl items, Block
168 : : // stmts etc? This could allow us to remove expand_macro_children or at least
169 : : // its extractor parameter
170 : : /**
171 : : * These functions allow to easily visit `std::unique_ptr`s as well as
172 : : * _replace_ them when necessary, e.g when expanding macro invocations in a
173 : : * list of expressions or types. The most generic version of the function will
174 : : * simply call the visitor again on the pointer, but there are two
175 : : * specializations for `std::unique_ptr<Expr>` and `std::unique_ptr<Type>` to
176 : : * enable replacing as well.
177 : : */
178 : 103873 : template <typename T> void visit (std::unique_ptr<T> &value)
179 : : {
180 : 103873 : value->accept_vis (*this);
181 : 33827 : }
182 : :
183 : : template <typename T> void visit (std::unique_ptr<AST::Expr> &expr)
184 : : {
185 : : maybe_expand_expr (expr);
186 : : }
187 : :
188 : : template <typename T> void visit (std::unique_ptr<AST::Type> &type)
189 : : {
190 : : maybe_expand_type (type);
191 : : }
192 : :
193 : : void visit (AST::Crate &crate) override;
194 : : void visit (AST::DelimTokenTree &) override;
195 : : void visit (AST::AttrInputMetaItemContainer &) override;
196 : : void visit (AST::IdentifierExpr &ident_expr) override;
197 : : void visit (AST::LifetimeParam &) override;
198 : : void visit (AST::ConstGenericParam &) override;
199 : :
200 : : void visit (AST::MacroInvocation ¯o_invoc) override;
201 : :
202 : : void visit (AST::PathInExpression &path) override;
203 : : void visit (AST::TypePathSegmentGeneric &segment) override;
204 : : void visit (AST::TypePathSegmentFunction &segment) override;
205 : : void visit (AST::QualifiedPathInExpression &path) override;
206 : : void visit (AST::QualifiedPathInType &path) override;
207 : :
208 : : void visit (AST::LiteralExpr &expr) override;
209 : : void visit (AST::AttrInputLiteral &) override;
210 : : void visit (AST::AttrInputMacro &) override;
211 : : void visit (AST::MetaItemLitExpr &) override;
212 : : void visit (AST::MetaItemPathExpr &) override;
213 : : void visit (AST::ErrorPropagationExpr &expr) override;
214 : : void visit (AST::ArithmeticOrLogicalExpr &expr) override;
215 : : void visit (AST::ComparisonExpr &expr) override;
216 : : void visit (AST::LazyBooleanExpr &expr) override;
217 : : void visit (AST::AssignmentExpr &expr) override;
218 : : void visit (AST::CompoundAssignmentExpr &expr) override;
219 : : void visit (AST::GroupedExpr &expr) override;
220 : : void visit (AST::StructExprStruct &expr) override;
221 : :
222 : : void visit (AST::CallExpr &expr) override;
223 : : void visit (AST::MethodCallExpr &expr) override;
224 : : void visit (AST::ClosureExprInner &expr) override;
225 : :
226 : : void visit (AST::BlockExpr &expr) override;
227 : :
228 : : void visit (AST::ClosureExprInnerTyped &expr) override;
229 : : void visit (AST::ContinueExpr &expr) override;
230 : : void visit (AST::IfExpr &expr) override;
231 : : void visit (AST::IfExprConseqElse &expr) override;
232 : : void visit (AST::IfLetExpr &expr) override;
233 : : void visit (AST::IfLetExprConseqElse &expr) override;
234 : : void visit (AST::MatchExpr &expr) override;
235 : : void visit (AST::TypeParam ¶m) override;
236 : : void visit (AST::LifetimeWhereClauseItem &) override;
237 : : void visit (AST::TypeBoundWhereClauseItem &item) override;
238 : : void visit (AST::Module &module) override;
239 : : void visit (AST::ExternCrate &crate) override;
240 : : void visit (AST::UseTreeGlob &) override;
241 : : void visit (AST::UseTreeList &) override;
242 : : void visit (AST::UseTreeRebind &) override;
243 : : void visit (AST::UseDeclaration &use_decl) override;
244 : : void visit (AST::Function &function) override;
245 : : void visit (AST::StructStruct &struct_item) override;
246 : : void visit (AST::TupleStruct &tuple_struct) override;
247 : : void visit (AST::EnumItem &item) override;
248 : : void visit (AST::EnumItemTuple &item) override;
249 : : void visit (AST::EnumItemStruct &item) override;
250 : : void visit (AST::EnumItemDiscriminant &item) override;
251 : : void visit (AST::Union &union_item) override;
252 : : void visit (AST::ConstantItem &const_item) override;
253 : : void visit (AST::StaticItem &static_item) override;
254 : : void visit (AST::TraitItemConst &item) override;
255 : : void visit (AST::Trait &trait) override;
256 : : void visit (AST::InherentImpl &impl) override;
257 : : void visit (AST::TraitImpl &impl) override;
258 : : void visit (AST::ExternalTypeItem &item) override;
259 : : void visit (AST::ExternalStaticItem &item) override;
260 : : void visit (AST::ExternBlock &block) override;
261 : :
262 : : // I don't think it would be possible to strip macros without expansion
263 : : void visit (AST::MacroMatchRepetition &) override;
264 : : void visit (AST::MacroMatcher &) override;
265 : : void visit (AST::MacroRulesDefinition &rules_def) override;
266 : : void visit (AST::MetaItemPath &) override;
267 : : void visit (AST::MetaItemSeq &) override;
268 : : void visit (AST::MetaListPaths &) override;
269 : : void visit (AST::MetaListNameValueStr &) override;
270 : : void visit (AST::StructPatternFieldIdent &field) override;
271 : : void visit (AST::GroupedPattern &pattern) override;
272 : :
273 : : void visit (AST::LetStmt &stmt) override;
274 : : void visit (AST::ExprStmt &stmt) override;
275 : :
276 : : void visit (AST::BareFunctionType &type) override;
277 : : void visit (AST::FunctionParam &type) override;
278 : : void visit (AST::SelfParam &type) override;
279 : :
280 : : template <typename T>
281 : : void expand_inner_attribute (T &item, AST::SimplePath &Path);
282 : :
283 : : template <typename T>
284 : : void visit_inner_using_attrs (T &item, std::vector<AST::Attribute> &attrs);
285 : :
286 : : template <typename T> void visit_inner_attrs (T &item);
287 : :
288 : : private:
289 : : MacroExpander &expander;
290 : : };
291 : :
292 : : } // namespace Rust
293 : :
294 : : #endif // RUST_EXPAND_VISITOR_H
|