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::RUSTC_STD_INTERNAL_SYMBOL, CODE_GENERATION},
48 : {Attrs::EXPORT_NAME, CODE_GENERATION},
49 : {Attrs::REPR, CODE_GENERATION},
50 : {Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
51 : {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
52 : {Attrs::PATH, EXPANSION},
53 : {Attrs::MACRO_USE, NAME_RESOLUTION},
54 : {Attrs::MACRO_EXPORT, NAME_RESOLUTION},
55 : {Attrs::PROC_MACRO, EXPANSION},
56 : {Attrs::PROC_MACRO_DERIVE, EXPANSION},
57 : {Attrs::PROC_MACRO_ATTRIBUTE, EXPANSION},
58 : // FIXME: This is not implemented yet, see
59 : // https://github.com/Rust-GCC/gccrs/issues/1475
60 : {Attrs::TARGET_FEATURE, CODE_GENERATION},
61 : // From now on, these are reserved by the compiler and gated through
62 : // #![feature(rustc_attrs)]
63 : {Attrs::FEATURE, STATIC_ANALYSIS},
64 : {Attrs::NO_CORE, CODE_GENERATION},
65 : {Attrs::NO_STD, CODE_GENERATION},
66 : {Attrs::DOC, EXTERNAL},
67 : {Attrs::CRATE_NAME, CODE_GENERATION},
68 : {Attrs::CRATE_TYPE, CODE_GENERATION},
69 : {Attrs::MAY_DANGLE, STATIC_ANALYSIS},
70 : {Attrs::RUSTC_DEPRECATED, STATIC_ANALYSIS},
71 : {Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION},
72 : {Attrs::STABLE, STATIC_ANALYSIS},
73 : {Attrs::UNSTABLE, STATIC_ANALYSIS},
74 : // assuming we keep these for static analysis
75 : {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
76 : {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
77 : {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
78 : {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS},
79 : {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
80 : {Attrs::TRACK_CALLER, CODE_GENERATION},
81 : {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
82 : {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
83 : {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
84 : {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
85 : {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
86 : {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
87 : // TODO: be careful about calling functions marked with this?
88 : {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION},
89 : {Attrs::COMPILER_BUILTINS, CODE_GENERATION},
90 : {Attrs::NO_BUILTINS, CODE_GENERATION},
91 : {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
92 : {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
93 : {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
94 : {Attrs::FUNDAMENTAL, TYPE_CHECK},
95 : {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
96 : {Attrs::RUSTFMT, EXTERNAL},
97 : {Attrs::TEST, CODE_GENERATION},
98 : {Attrs::NEEDS_ALLOCATOR, CODE_GENERATION},
99 : {Attrs::RUSTC_ALLOCATOR, CODE_GENERATION},
100 : {Attrs::RUSTC_ALLOCATOR_NOUNWIND, CODE_GENERATION},
101 : {Attrs::GLOBAL_ALLOCATOR, CODE_GENERATION},
102 : {Attrs::RUSTC_CONVERSION_SUGGESTION, TYPE_CHECK}};
103 :
104 : static const std::set<std::string> __outer_attributes
105 : = {Attrs::INLINE,
106 : Attrs::DERIVE_ATTR,
107 : Attrs::ALLOW_INTERNAL_UNSTABLE,
108 : Attrs::LANG,
109 : Attrs::REPR,
110 : Attrs::PATH,
111 : Attrs::TARGET_FEATURE,
112 : Attrs::TEST,
113 : Attrs::COLD,
114 : Attrs::MACRO_USE,
115 : Attrs::MACRO_EXPORT,
116 : Attrs::PROC_MACRO_ATTRIBUTE,
117 : Attrs::PROC_MACRO_DERIVE,
118 : Attrs::DEPRECATED,
119 : Attrs::MUST_USE,
120 : Attrs::LINK_NAME,
121 : Attrs::LINK_SECTION};
122 :
123 : bool
124 88388 : Attributes::is_known (const std::string &attribute_path)
125 : {
126 88388 : const auto &lookup
127 88388 : = BuiltinAttributeMappings::get ()->lookup_builtin (attribute_path);
128 :
129 88388 : return !lookup.is_error ();
130 : }
131 :
132 : bool
133 12363 : Attributes::valid_outer_attribute (const std::string &attribute_path)
134 : {
135 12363 : return __outer_attributes.find (attribute_path) != __outer_attributes.cend ();
136 : }
137 :
138 : tl::optional<std::string>
139 7108 : Attributes::extract_string_literal (const AST::Attribute &attr)
140 : {
141 7108 : if (!attr.has_attr_input ())
142 0 : return tl::nullopt;
143 :
144 7108 : auto &attr_input = attr.get_attr_input ();
145 :
146 7108 : if (attr_input.get_attr_input_type ()
147 : != AST::AttrInput::AttrInputType::LITERAL)
148 0 : return tl::nullopt;
149 :
150 7108 : auto &literal_expr
151 7108 : = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal ();
152 :
153 7108 : auto lit_type = literal_expr.get_lit_type ();
154 :
155 : // TODO: bring escape sequence handling out of lexing?
156 7108 : if (lit_type != AST::Literal::LitType::STRING
157 7108 : && lit_type != AST::Literal::LitType::RAW_STRING)
158 0 : return tl::nullopt;
159 :
160 7108 : return literal_expr.as_string ();
161 : }
162 : BuiltinAttributeMappings *
163 4315464 : BuiltinAttributeMappings::get ()
164 : {
165 4315464 : static BuiltinAttributeMappings *instance = nullptr;
166 4315464 : if (instance == nullptr)
167 4844 : instance = new BuiltinAttributeMappings ();
168 :
169 4315464 : return instance;
170 : }
171 :
172 : const BuiltinAttrDefinition &
173 3912127 : BuiltinAttributeMappings::lookup_builtin (const std::string &attr_name) const
174 : {
175 3912127 : auto it = mappings.find (attr_name);
176 3912127 : if (it == mappings.end ())
177 2 : return BuiltinAttrDefinition::error_node ();
178 :
179 3912125 : return it->second;
180 : }
181 :
182 4844 : BuiltinAttributeMappings::BuiltinAttributeMappings ()
183 : {
184 4844 : size_t ndefinitions = sizeof (__definitions) / sizeof (BuiltinAttrDefinition);
185 324548 : for (size_t i = 0; i < ndefinitions; i++)
186 : {
187 319704 : const BuiltinAttrDefinition &def = __definitions[i];
188 639408 : mappings.insert ({def.name, def});
189 : }
190 4844 : }
191 :
192 : tl::optional<BuiltinAttrDefinition>
193 81188 : lookup_builtin (const AST::Attribute &attribute)
194 : {
195 81188 : auto &segments = attribute.get_path ().get_segments ();
196 :
197 : // Builtin attributes always have a single segment. This avoids us creating
198 : // strings all over the place and performing a linear search in the builtins
199 : // map
200 81188 : if (segments.size () != 1)
201 0 : return tl::nullopt;
202 :
203 81188 : return BuiltinAttributeMappings::get ()->lookup_builtin (
204 81188 : segments.at (0).get_segment_name ());
205 : }
206 :
207 : } // namespace Analysis
208 : } // namespace Rust
|