Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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-ast-visitor.h"
20 : : #include "rust-system.h"
21 : : #include "rust-session-manager.h"
22 : : #include "rust-attributes.h"
23 : : #include "rust-ast.h"
24 : : #include "rust-ast-full.h"
25 : : #include "rust-diagnostics.h"
26 : : #include "rust-unicode.h"
27 : : #include "rust-attribute-values.h"
28 : :
29 : : namespace Rust {
30 : : namespace Analysis {
31 : :
32 : : bool
33 : 89260 : Attributes::is_known (const std::string &attribute_path)
34 : : {
35 : 89260 : const auto &lookup
36 : 89260 : = BuiltinAttributeMappings::get ()->lookup_builtin (attribute_path);
37 : :
38 : 89260 : return !lookup.is_error ();
39 : : }
40 : :
41 : : tl::optional<std::string>
42 : 6431 : Attributes::extract_string_literal (const AST::Attribute &attr)
43 : : {
44 : 6431 : if (!attr.has_attr_input ())
45 : 0 : return tl::nullopt;
46 : :
47 : 6431 : auto &attr_input = attr.get_attr_input ();
48 : :
49 : 6431 : if (attr_input.get_attr_input_type ()
50 : : != AST::AttrInput::AttrInputType::LITERAL)
51 : 0 : return tl::nullopt;
52 : :
53 : 6431 : auto &literal_expr
54 : 6431 : = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal ();
55 : :
56 : 6431 : auto lit_type = literal_expr.get_lit_type ();
57 : :
58 : : // TODO: bring escape sequence handling out of lexing?
59 : 6431 : if (lit_type != AST::Literal::LitType::STRING
60 : 6431 : && lit_type != AST::Literal::LitType::RAW_STRING)
61 : 0 : return tl::nullopt;
62 : :
63 : 6431 : return literal_expr.as_string ();
64 : : }
65 : :
66 : : using Attrs = Values::Attributes;
67 : :
68 : : // https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248
69 : : static const BuiltinAttrDefinition __definitions[]
70 : : = {{Attrs::INLINE, CODE_GENERATION},
71 : : {Attrs::COLD, CODE_GENERATION},
72 : : {Attrs::CFG, EXPANSION},
73 : : {Attrs::CFG_ATTR, EXPANSION},
74 : : {Attrs::DERIVE_ATTR, EXPANSION},
75 : : {Attrs::DEPRECATED, STATIC_ANALYSIS},
76 : : {Attrs::ALLOW, STATIC_ANALYSIS},
77 : : {Attrs::ALLOW_INTERNAL_UNSTABLE, STATIC_ANALYSIS},
78 : : {Attrs::DOC, HIR_LOWERING},
79 : : {Attrs::MUST_USE, STATIC_ANALYSIS},
80 : : {Attrs::LANG, HIR_LOWERING},
81 : : {Attrs::LINK_NAME, CODE_GENERATION},
82 : : {Attrs::LINK_SECTION, CODE_GENERATION},
83 : : {Attrs::NO_MANGLE, CODE_GENERATION},
84 : : {Attrs::REPR, CODE_GENERATION},
85 : : {Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
86 : : {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
87 : : {Attrs::PATH, EXPANSION},
88 : : {Attrs::MACRO_USE, NAME_RESOLUTION},
89 : : {Attrs::MACRO_EXPORT, NAME_RESOLUTION},
90 : : {Attrs::PROC_MACRO, EXPANSION},
91 : : {Attrs::PROC_MACRO_DERIVE, EXPANSION},
92 : : {Attrs::PROC_MACRO_ATTRIBUTE, EXPANSION},
93 : :
94 : : {Attrs::DERIVE, EXPANSION},
95 : : // FIXME: This is not implemented yet, see
96 : : // https://github.com/Rust-GCC/gccrs/issues/1475
97 : : {Attrs::TARGET_FEATURE, CODE_GENERATION},
98 : : // From now on, these are reserved by the compiler and gated through
99 : : // #![feature(rustc_attrs)]
100 : : {Attrs::RUSTC_DEPRECATED, STATIC_ANALYSIS},
101 : : {Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION},
102 : : {Attrs::STABLE, STATIC_ANALYSIS},
103 : : {Attrs::UNSTABLE, STATIC_ANALYSIS},
104 : :
105 : : // assuming we keep these for static analysis
106 : : {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
107 : : {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
108 : : {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
109 : : {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS},
110 : : {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
111 : : {Attrs::TRACK_CALLER, CODE_GENERATION},
112 : : {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
113 : : {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
114 : : {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
115 : : {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
116 : : {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
117 : :
118 : : {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
119 : :
120 : : // TODO: be careful about calling functions marked with this?
121 : : {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION},
122 : :
123 : : {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
124 : :
125 : : {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
126 : : {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
127 : :
128 : : {Attrs::FUNDAMENTAL, TYPE_CHECK},
129 : : {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
130 : : {Attrs::RUSTFMT, EXTERNAL},
131 : :
132 : : {Attrs::TEST, CODE_GENERATION}};
133 : :
134 : : BuiltinAttributeMappings *
135 : 3686920 : BuiltinAttributeMappings::get ()
136 : : {
137 : 3686920 : static BuiltinAttributeMappings *instance = nullptr;
138 : 3686920 : if (instance == nullptr)
139 : 4292 : instance = new BuiltinAttributeMappings ();
140 : :
141 : 3686920 : return instance;
142 : : }
143 : :
144 : : const BuiltinAttrDefinition &
145 : 3310268 : BuiltinAttributeMappings::lookup_builtin (const std::string &attr_name) const
146 : : {
147 : 3310268 : auto it = mappings.find (attr_name);
148 : 3310268 : if (it == mappings.end ())
149 : 730 : return BuiltinAttrDefinition::error_node ();
150 : :
151 : 3309538 : return it->second;
152 : : }
153 : :
154 : 4292 : BuiltinAttributeMappings::BuiltinAttributeMappings ()
155 : : {
156 : 4292 : size_t ndefinitions = sizeof (__definitions) / sizeof (BuiltinAttrDefinition);
157 : 214600 : for (size_t i = 0; i < ndefinitions; i++)
158 : : {
159 : 210308 : const BuiltinAttrDefinition &def = __definitions[i];
160 : 420616 : mappings.insert ({def.name, def});
161 : : }
162 : 4292 : }
163 : :
164 : 4383 : AttributeChecker::AttributeChecker () {}
165 : :
166 : : void
167 : 4383 : AttributeChecker::go (AST::Crate &crate)
168 : : {
169 : 4383 : visit (crate);
170 : 4383 : }
171 : :
172 : : void
173 : 4383 : AttributeChecker::visit (AST::Crate &crate)
174 : : {
175 : 4383 : check_inner_attributes (crate.get_inner_attrs ());
176 : 4383 : check_attributes (crate.get_inner_attrs ());
177 : :
178 : 22354 : for (auto &item : crate.items)
179 : 17971 : item->accept_vis (*this);
180 : 4383 : }
181 : :
182 : : static bool
183 : 12245 : is_builtin (const AST::Attribute &attribute, BuiltinAttrDefinition &builtin)
184 : : {
185 : 12245 : auto &segments = attribute.get_path ().get_segments ();
186 : :
187 : : // Builtin attributes always have a single segment. This avoids us creating
188 : : // strings all over the place and performing a linear search in the builtins
189 : : // map
190 : 12245 : if (segments.size () != 1)
191 : : return false;
192 : :
193 : 12245 : builtin = BuiltinAttributeMappings::get ()->lookup_builtin (
194 : 12245 : segments.at (0).get_segment_name ());
195 : :
196 : 12245 : return !builtin.is_error ();
197 : : }
198 : :
199 : : /**
200 : : * Check that the string given to #[doc(alias = ...)] or #[doc(alias(...))] is
201 : : * valid.
202 : : *
203 : : * This means no whitespace characters other than spaces and no quoting
204 : : * characters.
205 : : */
206 : : static void
207 : 700 : check_doc_alias (const std::string &alias_input, const location_t locus)
208 : : {
209 : : // FIXME: The locus here is for the whole attribute. Can we get the locus
210 : : // of the alias input instead?
211 : 1872 : for (auto c : alias_input)
212 : 1172 : if ((ISSPACE (c) && c != ' ') || c == '\'' || c == '\"')
213 : : {
214 : 7 : auto to_print = std::string (1, c);
215 : 7 : switch (c)
216 : : {
217 : 7 : case '\n':
218 : 7 : to_print = "\\n";
219 : 7 : break;
220 : 0 : case '\t':
221 : 0 : to_print = "\\t";
222 : 0 : break;
223 : : default:
224 : : break;
225 : : }
226 : 7 : rust_error_at (locus,
227 : : "invalid character used in %<#[doc(alias)]%> input: %qs",
228 : : to_print.c_str ());
229 : 7 : }
230 : :
231 : 700 : if (alias_input.empty ())
232 : : return;
233 : :
234 : 1400 : if (alias_input.front () == ' ' || alias_input.back () == ' ')
235 : 0 : rust_error_at (locus,
236 : : "%<#[doc(alias)]%> input cannot start or end with a space");
237 : : }
238 : :
239 : : static void
240 : 916 : check_doc_attribute (const AST::Attribute &attribute)
241 : : {
242 : 916 : if (!attribute.has_attr_input ())
243 : : {
244 : 1 : rust_error_at (
245 : : attribute.get_locus (),
246 : : "valid forms for the attribute are "
247 : : "%<#[doc(hidden|inline|...)]%> and %<#[doc = \" string \"]%>");
248 : 1 : return;
249 : : }
250 : :
251 : 915 : switch (attribute.get_attr_input ().get_attr_input_type ())
252 : : {
253 : : case AST::AttrInput::LITERAL:
254 : : case AST::AttrInput::MACRO:
255 : : case AST::AttrInput::META_ITEM:
256 : : break;
257 : : // FIXME: Handle them as well
258 : :
259 : 743 : case AST::AttrInput::TOKEN_TREE:
260 : 743 : {
261 : : // FIXME: This doesn't check for #[doc(alias(...))]
262 : 743 : const auto &option = static_cast<const AST::DelimTokenTree &> (
263 : 743 : attribute.get_attr_input ());
264 : 743 : auto *meta_item = option.parse_to_meta_item ();
265 : :
266 : 1497 : for (auto &item : meta_item->get_items ())
267 : : {
268 : 754 : if (item->is_key_value_pair ())
269 : : {
270 : 710 : auto name_value
271 : 710 : = static_cast<AST::MetaNameValueStr *> (item.get ())
272 : 710 : ->get_name_value_pair ();
273 : :
274 : : // FIXME: Check for other stuff than #[doc(alias = ...)]
275 : 710 : if (name_value.first.as_string () == "alias")
276 : 700 : check_doc_alias (name_value.second, attribute.get_locus ());
277 : 710 : }
278 : : }
279 : : break;
280 : : }
281 : : }
282 : : }
283 : :
284 : : static bool
285 : 6718 : is_proc_macro_type (const AST::Attribute &attribute)
286 : : {
287 : 6718 : BuiltinAttrDefinition result;
288 : 6718 : if (!is_builtin (attribute, result))
289 : : return false;
290 : :
291 : 6718 : auto name = result.name;
292 : 6700 : return name == Attrs::PROC_MACRO || name == Attrs::PROC_MACRO_DERIVE
293 : 13418 : || name == Attrs::PROC_MACRO_ATTRIBUTE;
294 : 6718 : }
295 : :
296 : : // Emit an error when one encountered attribute is either #[proc_macro],
297 : : // #[proc_macro_attribute] or #[proc_macro_derive]
298 : : static void
299 : 14213 : check_proc_macro_non_function (const AST::AttrVec &attributes)
300 : : {
301 : 18923 : for (auto &attr : attributes)
302 : : {
303 : 4710 : if (is_proc_macro_type (attr))
304 : 45 : rust_error_at (
305 : : attr.get_locus (),
306 : : "the %<#[%s]%> attribute may only be used on bare functions",
307 : 90 : attr.get_path ().get_segments ()[0].as_string ().c_str ());
308 : : }
309 : 14213 : }
310 : :
311 : : // Emit an error when one attribute is either proc_macro, proc_macro_attribute
312 : : // or proc_macro_derive
313 : : static void
314 : 3522 : check_proc_macro_non_root (AST::AttrVec attributes, location_t loc)
315 : : {
316 : 5530 : for (auto &attr : attributes)
317 : : {
318 : 2008 : if (is_proc_macro_type (attr))
319 : : {
320 : 9 : rust_error_at (
321 : : loc,
322 : : "functions tagged with %<#[%s]%> must currently "
323 : : "reside in the root of the crate",
324 : 18 : attr.get_path ().get_segments ().at (0).as_string ().c_str ());
325 : : }
326 : : }
327 : 3522 : }
328 : :
329 : : void
330 : 5222 : AttributeChecker::check_attribute (const AST::Attribute &attribute)
331 : : {
332 : 5222 : if (!attribute.empty_input ())
333 : : {
334 : 5181 : const auto &attr_input = attribute.get_attr_input ();
335 : 5181 : auto type = attr_input.get_attr_input_type ();
336 : 5181 : if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
337 : : {
338 : 2175 : const auto &option = static_cast<const AST::DelimTokenTree &> (
339 : 2175 : attribute.get_attr_input ());
340 : 2175 : std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
341 : 2175 : option.parse_to_meta_item ());
342 : 2175 : AST::DefaultASTVisitor::visit (meta_item);
343 : 2175 : }
344 : : }
345 : :
346 : 5222 : BuiltinAttrDefinition result;
347 : :
348 : : // This checker does not check non-builtin attributes
349 : 5222 : if (!is_builtin (attribute, result))
350 : 728 : return;
351 : :
352 : : // TODO: Add checks here for each builtin attribute
353 : : // TODO: Have an enum of builtins as well, switching on strings is annoying
354 : : // and costly
355 : 4494 : if (result.name == Attrs::DOC)
356 : 916 : check_doc_attribute (attribute);
357 : 5222 : }
358 : :
359 : : void
360 : 4383 : AttributeChecker::check_inner_attributes (const AST::AttrVec &attributes)
361 : : {
362 : 5269 : for (auto &attr : attributes)
363 : 886 : if (attr.is_derive ())
364 : 1 : rust_error_at (attr.get_locus (),
365 : : "derive attribute cannot be used at crate level");
366 : 4383 : }
367 : :
368 : : void
369 : 10848 : AttributeChecker::check_attributes (const AST::AttrVec &attributes)
370 : : {
371 : 16070 : for (auto &attr : attributes)
372 : 5222 : check_attribute (attr);
373 : 10848 : }
374 : :
375 : : void
376 : 0 : AttributeChecker::visit (AST::Token &)
377 : 0 : {}
378 : :
379 : : void
380 : 0 : AttributeChecker::visit (AST::DelimTokenTree &)
381 : 0 : {}
382 : :
383 : : void
384 : 490 : AttributeChecker::visit (AST::IdentifierExpr &)
385 : 490 : {}
386 : :
387 : : void
388 : 0 : AttributeChecker::visit (AST::Lifetime &)
389 : 0 : {}
390 : :
391 : : void
392 : 33 : AttributeChecker::visit (AST::LifetimeParam &)
393 : 33 : {}
394 : :
395 : : void
396 : 2 : AttributeChecker::visit (AST::ConstGenericParam &)
397 : 2 : {}
398 : :
399 : : // rust-path.h
400 : : void
401 : 38 : AttributeChecker::visit (AST::PathInExpression &)
402 : 38 : {}
403 : :
404 : : void
405 : 0 : AttributeChecker::visit (AST::TypePathSegment &)
406 : 0 : {}
407 : :
408 : : void
409 : 0 : AttributeChecker::visit (AST::TypePathSegmentGeneric &)
410 : 0 : {}
411 : :
412 : : void
413 : 0 : AttributeChecker::visit (AST::TypePathSegmentFunction &)
414 : 0 : {}
415 : :
416 : : void
417 : 4315 : AttributeChecker::visit (AST::TypePath &)
418 : 4315 : {}
419 : :
420 : : void
421 : 0 : AttributeChecker::visit (AST::QualifiedPathInExpression &)
422 : 0 : {}
423 : :
424 : : void
425 : 0 : AttributeChecker::visit (AST::QualifiedPathInType &)
426 : 0 : {}
427 : :
428 : : // rust-expr.h
429 : : void
430 : 1398 : AttributeChecker::visit (AST::LiteralExpr &)
431 : 1398 : {}
432 : :
433 : : void
434 : 0 : AttributeChecker::visit (AST::AttrInputLiteral &)
435 : 0 : {}
436 : :
437 : : void
438 : 0 : AttributeChecker::visit (AST::AttrInputMacro &)
439 : 0 : {}
440 : :
441 : : void
442 : 25 : AttributeChecker::visit (AST::MetaItemLitExpr &)
443 : 25 : {}
444 : :
445 : : void
446 : 1 : AttributeChecker::visit (AST::MetaItemPathExpr &attribute)
447 : : {
448 : 1 : if (!attribute.get_expr ().is_literal ())
449 : : {
450 : 1 : rust_error_at (attribute.get_expr ().get_locus (),
451 : : "malformed %<path%> attribute input");
452 : 1 : rust_inform (attribute.get_expr ().get_locus (),
453 : : "must be of the form: %<#[path = \"file\"]%>");
454 : : }
455 : 1 : }
456 : :
457 : : void
458 : 143 : AttributeChecker::visit (AST::BorrowExpr &)
459 : 143 : {}
460 : :
461 : : void
462 : 228 : AttributeChecker::visit (AST::DereferenceExpr &)
463 : 228 : {}
464 : :
465 : : void
466 : 0 : AttributeChecker::visit (AST::ErrorPropagationExpr &)
467 : 0 : {}
468 : :
469 : : void
470 : 15 : AttributeChecker::visit (AST::NegationExpr &)
471 : 15 : {}
472 : :
473 : : void
474 : 740 : AttributeChecker::visit (AST::ArithmeticOrLogicalExpr &)
475 : 740 : {}
476 : :
477 : : void
478 : 741 : AttributeChecker::visit (AST::ComparisonExpr &)
479 : 741 : {}
480 : :
481 : : void
482 : 28 : AttributeChecker::visit (AST::LazyBooleanExpr &)
483 : 28 : {}
484 : :
485 : : void
486 : 158 : AttributeChecker::visit (AST::TypeCastExpr &)
487 : 158 : {}
488 : :
489 : : void
490 : 1 : AttributeChecker::visit (AST::AssignmentExpr &)
491 : 1 : {}
492 : :
493 : : void
494 : 7 : AttributeChecker::visit (AST::CompoundAssignmentExpr &)
495 : 7 : {}
496 : :
497 : : void
498 : 12 : AttributeChecker::visit (AST::GroupedExpr &)
499 : 12 : {}
500 : :
501 : : void
502 : 0 : AttributeChecker::visit (AST::ArrayElemsValues &)
503 : 0 : {}
504 : :
505 : : void
506 : 0 : AttributeChecker::visit (AST::ArrayElemsCopied &)
507 : 0 : {}
508 : :
509 : : void
510 : 15 : AttributeChecker::visit (AST::ArrayExpr &)
511 : 15 : {}
512 : :
513 : : void
514 : 0 : AttributeChecker::visit (AST::ArrayIndexExpr &)
515 : 0 : {}
516 : :
517 : : void
518 : 52 : AttributeChecker::visit (AST::TupleExpr &)
519 : 52 : {}
520 : :
521 : : void
522 : 187 : AttributeChecker::visit (AST::TupleIndexExpr &)
523 : 187 : {}
524 : :
525 : : void
526 : 7 : AttributeChecker::visit (AST::StructExprStruct &)
527 : 7 : {}
528 : :
529 : : void
530 : 0 : AttributeChecker::visit (AST::StructExprFieldIdentifier &)
531 : 0 : {}
532 : :
533 : : void
534 : 0 : AttributeChecker::visit (AST::StructExprFieldIdentifierValue &)
535 : 0 : {}
536 : :
537 : : void
538 : 0 : AttributeChecker::visit (AST::StructExprFieldIndexValue &)
539 : 0 : {}
540 : :
541 : : void
542 : 155 : AttributeChecker::visit (AST::StructExprStructFields &)
543 : 155 : {}
544 : :
545 : : void
546 : 0 : AttributeChecker::visit (AST::StructExprStructBase &)
547 : 0 : {}
548 : :
549 : : void
550 : 647 : AttributeChecker::visit (AST::CallExpr &)
551 : 647 : {}
552 : :
553 : : void
554 : 276 : AttributeChecker::visit (AST::MethodCallExpr &)
555 : 276 : {}
556 : :
557 : : void
558 : 171 : AttributeChecker::visit (AST::FieldAccessExpr &)
559 : 171 : {}
560 : :
561 : : void
562 : 1 : AttributeChecker::visit (AST::ClosureExprInner &)
563 : 1 : {}
564 : :
565 : : void
566 : 10988 : AttributeChecker::visit (AST::BlockExpr &expr)
567 : : {
568 : 26440 : for (auto &stmt : expr.get_statements ())
569 : : {
570 : 15452 : if (stmt->get_stmt_kind () == AST::Stmt::Kind::Item)
571 : : {
572 : : // Non owning pointer, let it go out of scope
573 : 715 : auto item = static_cast<AST::Item *> (stmt.get ());
574 : 715 : check_proc_macro_non_root (item->get_outer_attrs (),
575 : 715 : item->get_locus ());
576 : : }
577 : : }
578 : 10988 : AST::DefaultASTVisitor::visit (expr);
579 : 10988 : }
580 : :
581 : : void
582 : 0 : AttributeChecker::visit (AST::ClosureExprInnerTyped &)
583 : 0 : {}
584 : :
585 : : void
586 : 0 : AttributeChecker::visit (AST::ContinueExpr &)
587 : 0 : {}
588 : :
589 : : void
590 : 0 : AttributeChecker::visit (AST::BreakExpr &)
591 : 0 : {}
592 : :
593 : : void
594 : 0 : AttributeChecker::visit (AST::RangeFromToExpr &)
595 : 0 : {}
596 : :
597 : : void
598 : 0 : AttributeChecker::visit (AST::RangeFromExpr &)
599 : 0 : {}
600 : :
601 : : void
602 : 0 : AttributeChecker::visit (AST::RangeToExpr &)
603 : 0 : {}
604 : :
605 : : void
606 : 0 : AttributeChecker::visit (AST::RangeFullExpr &)
607 : 0 : {}
608 : :
609 : : void
610 : 0 : AttributeChecker::visit (AST::RangeFromToInclExpr &)
611 : 0 : {}
612 : :
613 : : void
614 : 0 : AttributeChecker::visit (AST::RangeToInclExpr &)
615 : 0 : {}
616 : :
617 : : void
618 : 0 : AttributeChecker::visit (AST::ReturnExpr &)
619 : 0 : {}
620 : :
621 : : void
622 : 41 : AttributeChecker::visit (AST::LoopExpr &)
623 : 41 : {}
624 : :
625 : : void
626 : 18 : AttributeChecker::visit (AST::WhileLoopExpr &)
627 : 18 : {}
628 : :
629 : : void
630 : 2 : AttributeChecker::visit (AST::WhileLetLoopExpr &)
631 : 2 : {}
632 : :
633 : : void
634 : 1 : AttributeChecker::visit (AST::ForLoopExpr &)
635 : 1 : {}
636 : :
637 : : void
638 : 65 : AttributeChecker::visit (AST::IfExpr &)
639 : 65 : {}
640 : :
641 : : void
642 : 460 : AttributeChecker::visit (AST::IfExprConseqElse &)
643 : 460 : {}
644 : :
645 : : void
646 : 0 : AttributeChecker::visit (AST::IfLetExpr &)
647 : 0 : {}
648 : :
649 : : void
650 : 9 : AttributeChecker::visit (AST::IfLetExprConseqElse &)
651 : 9 : {}
652 : :
653 : : void
654 : 204 : AttributeChecker::visit (AST::MatchExpr &)
655 : 204 : {}
656 : :
657 : : void
658 : 0 : AttributeChecker::visit (AST::AwaitExpr &)
659 : 0 : {}
660 : :
661 : : void
662 : 0 : AttributeChecker::visit (AST::AsyncBlockExpr &)
663 : 0 : {}
664 : :
665 : : // rust-item.h
666 : : void
667 : 958 : AttributeChecker::visit (AST::TypeParam &)
668 : 958 : {}
669 : :
670 : : void
671 : 0 : AttributeChecker::visit (AST::LifetimeWhereClauseItem &)
672 : 0 : {}
673 : :
674 : : void
675 : 85 : AttributeChecker::visit (AST::TypeBoundWhereClauseItem &)
676 : 85 : {}
677 : :
678 : : void
679 : 1350 : AttributeChecker::visit (AST::Module &module)
680 : : {
681 : 1350 : check_attributes (module.get_outer_attrs ());
682 : 1350 : check_proc_macro_non_function (module.get_outer_attrs ());
683 : 4157 : for (auto &item : module.get_items ())
684 : : {
685 : 2807 : check_proc_macro_non_root (item->get_outer_attrs (), item->get_locus ());
686 : : }
687 : 1350 : AST::DefaultASTVisitor::visit (module);
688 : 1350 : }
689 : :
690 : : void
691 : 27 : AttributeChecker::visit (AST::ExternCrate &crate)
692 : : {
693 : 27 : check_proc_macro_non_function (crate.get_outer_attrs ());
694 : 27 : }
695 : :
696 : : void
697 : 0 : AttributeChecker::visit (AST::UseTreeGlob &)
698 : 0 : {}
699 : :
700 : : void
701 : 0 : AttributeChecker::visit (AST::UseTreeList &)
702 : 0 : {}
703 : :
704 : : void
705 : 0 : AttributeChecker::visit (AST::UseTreeRebind &)
706 : 0 : {}
707 : :
708 : : void
709 : 660 : AttributeChecker::visit (AST::UseDeclaration &declaration)
710 : : {
711 : 660 : check_proc_macro_non_function (declaration.get_outer_attrs ());
712 : 660 : }
713 : :
714 : : static void
715 : 1 : check_no_mangle_function (const AST::Attribute &attribute,
716 : : const AST::Function &fun)
717 : : {
718 : 1 : if (attribute.has_attr_input ())
719 : : {
720 : 0 : rust_error_at (attribute.get_locus (), ErrorCode::E0754,
721 : : "malformed %<no_mangle%> attribute input");
722 : 0 : rust_inform (attribute.get_locus (),
723 : : "must be of the form: %<#[no_mangle]%>");
724 : : }
725 : 1 : if (!is_ascii_only (fun.get_function_name ().as_string ()))
726 : 0 : rust_error_at (fun.get_function_name ().get_locus (),
727 : : "the %<#[no_mangle]%> attribute requires ASCII identifier");
728 : 1 : }
729 : :
730 : : void
731 : 9869 : AttributeChecker::visit (AST::Function &fun)
732 : : {
733 : 9885 : auto check_crate_type = [] (const char *name, AST::Attribute &attribute) {
734 : 16 : if (!Session::get_instance ().options.is_proc_macro ())
735 : 3 : rust_error_at (attribute.get_locus (),
736 : : "the %<#[%s]%> attribute is only usable with crates of "
737 : : "the %<proc-macro%> crate type",
738 : : name);
739 : 16 : };
740 : :
741 : 9869 : BuiltinAttrDefinition result;
742 : 10174 : for (auto &attribute : fun.get_outer_attrs ())
743 : : {
744 : 305 : if (!is_builtin (attribute, result))
745 : 0 : return;
746 : :
747 : 305 : auto name = result.name.c_str ();
748 : :
749 : 305 : if (result.name == Attrs::PROC_MACRO_DERIVE)
750 : : {
751 : 6 : if (!attribute.has_attr_input ())
752 : : {
753 : 1 : rust_error_at (attribute.get_locus (),
754 : : "malformed %qs attribute input", name);
755 : 1 : rust_inform (
756 : : attribute.get_locus (),
757 : : "must be of the form: %<#[proc_macro_derive(TraitName, "
758 : : "/*opt*/ attributes(name1, name2, ...))]%>");
759 : : }
760 : 6 : check_crate_type (name, attribute);
761 : : }
762 : 299 : else if (result.name == Attrs::PROC_MACRO
763 : 299 : || result.name == Attrs::PROC_MACRO_ATTRIBUTE)
764 : : {
765 : 10 : check_crate_type (name, attribute);
766 : : }
767 : 289 : else if (result.name == "no_mangle")
768 : 1 : check_no_mangle_function (attribute, fun);
769 : : }
770 : 9869 : if (fun.has_body ())
771 : 9862 : fun.get_definition ().value ()->accept_vis (*this);
772 : 9869 : }
773 : :
774 : : void
775 : 721 : AttributeChecker::visit (AST::TypeAlias &alias)
776 : : {
777 : 721 : check_proc_macro_non_function (alias.get_outer_attrs ());
778 : 721 : }
779 : :
780 : : void
781 : 1452 : AttributeChecker::visit (AST::StructStruct &struct_item)
782 : : {
783 : 1452 : check_attributes (struct_item.get_outer_attrs ());
784 : 1452 : check_proc_macro_non_function (struct_item.get_outer_attrs ());
785 : 1452 : }
786 : :
787 : : void
788 : 952 : AttributeChecker::visit (AST::TupleStruct &tuplestruct)
789 : : {
790 : 952 : check_proc_macro_non_function (tuplestruct.get_outer_attrs ());
791 : 952 : }
792 : :
793 : : void
794 : 0 : AttributeChecker::visit (AST::EnumItem &)
795 : 0 : {}
796 : :
797 : : void
798 : 0 : AttributeChecker::visit (AST::EnumItemTuple &)
799 : 0 : {}
800 : :
801 : : void
802 : 0 : AttributeChecker::visit (AST::EnumItemStruct &)
803 : 0 : {}
804 : :
805 : : void
806 : 0 : AttributeChecker::visit (AST::EnumItemDiscriminant &)
807 : 0 : {}
808 : :
809 : : void
810 : 540 : AttributeChecker::visit (AST::Enum &enumeration)
811 : : {
812 : 540 : check_proc_macro_non_function (enumeration.get_outer_attrs ());
813 : 540 : }
814 : :
815 : : void
816 : 107 : AttributeChecker::visit (AST::Union &u)
817 : : {
818 : 107 : check_proc_macro_non_function (u.get_outer_attrs ());
819 : 107 : }
820 : :
821 : : void
822 : 495 : AttributeChecker::visit (AST::ConstantItem &item)
823 : : {
824 : 495 : check_proc_macro_non_function (item.get_outer_attrs ());
825 : 495 : }
826 : :
827 : : void
828 : 57 : AttributeChecker::visit (AST::StaticItem &item)
829 : : {
830 : 57 : check_proc_macro_non_function (item.get_outer_attrs ());
831 : 57 : }
832 : :
833 : : void
834 : 0 : AttributeChecker::visit (AST::TraitItemType &)
835 : 0 : {}
836 : :
837 : : void
838 : 3663 : AttributeChecker::visit (AST::Trait &trait)
839 : : {
840 : 3663 : check_proc_macro_non_function (trait.get_outer_attrs ());
841 : 3663 : check_attributes (trait.get_outer_attrs ());
842 : 3663 : }
843 : :
844 : : void
845 : 739 : AttributeChecker::visit (AST::InherentImpl &impl)
846 : : {
847 : 739 : check_proc_macro_non_function (impl.get_outer_attrs ());
848 : 739 : AST::DefaultASTVisitor::visit (impl);
849 : 739 : }
850 : :
851 : : void
852 : 1995 : AttributeChecker::visit (AST::TraitImpl &impl)
853 : : {
854 : 1995 : check_proc_macro_non_function (impl.get_outer_attrs ());
855 : 1995 : AST::DefaultASTVisitor::visit (impl);
856 : 1995 : }
857 : :
858 : : void
859 : 0 : AttributeChecker::visit (AST::ExternalTypeItem &)
860 : 0 : {}
861 : :
862 : : void
863 : 0 : AttributeChecker::visit (AST::ExternalStaticItem &)
864 : 0 : {}
865 : :
866 : : void
867 : 1455 : AttributeChecker::visit (AST::ExternBlock &block)
868 : : {
869 : 1455 : check_proc_macro_non_function (block.get_outer_attrs ());
870 : 1455 : }
871 : :
872 : : // rust-macro.h
873 : : void
874 : 0 : AttributeChecker::visit (AST::MacroMatchFragment &)
875 : 0 : {}
876 : :
877 : : void
878 : 0 : AttributeChecker::visit (AST::MacroMatchRepetition &)
879 : 0 : {}
880 : :
881 : : void
882 : 0 : AttributeChecker::visit (AST::MacroMatcher &)
883 : 0 : {}
884 : :
885 : : void
886 : 946 : AttributeChecker::visit (AST::MacroRulesDefinition &)
887 : 946 : {}
888 : :
889 : : void
890 : 707 : AttributeChecker::visit (AST::MacroInvocation &)
891 : 707 : {}
892 : :
893 : : void
894 : 0 : AttributeChecker::visit (AST::MetaItemPath &)
895 : 0 : {}
896 : :
897 : : void
898 : 1080 : AttributeChecker::visit (AST::MetaWord &)
899 : 1080 : {}
900 : :
901 : : void
902 : 1709 : AttributeChecker::visit (AST::MetaNameValueStr &)
903 : 1709 : {}
904 : :
905 : : void
906 : 0 : AttributeChecker::visit (AST::MetaListPaths &)
907 : 0 : {}
908 : :
909 : : void
910 : 0 : AttributeChecker::visit (AST::MetaListNameValueStr &)
911 : 0 : {}
912 : :
913 : : // rust-pattern.h
914 : : void
915 : 0 : AttributeChecker::visit (AST::LiteralPattern &)
916 : 0 : {}
917 : :
918 : : void
919 : 0 : AttributeChecker::visit (AST::IdentifierPattern &)
920 : 0 : {}
921 : :
922 : : void
923 : 0 : AttributeChecker::visit (AST::WildcardPattern &)
924 : 0 : {}
925 : :
926 : : void
927 : 0 : AttributeChecker::visit (AST::RestPattern &)
928 : 0 : {}
929 : :
930 : : // void AttributeChecker::visit(RangePatternBound& ){}
931 : :
932 : : void
933 : 0 : AttributeChecker::visit (AST::RangePatternBoundLiteral &)
934 : 0 : {}
935 : :
936 : : void
937 : 0 : AttributeChecker::visit (AST::RangePatternBoundPath &)
938 : 0 : {}
939 : :
940 : : void
941 : 0 : AttributeChecker::visit (AST::RangePatternBoundQualPath &)
942 : 0 : {}
943 : :
944 : : void
945 : 0 : AttributeChecker::visit (AST::RangePattern &)
946 : 0 : {}
947 : :
948 : : void
949 : 0 : AttributeChecker::visit (AST::ReferencePattern &)
950 : 0 : {}
951 : :
952 : : // void AttributeChecker::visit(StructPatternField& ){}
953 : :
954 : : void
955 : 0 : AttributeChecker::visit (AST::StructPatternFieldTuplePat &)
956 : 0 : {}
957 : :
958 : : void
959 : 0 : AttributeChecker::visit (AST::StructPatternFieldIdentPat &)
960 : 0 : {}
961 : :
962 : : void
963 : 0 : AttributeChecker::visit (AST::StructPatternFieldIdent &)
964 : 0 : {}
965 : :
966 : : void
967 : 0 : AttributeChecker::visit (AST::StructPattern &)
968 : 0 : {}
969 : :
970 : : // void AttributeChecker::visit(TupleStructItems& ){}
971 : :
972 : : void
973 : 0 : AttributeChecker::visit (AST::TupleStructItemsNoRest &)
974 : 0 : {}
975 : :
976 : : void
977 : 0 : AttributeChecker::visit (AST::TupleStructItemsHasRest &)
978 : 0 : {}
979 : :
980 : : void
981 : 0 : AttributeChecker::visit (AST::TupleStructPattern &)
982 : 0 : {}
983 : :
984 : : // void AttributeChecker::visit(TuplePatternItems& ){}
985 : :
986 : : void
987 : 0 : AttributeChecker::visit (AST::TuplePatternItemsNoRest &)
988 : 0 : {}
989 : :
990 : : void
991 : 0 : AttributeChecker::visit (AST::TuplePatternItemsHasRest &)
992 : 0 : {}
993 : :
994 : : void
995 : 0 : AttributeChecker::visit (AST::TuplePattern &)
996 : 0 : {}
997 : :
998 : : void
999 : 0 : AttributeChecker::visit (AST::GroupedPattern &)
1000 : 0 : {}
1001 : :
1002 : : void
1003 : 0 : AttributeChecker::visit (AST::SlicePattern &)
1004 : 0 : {}
1005 : :
1006 : : void
1007 : 0 : AttributeChecker::visit (AST::AltPattern &)
1008 : 0 : {}
1009 : :
1010 : : // rust-stmt.h
1011 : : void
1012 : 17 : AttributeChecker::visit (AST::EmptyStmt &)
1013 : 17 : {}
1014 : :
1015 : : void
1016 : 9425 : AttributeChecker::visit (AST::LetStmt &)
1017 : 9425 : {}
1018 : :
1019 : : void
1020 : 5295 : AttributeChecker::visit (AST::ExprStmt &)
1021 : 5295 : {}
1022 : :
1023 : : // rust-type.h
1024 : : void
1025 : 0 : AttributeChecker::visit (AST::TraitBound &)
1026 : 0 : {}
1027 : :
1028 : : void
1029 : 0 : AttributeChecker::visit (AST::ImplTraitType &)
1030 : 0 : {}
1031 : :
1032 : : void
1033 : 4 : AttributeChecker::visit (AST::TraitObjectType &)
1034 : 4 : {}
1035 : :
1036 : : void
1037 : 2 : AttributeChecker::visit (AST::ParenthesisedType &)
1038 : 2 : {}
1039 : :
1040 : : void
1041 : 0 : AttributeChecker::visit (AST::ImplTraitTypeOneBound &)
1042 : 0 : {}
1043 : :
1044 : : void
1045 : 7 : AttributeChecker::visit (AST::TraitObjectTypeOneBound &)
1046 : 7 : {}
1047 : :
1048 : : void
1049 : 2 : AttributeChecker::visit (AST::TupleType &)
1050 : 2 : {}
1051 : :
1052 : : void
1053 : 2 : AttributeChecker::visit (AST::NeverType &)
1054 : 2 : {}
1055 : :
1056 : : void
1057 : 164 : AttributeChecker::visit (AST::RawPointerType &)
1058 : 164 : {}
1059 : :
1060 : : void
1061 : 166 : AttributeChecker::visit (AST::ReferenceType &)
1062 : 166 : {}
1063 : :
1064 : : void
1065 : 0 : AttributeChecker::visit (AST::ArrayType &)
1066 : 0 : {}
1067 : :
1068 : : void
1069 : 66 : AttributeChecker::visit (AST::SliceType &)
1070 : 66 : {}
1071 : :
1072 : : void
1073 : 0 : AttributeChecker::visit (AST::InferredType &)
1074 : 0 : {}
1075 : :
1076 : : void
1077 : 1 : AttributeChecker::visit (AST::BareFunctionType &)
1078 : 1 : {}
1079 : :
1080 : : void
1081 : 0 : AttributeChecker::visit (AST::SelfParam &)
1082 : 0 : {}
1083 : :
1084 : : void
1085 : 0 : AttributeChecker::visit (AST::VariadicParam &)
1086 : 0 : {}
1087 : :
1088 : : void
1089 : 0 : AttributeChecker::visit (AST::FunctionParam &)
1090 : 0 : {}
1091 : :
1092 : : } // namespace Analysis
1093 : : } // namespace Rust
|