LCOV - code coverage report
Current view: top level - gcc/rust/util - rust-attributes.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 66.9 % 625 418
Test Date: 2026-03-28 14:25:54 Functions: 57.6 % 170 98
Legend: Lines:     hit not hit

            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-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        28994 : Attributes::is_known (const std::string &attribute_path)
      34              : {
      35        28994 :   const auto &lookup
      36        28994 :     = BuiltinAttributeMappings::get ()->lookup_builtin (attribute_path);
      37              : 
      38        28994 :   return !lookup.is_error ();
      39              : }
      40              : 
      41              : tl::optional<std::string>
      42         6465 : Attributes::extract_string_literal (const AST::Attribute &attr)
      43              : {
      44         6465 :   if (!attr.has_attr_input ())
      45            0 :     return tl::nullopt;
      46              : 
      47         6465 :   auto &attr_input = attr.get_attr_input ();
      48              : 
      49         6465 :   if (attr_input.get_attr_input_type ()
      50              :       != AST::AttrInput::AttrInputType::LITERAL)
      51            0 :     return tl::nullopt;
      52              : 
      53         6465 :   auto &literal_expr
      54         6465 :     = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal ();
      55              : 
      56         6465 :   auto lit_type = literal_expr.get_lit_type ();
      57              : 
      58              :   // TODO: bring escape sequence handling out of lexing?
      59         6465 :   if (lit_type != AST::Literal::LitType::STRING
      60         6465 :       && lit_type != AST::Literal::LitType::RAW_STRING)
      61            0 :     return tl::nullopt;
      62              : 
      63         6465 :   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::EXPORT_NAME, CODE_GENERATION},
      85              :      {Attrs::REPR, CODE_GENERATION},
      86              :      {Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
      87              :      {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
      88              :      {Attrs::PATH, EXPANSION},
      89              :      {Attrs::MACRO_USE, NAME_RESOLUTION},
      90              :      {Attrs::MACRO_EXPORT, NAME_RESOLUTION},
      91              :      {Attrs::PROC_MACRO, EXPANSION},
      92              :      {Attrs::PROC_MACRO_DERIVE, EXPANSION},
      93              :      {Attrs::PROC_MACRO_ATTRIBUTE, EXPANSION},
      94              :      // FIXME: This is not implemented yet, see
      95              :      // https://github.com/Rust-GCC/gccrs/issues/1475
      96              :      {Attrs::TARGET_FEATURE, CODE_GENERATION},
      97              :      // From now on, these are reserved by the compiler and gated through
      98              :      // #![feature(rustc_attrs)]
      99              :      {Attrs::FEATURE, STATIC_ANALYSIS},
     100              :      {Attrs::NO_CORE, CODE_GENERATION},
     101              :      {Attrs::NO_STD, CODE_GENERATION},
     102              :      {Attrs::DOC, EXTERNAL},
     103              :      {Attrs::CRATE_NAME, CODE_GENERATION},
     104              :      {Attrs::CRATE_TYPE, CODE_GENERATION},
     105              :      {Attrs::MAY_DANGLE, STATIC_ANALYSIS},
     106              :      {Attrs::RUSTC_DEPRECATED, STATIC_ANALYSIS},
     107              :      {Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION},
     108              :      {Attrs::STABLE, STATIC_ANALYSIS},
     109              :      {Attrs::UNSTABLE, STATIC_ANALYSIS},
     110              :      // assuming we keep these for static analysis
     111              :      {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
     112              :      {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
     113              :      {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
     114              :      {Attrs::RUSTC_ALLOW_CONST_FN_UNSTABLE, STATIC_ANALYSIS},
     115              :      {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
     116              :      {Attrs::TRACK_CALLER, CODE_GENERATION},
     117              :      {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
     118              :      {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
     119              :      {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
     120              :      {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
     121              :      {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
     122              :      {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
     123              :      // TODO: be careful about calling functions marked with this?
     124              :      {Attrs::RUSTC_ARGS_REQUIRED_CONST, CODE_GENERATION},
     125              :      {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
     126              :      {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
     127              :      {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
     128              :      {Attrs::FUNDAMENTAL, TYPE_CHECK},
     129              :      {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
     130              :      {Attrs::RUSTFMT, EXTERNAL},
     131              :      {Attrs::TEST, CODE_GENERATION}};
     132              : 
     133              : static const std::set<std::string> __outer_attributes
     134              :   = {Attrs::INLINE,
     135              :      Attrs::DERIVE_ATTR,
     136              :      Attrs::ALLOW_INTERNAL_UNSTABLE,
     137              :      Attrs::LANG,
     138              :      Attrs::REPR,
     139              :      Attrs::PATH,
     140              :      Attrs::TARGET_FEATURE,
     141              :      Attrs::TEST,
     142              :      Attrs::COLD,
     143              :      Attrs::MACRO_USE,
     144              :      Attrs::MACRO_EXPORT,
     145              :      Attrs::PROC_MACRO_ATTRIBUTE,
     146              :      Attrs::PROC_MACRO_DERIVE,
     147              :      Attrs::DEPRECATED,
     148              :      Attrs::MUST_USE,
     149              :      Attrs::LINK_NAME,
     150              :      Attrs::LINK_SECTION};
     151              : 
     152              : BuiltinAttributeMappings *
     153       527770 : BuiltinAttributeMappings::get ()
     154              : {
     155       527770 :   static BuiltinAttributeMappings *instance = nullptr;
     156       527770 :   if (instance == nullptr)
     157         4522 :     instance = new BuiltinAttributeMappings ();
     158              : 
     159       527770 :   return instance;
     160              : }
     161              : 
     162              : const BuiltinAttrDefinition &
     163       146037 : BuiltinAttributeMappings::lookup_builtin (const std::string &attr_name) const
     164              : {
     165       146037 :   auto it = mappings.find (attr_name);
     166       146037 :   if (it == mappings.end ())
     167            2 :     return BuiltinAttrDefinition::error_node ();
     168              : 
     169       146035 :   return it->second;
     170              : }
     171              : 
     172         4522 : BuiltinAttributeMappings::BuiltinAttributeMappings ()
     173              : {
     174         4522 :   size_t ndefinitions = sizeof (__definitions) / sizeof (BuiltinAttrDefinition);
     175       257754 :   for (size_t i = 0; i < ndefinitions; i++)
     176              :     {
     177       253232 :       const BuiltinAttrDefinition &def = __definitions[i];
     178       506464 :       mappings.insert ({def.name, def});
     179              :     }
     180         4522 : }
     181              : 
     182         4522 : AttributeChecker::AttributeChecker () {}
     183              : 
     184              : void
     185         4522 : AttributeChecker::go (AST::Crate &crate)
     186              : {
     187         4522 :   visit (crate);
     188         4522 : }
     189              : 
     190              : void
     191         4522 : AttributeChecker::visit (AST::Crate &crate)
     192              : {
     193        15778 :   for (auto &attr : crate.get_inner_attrs ())
     194              :     {
     195        11256 :       check_inner_attribute (attr);
     196              :     }
     197              : 
     198        22836 :   for (auto &item : crate.items)
     199        18314 :     item->accept_vis (*this);
     200         4522 : }
     201              : 
     202              : tl::optional<BuiltinAttrDefinition>
     203        32137 : identify_builtin (const AST::Attribute &attribute)
     204              : {
     205        32137 :   auto &segments = attribute.get_path ().get_segments ();
     206              : 
     207              :   // Builtin attributes always have a single segment. This avoids us creating
     208              :   // strings all over the place and performing a linear search in the builtins
     209              :   // map
     210        32137 :   if (segments.size () != 1)
     211            0 :     return tl::nullopt;
     212              : 
     213        32137 :   return BuiltinAttributeMappings::get ()->lookup_builtin (
     214        32137 :     segments.at (0).get_segment_name ());
     215              : }
     216              : 
     217              : /**
     218              :  * Check that the string given to #[doc(alias = ...)] or #[doc(alias(...))] is
     219              :  * valid.
     220              :  *
     221              :  * This means no whitespace characters other than spaces and no quoting
     222              :  * characters.
     223              :  */
     224              : static void
     225          700 : check_doc_alias (const std::string &alias_input, const location_t locus)
     226              : {
     227              :   // FIXME: The locus here is for the whole attribute. Can we get the locus
     228              :   // of the alias input instead?
     229         1872 :   for (auto c : alias_input)
     230         1172 :     if ((ISSPACE (c) && c != ' ') || c == '\'' || c == '\"')
     231              :       {
     232            7 :         auto to_print = std::string (1, c);
     233            7 :         switch (c)
     234              :           {
     235            7 :           case '\n':
     236            7 :             to_print = "\\n";
     237            7 :             break;
     238            0 :           case '\t':
     239            0 :             to_print = "\\t";
     240            0 :             break;
     241              :           default:
     242              :             break;
     243              :           }
     244            7 :         rust_error_at (locus,
     245              :                        "invalid character used in %<#[doc(alias)]%> input: %qs",
     246              :                        to_print.c_str ());
     247            7 :       }
     248              : 
     249          700 :   if (alias_input.empty ())
     250              :     return;
     251              : 
     252         1400 :   if (alias_input.front () == ' ' || alias_input.back () == ' ')
     253            0 :     rust_error_at (locus,
     254              :                    "%<#[doc(alias)]%> input cannot start or end with a space");
     255              : }
     256              : 
     257              : static void
     258          946 : check_doc_attribute (const AST::Attribute &attribute)
     259              : {
     260          946 :   if (!attribute.has_attr_input ())
     261              :     {
     262            1 :       rust_error_at (
     263              :         attribute.get_locus (),
     264              :         "valid forms for the attribute are "
     265              :         "%<#[doc(hidden|inline|...)]%> and %<#[doc = \" string \"]%>");
     266            1 :       return;
     267              :     }
     268              : 
     269          945 :   switch (attribute.get_attr_input ().get_attr_input_type ())
     270              :     {
     271              :     case AST::AttrInput::LITERAL:
     272              :     case AST::AttrInput::MACRO:
     273              :     case AST::AttrInput::META_ITEM:
     274              :     case AST::AttrInput::EXPR:
     275              :       break;
     276              :       // FIXME: Handle them as well
     277              : 
     278          742 :     case AST::AttrInput::TOKEN_TREE:
     279          742 :       {
     280              :         // FIXME: This doesn't check for #[doc(alias(...))]
     281          742 :         const auto &option = static_cast<const AST::DelimTokenTree &> (
     282          742 :           attribute.get_attr_input ());
     283          742 :         auto *meta_item = option.parse_to_meta_item ();
     284              : 
     285         1491 :         for (auto &item : meta_item->get_items ())
     286              :           {
     287          749 :             if (item->is_key_value_pair ())
     288              :               {
     289          707 :                 auto name_value
     290          707 :                   = static_cast<AST::MetaNameValueStr *> (item.get ())
     291          707 :                       ->get_name_value_pair ();
     292              : 
     293              :                 // FIXME: Check for other stuff than #[doc(alias = ...)]
     294          707 :                 if (name_value.first.as_string () == "alias")
     295          700 :                   check_doc_alias (name_value.second, attribute.get_locus ());
     296          707 :               }
     297              :           }
     298              :         break;
     299              :       }
     300              :     }
     301              : }
     302              : 
     303              : static void
     304            1 : check_deprecated_attribute (const AST::Attribute &attribute)
     305              : {
     306            1 :   if (!attribute.has_attr_input ())
     307              :     return;
     308              : 
     309            0 :   const auto &input = attribute.get_attr_input ();
     310              : 
     311            0 :   if (input.get_attr_input_type () != AST::AttrInput::META_ITEM)
     312              :     return;
     313              : 
     314            0 :   auto &meta = static_cast<const AST::AttrInputMetaItemContainer &> (input);
     315              : 
     316            0 :   for (auto &current : meta.get_items ())
     317              :     {
     318            0 :       switch (current->get_kind ())
     319              :         {
     320            0 :         case AST::MetaItemInner::Kind::MetaItem:
     321            0 :           {
     322            0 :             auto *meta_item = static_cast<AST::MetaItem *> (current.get ());
     323              : 
     324            0 :             switch (meta_item->get_item_kind ())
     325              :               {
     326            0 :               case AST::MetaItem::ItemKind::NameValueStr:
     327            0 :                 {
     328            0 :                   auto *nv = static_cast<AST::MetaNameValueStr *> (meta_item);
     329              : 
     330            0 :                   const std::string key = nv->get_name ().as_string ();
     331              : 
     332            0 :                   if (key != "since" && key != "note")
     333              :                     {
     334            0 :                       rust_error_at (nv->get_locus (), "unknown meta item %qs",
     335              :                                      key.c_str ());
     336            0 :                       rust_inform (nv->get_locus (),
     337              :                                    "expected one of %<since%>, %<note%>");
     338              :                     }
     339            0 :                 }
     340            0 :                 break;
     341              : 
     342            0 :               case AST::MetaItem::ItemKind::Path:
     343            0 :                 {
     344              :                   // #[deprecated(a,a)]
     345            0 :                   auto *p = static_cast<AST::MetaItemPath *> (meta_item);
     346              : 
     347            0 :                   std::string ident = p->get_path ().as_string ();
     348              : 
     349            0 :                   rust_error_at (p->get_locus (), "unknown meta item %qs",
     350              :                                  ident.c_str ());
     351            0 :                   rust_inform (p->get_locus (),
     352              :                                "expected one of %<since%>, %<note%>");
     353            0 :                 }
     354            0 :                 break;
     355              : 
     356            0 :               case AST::MetaItem::ItemKind::Word:
     357            0 :                 {
     358              :                   // #[deprecated("a")]
     359            0 :                   auto *w = static_cast<AST::MetaWord *> (meta_item);
     360              : 
     361            0 :                   rust_error_at (
     362            0 :                     w->get_locus (),
     363              :                     "item in %<deprecated%> must be a key/value pair");
     364              :                 }
     365            0 :                 break;
     366              : 
     367            0 :               case AST::MetaItem::ItemKind::PathExpr:
     368            0 :                 {
     369              :                   // #[deprecated(since=a)]
     370            0 :                   auto *px = static_cast<AST::MetaItemPathExpr *> (meta_item);
     371              : 
     372            0 :                   rust_error_at (
     373            0 :                     px->get_locus (),
     374              :                     "expected unsuffixed literal or identifier, found %qs",
     375            0 :                     px->get_expr ().as_string ().c_str ());
     376              :                 }
     377            0 :                 break;
     378              : 
     379            0 :               case AST::MetaItem::ItemKind::Seq:
     380            0 :               case AST::MetaItem::ItemKind::ListPaths:
     381            0 :               case AST::MetaItem::ItemKind::ListNameValueStr:
     382            0 :               default:
     383            0 :                 gcc_unreachable ();
     384            0 :                 break;
     385              :               }
     386              :           }
     387            0 :           break;
     388              : 
     389            0 :         case AST::MetaItemInner::Kind::LitExpr:
     390            0 :         default:
     391            0 :           gcc_unreachable ();
     392            0 :           break;
     393              :         }
     394              :     }
     395              : }
     396              : 
     397              : /**
     398              :  * Emit an error when an attribute is attached
     399              :  * to an incompatable item type. e.g.:
     400              :  *
     401              :  * #[cold]
     402              :  * struct A(u8, u8);
     403              :  *
     404              :  * Note that "#[derive]" is handled
     405              :  * explicitly in rust-derive.cc
     406              :  */
     407              : static void
     408        14224 : check_valid_attribute_for_item (const AST::Attribute &attr,
     409              :                                 const AST::Item &item)
     410              : {
     411        28448 :   if (item.get_item_kind () != AST::Item::Kind::Function
     412        33205 :       && (attr.get_path () == Values::Attributes::TARGET_FEATURE
     413        23736 :           || attr.get_path () == Values::Attributes::COLD
     414        18980 :           || attr.get_path () == Values::Attributes::INLINE))
     415              :     {
     416            1 :       rust_error_at (attr.get_locus (),
     417              :                      "the %<#[%s]%> attribute may only be applied to functions",
     418            2 :                      attr.get_path ().as_string ().c_str ());
     419              :     }
     420        28446 :   else if (attr.get_path () == Values::Attributes::REPR
     421           43 :            && item.get_item_kind () != AST::Item::Kind::Enum
     422           41 :            && item.get_item_kind () != AST::Item::Kind::Union
     423        14252 :            && item.get_item_kind () != AST::Item::Kind::Struct)
     424              :     {
     425            1 :       rust_error_at (attr.get_locus (),
     426              :                      "the %<#[%s]%> attribute may only be applied "
     427              :                      "to structs, enums and unions",
     428            2 :                      attr.get_path ().as_string ().c_str ());
     429              :     }
     430        14224 : }
     431              : 
     432              : static bool
     433         6765 : is_proc_macro_type (const AST::Attribute &attribute)
     434              : {
     435         6765 :   auto result_opt = identify_builtin (attribute);
     436         6765 :   if (!result_opt.has_value ())
     437              :     return false;
     438         6765 :   auto result = result_opt.value ();
     439              : 
     440         6765 :   auto name = result.name;
     441         6747 :   return name == Attrs::PROC_MACRO || name == Attrs::PROC_MACRO_DERIVE
     442        13512 :          || name == Attrs::PROC_MACRO_ATTRIBUTE;
     443         6765 : }
     444              : 
     445              : // Emit an error when one encountered attribute is either #[proc_macro],
     446              : // #[proc_macro_attribute] or #[proc_macro_derive]
     447              : static void
     448         4757 : check_proc_macro_non_function (const AST::Attribute &attr)
     449              : {
     450         4757 :   if (is_proc_macro_type (attr))
     451           45 :     rust_error_at (attr.get_locus (),
     452              :                    "the %<#[%s]%> attribute may only be used on bare functions",
     453           90 :                    attr.get_path ().get_segments ()[0].as_string ().c_str ());
     454         4757 : }
     455              : 
     456              : // Emit an error when one attribute is either proc_macro, proc_macro_attribute
     457              : // or proc_macro_derive
     458              : static void
     459         2008 : check_proc_macro_non_root (const AST::Attribute &attr, location_t loc)
     460              : {
     461         2008 :   if (is_proc_macro_type (attr))
     462              :     {
     463            9 :       rust_error_at (
     464              :         loc,
     465              :         "functions tagged with %<#[%s]%> must currently "
     466              :         "reside in the root of the crate",
     467           18 :         attr.get_path ().get_segments ().at (0).as_string ().c_str ());
     468              :     }
     469         2008 : }
     470              : 
     471              : void
     472        11256 : AttributeChecker::check_inner_attribute (const AST::Attribute &attribute)
     473              : {
     474        11256 :   auto result_opt = identify_builtin (attribute);
     475        11256 :   if (!result_opt.has_value ())
     476            0 :     return;
     477        11256 :   auto result = result_opt.value ();
     478              : 
     479        11256 :   if (__outer_attributes.find (result.name) != __outer_attributes.end ())
     480            3 :     rust_error_at (attribute.get_locus (),
     481              :                    "attribute cannot be used at crate level");
     482        22512 : }
     483              : 
     484              : static void
     485            2 : check_link_section_attribute (const AST::Attribute &attribute)
     486              : {
     487            2 :   if (!attribute.has_attr_input ())
     488              :     {
     489            1 :       rust_error_at (attribute.get_locus (),
     490              :                      "malformed %<link_section%> attribute input");
     491            1 :       rust_inform (attribute.get_locus (),
     492              :                    "must be of the form: %<#[link_section = \"name\"]%>");
     493              :     }
     494            2 : }
     495              : 
     496              : static void
     497           10 : check_export_name_attribute (const AST::Attribute &attribute)
     498              : {
     499           10 :   if (!attribute.has_attr_input ())
     500              :     {
     501            2 :       rust_error_at (attribute.get_locus (),
     502              :                      "malformed %<export_name%> attribute input");
     503            2 :       rust_inform (attribute.get_locus (),
     504              :                    "must be of the form: %<#[export_name = \"name\"]%>");
     505            2 :       return;
     506              :     }
     507              : 
     508              :   // We don't support the whole extended_key_value_attributes feature, we only
     509              :   // support a subset for macros. We need to emit an error message when the
     510              :   // attribute does not contain a macro or a string literal.
     511            8 :   if (attribute.has_attr_input ())
     512              :     {
     513            8 :       auto &attr_input = attribute.get_attr_input ();
     514            8 :       switch (attr_input.get_attr_input_type ())
     515              :         {
     516            5 :         case AST::AttrInput::AttrInputType::LITERAL:
     517            5 :           {
     518            5 :             auto &literal_expr
     519              :               = static_cast<AST::AttrInputLiteral &> (attr_input)
     520            5 :                   .get_literal ();
     521            5 :             auto lit_type = literal_expr.get_lit_type ();
     522            5 :             switch (lit_type)
     523              :               {
     524              :               case AST::Literal::LitType::STRING:
     525              :               case AST::Literal::LitType::RAW_STRING:
     526              :               case AST::Literal::LitType::BYTE_STRING:
     527              :                 return;
     528              :               default:
     529              :                 break;
     530              :               }
     531              :             break;
     532              :           }
     533              :         case AST::AttrInput::AttrInputType::MACRO:
     534              :           return;
     535              :         default:
     536              :           break;
     537              :         }
     538              :     }
     539            4 :   rust_error_at (attribute.get_locus (), "attribute must be a string literal");
     540              : }
     541              : 
     542              : static void
     543           10 : check_lint_attribute (const AST::Attribute &attribute, const char *name)
     544              : {
     545           10 :   if (!attribute.has_attr_input ())
     546              :     {
     547            1 :       rust_error_at (attribute.get_locus (), "malformed %qs attribute input",
     548              :                      name);
     549            1 :       rust_inform (attribute.get_locus (),
     550              :                    "must be of the form: %<#[%s(lint1, lint2, ...)]%>", name);
     551              :     }
     552           10 : }
     553              : 
     554              : void
     555         4649 : AttributeChecker::visit (AST::Attribute &attribute)
     556              : {
     557         4649 :   auto &session = Session::get_instance ();
     558         4649 :   if (attribute.get_path () == Values::Attributes::CFG_ATTR)
     559              :     {
     560           11 :       if (!attribute.is_parsed_to_meta_item ())
     561           11 :         attribute.parse_attr_to_meta_item ();
     562           11 :       if (!attribute.check_cfg_predicate (session))
     563              :         return; // Do not emit errors for attribute that'll get stripped.
     564              :     }
     565              : 
     566         4641 :   if (auto builtin = identify_builtin (attribute))
     567              :     {
     568         4641 :       auto result = builtin.value ();
     569              :       // TODO: Add checks here for each builtin attribute
     570              :       // TODO: Have an enum of builtins as well, switching on strings is
     571              :       // annoying and costly
     572         4641 :       if (result.name == Attrs::DOC)
     573          946 :         check_doc_attribute (attribute);
     574         3695 :       else if (result.name == Attrs::DEPRECATED)
     575            1 :         check_deprecated_attribute (attribute);
     576         4641 :     }
     577              : 
     578         4641 :   AST::DefaultASTVisitor::visit (attribute);
     579              : }
     580              : 
     581              : void
     582            0 : AttributeChecker::visit (AST::Token &)
     583            0 : {}
     584              : 
     585              : void
     586         1389 : AttributeChecker::visit (AST::DelimTokenTree &)
     587         1389 : {}
     588              : 
     589              : void
     590          544 : AttributeChecker::visit (AST::IdentifierExpr &)
     591          544 : {}
     592              : 
     593              : void
     594            0 : AttributeChecker::visit (AST::Lifetime &)
     595            0 : {}
     596              : 
     597              : void
     598           59 : AttributeChecker::visit (AST::LifetimeParam &)
     599           59 : {}
     600              : 
     601              : void
     602           80 : AttributeChecker::visit (AST::ConstGenericParam &)
     603           80 : {}
     604              : 
     605              : // rust-path.h
     606              : void
     607          152 : AttributeChecker::visit (AST::PathInExpression &)
     608          152 : {}
     609              : 
     610              : void
     611            0 : AttributeChecker::visit (AST::TypePathSegment &)
     612            0 : {}
     613              : 
     614              : void
     615            0 : AttributeChecker::visit (AST::TypePathSegmentGeneric &)
     616            0 : {}
     617              : 
     618              : void
     619            0 : AttributeChecker::visit (AST::TypePathSegmentFunction &)
     620            0 : {}
     621              : 
     622              : void
     623         6024 : AttributeChecker::visit (AST::TypePath &)
     624         6024 : {}
     625              : 
     626              : void
     627            0 : AttributeChecker::visit (AST::QualifiedPathInExpression &)
     628            0 : {}
     629              : 
     630              : void
     631            0 : AttributeChecker::visit (AST::QualifiedPathInType &)
     632            0 : {}
     633              : 
     634              : // rust-expr.h
     635              : void
     636         1442 : AttributeChecker::visit (AST::LiteralExpr &)
     637         1442 : {}
     638              : 
     639              : void
     640         3211 : AttributeChecker::visit (AST::AttrInputLiteral &)
     641         3211 : {}
     642              : 
     643              : void
     644            0 : AttributeChecker::visit (AST::AttrInputMacro &)
     645            0 : {}
     646              : 
     647              : void
     648            0 : AttributeChecker::visit (AST::MetaItemLitExpr &)
     649            0 : {}
     650              : 
     651              : void
     652            1 : AttributeChecker::visit (AST::MetaItemPathExpr &attribute)
     653              : {
     654            1 :   if (!attribute.get_expr ().is_literal ())
     655              :     {
     656            1 :       rust_error_at (attribute.get_expr ().get_locus (),
     657              :                      "malformed %<path%> attribute input");
     658            1 :       rust_inform (attribute.get_expr ().get_locus (),
     659              :                    "must be of the form: %<#[path = \"file\"]%>");
     660              :     }
     661            1 : }
     662              : 
     663              : void
     664          143 : AttributeChecker::visit (AST::BorrowExpr &)
     665          143 : {}
     666              : 
     667              : void
     668          228 : AttributeChecker::visit (AST::DereferenceExpr &)
     669          228 : {}
     670              : 
     671              : void
     672            0 : AttributeChecker::visit (AST::ErrorPropagationExpr &)
     673            0 : {}
     674              : 
     675              : void
     676          135 : AttributeChecker::visit (AST::NegationExpr &)
     677          135 : {}
     678              : 
     679              : void
     680          797 : AttributeChecker::visit (AST::ArithmeticOrLogicalExpr &)
     681          797 : {}
     682              : 
     683              : void
     684          743 : AttributeChecker::visit (AST::ComparisonExpr &)
     685          743 : {}
     686              : 
     687              : void
     688           28 : AttributeChecker::visit (AST::LazyBooleanExpr &)
     689           28 : {}
     690              : 
     691              : void
     692          158 : AttributeChecker::visit (AST::TypeCastExpr &)
     693          158 : {}
     694              : 
     695              : void
     696           63 : AttributeChecker::visit (AST::AssignmentExpr &)
     697           63 : {}
     698              : 
     699              : void
     700            7 : AttributeChecker::visit (AST::CompoundAssignmentExpr &)
     701            7 : {}
     702              : 
     703              : void
     704           12 : AttributeChecker::visit (AST::GroupedExpr &)
     705           12 : {}
     706              : 
     707              : void
     708            0 : AttributeChecker::visit (AST::ArrayElemsValues &)
     709            0 : {}
     710              : 
     711              : void
     712            0 : AttributeChecker::visit (AST::ArrayElemsCopied &)
     713            0 : {}
     714              : 
     715              : void
     716           15 : AttributeChecker::visit (AST::ArrayExpr &)
     717           15 : {}
     718              : 
     719              : void
     720            0 : AttributeChecker::visit (AST::ArrayIndexExpr &)
     721            0 : {}
     722              : 
     723              : void
     724           60 : AttributeChecker::visit (AST::TupleExpr &)
     725           60 : {}
     726              : 
     727              : void
     728          187 : AttributeChecker::visit (AST::TupleIndexExpr &)
     729          187 : {}
     730              : 
     731              : void
     732            7 : AttributeChecker::visit (AST::StructExprStruct &)
     733            7 : {}
     734              : 
     735              : void
     736            0 : AttributeChecker::visit (AST::StructExprFieldIdentifier &)
     737            0 : {}
     738              : 
     739              : void
     740            0 : AttributeChecker::visit (AST::StructExprFieldIdentifierValue &)
     741            0 : {}
     742              : 
     743              : void
     744            0 : AttributeChecker::visit (AST::StructExprFieldIndexValue &)
     745            0 : {}
     746              : 
     747              : void
     748          155 : AttributeChecker::visit (AST::StructExprStructFields &)
     749          155 : {}
     750              : 
     751              : void
     752            0 : AttributeChecker::visit (AST::StructExprStructBase &)
     753            0 : {}
     754              : 
     755              : void
     756          647 : AttributeChecker::visit (AST::CallExpr &)
     757          647 : {}
     758              : 
     759              : void
     760          291 : AttributeChecker::visit (AST::MethodCallExpr &)
     761          291 : {}
     762              : 
     763              : void
     764          171 : AttributeChecker::visit (AST::FieldAccessExpr &)
     765          171 : {}
     766              : 
     767              : void
     768            1 : AttributeChecker::visit (AST::ClosureExprInner &)
     769            1 : {}
     770              : 
     771              : void
     772        12064 : AttributeChecker::visit (AST::BlockExpr &expr)
     773              : {
     774        27934 :   for (auto &stmt : expr.get_statements ())
     775              :     {
     776        15870 :       if (stmt->get_stmt_kind () == AST::Stmt::Kind::Item)
     777              :         {
     778              :           // Non owning pointer, let it go out of scope
     779          719 :           auto item = static_cast<AST::Item *> (stmt.get ());
     780          729 :           for (auto &attr : item->get_outer_attrs ())
     781           10 :             check_proc_macro_non_root (attr, item->get_locus ());
     782              :         }
     783              :     }
     784        12064 :   AST::DefaultASTVisitor::visit (expr);
     785        12064 : }
     786              : 
     787              : void
     788            0 : AttributeChecker::visit (AST::ClosureExprInnerTyped &)
     789            0 : {}
     790              : 
     791              : void
     792            0 : AttributeChecker::visit (AST::ContinueExpr &)
     793            0 : {}
     794              : 
     795              : void
     796            0 : AttributeChecker::visit (AST::BreakExpr &)
     797            0 : {}
     798              : 
     799              : void
     800            0 : AttributeChecker::visit (AST::RangeFromToExpr &)
     801            0 : {}
     802              : 
     803              : void
     804            0 : AttributeChecker::visit (AST::RangeFromExpr &)
     805            0 : {}
     806              : 
     807              : void
     808            0 : AttributeChecker::visit (AST::RangeToExpr &)
     809            0 : {}
     810              : 
     811              : void
     812            0 : AttributeChecker::visit (AST::RangeFullExpr &)
     813            0 : {}
     814              : 
     815              : void
     816            0 : AttributeChecker::visit (AST::RangeFromToInclExpr &)
     817            0 : {}
     818              : 
     819              : void
     820            0 : AttributeChecker::visit (AST::RangeToInclExpr &)
     821            0 : {}
     822              : 
     823              : void
     824            3 : AttributeChecker::visit (AST::ReturnExpr &)
     825            3 : {}
     826              : 
     827              : void
     828           52 : AttributeChecker::visit (AST::LoopExpr &)
     829           52 : {}
     830              : 
     831              : void
     832           18 : AttributeChecker::visit (AST::WhileLoopExpr &)
     833           18 : {}
     834              : 
     835              : void
     836            2 : AttributeChecker::visit (AST::WhileLetLoopExpr &)
     837            2 : {}
     838              : 
     839              : void
     840            1 : AttributeChecker::visit (AST::ForLoopExpr &)
     841            1 : {}
     842              : 
     843              : void
     844           71 : AttributeChecker::visit (AST::IfExpr &)
     845           71 : {}
     846              : 
     847              : void
     848          517 : AttributeChecker::visit (AST::IfExprConseqElse &)
     849          517 : {}
     850              : 
     851              : void
     852            0 : AttributeChecker::visit (AST::IfLetExpr &)
     853            0 : {}
     854              : 
     855              : void
     856            9 : AttributeChecker::visit (AST::IfLetExprConseqElse &)
     857            9 : {}
     858              : 
     859              : void
     860          509 : AttributeChecker::visit (AST::MatchExpr &)
     861          509 : {}
     862              : 
     863              : void
     864            0 : AttributeChecker::visit (AST::AwaitExpr &)
     865            0 : {}
     866              : 
     867              : void
     868            0 : AttributeChecker::visit (AST::AsyncBlockExpr &)
     869            0 : {}
     870              : 
     871              : // rust-item.h
     872              : void
     873         5746 : AttributeChecker::visit (AST::TypeParam &)
     874         5746 : {}
     875              : 
     876              : void
     877            0 : AttributeChecker::visit (AST::LifetimeWhereClauseItem &)
     878            0 : {}
     879              : 
     880              : void
     881           96 : AttributeChecker::visit (AST::TypeBoundWhereClauseItem &)
     882           96 : {}
     883              : 
     884              : void
     885         1306 : AttributeChecker::visit (AST::Module &module)
     886              : {
     887         1473 :   for (auto &attr : module.get_outer_attrs ())
     888              :     {
     889          167 :       check_valid_attribute_for_item (attr, module);
     890          167 :       check_proc_macro_non_function (attr);
     891              :     }
     892              : 
     893         4144 :   for (auto &item : module.get_items ())
     894         4836 :     for (auto &attr : item->get_outer_attrs ())
     895         1998 :       check_proc_macro_non_root (attr, item->get_locus ());
     896              : 
     897         1306 :   AST::DefaultASTVisitor::visit (module);
     898         1306 : }
     899              : 
     900              : void
     901           27 : AttributeChecker::visit (AST::ExternCrate &crate)
     902              : {
     903           30 :   for (auto &attr : crate.get_outer_attrs ())
     904              :     {
     905            3 :       check_valid_attribute_for_item (attr, crate);
     906            3 :       check_proc_macro_non_function (attr);
     907              :     }
     908           27 : }
     909              : 
     910              : void
     911            0 : AttributeChecker::visit (AST::UseTreeGlob &)
     912            0 : {}
     913              : 
     914              : void
     915            0 : AttributeChecker::visit (AST::UseTreeList &)
     916            0 : {}
     917              : 
     918              : void
     919            0 : AttributeChecker::visit (AST::UseTreeRebind &)
     920            0 : {}
     921              : 
     922              : void
     923          679 : AttributeChecker::visit (AST::UseDeclaration &declaration)
     924              : {
     925          683 :   for (auto &attr : declaration.get_outer_attrs ())
     926              :     {
     927            4 :       check_valid_attribute_for_item (attr, declaration);
     928            4 :       check_proc_macro_non_function (attr);
     929              :     }
     930          679 : }
     931              : 
     932              : static void
     933            1 : check_no_mangle_function (const AST::Attribute &attribute,
     934              :                           const AST::Function &fun)
     935              : {
     936            1 :   if (attribute.has_attr_input ())
     937              :     {
     938            0 :       rust_error_at (attribute.get_locus (), ErrorCode::E0754,
     939              :                      "malformed %<no_mangle%> attribute input");
     940            0 :       rust_inform (attribute.get_locus (),
     941              :                    "must be of the form: %<#[no_mangle]%>");
     942              :     }
     943            1 :   if (!is_ascii_only (fun.get_function_name ().as_string ()))
     944            0 :     rust_error_at (fun.get_function_name ().get_locus (),
     945              :                    "the %<#[no_mangle]%> attribute requires ASCII identifier");
     946            1 : }
     947              : 
     948              : void
     949        12606 : AttributeChecker::visit (AST::Function &fun)
     950              : {
     951        22073 :   for (auto &attr : fun.get_outer_attrs ())
     952         9467 :     check_valid_attribute_for_item (attr, fun);
     953              : 
     954        12622 :   auto check_crate_type = [] (const char *name, AST::Attribute &attribute) {
     955           16 :     if (!Session::get_instance ().options.is_proc_macro ())
     956            3 :       rust_error_at (attribute.get_locus (),
     957              :                      "the %<#[%s]%> attribute is only usable with crates of "
     958              :                      "the %<proc-macro%> crate type",
     959              :                      name);
     960           16 :   };
     961              : 
     962        12606 :   BuiltinAttrDefinition result;
     963        22073 :   for (auto &attribute : fun.get_outer_attrs ())
     964              :     {
     965         9467 :       auto result = identify_builtin (attribute);
     966         9467 :       if (!result)
     967            0 :         return;
     968              : 
     969         9467 :       auto name = result->name.c_str ();
     970              : 
     971         9467 :       if (result->name == Attrs::PROC_MACRO_DERIVE)
     972              :         {
     973            6 :           if (!attribute.has_attr_input ())
     974              :             {
     975            1 :               rust_error_at (attribute.get_locus (),
     976              :                              "malformed %qs attribute input", name);
     977            1 :               rust_inform (
     978              :                 attribute.get_locus (),
     979              :                 "must be of the form: %<#[proc_macro_derive(TraitName, "
     980              :                 "/*opt*/ attributes(name1, name2, ...))]%>");
     981              :             }
     982            6 :           check_crate_type (name, attribute);
     983              :         }
     984         9461 :       else if (result->name == Attrs::PROC_MACRO
     985         9461 :                || result->name == Attrs::PROC_MACRO_ATTRIBUTE)
     986              :         {
     987           10 :           check_crate_type (name, attribute);
     988              :         }
     989         9451 :       else if (result->name == Attrs::TARGET_FEATURE)
     990              :         {
     991            3 :           if (!attribute.has_attr_input ())
     992              :             {
     993            1 :               rust_error_at (attribute.get_locus (),
     994              :                              "malformed %<target_feature%> attribute input");
     995            1 :               rust_inform (attribute.get_locus (),
     996              :                            "must be of the form: %<#[target_feature(enable = "
     997              :                            "\"name\")]%>");
     998              :             }
     999            2 :           else if (!fun.get_qualifiers ().is_unsafe ())
    1000              :             {
    1001            1 :               rust_error_at (
    1002              :                 attribute.get_locus (),
    1003              :                 "the %<#[target_feature]%> attribute can only be applied "
    1004              :                 "to %<unsafe%> functions");
    1005              :             }
    1006              :         }
    1007         9448 :       else if (result->name == Attrs::NO_MANGLE)
    1008              :         {
    1009            2 :           if (attribute.has_attr_input ())
    1010              :             {
    1011            1 :               rust_error_at (attribute.get_locus (),
    1012              :                              "malformed %<no_mangle%> attribute input");
    1013            1 :               rust_inform (attribute.get_locus (),
    1014              :                            "must be of the form: %<#[no_mangle]%>");
    1015              :             }
    1016              :           else
    1017            1 :             check_no_mangle_function (attribute, fun);
    1018              :         }
    1019         9446 :       else if (result->name == Attrs::EXPORT_NAME)
    1020              :         {
    1021            6 :           check_export_name_attribute (attribute);
    1022              :         }
    1023         9430 :       else if (result->name == Attrs::ALLOW || result->name == "deny"
    1024        18870 :                || result->name == "warn" || result->name == "forbid")
    1025              :         {
    1026           10 :           check_lint_attribute (attribute, name);
    1027              :         }
    1028         9430 :       else if (result->name == Attrs::LINK_NAME)
    1029              :         {
    1030            1 :           if (!attribute.has_attr_input ())
    1031              :             {
    1032            1 :               rust_error_at (attribute.get_locus (),
    1033              :                              "malformed %<link_name%> attribute input");
    1034            1 :               rust_inform (attribute.get_locus (),
    1035              :                            "must be of the form: %<#[link_name = \"name\"]%>");
    1036              :             }
    1037              :         }
    1038         9429 :       else if (result->name == Attrs::LINK_SECTION)
    1039              :         {
    1040            1 :           check_link_section_attribute (attribute);
    1041              :         }
    1042         9467 :     }
    1043              : 
    1044        12606 :   if (fun.has_body ())
    1045        10898 :     fun.get_definition ().value ()->accept_vis (*this);
    1046        12606 : }
    1047              : 
    1048              : void
    1049          736 : AttributeChecker::visit (AST::TypeAlias &alias)
    1050              : {
    1051          739 :   for (auto &attr : alias.get_outer_attrs ())
    1052              :     {
    1053            3 :       check_valid_attribute_for_item (attr, alias);
    1054            3 :       check_proc_macro_non_function (attr);
    1055              :     }
    1056          736 : }
    1057              : 
    1058              : void
    1059         1499 : AttributeChecker::visit (AST::StructStruct &struct_item)
    1060              : {
    1061         1973 :   for (auto &attr : struct_item.get_outer_attrs ())
    1062              :     {
    1063          474 :       check_valid_attribute_for_item (attr, struct_item);
    1064          474 :       check_proc_macro_non_function (attr);
    1065              :     }
    1066              : 
    1067         1499 :   AST::DefaultASTVisitor::visit (struct_item);
    1068         1499 : }
    1069              : 
    1070              : void
    1071          963 : AttributeChecker::visit (AST::TupleStruct &tuplestruct)
    1072              : {
    1073          995 :   for (auto &attr : tuplestruct.get_outer_attrs ())
    1074              :     {
    1075           32 :       check_valid_attribute_for_item (attr, tuplestruct);
    1076           32 :       check_proc_macro_non_function (attr);
    1077              :     }
    1078          963 : }
    1079              : 
    1080              : void
    1081            0 : AttributeChecker::visit (AST::EnumItem &)
    1082            0 : {}
    1083              : 
    1084              : void
    1085            0 : AttributeChecker::visit (AST::EnumItemTuple &)
    1086            0 : {}
    1087              : 
    1088              : void
    1089            0 : AttributeChecker::visit (AST::EnumItemStruct &)
    1090            0 : {}
    1091              : 
    1092              : void
    1093            0 : AttributeChecker::visit (AST::EnumItemDiscriminant &)
    1094            0 : {}
    1095              : 
    1096              : void
    1097          544 : AttributeChecker::visit (AST::Enum &enumeration)
    1098              : {
    1099          697 :   for (auto &attr : enumeration.get_outer_attrs ())
    1100              :     {
    1101          153 :       check_valid_attribute_for_item (attr, enumeration);
    1102          153 :       check_proc_macro_non_function (attr);
    1103              :     }
    1104          544 : }
    1105              : 
    1106              : void
    1107          111 : AttributeChecker::visit (AST::Union &u)
    1108              : {
    1109          128 :   for (auto &attr : u.get_outer_attrs ())
    1110              :     {
    1111           17 :       check_valid_attribute_for_item (attr, u);
    1112           17 :       check_proc_macro_non_function (attr);
    1113              :     }
    1114          111 : }
    1115              : 
    1116              : void
    1117          566 : AttributeChecker::visit (AST::ConstantItem &item)
    1118              : {
    1119          569 :   for (auto &attr : item.get_outer_attrs ())
    1120              :     {
    1121            3 :       check_valid_attribute_for_item (attr, item);
    1122            3 :       check_proc_macro_non_function (attr);
    1123              :     }
    1124          566 : }
    1125              : 
    1126              : void
    1127           64 : AttributeChecker::visit (AST::StaticItem &item)
    1128              : {
    1129           72 :   for (auto &attr : item.get_outer_attrs ())
    1130              :     {
    1131            8 :       check_valid_attribute_for_item (attr, item);
    1132            8 :       check_proc_macro_non_function (attr);
    1133              : 
    1134            8 :       if (auto result = identify_builtin (attr))
    1135              :         {
    1136            8 :           if (result->name == Attrs::LINK_SECTION)
    1137            1 :             check_link_section_attribute (attr);
    1138            7 :           else if (result->name == Attrs::EXPORT_NAME)
    1139            4 :             check_export_name_attribute (attr);
    1140            8 :         }
    1141              :     }
    1142           64 : }
    1143              : 
    1144              : void
    1145          738 : AttributeChecker::visit (AST::TraitItemType &)
    1146          738 : {}
    1147              : 
    1148              : void
    1149         3743 : AttributeChecker::visit (AST::Trait &trait)
    1150              : {
    1151         7478 :   for (auto &attr : trait.get_outer_attrs ())
    1152              :     {
    1153         3735 :       check_valid_attribute_for_item (attr, trait);
    1154         3735 :       check_proc_macro_non_function (attr);
    1155              :     }
    1156         3743 :   AST::DefaultASTVisitor::visit (trait);
    1157         3743 : }
    1158              : 
    1159              : void
    1160          760 : AttributeChecker::visit (AST::InherentImpl &impl)
    1161              : {
    1162          906 :   for (auto &attr : impl.get_outer_attrs ())
    1163              :     {
    1164          146 :       check_valid_attribute_for_item (attr, impl);
    1165          146 :       check_proc_macro_non_function (attr);
    1166              :     }
    1167              : 
    1168          760 :   AST::DefaultASTVisitor::visit (impl);
    1169          760 : }
    1170              : 
    1171              : void
    1172         2010 : AttributeChecker::visit (AST::TraitImpl &impl)
    1173              : {
    1174         2018 :   for (auto &attr : impl.get_outer_attrs ())
    1175              :     {
    1176            8 :       check_valid_attribute_for_item (attr, impl);
    1177            8 :       check_proc_macro_non_function (attr);
    1178              :     }
    1179         2010 :   AST::DefaultASTVisitor::visit (impl);
    1180         2010 : }
    1181              : 
    1182              : void
    1183            0 : AttributeChecker::visit (AST::ExternalTypeItem &)
    1184            0 : {}
    1185              : 
    1186              : void
    1187            0 : AttributeChecker::visit (AST::ExternalStaticItem &)
    1188            0 : {}
    1189              : 
    1190              : void
    1191         1466 : AttributeChecker::visit (AST::ExternBlock &block)
    1192              : {
    1193         1470 :   for (auto &attr : block.get_outer_attrs ())
    1194              :     {
    1195            4 :       check_valid_attribute_for_item (attr, block);
    1196            4 :       check_proc_macro_non_function (attr);
    1197              :     }
    1198         1466 : }
    1199              : 
    1200              : // rust-macro.h
    1201              : void
    1202            0 : AttributeChecker::visit (AST::MacroMatchFragment &)
    1203            0 : {}
    1204              : 
    1205              : void
    1206            0 : AttributeChecker::visit (AST::MacroMatchRepetition &)
    1207            0 : {}
    1208              : 
    1209              : void
    1210            0 : AttributeChecker::visit (AST::MacroMatcher &)
    1211            0 : {}
    1212              : 
    1213              : void
    1214          966 : AttributeChecker::visit (AST::MacroRulesDefinition &)
    1215          966 : {}
    1216              : 
    1217              : void
    1218          713 : AttributeChecker::visit (AST::MacroInvocation &)
    1219          713 : {}
    1220              : 
    1221              : void
    1222            0 : AttributeChecker::visit (AST::MetaItemPath &)
    1223            0 : {}
    1224              : 
    1225              : void
    1226            4 : AttributeChecker::visit (AST::MetaWord &)
    1227            4 : {}
    1228              : 
    1229              : void
    1230            1 : AttributeChecker::visit (AST::MetaNameValueStr &)
    1231            1 : {}
    1232              : 
    1233              : void
    1234            0 : AttributeChecker::visit (AST::MetaListPaths &)
    1235            0 : {}
    1236              : 
    1237              : void
    1238            0 : AttributeChecker::visit (AST::MetaListNameValueStr &)
    1239            0 : {}
    1240              : 
    1241              : // rust-pattern.h
    1242              : void
    1243            0 : AttributeChecker::visit (AST::LiteralPattern &)
    1244            0 : {}
    1245              : 
    1246              : void
    1247            0 : AttributeChecker::visit (AST::IdentifierPattern &)
    1248            0 : {}
    1249              : 
    1250              : void
    1251            0 : AttributeChecker::visit (AST::WildcardPattern &)
    1252            0 : {}
    1253              : 
    1254              : void
    1255            0 : AttributeChecker::visit (AST::RestPattern &)
    1256            0 : {}
    1257              : 
    1258              : // void AttributeChecker::visit(RangePatternBound& ){}
    1259              : 
    1260              : void
    1261            0 : AttributeChecker::visit (AST::RangePatternBoundLiteral &)
    1262            0 : {}
    1263              : 
    1264              : void
    1265            0 : AttributeChecker::visit (AST::RangePatternBoundPath &)
    1266            0 : {}
    1267              : 
    1268              : void
    1269            0 : AttributeChecker::visit (AST::RangePatternBoundQualPath &)
    1270            0 : {}
    1271              : 
    1272              : void
    1273            0 : AttributeChecker::visit (AST::RangePattern &)
    1274            0 : {}
    1275              : 
    1276              : void
    1277            0 : AttributeChecker::visit (AST::ReferencePattern &)
    1278            0 : {}
    1279              : 
    1280              : // void AttributeChecker::visit(StructPatternField& ){}
    1281              : 
    1282              : void
    1283            0 : AttributeChecker::visit (AST::StructPatternFieldTuplePat &)
    1284            0 : {}
    1285              : 
    1286              : void
    1287            0 : AttributeChecker::visit (AST::StructPatternFieldIdentPat &)
    1288            0 : {}
    1289              : 
    1290              : void
    1291            0 : AttributeChecker::visit (AST::StructPatternFieldIdent &)
    1292            0 : {}
    1293              : 
    1294              : void
    1295            0 : AttributeChecker::visit (AST::StructPattern &)
    1296            0 : {}
    1297              : 
    1298              : // void AttributeChecker::visit(TupleStructItems& ){}
    1299              : 
    1300              : void
    1301            0 : AttributeChecker::visit (AST::TupleStructItemsNoRest &)
    1302            0 : {}
    1303              : 
    1304              : void
    1305            0 : AttributeChecker::visit (AST::TupleStructItemsHasRest &)
    1306            0 : {}
    1307              : 
    1308              : void
    1309            0 : AttributeChecker::visit (AST::TupleStructPattern &)
    1310            0 : {}
    1311              : 
    1312              : // void AttributeChecker::visit(TuplePatternItems& ){}
    1313              : 
    1314              : void
    1315            0 : AttributeChecker::visit (AST::TuplePatternItemsNoRest &)
    1316            0 : {}
    1317              : 
    1318              : void
    1319            0 : AttributeChecker::visit (AST::TuplePatternItemsHasRest &)
    1320            0 : {}
    1321              : 
    1322              : void
    1323            0 : AttributeChecker::visit (AST::TuplePattern &)
    1324            0 : {}
    1325              : 
    1326              : void
    1327            0 : AttributeChecker::visit (AST::GroupedPattern &)
    1328            0 : {}
    1329              : 
    1330              : void
    1331            0 : AttributeChecker::visit (AST::SlicePattern &)
    1332            0 : {}
    1333              : 
    1334              : void
    1335            0 : AttributeChecker::visit (AST::AltPattern &)
    1336            0 : {}
    1337              : 
    1338              : // rust-stmt.h
    1339              : void
    1340           18 : AttributeChecker::visit (AST::EmptyStmt &)
    1341           18 : {}
    1342              : 
    1343              : void
    1344         9688 : AttributeChecker::visit (AST::LetStmt &)
    1345         9688 : {}
    1346              : 
    1347              : void
    1348         5445 : AttributeChecker::visit (AST::ExprStmt &)
    1349         5445 : {}
    1350              : 
    1351              : // rust-type.h
    1352              : void
    1353          609 : AttributeChecker::visit (AST::TraitBound &)
    1354          609 : {}
    1355              : 
    1356              : void
    1357            0 : AttributeChecker::visit (AST::ImplTraitType &)
    1358            0 : {}
    1359              : 
    1360              : void
    1361            4 : AttributeChecker::visit (AST::TraitObjectType &)
    1362            4 : {}
    1363              : 
    1364              : void
    1365            2 : AttributeChecker::visit (AST::ParenthesisedType &)
    1366            2 : {}
    1367              : 
    1368              : void
    1369            2 : AttributeChecker::visit (AST::ImplTraitTypeOneBound &)
    1370            2 : {}
    1371              : 
    1372              : void
    1373            7 : AttributeChecker::visit (AST::TraitObjectTypeOneBound &)
    1374            7 : {}
    1375              : 
    1376              : void
    1377            3 : AttributeChecker::visit (AST::TupleType &)
    1378            3 : {}
    1379              : 
    1380              : void
    1381            2 : AttributeChecker::visit (AST::NeverType &)
    1382            2 : {}
    1383              : 
    1384              : void
    1385          239 : AttributeChecker::visit (AST::RawPointerType &)
    1386          239 : {}
    1387              : 
    1388              : void
    1389          176 : AttributeChecker::visit (AST::ReferenceType &)
    1390          176 : {}
    1391              : 
    1392              : void
    1393           39 : AttributeChecker::visit (AST::ArrayType &)
    1394           39 : {}
    1395              : 
    1396              : void
    1397           66 : AttributeChecker::visit (AST::SliceType &)
    1398           66 : {}
    1399              : 
    1400              : void
    1401            0 : AttributeChecker::visit (AST::InferredType &)
    1402            0 : {}
    1403              : 
    1404              : void
    1405           10 : AttributeChecker::visit (AST::BareFunctionType &)
    1406           10 : {}
    1407              : 
    1408              : void
    1409            0 : AttributeChecker::visit (AST::SelfParam &)
    1410            0 : {}
    1411              : 
    1412              : void
    1413            0 : AttributeChecker::visit (AST::VariadicParam &)
    1414            0 : {}
    1415              : 
    1416              : void
    1417            0 : AttributeChecker::visit (AST::FunctionParam &)
    1418            0 : {}
    1419              : 
    1420              : } // namespace Analysis
    1421              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.