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::RUSTC_ALLOCATOR, CODE_GENERATION},
99 : {Attrs::RUSTC_ALLOCATOR_NOUNWIND, CODE_GENERATION}};
100 :
101 : static const std::set<std::string> __outer_attributes
102 : = {Attrs::INLINE,
103 : Attrs::DERIVE_ATTR,
104 : Attrs::ALLOW_INTERNAL_UNSTABLE,
105 : Attrs::LANG,
106 : Attrs::REPR,
107 : Attrs::PATH,
108 : Attrs::TARGET_FEATURE,
109 : Attrs::TEST,
110 : Attrs::COLD,
111 : Attrs::MACRO_USE,
112 : Attrs::MACRO_EXPORT,
113 : Attrs::PROC_MACRO_ATTRIBUTE,
114 : Attrs::PROC_MACRO_DERIVE,
115 : Attrs::DEPRECATED,
116 : Attrs::MUST_USE,
117 : Attrs::LINK_NAME,
118 : Attrs::LINK_SECTION};
119 :
120 : bool
121 29461 : Attributes::is_known (const std::string &attribute_path)
122 : {
123 29461 : const auto &lookup
124 29461 : = BuiltinAttributeMappings::get ()->lookup_builtin (attribute_path);
125 :
126 29461 : return !lookup.is_error ();
127 : }
128 :
129 : bool
130 12067 : Attributes::valid_outer_attribute (const std::string &attribute_path)
131 : {
132 12067 : return __outer_attributes.find (attribute_path) != __outer_attributes.cend ();
133 : }
134 :
135 : tl::optional<std::string>
136 6912 : Attributes::extract_string_literal (const AST::Attribute &attr)
137 : {
138 6912 : if (!attr.has_attr_input ())
139 0 : return tl::nullopt;
140 :
141 6912 : auto &attr_input = attr.get_attr_input ();
142 :
143 6912 : if (attr_input.get_attr_input_type ()
144 : != AST::AttrInput::AttrInputType::LITERAL)
145 0 : return tl::nullopt;
146 :
147 6912 : auto &literal_expr
148 6912 : = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal ();
149 :
150 6912 : auto lit_type = literal_expr.get_lit_type ();
151 :
152 : // TODO: bring escape sequence handling out of lexing?
153 6912 : if (lit_type != AST::Literal::LitType::STRING
154 6912 : && lit_type != AST::Literal::LitType::RAW_STRING)
155 0 : return tl::nullopt;
156 :
157 6912 : return literal_expr.as_string ();
158 : }
159 : BuiltinAttributeMappings *
160 546338 : BuiltinAttributeMappings::get ()
161 : {
162 546338 : static BuiltinAttributeMappings *instance = nullptr;
163 546338 : if (instance == nullptr)
164 4770 : instance = new BuiltinAttributeMappings ();
165 :
166 546338 : return instance;
167 : }
168 :
169 : const BuiltinAttrDefinition &
170 146445 : BuiltinAttributeMappings::lookup_builtin (const std::string &attr_name) const
171 : {
172 146445 : auto it = mappings.find (attr_name);
173 146445 : if (it == mappings.end ())
174 2 : return BuiltinAttrDefinition::error_node ();
175 :
176 146443 : return it->second;
177 : }
178 :
179 4770 : BuiltinAttributeMappings::BuiltinAttributeMappings ()
180 : {
181 4770 : size_t ndefinitions = sizeof (__definitions) / sizeof (BuiltinAttrDefinition);
182 305280 : for (size_t i = 0; i < ndefinitions; i++)
183 : {
184 300510 : const BuiltinAttrDefinition &def = __definitions[i];
185 601020 : mappings.insert ({def.name, def});
186 : }
187 4770 : }
188 :
189 : tl::optional<BuiltinAttrDefinition>
190 29185 : lookup_builtin (const AST::Attribute &attribute)
191 : {
192 29185 : auto &segments = attribute.get_path ().get_segments ();
193 :
194 : // Builtin attributes always have a single segment. This avoids us creating
195 : // strings all over the place and performing a linear search in the builtins
196 : // map
197 29185 : if (segments.size () != 1)
198 0 : return tl::nullopt;
199 :
200 29185 : return BuiltinAttributeMappings::get ()->lookup_builtin (
201 29185 : segments.at (0).get_segment_name ());
202 : }
203 :
204 : } // namespace Analysis
205 : } // namespace Rust
|