Line data Source code
1 : // Copyright (C) 2020-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-attributes.h"
20 : #include "rust-ast.h"
21 : #include "rust-ast-full.h"
22 : #include "rust-attribute-values.h"
23 :
24 : namespace Rust {
25 : namespace Analysis {
26 :
27 : using Attrs = Values::Attributes;
28 :
29 : // https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248
30 : static const BuiltinAttrDefinition __definitions[]
31 : = {{Attrs::INLINE, CODE_GENERATION},
32 : {Attrs::COLD, CODE_GENERATION},
33 : {Attrs::CFG, EXPANSION},
34 : {Attrs::CFG_ATTR, EXPANSION},
35 : {Attrs::DERIVE_ATTR, EXPANSION},
36 : {Attrs::DEPRECATED, STATIC_ANALYSIS},
37 : {Attrs::ALLOW, STATIC_ANALYSIS},
38 : {Attrs::WARN, STATIC_ANALYSIS},
39 : {Attrs::DENY, STATIC_ANALYSIS},
40 : {Attrs::ALLOW_INTERNAL_UNSTABLE, STATIC_ANALYSIS},
41 : {Attrs::DOC, HIR_LOWERING},
42 : {Attrs::MUST_USE, STATIC_ANALYSIS},
43 : {Attrs::LANG, HIR_LOWERING},
44 : {Attrs::LINK_NAME, CODE_GENERATION},
45 : {Attrs::LINK_SECTION, CODE_GENERATION},
46 : {Attrs::NO_MANGLE, CODE_GENERATION},
47 : {Attrs::EXPORT_NAME, CODE_GENERATION},
48 : {Attrs::REPR, CODE_GENERATION},
49 : {Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
50 : {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
51 : {Attrs::PATH, EXPANSION},
52 : {Attrs::MACRO_USE, NAME_RESOLUTION},
53 : {Attrs::MACRO_EXPORT, NAME_RESOLUTION},
54 : {Attrs::PROC_MACRO, EXPANSION},
55 : {Attrs::PROC_MACRO_DERIVE, EXPANSION},
56 : {Attrs::PROC_MACRO_ATTRIBUTE, EXPANSION},
57 : // FIXME: This is not implemented yet, see
58 : // https://github.com/Rust-GCC/gccrs/issues/1475
59 : {Attrs::TARGET_FEATURE, CODE_GENERATION},
60 : // From now on, these are reserved by the compiler and gated through
61 : // #![feature(rustc_attrs)]
62 : {Attrs::FEATURE, STATIC_ANALYSIS},
63 : {Attrs::NO_CORE, CODE_GENERATION},
64 : {Attrs::NO_STD, CODE_GENERATION},
65 : {Attrs::DOC, EXTERNAL},
66 : {Attrs::CRATE_NAME, CODE_GENERATION},
67 : {Attrs::CRATE_TYPE, CODE_GENERATION},
68 : {Attrs::MAY_DANGLE, STATIC_ANALYSIS},
69 : {Attrs::RUSTC_DEPRECATED, STATIC_ANALYSIS},
70 : {Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION},
71 : {Attrs::STABLE, STATIC_ANALYSIS},
72 : {Attrs::UNSTABLE, STATIC_ANALYSIS},
73 : // assuming we keep these for static analysis
74 : {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
75 : {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
76 : {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
77 : {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS},
78 : {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
79 : {Attrs::TRACK_CALLER, CODE_GENERATION},
80 : {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
81 : {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
82 : {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
83 : {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
84 : {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
85 : {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
86 : // TODO: be careful about calling functions marked with this?
87 : {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION},
88 : {Attrs::COMPILER_BUILTINS, CODE_GENERATION},
89 : {Attrs::NO_BUILTINS, CODE_GENERATION},
90 : {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
91 : {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
92 : {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
93 : {Attrs::FUNDAMENTAL, TYPE_CHECK},
94 : {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
95 : {Attrs::RUSTFMT, EXTERNAL},
96 : {Attrs::TEST, CODE_GENERATION}};
97 :
98 : static const std::set<std::string> __outer_attributes
99 : = {Attrs::INLINE,
100 : Attrs::DERIVE_ATTR,
101 : Attrs::ALLOW_INTERNAL_UNSTABLE,
102 : Attrs::LANG,
103 : Attrs::REPR,
104 : Attrs::PATH,
105 : Attrs::TARGET_FEATURE,
106 : Attrs::TEST,
107 : Attrs::COLD,
108 : Attrs::MACRO_USE,
109 : Attrs::MACRO_EXPORT,
110 : Attrs::PROC_MACRO_ATTRIBUTE,
111 : Attrs::PROC_MACRO_DERIVE,
112 : Attrs::DEPRECATED,
113 : Attrs::MUST_USE,
114 : Attrs::LINK_NAME,
115 : Attrs::LINK_SECTION};
116 :
117 : bool
118 29298 : Attributes::is_known (const std::string &attribute_path)
119 : {
120 29298 : const auto &lookup
121 29298 : = BuiltinAttributeMappings::get ()->lookup_builtin (attribute_path);
122 :
123 29298 : return !lookup.is_error ();
124 : }
125 :
126 : bool
127 11908 : Attributes::valid_outer_attribute (const std::string &attribute_path)
128 : {
129 11908 : return __outer_attributes.find (attribute_path) != __outer_attributes.cend ();
130 : }
131 :
132 : tl::optional<std::string>
133 6768 : Attributes::extract_string_literal (const AST::Attribute &attr)
134 : {
135 6768 : if (!attr.has_attr_input ())
136 0 : return tl::nullopt;
137 :
138 6768 : auto &attr_input = attr.get_attr_input ();
139 :
140 6768 : if (attr_input.get_attr_input_type ()
141 : != AST::AttrInput::AttrInputType::LITERAL)
142 0 : return tl::nullopt;
143 :
144 6768 : auto &literal_expr
145 6768 : = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal ();
146 :
147 6768 : auto lit_type = literal_expr.get_lit_type ();
148 :
149 : // TODO: bring escape sequence handling out of lexing?
150 6768 : if (lit_type != AST::Literal::LitType::STRING
151 6768 : && lit_type != AST::Literal::LitType::RAW_STRING)
152 0 : return tl::nullopt;
153 :
154 6768 : return literal_expr.as_string ();
155 : }
156 : BuiltinAttributeMappings *
157 540117 : BuiltinAttributeMappings::get ()
158 : {
159 540117 : static BuiltinAttributeMappings *instance = nullptr;
160 540117 : if (instance == nullptr)
161 4695 : instance = new BuiltinAttributeMappings ();
162 :
163 540117 : return instance;
164 : }
165 :
166 : const BuiltinAttrDefinition &
167 145338 : BuiltinAttributeMappings::lookup_builtin (const std::string &attr_name) const
168 : {
169 145338 : auto it = mappings.find (attr_name);
170 145338 : if (it == mappings.end ())
171 2 : return BuiltinAttrDefinition::error_node ();
172 :
173 145336 : return it->second;
174 : }
175 :
176 4695 : BuiltinAttributeMappings::BuiltinAttributeMappings ()
177 : {
178 4695 : size_t ndefinitions = sizeof (__definitions) / sizeof (BuiltinAttrDefinition);
179 286395 : for (size_t i = 0; i < ndefinitions; i++)
180 : {
181 281700 : const BuiltinAttrDefinition &def = __definitions[i];
182 563400 : mappings.insert ({def.name, def});
183 : }
184 4695 : }
185 :
186 : tl::optional<BuiltinAttrDefinition>
187 28934 : lookup_builtin (const AST::Attribute &attribute)
188 : {
189 28934 : auto &segments = attribute.get_path ().get_segments ();
190 :
191 : // Builtin attributes always have a single segment. This avoids us creating
192 : // strings all over the place and performing a linear search in the builtins
193 : // map
194 28934 : if (segments.size () != 1)
195 0 : return tl::nullopt;
196 :
197 28934 : return BuiltinAttributeMappings::get ()->lookup_builtin (
198 28934 : segments.at (0).get_segment_name ());
199 : }
200 :
201 : } // namespace Analysis
202 : } // namespace Rust
|