gccrs: Remove obsolete classes and functions.
[official-gcc.git] / gcc / rust / util / rust-attributes.cc
blob715e9a0b361ac2bd7f8cbddfa16d34a50d8cb538
1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 // This file is part of GCC.
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.
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.
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/>.
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"
29 namespace Rust {
30 namespace Analysis {
32 using Attrs = Values::Attributes;
34 // https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248
35 static const BuiltinAttrDefinition __definitions[]
36 = {{Attrs::INLINE, CODE_GENERATION},
37 {Attrs::COLD, CODE_GENERATION},
38 {Attrs::CFG, EXPANSION},
39 {Attrs::CFG_ATTR, EXPANSION},
40 {Attrs::DEPRECATED, STATIC_ANALYSIS},
41 {Attrs::ALLOW, STATIC_ANALYSIS},
42 {Attrs::ALLOW_INTERNAL_UNSTABLE, STATIC_ANALYSIS},
43 {Attrs::DOC, HIR_LOWERING},
44 {Attrs::MUST_USE, STATIC_ANALYSIS},
45 {Attrs::LANG, HIR_LOWERING},
46 {Attrs::LINK_SECTION, CODE_GENERATION},
47 {Attrs::NO_MANGLE, CODE_GENERATION},
48 {Attrs::REPR, CODE_GENERATION},
49 {Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
50 {Attrs::PATH, EXPANSION},
51 {Attrs::MACRO_USE, NAME_RESOLUTION},
52 {Attrs::MACRO_EXPORT, NAME_RESOLUTION},
53 {Attrs::PROC_MACRO, EXPANSION},
54 {Attrs::PROC_MACRO_DERIVE, EXPANSION},
55 {Attrs::PROC_MACRO_ATTRIBUTE, EXPANSION},
56 // FIXME: This is not implemented yet, see
57 // https://github.com/Rust-GCC/gccrs/issues/1475
58 {Attrs::TARGET_FEATURE, CODE_GENERATION},
59 // From now on, these are reserved by the compiler and gated through
60 // #![feature(rustc_attrs)]
61 {Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION},
62 {Attrs::STABLE, STATIC_ANALYSIS}};
64 BuiltinAttributeMappings *
65 BuiltinAttributeMappings::get ()
67 static BuiltinAttributeMappings *instance = nullptr;
68 if (instance == nullptr)
69 instance = new BuiltinAttributeMappings ();
71 return instance;
74 const BuiltinAttrDefinition &
75 BuiltinAttributeMappings::lookup_builtin (const std::string &attr_name) const
77 auto it = mappings.find (attr_name);
78 if (it == mappings.end ())
79 return BuiltinAttrDefinition::error_node ();
81 return it->second;
84 BuiltinAttributeMappings::BuiltinAttributeMappings ()
86 size_t ndefinitions = sizeof (__definitions) / sizeof (BuiltinAttrDefinition);
87 for (size_t i = 0; i < ndefinitions; i++)
89 const BuiltinAttrDefinition &def = __definitions[i];
90 mappings.insert ({def.name, def});
94 AttributeChecker::AttributeChecker () {}
96 void
97 AttributeChecker::go (AST::Crate &crate)
99 visit (crate);
102 void
103 AttributeChecker::visit (AST::Crate &crate)
105 check_attributes (crate.get_inner_attrs ());
107 for (auto &item : crate.items)
108 item->accept_vis (*this);
111 static bool
112 is_builtin (const AST::Attribute &attribute, BuiltinAttrDefinition &builtin)
114 auto &segments = attribute.get_path ().get_segments ();
116 // Builtin attributes always have a single segment. This avoids us creating
117 // strings all over the place and performing a linear search in the builtins
118 // map
119 if (segments.size () != 1)
120 return false;
122 builtin = BuiltinAttributeMappings::get ()->lookup_builtin (
123 segments.at (0).get_segment_name ());
125 return !builtin.is_error ();
129 * Check that the string given to #[doc(alias = ...)] or #[doc(alias(...))] is
130 * valid.
132 * This means no whitespace characters other than spaces and no quoting
133 * characters.
135 static void
136 check_doc_alias (const std::string &alias_input, const location_t locus)
138 // FIXME: The locus here is for the whole attribute. Can we get the locus
139 // of the alias input instead?
140 for (auto c : alias_input)
141 if ((ISSPACE (c) && c != ' ') || c == '\'' || c == '\"')
143 auto to_print = std::string (1, c);
144 switch (c)
146 case '\n':
147 to_print = "\\n";
148 break;
149 case '\t':
150 to_print = "\\t";
151 break;
152 default:
153 break;
155 rust_error_at (locus,
156 "invalid character used in %<#[doc(alias)]%> input: %qs",
157 to_print.c_str ());
160 if (alias_input.empty ())
161 return;
163 if (alias_input.front () == ' ' || alias_input.back () == ' ')
164 rust_error_at (locus,
165 "%<#[doc(alias)]%> input cannot start or end with a space");
168 static void
169 check_doc_attribute (const AST::Attribute &attribute)
171 if (!attribute.has_attr_input ())
173 rust_error_at (
174 attribute.get_locus (),
175 // FIXME: Improve error message here. Rustc has a very good one
176 "%<#[doc]%> cannot be an empty attribute");
177 return;
180 switch (attribute.get_attr_input ().get_attr_input_type ())
182 case AST::AttrInput::LITERAL:
183 case AST::AttrInput::MACRO:
184 case AST::AttrInput::META_ITEM:
185 break;
186 // FIXME: Handle them as well
188 case AST::AttrInput::TOKEN_TREE: {
189 // FIXME: This doesn't check for #[doc(alias(...))]
190 const auto &option = static_cast<const AST::DelimTokenTree &> (
191 attribute.get_attr_input ());
192 auto *meta_item = option.parse_to_meta_item ();
194 for (auto &item : meta_item->get_items ())
196 if (item->is_key_value_pair ())
198 auto name_value
199 = static_cast<AST::MetaNameValueStr *> (item.get ())
200 ->get_name_value_pair ();
202 // FIXME: Check for other stuff than #[doc(alias = ...)]
203 if (name_value.first.as_string () == "alias")
204 check_doc_alias (name_value.second, attribute.get_locus ());
207 break;
212 static bool
213 is_proc_macro_type (const AST::Attribute &attribute)
215 BuiltinAttrDefinition result;
216 if (!is_builtin (attribute, result))
217 return false;
219 auto name = result.name;
220 return name == Attrs::PROC_MACRO || name == Attrs::PROC_MACRO_DERIVE
221 || name == Attrs::PROC_MACRO_ATTRIBUTE;
224 // Emit an error when one encountered attribute is either #[proc_macro],
225 // #[proc_macro_attribute] or #[proc_macro_derive]
226 static void
227 check_proc_macro_non_function (const AST::AttrVec &attributes)
229 for (auto &attr : attributes)
231 if (is_proc_macro_type (attr))
232 rust_error_at (
233 attr.get_locus (),
234 "the %<#[%s]%> attribute may only be used on bare functions",
235 attr.get_path ().get_segments ()[0].as_string ().c_str ());
239 // Emit an error when one attribute is either proc_macro, proc_macro_attribute
240 // or proc_macro_derive
241 static void
242 check_proc_macro_non_root (AST::AttrVec attributes, location_t loc)
244 for (auto &attr : attributes)
246 if (is_proc_macro_type (attr))
248 rust_error_at (
249 loc,
250 "functions tagged with %<#[%s]%> must currently "
251 "reside in the root of the crate",
252 attr.get_path ().get_segments ().at (0).as_string ().c_str ());
257 void
258 AttributeChecker::check_attribute (const AST::Attribute &attribute)
260 BuiltinAttrDefinition result;
262 // This checker does not check non-builtin attributes
263 if (!is_builtin (attribute, result))
264 return;
266 // TODO: Add checks here for each builtin attribute
267 // TODO: Have an enum of builtins as well, switching on strings is annoying
268 // and costly
269 if (result.name == Attrs::DOC)
270 check_doc_attribute (attribute);
273 void
274 AttributeChecker::check_attributes (const AST::AttrVec &attributes)
276 for (auto &attr : attributes)
277 check_attribute (attr);
280 void
281 AttributeChecker::visit (AST::Token &)
284 void
285 AttributeChecker::visit (AST::DelimTokenTree &)
288 void
289 AttributeChecker::visit (AST::AttrInputMetaItemContainer &)
292 void
293 AttributeChecker::visit (AST::IdentifierExpr &)
296 void
297 AttributeChecker::visit (AST::Lifetime &)
300 void
301 AttributeChecker::visit (AST::LifetimeParam &)
304 void
305 AttributeChecker::visit (AST::ConstGenericParam &)
308 // rust-path.h
309 void
310 AttributeChecker::visit (AST::PathInExpression &)
313 void
314 AttributeChecker::visit (AST::TypePathSegment &)
317 void
318 AttributeChecker::visit (AST::TypePathSegmentGeneric &)
321 void
322 AttributeChecker::visit (AST::TypePathSegmentFunction &)
325 void
326 AttributeChecker::visit (AST::TypePath &)
329 void
330 AttributeChecker::visit (AST::QualifiedPathInExpression &)
333 void
334 AttributeChecker::visit (AST::QualifiedPathInType &)
337 // rust-expr.h
338 void
339 AttributeChecker::visit (AST::LiteralExpr &)
342 void
343 AttributeChecker::visit (AST::AttrInputLiteral &)
346 void
347 AttributeChecker::visit (AST::AttrInputMacro &)
350 void
351 AttributeChecker::visit (AST::MetaItemLitExpr &)
354 void
355 AttributeChecker::visit (AST::MetaItemPathLit &)
358 void
359 AttributeChecker::visit (AST::BorrowExpr &)
362 void
363 AttributeChecker::visit (AST::DereferenceExpr &)
366 void
367 AttributeChecker::visit (AST::ErrorPropagationExpr &)
370 void
371 AttributeChecker::visit (AST::NegationExpr &)
374 void
375 AttributeChecker::visit (AST::ArithmeticOrLogicalExpr &)
378 void
379 AttributeChecker::visit (AST::ComparisonExpr &)
382 void
383 AttributeChecker::visit (AST::LazyBooleanExpr &)
386 void
387 AttributeChecker::visit (AST::TypeCastExpr &)
390 void
391 AttributeChecker::visit (AST::AssignmentExpr &)
394 void
395 AttributeChecker::visit (AST::CompoundAssignmentExpr &)
398 void
399 AttributeChecker::visit (AST::GroupedExpr &)
402 void
403 AttributeChecker::visit (AST::ArrayElemsValues &)
406 void
407 AttributeChecker::visit (AST::ArrayElemsCopied &)
410 void
411 AttributeChecker::visit (AST::ArrayExpr &)
414 void
415 AttributeChecker::visit (AST::ArrayIndexExpr &)
418 void
419 AttributeChecker::visit (AST::TupleExpr &)
422 void
423 AttributeChecker::visit (AST::TupleIndexExpr &)
426 void
427 AttributeChecker::visit (AST::StructExprStruct &)
430 void
431 AttributeChecker::visit (AST::StructExprFieldIdentifier &)
434 void
435 AttributeChecker::visit (AST::StructExprFieldIdentifierValue &)
438 void
439 AttributeChecker::visit (AST::StructExprFieldIndexValue &)
442 void
443 AttributeChecker::visit (AST::StructExprStructFields &)
446 void
447 AttributeChecker::visit (AST::StructExprStructBase &)
450 void
451 AttributeChecker::visit (AST::CallExpr &)
454 void
455 AttributeChecker::visit (AST::MethodCallExpr &)
458 void
459 AttributeChecker::visit (AST::FieldAccessExpr &)
462 void
463 AttributeChecker::visit (AST::ClosureExprInner &)
466 void
467 AttributeChecker::visit (AST::BlockExpr &expr)
469 for (auto &stmt : expr.get_statements ())
471 if (stmt->get_stmt_kind () == AST::Stmt::Kind::Item)
473 // Non owning pointer, let it go out of scope
474 auto item = static_cast<AST::Item *> (stmt.get ());
475 check_proc_macro_non_root (item->get_outer_attrs (),
476 item->get_locus ());
479 AST::DefaultASTVisitor::visit (expr);
482 void
483 AttributeChecker::visit (AST::ClosureExprInnerTyped &)
486 void
487 AttributeChecker::visit (AST::ContinueExpr &)
490 void
491 AttributeChecker::visit (AST::BreakExpr &)
494 void
495 AttributeChecker::visit (AST::RangeFromToExpr &)
498 void
499 AttributeChecker::visit (AST::RangeFromExpr &)
502 void
503 AttributeChecker::visit (AST::RangeToExpr &)
506 void
507 AttributeChecker::visit (AST::RangeFullExpr &)
510 void
511 AttributeChecker::visit (AST::RangeFromToInclExpr &)
514 void
515 AttributeChecker::visit (AST::RangeToInclExpr &)
518 void
519 AttributeChecker::visit (AST::ReturnExpr &)
522 void
523 AttributeChecker::visit (AST::LoopExpr &)
526 void
527 AttributeChecker::visit (AST::WhileLoopExpr &)
530 void
531 AttributeChecker::visit (AST::WhileLetLoopExpr &)
534 void
535 AttributeChecker::visit (AST::ForLoopExpr &)
538 void
539 AttributeChecker::visit (AST::IfExpr &)
542 void
543 AttributeChecker::visit (AST::IfExprConseqElse &)
546 void
547 AttributeChecker::visit (AST::IfLetExpr &)
550 void
551 AttributeChecker::visit (AST::IfLetExprConseqElse &)
554 void
555 AttributeChecker::visit (AST::MatchExpr &)
558 void
559 AttributeChecker::visit (AST::AwaitExpr &)
562 void
563 AttributeChecker::visit (AST::AsyncBlockExpr &)
566 // rust-item.h
567 void
568 AttributeChecker::visit (AST::TypeParam &)
571 void
572 AttributeChecker::visit (AST::LifetimeWhereClauseItem &)
575 void
576 AttributeChecker::visit (AST::TypeBoundWhereClauseItem &)
579 void
580 AttributeChecker::visit (AST::Module &module)
582 check_proc_macro_non_function (module.get_outer_attrs ());
583 for (auto &item : module.get_items ())
585 check_proc_macro_non_root (item->get_outer_attrs (), item->get_locus ());
587 AST::DefaultASTVisitor::visit (module);
590 void
591 AttributeChecker::visit (AST::ExternCrate &crate)
593 check_proc_macro_non_function (crate.get_outer_attrs ());
596 void
597 AttributeChecker::visit (AST::UseTreeGlob &)
600 void
601 AttributeChecker::visit (AST::UseTreeList &)
604 void
605 AttributeChecker::visit (AST::UseTreeRebind &)
608 void
609 AttributeChecker::visit (AST::UseDeclaration &declaration)
611 check_proc_macro_non_function (declaration.get_outer_attrs ());
614 static void
615 check_no_mangle_function (const AST::Attribute &attribute,
616 const AST::Function &fun)
618 if (attribute.has_attr_input ())
620 rust_error_at (attribute.get_locus (), ErrorCode::E0754,
621 "malformed %<no_mangle%> attribute input");
622 rust_inform (attribute.get_locus (),
623 "must be of the form: %<#[no_mangle]%>");
625 if (!is_ascii_only (fun.get_function_name ().as_string ()))
626 rust_error_at (fun.get_function_name ().get_locus (),
627 "the %<#[no_mangle]%> attribute requires ASCII identifier");
630 void
631 AttributeChecker::visit (AST::Function &fun)
633 auto check_crate_type = [] (const char *name, AST::Attribute &attribute) {
634 if (!Session::get_instance ().options.is_proc_macro ())
635 rust_error_at (attribute.get_locus (),
636 "the %<#[%s]%> attribute is only usable with crates of "
637 "the %<proc-macro%> crate type",
638 name);
641 BuiltinAttrDefinition result;
642 for (auto &attribute : fun.get_outer_attrs ())
644 if (!is_builtin (attribute, result))
645 return;
647 auto name = result.name.c_str ();
649 if (result.name == Attrs::PROC_MACRO_DERIVE)
651 if (!attribute.has_attr_input ())
653 rust_error_at (attribute.get_locus (),
654 "malformed %<%s%> attribute input", name);
655 rust_inform (
656 attribute.get_locus (),
657 "must be of the form: %<#[proc_macro_derive(TraitName, "
658 "/*opt*/ attributes(name1, name2, ...))]%>");
660 check_crate_type (name, attribute);
662 else if (result.name == Attrs::PROC_MACRO
663 || result.name == Attrs::PROC_MACRO_ATTRIBUTE)
665 check_crate_type (name, attribute);
667 else if (result.name == "no_mangle")
668 check_no_mangle_function (attribute, fun);
670 if (fun.has_body ())
671 fun.get_definition ().value ()->accept_vis (*this);
674 void
675 AttributeChecker::visit (AST::TypeAlias &alias)
677 check_proc_macro_non_function (alias.get_outer_attrs ());
680 void
681 AttributeChecker::visit (AST::StructStruct &struct_item)
683 check_attributes (struct_item.get_outer_attrs ());
684 check_proc_macro_non_function (struct_item.get_outer_attrs ());
687 void
688 AttributeChecker::visit (AST::TupleStruct &tuplestruct)
690 check_proc_macro_non_function (tuplestruct.get_outer_attrs ());
693 void
694 AttributeChecker::visit (AST::EnumItem &)
697 void
698 AttributeChecker::visit (AST::EnumItemTuple &)
701 void
702 AttributeChecker::visit (AST::EnumItemStruct &)
705 void
706 AttributeChecker::visit (AST::EnumItemDiscriminant &)
709 void
710 AttributeChecker::visit (AST::Enum &enumeration)
712 check_proc_macro_non_function (enumeration.get_outer_attrs ());
715 void
716 AttributeChecker::visit (AST::Union &u)
718 check_proc_macro_non_function (u.get_outer_attrs ());
721 void
722 AttributeChecker::visit (AST::ConstantItem &item)
724 check_proc_macro_non_function (item.get_outer_attrs ());
727 void
728 AttributeChecker::visit (AST::StaticItem &item)
730 check_proc_macro_non_function (item.get_outer_attrs ());
733 void
734 AttributeChecker::visit (AST::TraitItemConst &)
737 void
738 AttributeChecker::visit (AST::TraitItemType &)
741 void
742 AttributeChecker::visit (AST::Trait &trait)
744 check_proc_macro_non_function (trait.get_outer_attrs ());
747 void
748 AttributeChecker::visit (AST::InherentImpl &impl)
750 check_proc_macro_non_function (impl.get_outer_attrs ());
751 AST::DefaultASTVisitor::visit (impl);
754 void
755 AttributeChecker::visit (AST::TraitImpl &impl)
757 check_proc_macro_non_function (impl.get_outer_attrs ());
758 AST::DefaultASTVisitor::visit (impl);
761 void
762 AttributeChecker::visit (AST::ExternalTypeItem &)
765 void
766 AttributeChecker::visit (AST::ExternalStaticItem &)
769 void
770 AttributeChecker::visit (AST::ExternalFunctionItem &)
773 void
774 AttributeChecker::visit (AST::ExternBlock &block)
776 check_proc_macro_non_function (block.get_outer_attrs ());
779 // rust-macro.h
780 void
781 AttributeChecker::visit (AST::MacroMatchFragment &)
784 void
785 AttributeChecker::visit (AST::MacroMatchRepetition &)
788 void
789 AttributeChecker::visit (AST::MacroMatcher &)
792 void
793 AttributeChecker::visit (AST::MacroRulesDefinition &)
796 void
797 AttributeChecker::visit (AST::MacroInvocation &)
800 void
801 AttributeChecker::visit (AST::MetaItemPath &)
804 void
805 AttributeChecker::visit (AST::MetaItemSeq &)
808 void
809 AttributeChecker::visit (AST::MetaWord &)
812 void
813 AttributeChecker::visit (AST::MetaNameValueStr &)
816 void
817 AttributeChecker::visit (AST::MetaListPaths &)
820 void
821 AttributeChecker::visit (AST::MetaListNameValueStr &)
824 // rust-pattern.h
825 void
826 AttributeChecker::visit (AST::LiteralPattern &)
829 void
830 AttributeChecker::visit (AST::IdentifierPattern &)
833 void
834 AttributeChecker::visit (AST::WildcardPattern &)
837 void
838 AttributeChecker::visit (AST::RestPattern &)
841 // void AttributeChecker::visit(RangePatternBound& ){}
843 void
844 AttributeChecker::visit (AST::RangePatternBoundLiteral &)
847 void
848 AttributeChecker::visit (AST::RangePatternBoundPath &)
851 void
852 AttributeChecker::visit (AST::RangePatternBoundQualPath &)
855 void
856 AttributeChecker::visit (AST::RangePattern &)
859 void
860 AttributeChecker::visit (AST::ReferencePattern &)
863 // void AttributeChecker::visit(StructPatternField& ){}
865 void
866 AttributeChecker::visit (AST::StructPatternFieldTuplePat &)
869 void
870 AttributeChecker::visit (AST::StructPatternFieldIdentPat &)
873 void
874 AttributeChecker::visit (AST::StructPatternFieldIdent &)
877 void
878 AttributeChecker::visit (AST::StructPattern &)
881 // void AttributeChecker::visit(TupleStructItems& ){}
883 void
884 AttributeChecker::visit (AST::TupleStructItemsNoRange &)
887 void
888 AttributeChecker::visit (AST::TupleStructItemsRange &)
891 void
892 AttributeChecker::visit (AST::TupleStructPattern &)
895 // void AttributeChecker::visit(TuplePatternItems& ){}
897 void
898 AttributeChecker::visit (AST::TuplePatternItemsMultiple &)
901 void
902 AttributeChecker::visit (AST::TuplePatternItemsRanged &)
905 void
906 AttributeChecker::visit (AST::TuplePattern &)
909 void
910 AttributeChecker::visit (AST::GroupedPattern &)
913 void
914 AttributeChecker::visit (AST::SlicePattern &)
917 void
918 AttributeChecker::visit (AST::AltPattern &)
921 // rust-stmt.h
922 void
923 AttributeChecker::visit (AST::EmptyStmt &)
926 void
927 AttributeChecker::visit (AST::LetStmt &)
930 void
931 AttributeChecker::visit (AST::ExprStmt &)
934 // rust-type.h
935 void
936 AttributeChecker::visit (AST::TraitBound &)
939 void
940 AttributeChecker::visit (AST::ImplTraitType &)
943 void
944 AttributeChecker::visit (AST::TraitObjectType &)
947 void
948 AttributeChecker::visit (AST::ParenthesisedType &)
951 void
952 AttributeChecker::visit (AST::ImplTraitTypeOneBound &)
955 void
956 AttributeChecker::visit (AST::TraitObjectTypeOneBound &)
959 void
960 AttributeChecker::visit (AST::TupleType &)
963 void
964 AttributeChecker::visit (AST::NeverType &)
967 void
968 AttributeChecker::visit (AST::RawPointerType &)
971 void
972 AttributeChecker::visit (AST::ReferenceType &)
975 void
976 AttributeChecker::visit (AST::ArrayType &)
979 void
980 AttributeChecker::visit (AST::SliceType &)
983 void
984 AttributeChecker::visit (AST::InferredType &)
987 void
988 AttributeChecker::visit (AST::BareFunctionType &)
991 void
992 AttributeChecker::visit (AST::SelfParam &)
995 void
996 AttributeChecker::visit (AST::VariadicParam &)
999 void
1000 AttributeChecker::visit (AST::FunctionParam &)
1003 } // namespace Analysis
1004 } // namespace Rust