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 : : #include "rust-ast-visitor.h"
20 : : #include "rust-system.h"
21 : : #include "rust-session-manager.h"
22 : : #include "rust-attributes.h"
23 : : #include "rust-ast.h"
24 : : #include "rust-ast-full.h"
25 : : #include "rust-diagnostics.h"
26 : : #include "rust-unicode.h"
27 : : #include "rust-attribute-values.h"
28 : :
29 : : namespace Rust {
30 : : namespace Analysis {
31 : :
32 : : bool
33 : 89355 : Attributes::is_known (const std::string &attribute_path)
34 : : {
35 : 89355 : const auto &lookup
36 : 89355 : = BuiltinAttributeMappings::get ()->lookup_builtin (attribute_path);
37 : :
38 : 89355 : return !lookup.is_error ();
39 : : }
40 : :
41 : : tl::optional<std::string>
42 : 6519 : Attributes::extract_string_literal (const AST::Attribute &attr)
43 : : {
44 : 6519 : if (!attr.has_attr_input ())
45 : 0 : return tl::nullopt;
46 : :
47 : 6519 : auto &attr_input = attr.get_attr_input ();
48 : :
49 : 6519 : if (attr_input.get_attr_input_type ()
50 : : != AST::AttrInput::AttrInputType::LITERAL)
51 : 0 : return tl::nullopt;
52 : :
53 : 6519 : auto &literal_expr
54 : 6519 : = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal ();
55 : :
56 : 6519 : auto lit_type = literal_expr.get_lit_type ();
57 : :
58 : : // TODO: bring escape sequence handling out of lexing?
59 : 6519 : if (lit_type != AST::Literal::LitType::STRING
60 : 6519 : && lit_type != AST::Literal::LitType::RAW_STRING)
61 : 0 : return tl::nullopt;
62 : :
63 : 6519 : return literal_expr.as_string ();
64 : : }
65 : :
66 : : using Attrs = Values::Attributes;
67 : :
68 : : // https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248
69 : : static const BuiltinAttrDefinition __definitions[]
70 : : = {{Attrs::INLINE, CODE_GENERATION},
71 : : {Attrs::COLD, CODE_GENERATION},
72 : : {Attrs::CFG, EXPANSION},
73 : : {Attrs::CFG_ATTR, EXPANSION},
74 : : {Attrs::DERIVE_ATTR, EXPANSION},
75 : : {Attrs::DEPRECATED, STATIC_ANALYSIS},
76 : : {Attrs::ALLOW, STATIC_ANALYSIS},
77 : : {Attrs::ALLOW_INTERNAL_UNSTABLE, STATIC_ANALYSIS},
78 : : {Attrs::DOC, HIR_LOWERING},
79 : : {Attrs::MUST_USE, STATIC_ANALYSIS},
80 : : {Attrs::LANG, HIR_LOWERING},
81 : : {Attrs::LINK_NAME, CODE_GENERATION},
82 : : {Attrs::LINK_SECTION, CODE_GENERATION},
83 : : {Attrs::NO_MANGLE, CODE_GENERATION},
84 : : {Attrs::REPR, CODE_GENERATION},
85 : : {Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
86 : : {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
87 : : {Attrs::PATH, EXPANSION},
88 : : {Attrs::MACRO_USE, NAME_RESOLUTION},
89 : : {Attrs::MACRO_EXPORT, NAME_RESOLUTION},
90 : : {Attrs::PROC_MACRO, EXPANSION},
91 : : {Attrs::PROC_MACRO_DERIVE, EXPANSION},
92 : : {Attrs::PROC_MACRO_ATTRIBUTE, EXPANSION},
93 : : // FIXME: This is not implemented yet, see
94 : : // https://github.com/Rust-GCC/gccrs/issues/1475
95 : : {Attrs::TARGET_FEATURE, CODE_GENERATION},
96 : : // From now on, these are reserved by the compiler and gated through
97 : : // #![feature(rustc_attrs)]
98 : : {Attrs::RUSTC_DEPRECATED, STATIC_ANALYSIS},
99 : : {Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION},
100 : : {Attrs::STABLE, STATIC_ANALYSIS},
101 : : {Attrs::UNSTABLE, STATIC_ANALYSIS},
102 : : // assuming we keep these for static analysis
103 : : {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
104 : : {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
105 : : {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
106 : : {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS},
107 : : {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
108 : : {Attrs::TRACK_CALLER, CODE_GENERATION},
109 : : {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
110 : : {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
111 : : {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
112 : : {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
113 : : {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
114 : : {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
115 : : // TODO: be careful about calling functions marked with this?
116 : : {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION},
117 : : {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
118 : : {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
119 : : {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
120 : : {Attrs::FUNDAMENTAL, TYPE_CHECK},
121 : : {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
122 : : {Attrs::RUSTFMT, EXTERNAL},
123 : : {Attrs::TEST, CODE_GENERATION}};
124 : :
125 : : static const std::set<std::string> __outer_attributes
126 : : = {Attrs::INLINE, Attrs::DERIVE_ATTR, Attrs::ALLOW_INTERNAL_UNSTABLE,
127 : : Attrs::LANG, Attrs::REPR, Attrs::PATH,
128 : : Attrs::TARGET_FEATURE, Attrs::TEST};
129 : :
130 : : BuiltinAttributeMappings *
131 : 3690848 : BuiltinAttributeMappings::get ()
132 : : {
133 : 3690848 : static BuiltinAttributeMappings *instance = nullptr;
134 : 3690848 : if (instance == nullptr)
135 : 4358 : instance = new BuiltinAttributeMappings ();
136 : :
137 : 3690848 : return instance;
138 : : }
139 : :
140 : : const BuiltinAttrDefinition &
141 : 3311492 : BuiltinAttributeMappings::lookup_builtin (const std::string &attr_name) const
142 : : {
143 : 3311492 : auto it = mappings.find (attr_name);
144 : 3311492 : if (it == mappings.end ())
145 : 1490 : return BuiltinAttrDefinition::error_node ();
146 : :
147 : 3310002 : return it->second;
148 : : }
149 : :
150 : 4358 : BuiltinAttributeMappings::BuiltinAttributeMappings ()
151 : : {
152 : 4358 : size_t ndefinitions = sizeof (__definitions) / sizeof (BuiltinAttrDefinition);
153 : 213542 : for (size_t i = 0; i < ndefinitions; i++)
154 : : {
155 : 209184 : const BuiltinAttrDefinition &def = __definitions[i];
156 : 418368 : mappings.insert ({def.name, def});
157 : : }
158 : 4358 : }
159 : :
160 : 4449 : AttributeChecker::AttributeChecker () {}
161 : :
162 : : void
163 : 4449 : AttributeChecker::go (AST::Crate &crate)
164 : : {
165 : 4449 : visit (crate);
166 : 4449 : }
167 : :
168 : : void
169 : 4449 : AttributeChecker::visit (AST::Crate &crate)
170 : : {
171 : 4449 : check_inner_attributes (crate.get_inner_attrs ());
172 : 4449 : check_attributes (crate.get_inner_attrs ());
173 : :
174 : 22627 : for (auto &item : crate.items)
175 : 18178 : item->accept_vis (*this);
176 : 4449 : }
177 : :
178 : : static bool
179 : 13257 : is_builtin (const AST::Attribute &attribute, BuiltinAttrDefinition &builtin)
180 : : {
181 : 13257 : auto &segments = attribute.get_path ().get_segments ();
182 : :
183 : : // Builtin attributes always have a single segment. This avoids us creating
184 : : // strings all over the place and performing a linear search in the builtins
185 : : // map
186 : 13257 : if (segments.size () != 1)
187 : : return false;
188 : :
189 : 13257 : builtin = BuiltinAttributeMappings::get ()->lookup_builtin (
190 : 13257 : segments.at (0).get_segment_name ());
191 : :
192 : 13257 : return !builtin.is_error ();
193 : : }
194 : :
195 : : /**
196 : : * Check that the string given to #[doc(alias = ...)] or #[doc(alias(...))] is
197 : : * valid.
198 : : *
199 : : * This means no whitespace characters other than spaces and no quoting
200 : : * characters.
201 : : */
202 : : static void
203 : 700 : check_doc_alias (const std::string &alias_input, const location_t locus)
204 : : {
205 : : // FIXME: The locus here is for the whole attribute. Can we get the locus
206 : : // of the alias input instead?
207 : 1872 : for (auto c : alias_input)
208 : 1172 : if ((ISSPACE (c) && c != ' ') || c == '\'' || c == '\"')
209 : : {
210 : 7 : auto to_print = std::string (1, c);
211 : 7 : switch (c)
212 : : {
213 : 7 : case '\n':
214 : 7 : to_print = "\\n";
215 : 7 : break;
216 : 0 : case '\t':
217 : 0 : to_print = "\\t";
218 : 0 : break;
219 : : default:
220 : : break;
221 : : }
222 : 7 : rust_error_at (locus,
223 : : "invalid character used in %<#[doc(alias)]%> input: %qs",
224 : : to_print.c_str ());
225 : 7 : }
226 : :
227 : 700 : if (alias_input.empty ())
228 : : return;
229 : :
230 : 1400 : if (alias_input.front () == ' ' || alias_input.back () == ' ')
231 : 0 : rust_error_at (locus,
232 : : "%<#[doc(alias)]%> input cannot start or end with a space");
233 : : }
234 : :
235 : : static void
236 : 916 : check_doc_attribute (const AST::Attribute &attribute)
237 : : {
238 : 916 : if (!attribute.has_attr_input ())
239 : : {
240 : 1 : rust_error_at (
241 : : attribute.get_locus (),
242 : : "valid forms for the attribute are "
243 : : "%<#[doc(hidden|inline|...)]%> and %<#[doc = \" string \"]%>");
244 : 1 : return;
245 : : }
246 : :
247 : 915 : switch (attribute.get_attr_input ().get_attr_input_type ())
248 : : {
249 : : case AST::AttrInput::LITERAL:
250 : : case AST::AttrInput::MACRO:
251 : : case AST::AttrInput::META_ITEM:
252 : : break;
253 : : // FIXME: Handle them as well
254 : :
255 : 743 : case AST::AttrInput::TOKEN_TREE:
256 : 743 : {
257 : : // FIXME: This doesn't check for #[doc(alias(...))]
258 : 743 : const auto &option = static_cast<const AST::DelimTokenTree &> (
259 : 743 : attribute.get_attr_input ());
260 : 743 : auto *meta_item = option.parse_to_meta_item ();
261 : :
262 : 1497 : for (auto &item : meta_item->get_items ())
263 : : {
264 : 754 : if (item->is_key_value_pair ())
265 : : {
266 : 710 : auto name_value
267 : 710 : = static_cast<AST::MetaNameValueStr *> (item.get ())
268 : 710 : ->get_name_value_pair ();
269 : :
270 : : // FIXME: Check for other stuff than #[doc(alias = ...)]
271 : 710 : if (name_value.first.as_string () == "alias")
272 : 700 : check_doc_alias (name_value.second, attribute.get_locus ());
273 : 710 : }
274 : : }
275 : : break;
276 : : }
277 : : }
278 : : }
279 : :
280 : : static bool
281 : 6762 : is_proc_macro_type (const AST::Attribute &attribute)
282 : : {
283 : 6762 : BuiltinAttrDefinition result;
284 : 6762 : if (!is_builtin (attribute, result))
285 : : return false;
286 : :
287 : 6762 : auto name = result.name;
288 : 6744 : return name == Attrs::PROC_MACRO || name == Attrs::PROC_MACRO_DERIVE
289 : 13506 : || name == Attrs::PROC_MACRO_ATTRIBUTE;
290 : 6762 : }
291 : :
292 : : // Emit an error when one encountered attribute is either #[proc_macro],
293 : : // #[proc_macro_attribute] or #[proc_macro_derive]
294 : : static void
295 : 14368 : check_proc_macro_non_function (const AST::AttrVec &attributes)
296 : : {
297 : 19122 : for (auto &attr : attributes)
298 : : {
299 : 4754 : if (is_proc_macro_type (attr))
300 : 45 : rust_error_at (
301 : : attr.get_locus (),
302 : : "the %<#[%s]%> attribute may only be used on bare functions",
303 : 90 : attr.get_path ().get_segments ()[0].as_string ().c_str ());
304 : : }
305 : 14368 : }
306 : :
307 : : // Emit an error when one attribute is either proc_macro, proc_macro_attribute
308 : : // or proc_macro_derive
309 : : static void
310 : 3530 : check_proc_macro_non_root (AST::AttrVec attributes, location_t loc)
311 : : {
312 : 5538 : for (auto &attr : attributes)
313 : : {
314 : 2008 : if (is_proc_macro_type (attr))
315 : : {
316 : 9 : rust_error_at (
317 : : loc,
318 : : "functions tagged with %<#[%s]%> must currently "
319 : : "reside in the root of the crate",
320 : 18 : attr.get_path ().get_segments ().at (0).as_string ().c_str ());
321 : : }
322 : : }
323 : 3530 : }
324 : :
325 : : void
326 : 904 : AttributeChecker::check_inner_attribute (const AST::Attribute &attribute)
327 : : {
328 : 904 : BuiltinAttrDefinition result;
329 : :
330 : 904 : if (!is_builtin (attribute, result))
331 : 744 : return;
332 : :
333 : 160 : if (__outer_attributes.find (result.name) != __outer_attributes.end ())
334 : 2 : rust_error_at (attribute.get_locus (),
335 : : "attribute cannot be used at crate level");
336 : 904 : }
337 : :
338 : : void
339 : 4449 : AttributeChecker::check_inner_attributes (const AST::AttrVec &attributes)
340 : : {
341 : 5353 : for (auto &attr : attributes)
342 : 904 : check_inner_attribute (attr);
343 : 4449 : }
344 : :
345 : : void
346 : 5284 : AttributeChecker::check_attribute (const AST::Attribute &attribute)
347 : : {
348 : 5284 : if (!attribute.empty_input ())
349 : : {
350 : 5242 : const auto &attr_input = attribute.get_attr_input ();
351 : 5242 : auto type = attr_input.get_attr_input_type ();
352 : 5242 : if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
353 : : {
354 : 2192 : const auto &option = static_cast<const AST::DelimTokenTree &> (
355 : 2192 : attribute.get_attr_input ());
356 : 2192 : std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
357 : 2192 : option.parse_to_meta_item ());
358 : 2192 : AST::DefaultASTVisitor::visit (meta_item);
359 : 2192 : }
360 : : }
361 : :
362 : 5284 : BuiltinAttrDefinition result;
363 : :
364 : : // This checker does not check non-builtin attributes
365 : 5284 : if (!is_builtin (attribute, result))
366 : 744 : return;
367 : :
368 : : // TODO: Add checks here for each builtin attribute
369 : : // TODO: Have an enum of builtins as well, switching on strings is annoying
370 : : // and costly
371 : 4540 : if (result.name == Attrs::DOC)
372 : 916 : check_doc_attribute (attribute);
373 : 5284 : }
374 : :
375 : : void
376 : 11003 : AttributeChecker::check_attributes (const AST::AttrVec &attributes)
377 : : {
378 : 16287 : for (auto &attr : attributes)
379 : 5284 : check_attribute (attr);
380 : 11003 : }
381 : :
382 : : void
383 : 0 : AttributeChecker::visit (AST::Token &)
384 : 0 : {}
385 : :
386 : : void
387 : 0 : AttributeChecker::visit (AST::DelimTokenTree &)
388 : 0 : {}
389 : :
390 : : void
391 : 511 : AttributeChecker::visit (AST::IdentifierExpr &)
392 : 511 : {}
393 : :
394 : : void
395 : 0 : AttributeChecker::visit (AST::Lifetime &)
396 : 0 : {}
397 : :
398 : : void
399 : 33 : AttributeChecker::visit (AST::LifetimeParam &)
400 : 33 : {}
401 : :
402 : : void
403 : 23 : AttributeChecker::visit (AST::ConstGenericParam &)
404 : 23 : {}
405 : :
406 : : // rust-path.h
407 : : void
408 : 38 : AttributeChecker::visit (AST::PathInExpression &)
409 : 38 : {}
410 : :
411 : : void
412 : 0 : AttributeChecker::visit (AST::TypePathSegment &)
413 : 0 : {}
414 : :
415 : : void
416 : 0 : AttributeChecker::visit (AST::TypePathSegmentGeneric &)
417 : 0 : {}
418 : :
419 : : void
420 : 0 : AttributeChecker::visit (AST::TypePathSegmentFunction &)
421 : 0 : {}
422 : :
423 : : void
424 : 4352 : AttributeChecker::visit (AST::TypePath &)
425 : 4352 : {}
426 : :
427 : : void
428 : 0 : AttributeChecker::visit (AST::QualifiedPathInExpression &)
429 : 0 : {}
430 : :
431 : : void
432 : 0 : AttributeChecker::visit (AST::QualifiedPathInType &)
433 : 0 : {}
434 : :
435 : : // rust-expr.h
436 : : void
437 : 1414 : AttributeChecker::visit (AST::LiteralExpr &)
438 : 1414 : {}
439 : :
440 : : void
441 : 0 : AttributeChecker::visit (AST::AttrInputLiteral &)
442 : 0 : {}
443 : :
444 : : void
445 : 0 : AttributeChecker::visit (AST::AttrInputMacro &)
446 : 0 : {}
447 : :
448 : : void
449 : 26 : AttributeChecker::visit (AST::MetaItemLitExpr &)
450 : 26 : {}
451 : :
452 : : void
453 : 1 : AttributeChecker::visit (AST::MetaItemPathExpr &attribute)
454 : : {
455 : 1 : if (!attribute.get_expr ().is_literal ())
456 : : {
457 : 1 : rust_error_at (attribute.get_expr ().get_locus (),
458 : : "malformed %<path%> attribute input");
459 : 1 : rust_inform (attribute.get_expr ().get_locus (),
460 : : "must be of the form: %<#[path = \"file\"]%>");
461 : : }
462 : 1 : }
463 : :
464 : : void
465 : 143 : AttributeChecker::visit (AST::BorrowExpr &)
466 : 143 : {}
467 : :
468 : : void
469 : 228 : AttributeChecker::visit (AST::DereferenceExpr &)
470 : 228 : {}
471 : :
472 : : void
473 : 0 : AttributeChecker::visit (AST::ErrorPropagationExpr &)
474 : 0 : {}
475 : :
476 : : void
477 : 15 : AttributeChecker::visit (AST::NegationExpr &)
478 : 15 : {}
479 : :
480 : : void
481 : 769 : AttributeChecker::visit (AST::ArithmeticOrLogicalExpr &)
482 : 769 : {}
483 : :
484 : : void
485 : 742 : AttributeChecker::visit (AST::ComparisonExpr &)
486 : 742 : {}
487 : :
488 : : void
489 : 28 : AttributeChecker::visit (AST::LazyBooleanExpr &)
490 : 28 : {}
491 : :
492 : : void
493 : 158 : AttributeChecker::visit (AST::TypeCastExpr &)
494 : 158 : {}
495 : :
496 : : void
497 : 1 : AttributeChecker::visit (AST::AssignmentExpr &)
498 : 1 : {}
499 : :
500 : : void
501 : 7 : AttributeChecker::visit (AST::CompoundAssignmentExpr &)
502 : 7 : {}
503 : :
504 : : void
505 : 12 : AttributeChecker::visit (AST::GroupedExpr &)
506 : 12 : {}
507 : :
508 : : void
509 : 0 : AttributeChecker::visit (AST::ArrayElemsValues &)
510 : 0 : {}
511 : :
512 : : void
513 : 0 : AttributeChecker::visit (AST::ArrayElemsCopied &)
514 : 0 : {}
515 : :
516 : : void
517 : 15 : AttributeChecker::visit (AST::ArrayExpr &)
518 : 15 : {}
519 : :
520 : : void
521 : 0 : AttributeChecker::visit (AST::ArrayIndexExpr &)
522 : 0 : {}
523 : :
524 : : void
525 : 52 : AttributeChecker::visit (AST::TupleExpr &)
526 : 52 : {}
527 : :
528 : : void
529 : 187 : AttributeChecker::visit (AST::TupleIndexExpr &)
530 : 187 : {}
531 : :
532 : : void
533 : 7 : AttributeChecker::visit (AST::StructExprStruct &)
534 : 7 : {}
535 : :
536 : : void
537 : 0 : AttributeChecker::visit (AST::StructExprFieldIdentifier &)
538 : 0 : {}
539 : :
540 : : void
541 : 0 : AttributeChecker::visit (AST::StructExprFieldIdentifierValue &)
542 : 0 : {}
543 : :
544 : : void
545 : 0 : AttributeChecker::visit (AST::StructExprFieldIndexValue &)
546 : 0 : {}
547 : :
548 : : void
549 : 155 : AttributeChecker::visit (AST::StructExprStructFields &)
550 : 155 : {}
551 : :
552 : : void
553 : 0 : AttributeChecker::visit (AST::StructExprStructBase &)
554 : 0 : {}
555 : :
556 : : void
557 : 647 : AttributeChecker::visit (AST::CallExpr &)
558 : 647 : {}
559 : :
560 : : void
561 : 276 : AttributeChecker::visit (AST::MethodCallExpr &)
562 : 276 : {}
563 : :
564 : : void
565 : 171 : AttributeChecker::visit (AST::FieldAccessExpr &)
566 : 171 : {}
567 : :
568 : : void
569 : 1 : AttributeChecker::visit (AST::ClosureExprInner &)
570 : 1 : {}
571 : :
572 : : void
573 : 11075 : AttributeChecker::visit (AST::BlockExpr &expr)
574 : : {
575 : 26668 : for (auto &stmt : expr.get_statements ())
576 : : {
577 : 15593 : if (stmt->get_stmt_kind () == AST::Stmt::Kind::Item)
578 : : {
579 : : // Non owning pointer, let it go out of scope
580 : 716 : auto item = static_cast<AST::Item *> (stmt.get ());
581 : 716 : check_proc_macro_non_root (item->get_outer_attrs (),
582 : 716 : item->get_locus ());
583 : : }
584 : : }
585 : 11075 : AST::DefaultASTVisitor::visit (expr);
586 : 11075 : }
587 : :
588 : : void
589 : 0 : AttributeChecker::visit (AST::ClosureExprInnerTyped &)
590 : 0 : {}
591 : :
592 : : void
593 : 0 : AttributeChecker::visit (AST::ContinueExpr &)
594 : 0 : {}
595 : :
596 : : void
597 : 0 : AttributeChecker::visit (AST::BreakExpr &)
598 : 0 : {}
599 : :
600 : : void
601 : 0 : AttributeChecker::visit (AST::RangeFromToExpr &)
602 : 0 : {}
603 : :
604 : : void
605 : 0 : AttributeChecker::visit (AST::RangeFromExpr &)
606 : 0 : {}
607 : :
608 : : void
609 : 0 : AttributeChecker::visit (AST::RangeToExpr &)
610 : 0 : {}
611 : :
612 : : void
613 : 0 : AttributeChecker::visit (AST::RangeFullExpr &)
614 : 0 : {}
615 : :
616 : : void
617 : 0 : AttributeChecker::visit (AST::RangeFromToInclExpr &)
618 : 0 : {}
619 : :
620 : : void
621 : 0 : AttributeChecker::visit (AST::RangeToInclExpr &)
622 : 0 : {}
623 : :
624 : : void
625 : 0 : AttributeChecker::visit (AST::ReturnExpr &)
626 : 0 : {}
627 : :
628 : : void
629 : 41 : AttributeChecker::visit (AST::LoopExpr &)
630 : 41 : {}
631 : :
632 : : void
633 : 18 : AttributeChecker::visit (AST::WhileLoopExpr &)
634 : 18 : {}
635 : :
636 : : void
637 : 2 : AttributeChecker::visit (AST::WhileLetLoopExpr &)
638 : 2 : {}
639 : :
640 : : void
641 : 1 : AttributeChecker::visit (AST::ForLoopExpr &)
642 : 1 : {}
643 : :
644 : : void
645 : 65 : AttributeChecker::visit (AST::IfExpr &)
646 : 65 : {}
647 : :
648 : : void
649 : 460 : AttributeChecker::visit (AST::IfExprConseqElse &)
650 : 460 : {}
651 : :
652 : : void
653 : 0 : AttributeChecker::visit (AST::IfLetExpr &)
654 : 0 : {}
655 : :
656 : : void
657 : 9 : AttributeChecker::visit (AST::IfLetExprConseqElse &)
658 : 9 : {}
659 : :
660 : : void
661 : 218 : AttributeChecker::visit (AST::MatchExpr &)
662 : 218 : {}
663 : :
664 : : void
665 : 0 : AttributeChecker::visit (AST::AwaitExpr &)
666 : 0 : {}
667 : :
668 : : void
669 : 0 : AttributeChecker::visit (AST::AsyncBlockExpr &)
670 : 0 : {}
671 : :
672 : : // rust-item.h
673 : : void
674 : 965 : AttributeChecker::visit (AST::TypeParam &)
675 : 965 : {}
676 : :
677 : : void
678 : 0 : AttributeChecker::visit (AST::LifetimeWhereClauseItem &)
679 : 0 : {}
680 : :
681 : : void
682 : 85 : AttributeChecker::visit (AST::TypeBoundWhereClauseItem &)
683 : 85 : {}
684 : :
685 : : void
686 : 1357 : AttributeChecker::visit (AST::Module &module)
687 : : {
688 : 1357 : check_attributes (module.get_outer_attrs ());
689 : 1357 : check_proc_macro_non_function (module.get_outer_attrs ());
690 : 4171 : for (auto &item : module.get_items ())
691 : : {
692 : 2814 : check_proc_macro_non_root (item->get_outer_attrs (), item->get_locus ());
693 : : }
694 : 1357 : AST::DefaultASTVisitor::visit (module);
695 : 1357 : }
696 : :
697 : : void
698 : 27 : AttributeChecker::visit (AST::ExternCrate &crate)
699 : : {
700 : 27 : check_proc_macro_non_function (crate.get_outer_attrs ());
701 : 27 : }
702 : :
703 : : void
704 : 0 : AttributeChecker::visit (AST::UseTreeGlob &)
705 : 0 : {}
706 : :
707 : : void
708 : 0 : AttributeChecker::visit (AST::UseTreeList &)
709 : 0 : {}
710 : :
711 : : void
712 : 0 : AttributeChecker::visit (AST::UseTreeRebind &)
713 : 0 : {}
714 : :
715 : : void
716 : 660 : AttributeChecker::visit (AST::UseDeclaration &declaration)
717 : : {
718 : 660 : check_proc_macro_non_function (declaration.get_outer_attrs ());
719 : 660 : }
720 : :
721 : : static void
722 : 1 : check_no_mangle_function (const AST::Attribute &attribute,
723 : : const AST::Function &fun)
724 : : {
725 : 1 : if (attribute.has_attr_input ())
726 : : {
727 : 0 : rust_error_at (attribute.get_locus (), ErrorCode::E0754,
728 : : "malformed %<no_mangle%> attribute input");
729 : 0 : rust_inform (attribute.get_locus (),
730 : : "must be of the form: %<#[no_mangle]%>");
731 : : }
732 : 1 : if (!is_ascii_only (fun.get_function_name ().as_string ()))
733 : 0 : rust_error_at (fun.get_function_name ().get_locus (),
734 : : "the %<#[no_mangle]%> attribute requires ASCII identifier");
735 : 1 : }
736 : :
737 : : void
738 : 9956 : AttributeChecker::visit (AST::Function &fun)
739 : : {
740 : 9972 : auto check_crate_type = [] (const char *name, AST::Attribute &attribute) {
741 : 16 : if (!Session::get_instance ().options.is_proc_macro ())
742 : 3 : rust_error_at (attribute.get_locus (),
743 : : "the %<#[%s]%> attribute is only usable with crates of "
744 : : "the %<proc-macro%> crate type",
745 : : name);
746 : 16 : };
747 : :
748 : 9956 : BuiltinAttrDefinition result;
749 : 10263 : for (auto &attribute : fun.get_outer_attrs ())
750 : : {
751 : 307 : if (!is_builtin (attribute, result))
752 : 0 : return;
753 : :
754 : 307 : auto name = result.name.c_str ();
755 : :
756 : 307 : if (result.name == Attrs::PROC_MACRO_DERIVE)
757 : : {
758 : 6 : if (!attribute.has_attr_input ())
759 : : {
760 : 1 : rust_error_at (attribute.get_locus (),
761 : : "malformed %qs attribute input", name);
762 : 1 : rust_inform (
763 : : attribute.get_locus (),
764 : : "must be of the form: %<#[proc_macro_derive(TraitName, "
765 : : "/*opt*/ attributes(name1, name2, ...))]%>");
766 : : }
767 : 6 : check_crate_type (name, attribute);
768 : : }
769 : 301 : else if (result.name == Attrs::PROC_MACRO
770 : 301 : || result.name == Attrs::PROC_MACRO_ATTRIBUTE)
771 : : {
772 : 10 : check_crate_type (name, attribute);
773 : : }
774 : 291 : else if (result.name == "no_mangle")
775 : 1 : check_no_mangle_function (attribute, fun);
776 : : }
777 : 9956 : if (fun.has_body ())
778 : 9949 : fun.get_definition ().value ()->accept_vis (*this);
779 : 9956 : }
780 : :
781 : : void
782 : 722 : AttributeChecker::visit (AST::TypeAlias &alias)
783 : : {
784 : 722 : check_proc_macro_non_function (alias.get_outer_attrs ());
785 : 722 : }
786 : :
787 : : void
788 : 1482 : AttributeChecker::visit (AST::StructStruct &struct_item)
789 : : {
790 : 1482 : check_attributes (struct_item.get_outer_attrs ());
791 : 1482 : check_proc_macro_non_function (struct_item.get_outer_attrs ());
792 : 1482 : }
793 : :
794 : : void
795 : 953 : AttributeChecker::visit (AST::TupleStruct &tuplestruct)
796 : : {
797 : 953 : check_proc_macro_non_function (tuplestruct.get_outer_attrs ());
798 : 953 : }
799 : :
800 : : void
801 : 0 : AttributeChecker::visit (AST::EnumItem &)
802 : 0 : {}
803 : :
804 : : void
805 : 0 : AttributeChecker::visit (AST::EnumItemTuple &)
806 : 0 : {}
807 : :
808 : : void
809 : 0 : AttributeChecker::visit (AST::EnumItemStruct &)
810 : 0 : {}
811 : :
812 : : void
813 : 0 : AttributeChecker::visit (AST::EnumItemDiscriminant &)
814 : 0 : {}
815 : :
816 : : void
817 : 540 : AttributeChecker::visit (AST::Enum &enumeration)
818 : : {
819 : 540 : check_proc_macro_non_function (enumeration.get_outer_attrs ());
820 : 540 : }
821 : :
822 : : void
823 : 107 : AttributeChecker::visit (AST::Union &u)
824 : : {
825 : 107 : check_proc_macro_non_function (u.get_outer_attrs ());
826 : 107 : }
827 : :
828 : : void
829 : 523 : AttributeChecker::visit (AST::ConstantItem &item)
830 : : {
831 : 523 : check_proc_macro_non_function (item.get_outer_attrs ());
832 : 523 : }
833 : :
834 : : void
835 : 57 : AttributeChecker::visit (AST::StaticItem &item)
836 : : {
837 : 57 : check_proc_macro_non_function (item.get_outer_attrs ());
838 : 57 : }
839 : :
840 : : void
841 : 0 : AttributeChecker::visit (AST::TraitItemType &)
842 : 0 : {}
843 : :
844 : : void
845 : 3715 : AttributeChecker::visit (AST::Trait &trait)
846 : : {
847 : 3715 : check_proc_macro_non_function (trait.get_outer_attrs ());
848 : 3715 : check_attributes (trait.get_outer_attrs ());
849 : 3715 : }
850 : :
851 : : void
852 : 760 : AttributeChecker::visit (AST::InherentImpl &impl)
853 : : {
854 : 760 : check_proc_macro_non_function (impl.get_outer_attrs ());
855 : 760 : AST::DefaultASTVisitor::visit (impl);
856 : 760 : }
857 : :
858 : : void
859 : 2003 : AttributeChecker::visit (AST::TraitImpl &impl)
860 : : {
861 : 2003 : check_proc_macro_non_function (impl.get_outer_attrs ());
862 : 2003 : AST::DefaultASTVisitor::visit (impl);
863 : 2003 : }
864 : :
865 : : void
866 : 0 : AttributeChecker::visit (AST::ExternalTypeItem &)
867 : 0 : {}
868 : :
869 : : void
870 : 0 : AttributeChecker::visit (AST::ExternalStaticItem &)
871 : 0 : {}
872 : :
873 : : void
874 : 1462 : AttributeChecker::visit (AST::ExternBlock &block)
875 : : {
876 : 1462 : check_proc_macro_non_function (block.get_outer_attrs ());
877 : 1462 : }
878 : :
879 : : // rust-macro.h
880 : : void
881 : 0 : AttributeChecker::visit (AST::MacroMatchFragment &)
882 : 0 : {}
883 : :
884 : : void
885 : 0 : AttributeChecker::visit (AST::MacroMatchRepetition &)
886 : 0 : {}
887 : :
888 : : void
889 : 0 : AttributeChecker::visit (AST::MacroMatcher &)
890 : 0 : {}
891 : :
892 : : void
893 : 954 : AttributeChecker::visit (AST::MacroRulesDefinition &)
894 : 954 : {}
895 : :
896 : : void
897 : 708 : AttributeChecker::visit (AST::MacroInvocation &)
898 : 708 : {}
899 : :
900 : : void
901 : 0 : AttributeChecker::visit (AST::MetaItemPath &)
902 : 0 : {}
903 : :
904 : : void
905 : 1096 : AttributeChecker::visit (AST::MetaWord &)
906 : 1096 : {}
907 : :
908 : : void
909 : 1709 : AttributeChecker::visit (AST::MetaNameValueStr &)
910 : 1709 : {}
911 : :
912 : : void
913 : 0 : AttributeChecker::visit (AST::MetaListPaths &)
914 : 0 : {}
915 : :
916 : : void
917 : 0 : AttributeChecker::visit (AST::MetaListNameValueStr &)
918 : 0 : {}
919 : :
920 : : // rust-pattern.h
921 : : void
922 : 0 : AttributeChecker::visit (AST::LiteralPattern &)
923 : 0 : {}
924 : :
925 : : void
926 : 0 : AttributeChecker::visit (AST::IdentifierPattern &)
927 : 0 : {}
928 : :
929 : : void
930 : 0 : AttributeChecker::visit (AST::WildcardPattern &)
931 : 0 : {}
932 : :
933 : : void
934 : 0 : AttributeChecker::visit (AST::RestPattern &)
935 : 0 : {}
936 : :
937 : : // void AttributeChecker::visit(RangePatternBound& ){}
938 : :
939 : : void
940 : 0 : AttributeChecker::visit (AST::RangePatternBoundLiteral &)
941 : 0 : {}
942 : :
943 : : void
944 : 0 : AttributeChecker::visit (AST::RangePatternBoundPath &)
945 : 0 : {}
946 : :
947 : : void
948 : 0 : AttributeChecker::visit (AST::RangePatternBoundQualPath &)
949 : 0 : {}
950 : :
951 : : void
952 : 0 : AttributeChecker::visit (AST::RangePattern &)
953 : 0 : {}
954 : :
955 : : void
956 : 0 : AttributeChecker::visit (AST::ReferencePattern &)
957 : 0 : {}
958 : :
959 : : // void AttributeChecker::visit(StructPatternField& ){}
960 : :
961 : : void
962 : 0 : AttributeChecker::visit (AST::StructPatternFieldTuplePat &)
963 : 0 : {}
964 : :
965 : : void
966 : 0 : AttributeChecker::visit (AST::StructPatternFieldIdentPat &)
967 : 0 : {}
968 : :
969 : : void
970 : 0 : AttributeChecker::visit (AST::StructPatternFieldIdent &)
971 : 0 : {}
972 : :
973 : : void
974 : 0 : AttributeChecker::visit (AST::StructPattern &)
975 : 0 : {}
976 : :
977 : : // void AttributeChecker::visit(TupleStructItems& ){}
978 : :
979 : : void
980 : 0 : AttributeChecker::visit (AST::TupleStructItemsNoRest &)
981 : 0 : {}
982 : :
983 : : void
984 : 0 : AttributeChecker::visit (AST::TupleStructItemsHasRest &)
985 : 0 : {}
986 : :
987 : : void
988 : 0 : AttributeChecker::visit (AST::TupleStructPattern &)
989 : 0 : {}
990 : :
991 : : // void AttributeChecker::visit(TuplePatternItems& ){}
992 : :
993 : : void
994 : 0 : AttributeChecker::visit (AST::TuplePatternItemsNoRest &)
995 : 0 : {}
996 : :
997 : : void
998 : 0 : AttributeChecker::visit (AST::TuplePatternItemsHasRest &)
999 : 0 : {}
1000 : :
1001 : : void
1002 : 0 : AttributeChecker::visit (AST::TuplePattern &)
1003 : 0 : {}
1004 : :
1005 : : void
1006 : 0 : AttributeChecker::visit (AST::GroupedPattern &)
1007 : 0 : {}
1008 : :
1009 : : void
1010 : 0 : AttributeChecker::visit (AST::SlicePattern &)
1011 : 0 : {}
1012 : :
1013 : : void
1014 : 0 : AttributeChecker::visit (AST::AltPattern &)
1015 : 0 : {}
1016 : :
1017 : : // rust-stmt.h
1018 : : void
1019 : 17 : AttributeChecker::visit (AST::EmptyStmt &)
1020 : 17 : {}
1021 : :
1022 : : void
1023 : 9535 : AttributeChecker::visit (AST::LetStmt &)
1024 : 9535 : {}
1025 : :
1026 : : void
1027 : 5325 : AttributeChecker::visit (AST::ExprStmt &)
1028 : 5325 : {}
1029 : :
1030 : : // rust-type.h
1031 : : void
1032 : 0 : AttributeChecker::visit (AST::TraitBound &)
1033 : 0 : {}
1034 : :
1035 : : void
1036 : 0 : AttributeChecker::visit (AST::ImplTraitType &)
1037 : 0 : {}
1038 : :
1039 : : void
1040 : 4 : AttributeChecker::visit (AST::TraitObjectType &)
1041 : 4 : {}
1042 : :
1043 : : void
1044 : 2 : AttributeChecker::visit (AST::ParenthesisedType &)
1045 : 2 : {}
1046 : :
1047 : : void
1048 : 0 : AttributeChecker::visit (AST::ImplTraitTypeOneBound &)
1049 : 0 : {}
1050 : :
1051 : : void
1052 : 7 : AttributeChecker::visit (AST::TraitObjectTypeOneBound &)
1053 : 7 : {}
1054 : :
1055 : : void
1056 : 2 : AttributeChecker::visit (AST::TupleType &)
1057 : 2 : {}
1058 : :
1059 : : void
1060 : 2 : AttributeChecker::visit (AST::NeverType &)
1061 : 2 : {}
1062 : :
1063 : : void
1064 : 164 : AttributeChecker::visit (AST::RawPointerType &)
1065 : 164 : {}
1066 : :
1067 : : void
1068 : 166 : AttributeChecker::visit (AST::ReferenceType &)
1069 : 166 : {}
1070 : :
1071 : : void
1072 : 0 : AttributeChecker::visit (AST::ArrayType &)
1073 : 0 : {}
1074 : :
1075 : : void
1076 : 66 : AttributeChecker::visit (AST::SliceType &)
1077 : 66 : {}
1078 : :
1079 : : void
1080 : 0 : AttributeChecker::visit (AST::InferredType &)
1081 : 0 : {}
1082 : :
1083 : : void
1084 : 1 : AttributeChecker::visit (AST::BareFunctionType &)
1085 : 1 : {}
1086 : :
1087 : : void
1088 : 0 : AttributeChecker::visit (AST::SelfParam &)
1089 : 0 : {}
1090 : :
1091 : : void
1092 : 0 : AttributeChecker::visit (AST::VariadicParam &)
1093 : 0 : {}
1094 : :
1095 : : void
1096 : 0 : AttributeChecker::visit (AST::FunctionParam &)
1097 : 0 : {}
1098 : :
1099 : : } // namespace Analysis
1100 : : } // namespace Rust
|