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