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
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
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"
24 #include "rust-ast-full.h"
25 #include "rust-diagnostics.h"
26 #include "rust-unicode.h"
27 #include "rust-attribute-values.h"
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 ();
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 ();
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 () {}
97 AttributeChecker::go (AST::Crate
&crate
)
103 AttributeChecker::visit (AST::Crate
&crate
)
105 check_attributes (crate
.get_inner_attrs ());
107 for (auto &item
: crate
.items
)
108 item
->accept_vis (*this);
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
119 if (segments
.size () != 1)
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
132 * This means no whitespace characters other than spaces and no quoting
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
);
155 rust_error_at (locus
,
156 "invalid character used in %<#[doc(alias)]%> input: %qs",
160 if (alias_input
.empty ())
163 if (alias_input
.front () == ' ' || alias_input
.back () == ' ')
164 rust_error_at (locus
,
165 "%<#[doc(alias)]%> input cannot start or end with a space");
169 check_doc_attribute (const AST::Attribute
&attribute
)
171 if (!attribute
.has_attr_input ())
174 attribute
.get_locus (),
175 // FIXME: Improve error message here. Rustc has a very good one
176 "%<#[doc]%> cannot be an empty attribute");
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
:
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 ())
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 ());
213 is_proc_macro_type (const AST::Attribute
&attribute
)
215 BuiltinAttrDefinition result
;
216 if (!is_builtin (attribute
, result
))
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]
227 check_proc_macro_non_function (const AST::AttrVec
&attributes
)
229 for (auto &attr
: attributes
)
231 if (is_proc_macro_type (attr
))
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
242 check_proc_macro_non_root (AST::AttrVec attributes
, location_t loc
)
244 for (auto &attr
: attributes
)
246 if (is_proc_macro_type (attr
))
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 ());
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
))
266 // TODO: Add checks here for each builtin attribute
267 // TODO: Have an enum of builtins as well, switching on strings is annoying
269 if (result
.name
== Attrs::DOC
)
270 check_doc_attribute (attribute
);
274 AttributeChecker::check_attributes (const AST::AttrVec
&attributes
)
276 for (auto &attr
: attributes
)
277 check_attribute (attr
);
281 AttributeChecker::visit (AST::Token
&)
285 AttributeChecker::visit (AST::DelimTokenTree
&)
289 AttributeChecker::visit (AST::AttrInputMetaItemContainer
&)
293 AttributeChecker::visit (AST::IdentifierExpr
&)
297 AttributeChecker::visit (AST::Lifetime
&)
301 AttributeChecker::visit (AST::LifetimeParam
&)
305 AttributeChecker::visit (AST::ConstGenericParam
&)
310 AttributeChecker::visit (AST::PathInExpression
&)
314 AttributeChecker::visit (AST::TypePathSegment
&)
318 AttributeChecker::visit (AST::TypePathSegmentGeneric
&)
322 AttributeChecker::visit (AST::TypePathSegmentFunction
&)
326 AttributeChecker::visit (AST::TypePath
&)
330 AttributeChecker::visit (AST::QualifiedPathInExpression
&)
334 AttributeChecker::visit (AST::QualifiedPathInType
&)
339 AttributeChecker::visit (AST::LiteralExpr
&)
343 AttributeChecker::visit (AST::AttrInputLiteral
&)
347 AttributeChecker::visit (AST::AttrInputMacro
&)
351 AttributeChecker::visit (AST::MetaItemLitExpr
&)
355 AttributeChecker::visit (AST::MetaItemPathLit
&)
359 AttributeChecker::visit (AST::BorrowExpr
&)
363 AttributeChecker::visit (AST::DereferenceExpr
&)
367 AttributeChecker::visit (AST::ErrorPropagationExpr
&)
371 AttributeChecker::visit (AST::NegationExpr
&)
375 AttributeChecker::visit (AST::ArithmeticOrLogicalExpr
&)
379 AttributeChecker::visit (AST::ComparisonExpr
&)
383 AttributeChecker::visit (AST::LazyBooleanExpr
&)
387 AttributeChecker::visit (AST::TypeCastExpr
&)
391 AttributeChecker::visit (AST::AssignmentExpr
&)
395 AttributeChecker::visit (AST::CompoundAssignmentExpr
&)
399 AttributeChecker::visit (AST::GroupedExpr
&)
403 AttributeChecker::visit (AST::ArrayElemsValues
&)
407 AttributeChecker::visit (AST::ArrayElemsCopied
&)
411 AttributeChecker::visit (AST::ArrayExpr
&)
415 AttributeChecker::visit (AST::ArrayIndexExpr
&)
419 AttributeChecker::visit (AST::TupleExpr
&)
423 AttributeChecker::visit (AST::TupleIndexExpr
&)
427 AttributeChecker::visit (AST::StructExprStruct
&)
431 AttributeChecker::visit (AST::StructExprFieldIdentifier
&)
435 AttributeChecker::visit (AST::StructExprFieldIdentifierValue
&)
439 AttributeChecker::visit (AST::StructExprFieldIndexValue
&)
443 AttributeChecker::visit (AST::StructExprStructFields
&)
447 AttributeChecker::visit (AST::StructExprStructBase
&)
451 AttributeChecker::visit (AST::CallExpr
&)
455 AttributeChecker::visit (AST::MethodCallExpr
&)
459 AttributeChecker::visit (AST::FieldAccessExpr
&)
463 AttributeChecker::visit (AST::ClosureExprInner
&)
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 (),
479 AST::DefaultASTVisitor::visit (expr
);
483 AttributeChecker::visit (AST::ClosureExprInnerTyped
&)
487 AttributeChecker::visit (AST::ContinueExpr
&)
491 AttributeChecker::visit (AST::BreakExpr
&)
495 AttributeChecker::visit (AST::RangeFromToExpr
&)
499 AttributeChecker::visit (AST::RangeFromExpr
&)
503 AttributeChecker::visit (AST::RangeToExpr
&)
507 AttributeChecker::visit (AST::RangeFullExpr
&)
511 AttributeChecker::visit (AST::RangeFromToInclExpr
&)
515 AttributeChecker::visit (AST::RangeToInclExpr
&)
519 AttributeChecker::visit (AST::ReturnExpr
&)
523 AttributeChecker::visit (AST::LoopExpr
&)
527 AttributeChecker::visit (AST::WhileLoopExpr
&)
531 AttributeChecker::visit (AST::WhileLetLoopExpr
&)
535 AttributeChecker::visit (AST::ForLoopExpr
&)
539 AttributeChecker::visit (AST::IfExpr
&)
543 AttributeChecker::visit (AST::IfExprConseqElse
&)
547 AttributeChecker::visit (AST::IfLetExpr
&)
551 AttributeChecker::visit (AST::IfLetExprConseqElse
&)
555 AttributeChecker::visit (AST::MatchExpr
&)
559 AttributeChecker::visit (AST::AwaitExpr
&)
563 AttributeChecker::visit (AST::AsyncBlockExpr
&)
568 AttributeChecker::visit (AST::TypeParam
&)
572 AttributeChecker::visit (AST::LifetimeWhereClauseItem
&)
576 AttributeChecker::visit (AST::TypeBoundWhereClauseItem
&)
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
);
591 AttributeChecker::visit (AST::ExternCrate
&crate
)
593 check_proc_macro_non_function (crate
.get_outer_attrs ());
597 AttributeChecker::visit (AST::UseTreeGlob
&)
601 AttributeChecker::visit (AST::UseTreeList
&)
605 AttributeChecker::visit (AST::UseTreeRebind
&)
609 AttributeChecker::visit (AST::UseDeclaration
&declaration
)
611 check_proc_macro_non_function (declaration
.get_outer_attrs ());
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");
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",
641 BuiltinAttrDefinition result
;
642 for (auto &attribute
: fun
.get_outer_attrs ())
644 if (!is_builtin (attribute
, result
))
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
);
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
);
671 fun
.get_definition ().value ()->accept_vis (*this);
675 AttributeChecker::visit (AST::TypeAlias
&alias
)
677 check_proc_macro_non_function (alias
.get_outer_attrs ());
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 ());
688 AttributeChecker::visit (AST::TupleStruct
&tuplestruct
)
690 check_proc_macro_non_function (tuplestruct
.get_outer_attrs ());
694 AttributeChecker::visit (AST::EnumItem
&)
698 AttributeChecker::visit (AST::EnumItemTuple
&)
702 AttributeChecker::visit (AST::EnumItemStruct
&)
706 AttributeChecker::visit (AST::EnumItemDiscriminant
&)
710 AttributeChecker::visit (AST::Enum
&enumeration
)
712 check_proc_macro_non_function (enumeration
.get_outer_attrs ());
716 AttributeChecker::visit (AST::Union
&u
)
718 check_proc_macro_non_function (u
.get_outer_attrs ());
722 AttributeChecker::visit (AST::ConstantItem
&item
)
724 check_proc_macro_non_function (item
.get_outer_attrs ());
728 AttributeChecker::visit (AST::StaticItem
&item
)
730 check_proc_macro_non_function (item
.get_outer_attrs ());
734 AttributeChecker::visit (AST::TraitItemConst
&)
738 AttributeChecker::visit (AST::TraitItemType
&)
742 AttributeChecker::visit (AST::Trait
&trait
)
744 check_proc_macro_non_function (trait
.get_outer_attrs ());
748 AttributeChecker::visit (AST::InherentImpl
&impl
)
750 check_proc_macro_non_function (impl
.get_outer_attrs ());
751 AST::DefaultASTVisitor::visit (impl
);
755 AttributeChecker::visit (AST::TraitImpl
&impl
)
757 check_proc_macro_non_function (impl
.get_outer_attrs ());
758 AST::DefaultASTVisitor::visit (impl
);
762 AttributeChecker::visit (AST::ExternalTypeItem
&)
766 AttributeChecker::visit (AST::ExternalStaticItem
&)
770 AttributeChecker::visit (AST::ExternalFunctionItem
&)
774 AttributeChecker::visit (AST::ExternBlock
&block
)
776 check_proc_macro_non_function (block
.get_outer_attrs ());
781 AttributeChecker::visit (AST::MacroMatchFragment
&)
785 AttributeChecker::visit (AST::MacroMatchRepetition
&)
789 AttributeChecker::visit (AST::MacroMatcher
&)
793 AttributeChecker::visit (AST::MacroRulesDefinition
&)
797 AttributeChecker::visit (AST::MacroInvocation
&)
801 AttributeChecker::visit (AST::MetaItemPath
&)
805 AttributeChecker::visit (AST::MetaItemSeq
&)
809 AttributeChecker::visit (AST::MetaWord
&)
813 AttributeChecker::visit (AST::MetaNameValueStr
&)
817 AttributeChecker::visit (AST::MetaListPaths
&)
821 AttributeChecker::visit (AST::MetaListNameValueStr
&)
826 AttributeChecker::visit (AST::LiteralPattern
&)
830 AttributeChecker::visit (AST::IdentifierPattern
&)
834 AttributeChecker::visit (AST::WildcardPattern
&)
838 AttributeChecker::visit (AST::RestPattern
&)
841 // void AttributeChecker::visit(RangePatternBound& ){}
844 AttributeChecker::visit (AST::RangePatternBoundLiteral
&)
848 AttributeChecker::visit (AST::RangePatternBoundPath
&)
852 AttributeChecker::visit (AST::RangePatternBoundQualPath
&)
856 AttributeChecker::visit (AST::RangePattern
&)
860 AttributeChecker::visit (AST::ReferencePattern
&)
863 // void AttributeChecker::visit(StructPatternField& ){}
866 AttributeChecker::visit (AST::StructPatternFieldTuplePat
&)
870 AttributeChecker::visit (AST::StructPatternFieldIdentPat
&)
874 AttributeChecker::visit (AST::StructPatternFieldIdent
&)
878 AttributeChecker::visit (AST::StructPattern
&)
881 // void AttributeChecker::visit(TupleStructItems& ){}
884 AttributeChecker::visit (AST::TupleStructItemsNoRange
&)
888 AttributeChecker::visit (AST::TupleStructItemsRange
&)
892 AttributeChecker::visit (AST::TupleStructPattern
&)
895 // void AttributeChecker::visit(TuplePatternItems& ){}
898 AttributeChecker::visit (AST::TuplePatternItemsMultiple
&)
902 AttributeChecker::visit (AST::TuplePatternItemsRanged
&)
906 AttributeChecker::visit (AST::TuplePattern
&)
910 AttributeChecker::visit (AST::GroupedPattern
&)
914 AttributeChecker::visit (AST::SlicePattern
&)
918 AttributeChecker::visit (AST::AltPattern
&)
923 AttributeChecker::visit (AST::EmptyStmt
&)
927 AttributeChecker::visit (AST::LetStmt
&)
931 AttributeChecker::visit (AST::ExprStmt
&)
936 AttributeChecker::visit (AST::TraitBound
&)
940 AttributeChecker::visit (AST::ImplTraitType
&)
944 AttributeChecker::visit (AST::TraitObjectType
&)
948 AttributeChecker::visit (AST::ParenthesisedType
&)
952 AttributeChecker::visit (AST::ImplTraitTypeOneBound
&)
956 AttributeChecker::visit (AST::TraitObjectTypeOneBound
&)
960 AttributeChecker::visit (AST::TupleType
&)
964 AttributeChecker::visit (AST::NeverType
&)
968 AttributeChecker::visit (AST::RawPointerType
&)
972 AttributeChecker::visit (AST::ReferenceType
&)
976 AttributeChecker::visit (AST::ArrayType
&)
980 AttributeChecker::visit (AST::SliceType
&)
984 AttributeChecker::visit (AST::InferredType
&)
988 AttributeChecker::visit (AST::BareFunctionType
&)
992 AttributeChecker::visit (AST::SelfParam
&)
996 AttributeChecker::visit (AST::VariadicParam
&)
1000 AttributeChecker::visit (AST::FunctionParam
&)
1003 } // namespace Analysis