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