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