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
32 : : is_derive (AST::Attribute &attr);
33 : :
34 : : /**
35 : : * Whether or not an attribute is builtin
36 : : */
37 : : bool
38 : : is_builtin (AST::Attribute &attr);
39 : :
40 : : class ExpandVisitor : public AST::DefaultASTVisitor
41 : : {
42 : : public:
43 : 5280 : ExpandVisitor (MacroExpander &expander) : expander (expander) {}
44 : :
45 : : /* Expand all of the macro invocations currently contained in a crate */
46 : : void go (AST::Crate &crate);
47 : :
48 : : using AST::DefaultASTVisitor::visit;
49 : :
50 : : /*
51 : : Maybe expand a macro invocation in lieu of an expression
52 : : expr : Core guidelines R33, this function reseat the pointer.
53 : : */
54 : : void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr);
55 : :
56 : : /*
57 : : Maybe expand a macro invocation in lieu of a type
58 : : type : Core guidelines R33, this function reseat the pointer.
59 : : */
60 : : void maybe_expand_type (std::unique_ptr<AST::Type> &type);
61 : :
62 : : /**
63 : : * Expand all macro invocations in lieu of types within a vector of struct
64 : : * fields
65 : : */
66 : : void expand_struct_fields (std::vector<AST::StructField> &fields);
67 : :
68 : : /**
69 : : * Expand all macro invocations in lieu of types within a vector of tuple
70 : : * fields
71 : : */
72 : : void expand_tuple_fields (std::vector<AST::TupleField> &fields);
73 : :
74 : : /**
75 : : * Expand all macro invocations in lieu of types within a list of function
76 : : * parameters
77 : : */
78 : : void
79 : : expand_function_params (std::vector<std::unique_ptr<AST::Param>> ¶ms);
80 : :
81 : : /**
82 : : * Expand all macro invocations in lieu of types within a list of generic
83 : : * arguments
84 : : */
85 : : void expand_generic_args (AST::GenericArgs &args);
86 : :
87 : : /**
88 : : * Expand a macro invocation in lieu of a qualified path type
89 : : */
90 : : void expand_qualified_path_type (AST::QualifiedPathType &path_type);
91 : :
92 : : // FIXME: Add documentation
93 : : void expand_closure_params (std::vector<AST::ClosureParam> ¶ms);
94 : : void expand_where_clause (AST::WhereClause &where_clause);
95 : :
96 : : /**
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.
102 : : *
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
107 : : */
108 : : template <typename T, typename U>
109 : 7377 : void expand_macro_children (MacroExpander::ContextType ctx, T &values,
110 : : std::function<U (AST::SingleASTNode)> extractor)
111 : : {
112 : 7377 : expander.push_context (ctx);
113 : :
114 : 7377 : expand_macro_children (values, extractor);
115 : :
116 : 7377 : expander.pop_context ();
117 : 7377 : }
118 : :
119 : : /**
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}`
123 : : */
124 : : template <typename T, typename U>
125 : 29605 : void expand_macro_children (T &values,
126 : : std::function<U (AST::SingleASTNode)> extractor)
127 : : {
128 : 77428 : for (auto it = values.begin (); it != values.end ();)
129 : : {
130 : 47823 : auto &value = *it;
131 : :
132 : : // Perform expansion
133 : 47823 : value->accept_vis (*this);
134 : :
135 : 47823 : auto final_fragment = expander.take_expanded_fragment ();
136 : :
137 : : // FIXME: Is that correct? It seems *extremely* dodgy
138 : 47823 : if (final_fragment.should_expand ())
139 : : {
140 : 531 : it = values.erase (it);
141 : 2583 : for (auto &node : final_fragment.get_nodes ())
142 : : {
143 : 2052 : auto new_node = extractor (node);
144 : 2052 : if (new_node != nullptr)
145 : : {
146 : 2039 : it = values.insert (it, std::move (new_node));
147 : 2039 : it++;
148 : : }
149 : : }
150 : : }
151 : : else
152 : : {
153 : 47292 : ++it;
154 : : }
155 : : }
156 : 29605 : }
157 : :
158 : : /**
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.
163 : : *
164 : : * @param values Vector of values to mutate in-place and append into
165 : : */
166 : : void expand_inner_items (std::vector<std::unique_ptr<AST::Item>> &values);
167 : : void expand_inner_stmts (AST::BlockExpr &expr);
168 : :
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
172 : : /**
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.
179 : : */
180 : 29592 : template <typename T> void visit (std::unique_ptr<T> &value)
181 : : {
182 : 29592 : value->accept_vis (*this);
183 : 11748 : }
184 : :
185 : : template <typename T> void visit (std::unique_ptr<AST::Expr> &expr)
186 : : {
187 : : maybe_expand_expr (expr);
188 : : }
189 : :
190 : : template <typename T> void visit (std::unique_ptr<AST::Type> &type)
191 : : {
192 : : maybe_expand_type (type);
193 : : }
194 : :
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;
201 : :
202 : : void visit (AST::MacroInvocation ¯o_invoc) override;
203 : :
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;
209 : :
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;
223 : :
224 : : void visit (AST::CallExpr &expr) override;
225 : : void visit (AST::MethodCallExpr &expr) override;
226 : : void visit (AST::ClosureExprInner &expr) override;
227 : :
228 : : void visit (AST::BlockExpr &expr) override;
229 : :
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;
262 : :
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;
273 : :
274 : : void visit (AST::LetStmt &stmt) override;
275 : : void visit (AST::ExprStmt &stmt) override;
276 : :
277 : : void visit (AST::BareFunctionType &type) override;
278 : : void visit (AST::FunctionParam &type) override;
279 : : void visit (AST::SelfParam &type) override;
280 : :
281 : : template <typename T>
282 : : void expand_inner_attribute (T &item, AST::SimplePath &Path);
283 : :
284 : : template <typename T>
285 : : void visit_inner_using_attrs (T &item, std::vector<AST::Attribute> &attrs);
286 : :
287 : : template <typename T> void visit_inner_attrs (T &item);
288 : :
289 : : private:
290 : : MacroExpander &expander;
291 : : };
292 : :
293 : : } // namespace Rust
294 : :
295 : : #endif // RUST_EXPAND_VISITOR_H
|