Line data Source code
1 : // Copyright (C) 2026 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-attribute-checker.h"
20 : #include "rust-attributes.h"
21 : #include "rust-attribute-values.h"
22 : #include "rust-diagnostics.h"
23 : #include "rust-session-manager.h"
24 :
25 : namespace Rust {
26 : namespace Analysis {
27 :
28 : using Attrs = Values::Attributes;
29 :
30 : static bool
31 6921 : is_proc_macro_type (const AST::Attribute &attribute)
32 : {
33 6921 : auto result_opt = lookup_builtin (attribute);
34 6921 : if (!result_opt.has_value ())
35 : return false;
36 6921 : auto result = result_opt.value ();
37 :
38 6921 : auto name = result.name;
39 6903 : return name == Attrs::PROC_MACRO || name == Attrs::PROC_MACRO_DERIVE
40 13824 : || name == Attrs::PROC_MACRO_ATTRIBUTE;
41 6921 : }
42 :
43 : // Emit an error when one encountered attribute is either #[proc_macro],
44 : // #[proc_macro_attribute] or #[proc_macro_derive]
45 : static void
46 4912 : check_proc_macro_non_function (const AST::Attribute &attr)
47 : {
48 4912 : if (is_proc_macro_type (attr))
49 45 : rust_error_at (attr.get_locus (),
50 : "the %<#[%s]%> attribute may only be used on bare functions",
51 90 : attr.get_path ().get_segments ()[0].as_string ().c_str ());
52 4912 : }
53 :
54 : // Emit an error when one attribute is either proc_macro, proc_macro_attribute
55 : // or proc_macro_derive
56 : static void
57 2009 : check_proc_macro_non_root (const AST::Attribute &attr, location_t loc)
58 : {
59 2009 : if (is_proc_macro_type (attr))
60 : {
61 9 : rust_error_at (
62 : loc,
63 : "functions tagged with %<#[%s]%> must currently "
64 : "reside in the root of the crate",
65 18 : attr.get_path ().get_segments ().at (0).as_string ().c_str ());
66 : }
67 2009 : }
68 :
69 4684 : AttributeChecker::AttributeChecker () {}
70 :
71 : void
72 4684 : AttributeChecker::go (AST::Crate &crate)
73 : {
74 4684 : visit (crate);
75 4684 : }
76 :
77 : void
78 16668 : AttributeChecker::visit (AST::Attribute &attribute)
79 : {
80 16668 : auto &session = Session::get_instance ();
81 16668 : if (attribute.get_path () == Values::Attributes::CFG_ATTR)
82 : {
83 14 : if (!attribute.is_parsed_to_meta_item ())
84 14 : attribute.parse_attr_to_meta_item ();
85 14 : if (!attribute.check_cfg_predicate (session))
86 : return; // Do not emit errors for attribute that'll get stripped.
87 : }
88 :
89 16660 : AST::DefaultASTVisitor::visit (attribute);
90 : }
91 :
92 : void
93 0 : AttributeChecker::visit (AST::Token &)
94 0 : {}
95 :
96 : void
97 8519 : AttributeChecker::visit (AST::DelimTokenTree &)
98 8519 : {}
99 :
100 : void
101 544 : AttributeChecker::visit (AST::IdentifierExpr &)
102 544 : {}
103 :
104 : void
105 0 : AttributeChecker::visit (AST::Lifetime &)
106 0 : {}
107 :
108 : void
109 59 : AttributeChecker::visit (AST::LifetimeParam &)
110 59 : {}
111 :
112 : void
113 83 : AttributeChecker::visit (AST::ConstGenericParam &)
114 83 : {}
115 :
116 : // rust-path.h
117 : void
118 152 : AttributeChecker::visit (AST::PathInExpression &)
119 152 : {}
120 :
121 : void
122 0 : AttributeChecker::visit (AST::TypePathSegment &)
123 0 : {}
124 :
125 : void
126 0 : AttributeChecker::visit (AST::TypePathSegmentGeneric &)
127 0 : {}
128 :
129 : void
130 0 : AttributeChecker::visit (AST::TypePathSegmentFunction &)
131 0 : {}
132 :
133 : void
134 6027 : AttributeChecker::visit (AST::TypePath &)
135 6027 : {}
136 :
137 : void
138 0 : AttributeChecker::visit (AST::QualifiedPathInExpression &)
139 0 : {}
140 :
141 : void
142 0 : AttributeChecker::visit (AST::QualifiedPathInType &)
143 0 : {}
144 :
145 : // rust-expr.h
146 : void
147 1583 : AttributeChecker::visit (AST::LiteralExpr &)
148 1583 : {}
149 :
150 : void
151 3406 : AttributeChecker::visit (AST::AttrInputLiteral &)
152 3406 : {}
153 :
154 : void
155 0 : AttributeChecker::visit (AST::MetaItemLitExpr &)
156 0 : {}
157 :
158 : void
159 1 : AttributeChecker::visit (AST::MetaItemPathExpr &attribute)
160 : {
161 1 : if (!attribute.get_expr ().is_literal ())
162 : {
163 1 : rust_error_at (attribute.get_expr ().get_locus (),
164 : "malformed %<path%> attribute input");
165 1 : rust_inform (attribute.get_expr ().get_locus (),
166 : "must be of the form: %<#[path = \"file\"]%>");
167 : }
168 1 : }
169 :
170 : void
171 143 : AttributeChecker::visit (AST::BorrowExpr &)
172 143 : {}
173 :
174 : void
175 228 : AttributeChecker::visit (AST::DereferenceExpr &)
176 228 : {}
177 :
178 : void
179 0 : AttributeChecker::visit (AST::ErrorPropagationExpr &)
180 0 : {}
181 :
182 : void
183 135 : AttributeChecker::visit (AST::NegationExpr &)
184 135 : {}
185 :
186 : void
187 798 : AttributeChecker::visit (AST::ArithmeticOrLogicalExpr &)
188 798 : {}
189 :
190 : void
191 743 : AttributeChecker::visit (AST::ComparisonExpr &)
192 743 : {}
193 :
194 : void
195 28 : AttributeChecker::visit (AST::LazyBooleanExpr &)
196 28 : {}
197 :
198 : void
199 158 : AttributeChecker::visit (AST::TypeCastExpr &)
200 158 : {}
201 :
202 : void
203 63 : AttributeChecker::visit (AST::AssignmentExpr &)
204 63 : {}
205 :
206 : void
207 7 : AttributeChecker::visit (AST::CompoundAssignmentExpr &)
208 7 : {}
209 :
210 : void
211 12 : AttributeChecker::visit (AST::GroupedExpr &)
212 12 : {}
213 :
214 : void
215 0 : AttributeChecker::visit (AST::ArrayElemsValues &)
216 0 : {}
217 :
218 : void
219 0 : AttributeChecker::visit (AST::ArrayElemsCopied &)
220 0 : {}
221 :
222 : void
223 15 : AttributeChecker::visit (AST::ArrayExpr &)
224 15 : {}
225 :
226 : void
227 0 : AttributeChecker::visit (AST::ArrayIndexExpr &)
228 0 : {}
229 :
230 : void
231 60 : AttributeChecker::visit (AST::TupleExpr &)
232 60 : {}
233 :
234 : void
235 187 : AttributeChecker::visit (AST::TupleIndexExpr &)
236 187 : {}
237 :
238 : void
239 7 : AttributeChecker::visit (AST::StructExprStruct &)
240 7 : {}
241 :
242 : void
243 0 : AttributeChecker::visit (AST::StructExprFieldIdentifier &)
244 0 : {}
245 :
246 : void
247 0 : AttributeChecker::visit (AST::StructExprFieldIdentifierValue &)
248 0 : {}
249 :
250 : void
251 0 : AttributeChecker::visit (AST::StructExprFieldIndexValue &)
252 0 : {}
253 :
254 : void
255 155 : AttributeChecker::visit (AST::StructExprStructFields &)
256 155 : {}
257 :
258 : void
259 0 : AttributeChecker::visit (AST::StructExprStructBase &)
260 0 : {}
261 :
262 : void
263 649 : AttributeChecker::visit (AST::CallExpr &)
264 649 : {}
265 :
266 : void
267 291 : AttributeChecker::visit (AST::MethodCallExpr &)
268 291 : {}
269 :
270 : void
271 171 : AttributeChecker::visit (AST::FieldAccessExpr &)
272 171 : {}
273 :
274 : void
275 1 : AttributeChecker::visit (AST::ClosureExprInner &)
276 1 : {}
277 :
278 : void
279 12224 : AttributeChecker::visit (AST::BlockExpr &expr)
280 : {
281 28603 : for (auto &stmt : expr.get_statements ())
282 : {
283 16379 : if (stmt->get_stmt_kind () == AST::Stmt::Kind::Item)
284 : {
285 : // Non owning pointer, let it go out of scope
286 723 : auto item = static_cast<AST::Item *> (stmt.get ());
287 733 : for (auto &attr : item->get_outer_attrs ())
288 10 : check_proc_macro_non_root (attr, item->get_locus ());
289 : }
290 : }
291 12224 : AST::DefaultASTVisitor::visit (expr);
292 12224 : }
293 :
294 : void
295 0 : AttributeChecker::visit (AST::ClosureExprInnerTyped &)
296 0 : {}
297 :
298 : void
299 0 : AttributeChecker::visit (AST::ContinueExpr &)
300 0 : {}
301 :
302 : void
303 0 : AttributeChecker::visit (AST::BreakExpr &)
304 0 : {}
305 :
306 : void
307 0 : AttributeChecker::visit (AST::RangeFromToExpr &)
308 0 : {}
309 :
310 : void
311 0 : AttributeChecker::visit (AST::RangeFromExpr &)
312 0 : {}
313 :
314 : void
315 0 : AttributeChecker::visit (AST::RangeToExpr &)
316 0 : {}
317 :
318 : void
319 0 : AttributeChecker::visit (AST::RangeFullExpr &)
320 0 : {}
321 :
322 : void
323 0 : AttributeChecker::visit (AST::RangeFromToInclExpr &)
324 0 : {}
325 :
326 : void
327 0 : AttributeChecker::visit (AST::RangeToInclExpr &)
328 0 : {}
329 :
330 : void
331 3 : AttributeChecker::visit (AST::ReturnExpr &)
332 3 : {}
333 :
334 : void
335 52 : AttributeChecker::visit (AST::LoopExpr &)
336 52 : {}
337 :
338 : void
339 18 : AttributeChecker::visit (AST::WhileLoopExpr &)
340 18 : {}
341 :
342 : void
343 2 : AttributeChecker::visit (AST::WhileLetLoopExpr &)
344 2 : {}
345 :
346 : void
347 1 : AttributeChecker::visit (AST::ForLoopExpr &)
348 1 : {}
349 :
350 : void
351 71 : AttributeChecker::visit (AST::IfExpr &)
352 71 : {}
353 :
354 : void
355 517 : AttributeChecker::visit (AST::IfExprConseqElse &)
356 517 : {}
357 :
358 : void
359 0 : AttributeChecker::visit (AST::IfLetExpr &)
360 0 : {}
361 :
362 : void
363 9 : AttributeChecker::visit (AST::IfLetExprConseqElse &)
364 9 : {}
365 :
366 : void
367 512 : AttributeChecker::visit (AST::MatchExpr &)
368 512 : {}
369 :
370 : void
371 0 : AttributeChecker::visit (AST::AwaitExpr &)
372 0 : {}
373 :
374 : void
375 0 : AttributeChecker::visit (AST::AsyncBlockExpr &)
376 0 : {}
377 :
378 : // rust-item.h
379 : void
380 5899 : AttributeChecker::visit (AST::TypeParam &)
381 5899 : {}
382 :
383 : void
384 0 : AttributeChecker::visit (AST::LifetimeWhereClauseItem &)
385 0 : {}
386 :
387 : void
388 96 : AttributeChecker::visit (AST::TypeBoundWhereClauseItem &)
389 96 : {}
390 :
391 : void
392 1307 : AttributeChecker::visit (AST::Module &module)
393 : {
394 1474 : for (auto &attr : module.get_outer_attrs ())
395 167 : check_proc_macro_non_function (attr);
396 :
397 4146 : for (auto &item : module.get_items ())
398 4838 : for (auto &attr : item->get_outer_attrs ())
399 1999 : check_proc_macro_non_root (attr, item->get_locus ());
400 :
401 1307 : AST::DefaultASTVisitor::visit (module);
402 1307 : }
403 :
404 : void
405 27 : AttributeChecker::visit (AST::ExternCrate &crate)
406 : {
407 30 : for (auto &attr : crate.get_outer_attrs ())
408 3 : check_proc_macro_non_function (attr);
409 27 : }
410 :
411 : void
412 0 : AttributeChecker::visit (AST::UseTreeGlob &)
413 0 : {}
414 :
415 : void
416 0 : AttributeChecker::visit (AST::UseTreeList &)
417 0 : {}
418 :
419 : void
420 0 : AttributeChecker::visit (AST::UseTreeRebind &)
421 0 : {}
422 :
423 : void
424 682 : AttributeChecker::visit (AST::UseDeclaration &declaration)
425 : {
426 687 : for (auto &attr : declaration.get_outer_attrs ())
427 5 : check_proc_macro_non_function (attr);
428 682 : }
429 :
430 : void
431 12766 : AttributeChecker::visit (AST::Function &fun)
432 : {
433 12766 : if (fun.has_body ())
434 11056 : fun.get_definition ().value ()->accept_vis (*this);
435 12766 : }
436 :
437 : void
438 736 : AttributeChecker::visit (AST::TypeAlias &alias)
439 : {
440 739 : for (auto &attr : alias.get_outer_attrs ())
441 3 : check_proc_macro_non_function (attr);
442 736 : }
443 :
444 : void
445 1502 : AttributeChecker::visit (AST::StructStruct &struct_item)
446 : {
447 1977 : for (auto &attr : struct_item.get_outer_attrs ())
448 : {
449 475 : check_proc_macro_non_function (attr);
450 : }
451 :
452 1502 : AST::DefaultASTVisitor::visit (struct_item);
453 1502 : }
454 :
455 : void
456 965 : AttributeChecker::visit (AST::TupleStruct &tuplestruct)
457 : {
458 997 : for (auto &attr : tuplestruct.get_outer_attrs ())
459 32 : check_proc_macro_non_function (attr);
460 965 : }
461 :
462 : void
463 0 : AttributeChecker::visit (AST::EnumItem &)
464 0 : {}
465 :
466 : void
467 0 : AttributeChecker::visit (AST::EnumItemTuple &)
468 0 : {}
469 :
470 : void
471 0 : AttributeChecker::visit (AST::EnumItemStruct &)
472 0 : {}
473 :
474 : void
475 0 : AttributeChecker::visit (AST::EnumItemDiscriminant &)
476 0 : {}
477 :
478 : void
479 550 : AttributeChecker::visit (AST::Enum &enumeration)
480 : {
481 704 : for (auto &attr : enumeration.get_outer_attrs ())
482 154 : check_proc_macro_non_function (attr);
483 550 : }
484 :
485 : void
486 111 : AttributeChecker::visit (AST::Union &u)
487 : {
488 128 : for (auto &attr : u.get_outer_attrs ())
489 17 : check_proc_macro_non_function (attr);
490 111 : }
491 :
492 : void
493 571 : AttributeChecker::visit (AST::ConstantItem &item)
494 : {
495 574 : for (auto &attr : item.get_outer_attrs ())
496 3 : check_proc_macro_non_function (attr);
497 571 : }
498 :
499 : void
500 64 : AttributeChecker::visit (AST::StaticItem &item)
501 : {
502 72 : for (auto &attr : item.get_outer_attrs ())
503 8 : check_proc_macro_non_function (attr);
504 64 : }
505 :
506 : void
507 738 : AttributeChecker::visit (AST::TraitItemType &)
508 738 : {}
509 :
510 : void
511 3896 : AttributeChecker::visit (AST::Trait &trait)
512 : {
513 7783 : for (auto &attr : trait.get_outer_attrs ())
514 3887 : check_proc_macro_non_function (attr);
515 :
516 3896 : AST::DefaultASTVisitor::visit (trait);
517 3896 : }
518 :
519 : void
520 762 : AttributeChecker::visit (AST::InherentImpl &impl)
521 : {
522 908 : for (auto &attr : impl.get_outer_attrs ())
523 146 : check_proc_macro_non_function (attr);
524 :
525 762 : AST::DefaultASTVisitor::visit (impl);
526 762 : }
527 :
528 : void
529 2011 : AttributeChecker::visit (AST::TraitImpl &impl)
530 : {
531 2019 : for (auto &attr : impl.get_outer_attrs ())
532 8 : check_proc_macro_non_function (attr);
533 :
534 2011 : AST::DefaultASTVisitor::visit (impl);
535 2011 : }
536 :
537 : void
538 0 : AttributeChecker::visit (AST::ExternalTypeItem &)
539 0 : {}
540 :
541 : void
542 0 : AttributeChecker::visit (AST::ExternalStaticItem &)
543 0 : {}
544 :
545 : void
546 1610 : AttributeChecker::visit (AST::ExternBlock &block)
547 : {
548 1614 : for (auto &attr : block.get_outer_attrs ())
549 4 : check_proc_macro_non_function (attr);
550 1610 : }
551 :
552 : // rust-macro.h
553 : void
554 0 : AttributeChecker::visit (AST::MacroMatchFragment &)
555 0 : {}
556 :
557 : void
558 0 : AttributeChecker::visit (AST::MacroMatchRepetition &)
559 0 : {}
560 :
561 : void
562 0 : AttributeChecker::visit (AST::MacroMatcher &)
563 0 : {}
564 :
565 : void
566 971 : AttributeChecker::visit (AST::MacroRulesDefinition &)
567 971 : {}
568 :
569 : void
570 714 : AttributeChecker::visit (AST::MacroInvocation &)
571 714 : {}
572 :
573 : void
574 0 : AttributeChecker::visit (AST::MetaItemPath &)
575 0 : {}
576 :
577 : void
578 10 : AttributeChecker::visit (AST::MetaWord &)
579 10 : {}
580 :
581 : void
582 1 : AttributeChecker::visit (AST::MetaNameValueStr &)
583 1 : {}
584 :
585 : void
586 0 : AttributeChecker::visit (AST::MetaListPaths &)
587 0 : {}
588 :
589 : void
590 0 : AttributeChecker::visit (AST::MetaListNameValueStr &)
591 0 : {}
592 :
593 : // rust-pattern.h
594 : void
595 0 : AttributeChecker::visit (AST::LiteralPattern &)
596 0 : {}
597 :
598 : void
599 0 : AttributeChecker::visit (AST::IdentifierPattern &)
600 0 : {}
601 :
602 : void
603 0 : AttributeChecker::visit (AST::WildcardPattern &)
604 0 : {}
605 :
606 : void
607 0 : AttributeChecker::visit (AST::RestPattern &)
608 0 : {}
609 :
610 : // void AttributeChecker::visit(RangePatternBound& ){}
611 :
612 : void
613 0 : AttributeChecker::visit (AST::RangePatternBoundLiteral &)
614 0 : {}
615 :
616 : void
617 0 : AttributeChecker::visit (AST::RangePatternBoundPath &)
618 0 : {}
619 :
620 : void
621 0 : AttributeChecker::visit (AST::RangePatternBoundQualPath &)
622 0 : {}
623 :
624 : void
625 0 : AttributeChecker::visit (AST::RangePattern &)
626 0 : {}
627 :
628 : void
629 0 : AttributeChecker::visit (AST::ReferencePattern &)
630 0 : {}
631 :
632 : // void AttributeChecker::visit(StructPatternField& ){}
633 :
634 : void
635 0 : AttributeChecker::visit (AST::StructPatternFieldTuplePat &)
636 0 : {}
637 :
638 : void
639 0 : AttributeChecker::visit (AST::StructPatternFieldIdentPat &)
640 0 : {}
641 :
642 : void
643 0 : AttributeChecker::visit (AST::StructPatternFieldIdent &)
644 0 : {}
645 :
646 : void
647 0 : AttributeChecker::visit (AST::StructPattern &)
648 0 : {}
649 :
650 : // void AttributeChecker::visit(TupleStructItems& ){}
651 :
652 : void
653 0 : AttributeChecker::visit (AST::TupleStructItemsNoRest &)
654 0 : {}
655 :
656 : void
657 0 : AttributeChecker::visit (AST::TupleStructItemsHasRest &)
658 0 : {}
659 :
660 : void
661 0 : AttributeChecker::visit (AST::TupleStructPattern &)
662 0 : {}
663 :
664 : // void AttributeChecker::visit(TuplePatternItems& ){}
665 :
666 : void
667 0 : AttributeChecker::visit (AST::TuplePatternItemsNoRest &)
668 0 : {}
669 :
670 : void
671 0 : AttributeChecker::visit (AST::TuplePatternItemsHasRest &)
672 0 : {}
673 :
674 : void
675 0 : AttributeChecker::visit (AST::TuplePattern &)
676 0 : {}
677 :
678 : void
679 0 : AttributeChecker::visit (AST::GroupedPattern &)
680 0 : {}
681 :
682 : void
683 0 : AttributeChecker::visit (AST::SlicePattern &)
684 0 : {}
685 :
686 : void
687 0 : AttributeChecker::visit (AST::AltPattern &)
688 0 : {}
689 :
690 : // rust-stmt.h
691 : void
692 18 : AttributeChecker::visit (AST::EmptyStmt &)
693 18 : {}
694 :
695 : void
696 9699 : AttributeChecker::visit (AST::LetStmt &)
697 9699 : {}
698 :
699 : void
700 5939 : AttributeChecker::visit (AST::ExprStmt &)
701 5939 : {}
702 :
703 : // rust-type.h
704 : void
705 611 : AttributeChecker::visit (AST::TraitBound &)
706 611 : {}
707 :
708 : void
709 0 : AttributeChecker::visit (AST::ImplTraitType &)
710 0 : {}
711 :
712 : void
713 4 : AttributeChecker::visit (AST::TraitObjectType &)
714 4 : {}
715 :
716 : void
717 2 : AttributeChecker::visit (AST::ParenthesisedType &)
718 2 : {}
719 :
720 : void
721 2 : AttributeChecker::visit (AST::ImplTraitTypeOneBound &)
722 2 : {}
723 :
724 : void
725 7 : AttributeChecker::visit (AST::TraitObjectTypeOneBound &)
726 7 : {}
727 :
728 : void
729 3 : AttributeChecker::visit (AST::TupleType &)
730 3 : {}
731 :
732 : void
733 2 : AttributeChecker::visit (AST::NeverType &)
734 2 : {}
735 :
736 : void
737 239 : AttributeChecker::visit (AST::RawPointerType &)
738 239 : {}
739 :
740 : void
741 176 : AttributeChecker::visit (AST::ReferenceType &)
742 176 : {}
743 :
744 : void
745 40 : AttributeChecker::visit (AST::ArrayType &)
746 40 : {}
747 :
748 : void
749 66 : AttributeChecker::visit (AST::SliceType &)
750 66 : {}
751 :
752 : void
753 0 : AttributeChecker::visit (AST::InferredType &)
754 0 : {}
755 :
756 : void
757 10 : AttributeChecker::visit (AST::BareFunctionType &)
758 10 : {}
759 :
760 : void
761 0 : AttributeChecker::visit (AST::SelfParam &)
762 0 : {}
763 :
764 : void
765 0 : AttributeChecker::visit (AST::VariadicParam &)
766 0 : {}
767 :
768 : void
769 0 : AttributeChecker::visit (AST::FunctionParam &)
770 0 : {}
771 :
772 : } // namespace Analysis
773 : } // namespace Rust
|