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