LCOV - code coverage report
Current view: top level - gcc/rust/checks/errors - rust-builtin-attribute-checker.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 78.9 % 261 206
Test Date: 2026-07-11 15:47:05 Functions: 100.0 % 38 38
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 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-builtin-attribute-checker.h"
      20              : #include "optional.h"
      21              : #include "rust-attributes.h"
      22              : #include "rust-attribute-values.h"
      23              : #include "rust-session-manager.h"
      24              : 
      25              : namespace Rust {
      26              : namespace Analysis {
      27              : 
      28              : using Attrs = Values::Attributes;
      29              : 
      30              : void
      31        12067 : check_inner_attribute (const AST::Attribute &attribute)
      32              : {
      33        12067 :   auto result_opt = lookup_builtin (attribute);
      34        12067 :   if (!result_opt.has_value ())
      35            0 :     return;
      36        12067 :   auto result = result_opt.value ();
      37              : 
      38        12067 :   if (Attributes::valid_outer_attribute (result.name))
      39            3 :     rust_error_at (attribute.get_locus (),
      40              :                    "attribute cannot be used at crate level");
      41        24134 : }
      42              : 
      43              : /**
      44              :  * Check that the string given to #[doc(alias = ...)] or #[doc(alias(...))] is
      45              :  * valid.
      46              :  *
      47              :  * This means no whitespace characters other than spaces and no quoting
      48              :  * characters.
      49              :  */
      50              : static void
      51          700 : check_doc_alias (const std::string &alias_input, const location_t locus)
      52              : {
      53              :   // FIXME: The locus here is for the whole attribute. Can we get the locus
      54              :   // of the alias input instead?
      55         1872 :   for (auto c : alias_input)
      56         1172 :     if ((ISSPACE (c) && c != ' ') || c == '\'' || c == '\"')
      57              :       {
      58            7 :         auto to_print = std::string (1, c);
      59            7 :         switch (c)
      60              :           {
      61            7 :           case '\n':
      62            7 :             to_print = "\\n";
      63            7 :             break;
      64            0 :           case '\t':
      65            0 :             to_print = "\\t";
      66            0 :             break;
      67              :           default:
      68              :             break;
      69              :           }
      70            7 :         rust_error_at (locus,
      71              :                        "invalid character used in %<#[doc(alias)]%> input: %qs",
      72              :                        to_print.c_str ());
      73            7 :       }
      74              : 
      75          700 :   if (alias_input.empty ())
      76              :     return;
      77              : 
      78         1400 :   if (alias_input.front () == ' ' || alias_input.back () == ' ')
      79            0 :     rust_error_at (locus,
      80              :                    "%<#[doc(alias)]%> input cannot start or end with a space");
      81              : }
      82              : 
      83              : // This namespace contains handlers for the builtin attribute checker,
      84              : // those handlers must verify the attribute internal structure and emit the
      85              : // appropriate error message if the structure is incorrect.
      86              : //
      87              : // They DO NOT check the attribute validity on the parent item.
      88              : namespace handlers {
      89              : 
      90              : void
      91         8935 : doc (const AST::Attribute &attribute)
      92              : {
      93         8935 :   if (!attribute.has_attr_input ())
      94              :     {
      95            2 :       rust_error_at (
      96              :         attribute.get_locus (),
      97              :         "valid forms for the attribute are "
      98              :         "%<#[doc(hidden|inline|...)]%> and %<#[doc = \" string \"]%>");
      99            2 :       return;
     100              :     }
     101              : 
     102         8933 :   switch (attribute.get_attr_input ().get_attr_input_type ())
     103              :     {
     104              :     case AST::AttrInput::LITERAL:
     105              :     case AST::AttrInput::META_ITEM:
     106              :     case AST::AttrInput::EXPR:
     107              :       break;
     108              :       // FIXME: Handle them as well
     109              : 
     110          799 :     case AST::AttrInput::TOKEN_TREE:
     111          799 :       {
     112              :         // FIXME: This doesn't check for #[doc(alias(...))]
     113          799 :         const auto &option = static_cast<const AST::DelimTokenTree &> (
     114          799 :           attribute.get_attr_input ());
     115          799 :         auto *meta_item = option.parse_to_meta_item ();
     116              : 
     117         1605 :         for (auto &item : meta_item->get_items ())
     118              :           {
     119          806 :             if (item->is_key_value_pair ())
     120              :               {
     121          707 :                 auto name_value
     122          707 :                   = static_cast<AST::MetaNameValueStr *> (item.get ())
     123          707 :                       ->get_name_value_pair ();
     124              : 
     125              :                 // FIXME: Check for other stuff than #[doc(alias = ...)]
     126          707 :                 if (name_value.first.as_string () == "alias")
     127          700 :                   check_doc_alias (name_value.second, attribute.get_locus ());
     128          707 :               }
     129              :           }
     130              :         break;
     131              :       }
     132              :     }
     133              : }
     134              : 
     135              : void
     136            6 : deprecated (const AST::Attribute &attribute)
     137              : {
     138            6 :   if (!attribute.has_attr_input ())
     139              :     return;
     140              : 
     141            4 :   const auto &input = attribute.get_attr_input ();
     142              : 
     143            4 :   if (input.get_attr_input_type () != AST::AttrInput::META_ITEM)
     144              :     return;
     145              : 
     146            0 :   auto &meta = static_cast<const AST::AttrInputMetaItemContainer &> (input);
     147              : 
     148            0 :   for (auto &current : meta.get_items ())
     149              :     {
     150            0 :       switch (current->get_kind ())
     151              :         {
     152            0 :         case AST::MetaItemInner::Kind::MetaItem:
     153            0 :           {
     154            0 :             auto *meta_item = static_cast<AST::MetaItem *> (current.get ());
     155              : 
     156            0 :             switch (meta_item->get_item_kind ())
     157              :               {
     158            0 :               case AST::MetaItem::ItemKind::NameValueStr:
     159            0 :                 {
     160            0 :                   auto *nv = static_cast<AST::MetaNameValueStr *> (meta_item);
     161              : 
     162            0 :                   const std::string key = nv->get_name ().as_string ();
     163              : 
     164            0 :                   if (key != "since" && key != "note")
     165              :                     {
     166            0 :                       rust_error_at (nv->get_locus (), "unknown meta item %qs",
     167              :                                      key.c_str ());
     168            0 :                       rust_inform (nv->get_locus (),
     169              :                                    "expected one of %<since%>, %<note%>");
     170              :                     }
     171            0 :                 }
     172            0 :                 break;
     173              : 
     174            0 :               case AST::MetaItem::ItemKind::Path:
     175            0 :                 {
     176              :                   // #[deprecated(a,a)]
     177            0 :                   auto *p = static_cast<AST::MetaItemPath *> (meta_item);
     178              : 
     179            0 :                   std::string ident = p->get_path ().as_string ();
     180              : 
     181            0 :                   rust_error_at (p->get_locus (), "unknown meta item %qs",
     182              :                                  ident.c_str ());
     183            0 :                   rust_inform (p->get_locus (),
     184              :                                "expected one of %<since%>, %<note%>");
     185            0 :                 }
     186            0 :                 break;
     187              : 
     188            0 :               case AST::MetaItem::ItemKind::Word:
     189            0 :                 {
     190              :                   // #[deprecated("a")]
     191            0 :                   auto *w = static_cast<AST::MetaWord *> (meta_item);
     192              : 
     193            0 :                   rust_error_at (
     194            0 :                     w->get_locus (),
     195              :                     "item in %<deprecated%> must be a key/value pair");
     196              :                 }
     197            0 :                 break;
     198              : 
     199            0 :               case AST::MetaItem::ItemKind::PathExpr:
     200            0 :                 {
     201              :                   // #[deprecated(since=a)]
     202            0 :                   auto *px = static_cast<AST::MetaItemPathExpr *> (meta_item);
     203              : 
     204            0 :                   rust_error_at (
     205            0 :                     px->get_locus (),
     206              :                     "expected unsuffixed literal or identifier, found %qs",
     207            0 :                     px->get_expr ().as_string ().c_str ());
     208              :                 }
     209            0 :                 break;
     210              : 
     211            0 :               case AST::MetaItem::ItemKind::Seq:
     212            0 :               case AST::MetaItem::ItemKind::ListPaths:
     213            0 :               case AST::MetaItem::ItemKind::ListNameValueStr:
     214            0 :               default:
     215            0 :                 gcc_unreachable ();
     216            0 :                 break;
     217              :               }
     218              :           }
     219            0 :           break;
     220              : 
     221            0 :         case AST::MetaItemInner::Kind::LitExpr:
     222            0 :         default:
     223            0 :           gcc_unreachable ();
     224            0 :           break;
     225              :         }
     226              :     }
     227              : }
     228              : 
     229              : void
     230            2 : link_section (const AST::Attribute &attribute)
     231              : {
     232            2 :   if (!attribute.has_attr_input ())
     233              :     {
     234            1 :       rust_error_at (attribute.get_locus (),
     235              :                      "malformed %<link_section%> attribute input");
     236            1 :       rust_inform (attribute.get_locus (),
     237              :                    "must be of the form: %<#[link_section = \"name\"]%>");
     238              :     }
     239            2 : }
     240              : 
     241              : void
     242           11 : export_name (const AST::Attribute &attribute)
     243              : {
     244           11 :   if (!attribute.has_attr_input ())
     245              :     {
     246            2 :       rust_error_at (attribute.get_locus (),
     247              :                      "malformed %<export_name%> attribute input");
     248            2 :       rust_inform (attribute.get_locus (),
     249              :                    "must be of the form: %<#[export_name = \"name\"]%>");
     250            2 :       return;
     251              :     }
     252              : 
     253            9 :   auto &attr_input = attribute.get_attr_input ();
     254            9 :   if (attr_input.get_attr_input_type ()
     255              :       == AST::AttrInput::AttrInputType::LITERAL)
     256              :     {
     257            7 :       auto &literal_expr
     258            7 :         = static_cast<AST::AttrInputLiteral &> (attr_input).get_literal ();
     259            7 :       auto lit_type = literal_expr.get_lit_type ();
     260            7 :       switch (lit_type)
     261              :         {
     262              :         case AST::Literal::LitType::STRING:
     263              :         case AST::Literal::LitType::RAW_STRING:
     264              :         case AST::Literal::LitType::BYTE_STRING:
     265              :           return;
     266              :         default:
     267              :           break;
     268              :         }
     269              :     }
     270              : 
     271            4 :   rust_error_at (attribute.get_locus (), "attribute must be a string literal");
     272              : }
     273              : 
     274              : void
     275          102 : lint (const AST::Attribute &attribute)
     276              : {
     277          102 :   if (!attribute.has_attr_input ())
     278              :     {
     279            1 :       auto name = attribute.get_path ().as_string ();
     280            1 :       rust_error_at (attribute.get_locus (), "malformed %qs attribute input",
     281              :                      name.c_str ());
     282            1 :       rust_inform (attribute.get_locus (),
     283              :                    "must be of the form: %<#[%s(lint1, lint2, ...)]%>",
     284              :                    name.c_str ());
     285            1 :     }
     286          102 : }
     287              : 
     288              : void
     289            8 : link_name (const AST::Attribute &attribute)
     290              : {
     291            8 :   if (!attribute.has_attr_input ())
     292              :     {
     293            1 :       rust_error_at (attribute.get_locus (),
     294              :                      "malformed %<link_name%> attribute input");
     295            1 :       rust_inform (attribute.get_locus (),
     296              :                    "must be of the form: %<#[link_name = \"name\"]%>");
     297              :     }
     298            8 : }
     299              : 
     300              : namespace {
     301              : void
     302           58 : check_crate_type (const AST::Attribute &attribute)
     303              : {
     304           58 :   if (!Session::get_instance ().options.is_proc_macro ())
     305              :     {
     306            3 :       auto name = attribute.get_path ().as_string ();
     307              : 
     308            3 :       rust_error_at (attribute.get_locus (),
     309              :                      "the %<#[%s]%> attribute is only usable with crates of "
     310              :                      "the %<proc-macro%> crate type",
     311              :                      name.c_str ());
     312            3 :     }
     313           58 : }
     314              : } // namespace
     315              : 
     316              : static void
     317           20 : proc_macro_derive (const AST::Attribute &attribute)
     318              : {
     319           20 :   if (!attribute.has_attr_input ())
     320              :     {
     321            1 :       auto name = attribute.get_path ().as_string ();
     322            1 :       rust_error_at (attribute.get_locus (), "malformed %qs attribute input",
     323              :                      name.c_str ());
     324            1 :       rust_inform (attribute.get_locus (),
     325              :                    "must be of the form: %<#[proc_macro_derive(TraitName, "
     326              :                    "/*opt*/ attributes(name1, name2, ...))]%>");
     327            1 :     }
     328           20 :   check_crate_type (attribute);
     329           20 : }
     330              : 
     331              : static void
     332           38 : proc_macro (const AST::Attribute &attribute)
     333              : {
     334           38 :   check_crate_type (attribute);
     335           38 : }
     336              : 
     337              : static void
     338            4 : target_feature (const AST::Attribute &attribute)
     339              : {
     340            4 :   if (!attribute.has_attr_input ())
     341              :     {
     342            1 :       rust_error_at (attribute.get_locus (),
     343              :                      "malformed %<target_feature%> attribute input");
     344            1 :       rust_inform (attribute.get_locus (),
     345              :                    "must be of the form: %<#[target_feature(enable = "
     346              :                    "\"name\")]%>");
     347              :     }
     348            4 : }
     349              : 
     350              : void
     351            2 : no_mangle (const AST::Attribute &attribute)
     352              : {
     353            2 :   if (attribute.has_attr_input ())
     354              :     {
     355            1 :       rust_error_at (attribute.get_locus (), ErrorCode::E0754,
     356              :                      "malformed %<no_mangle%> attribute input");
     357            1 :       rust_inform (attribute.get_locus (),
     358              :                    "must be of the form: %<#[no_mangle]%>");
     359              :     }
     360            2 : }
     361              : void
     362            2 : rustc_std_internal_symbol (const AST::Attribute &attribute)
     363              : {
     364            2 :   if (attribute.has_attr_input ())
     365              :     {
     366            1 :       rust_error_at (attribute.get_locus (),
     367              :                      "malformed %<rustc_std_internal_symbol%> attribute input");
     368            1 :       rust_inform (attribute.get_locus (),
     369              :                    "must be of the form: %<#[rustc_std_internal_symbol]%>");
     370              :     }
     371            2 : }
     372              : 
     373              : void
     374            3 : rustc_allocator (const AST::Attribute &attribute)
     375              : {
     376            3 :   if (attribute.has_attr_input ())
     377              :     {
     378            1 :       rust_error_at (attribute.get_locus (),
     379              :                      "malformed %<rustc_allocator%> attribute input");
     380            1 :       rust_inform (attribute.get_locus (),
     381              :                    "must be of the form: %<#[rustc_allocator]%>");
     382              :     }
     383            3 : }
     384              : 
     385              : void
     386            2 : rustc_allocator_nounwind (const AST::Attribute &attribute)
     387              : {
     388            2 :   if (attribute.has_attr_input ())
     389              :     {
     390            1 :       rust_error_at (attribute.get_locus (),
     391              :                      "malformed %<rustc_allocator_nounwind%> attribute input");
     392            1 :       rust_inform (attribute.get_locus (),
     393              :                    "must be of the form: %<#[rustc_allocator_nounwind]%>");
     394              :     }
     395            2 : }
     396              : 
     397              : } // namespace handlers
     398              : 
     399              : const std::unordered_map<std::string, std::function<void (AST::Attribute &)>>
     400              :   attribute_checking_handlers = {
     401              :     {Attrs::DOC, handlers::doc},
     402              :     {Attrs::DEPRECATED, handlers::deprecated},
     403              :     {Attrs::LINK_SECTION, handlers::link_section},
     404              :     {Attrs::EXPORT_NAME, handlers::export_name},
     405              :     {Attrs::NO_MANGLE, handlers::no_mangle},
     406              :     {Attrs::ALLOW, handlers::lint},
     407              :     {Attrs::DENY, handlers::lint},
     408              :     {Attrs::WARN, handlers::lint},
     409              :     {Attrs::FORBID, handlers::lint},
     410              :     {Attrs::LINK_NAME, handlers::link_name},
     411              :     {Attrs::PROC_MACRO_DERIVE, handlers::proc_macro_derive},
     412              :     {Attrs::PROC_MACRO, handlers::proc_macro},
     413              :     {Attrs::PROC_MACRO_ATTRIBUTE, handlers::proc_macro},
     414              :     {Attrs::TARGET_FEATURE, handlers::target_feature},
     415              :     {Attrs::RUSTC_STD_INTERNAL_SYMBOL, handlers::rustc_std_internal_symbol},
     416              :     {Attrs::RUSTC_ALLOCATOR, handlers::rustc_allocator},
     417              :     {Attrs::RUSTC_ALLOCATOR_NOUNWIND, handlers::rustc_allocator_nounwind},
     418              : };
     419              : 
     420              : tl::optional<std::function<void (AST::Attribute &)>>
     421        28987 : lookup_handler (std::string attr_name)
     422              : {
     423        28987 :   auto res = attribute_checking_handlers.find (attr_name);
     424        28987 :   if (res != attribute_checking_handlers.cend ())
     425         9135 :     return res->second;
     426        19852 :   return tl::nullopt;
     427              : }
     428              : 
     429              : static void
     430            2 : check_no_mangle_function (const AST::Attribute &attribute,
     431              :                           const AST::Function &fun)
     432              : {
     433            2 :   if (!is_ascii_only (fun.get_function_name ().as_string ()))
     434            0 :     rust_error_at (fun.get_function_name ().get_locus (),
     435              :                    "the %<#[no_mangle]%> attribute requires ASCII identifier");
     436            2 : }
     437              : 
     438              : /**
     439              :  * Emit an error when an attribute is attached
     440              :  * to an incompatable item type. e.g.:
     441              :  *
     442              :  * #[cold]
     443              :  * struct A(u8, u8);
     444              :  *
     445              :  * Note that "#[derive]" is handled
     446              :  * explicitly in rust-derive.cc
     447              :  */
     448              : void
     449        15159 : check_valid_attribute_for_item (const AST::Attribute &attr,
     450              :                                 const AST::Item &item)
     451              : {
     452        30318 :   if (item.get_item_kind () != AST::Item::Kind::Function
     453        35357 :       && (attr.get_path () == Values::Attributes::TARGET_FEATURE
     454        25235 :           || attr.get_path () == Values::Attributes::COLD
     455        20197 :           || attr.get_path () == Values::Attributes::INLINE))
     456              :     {
     457            1 :       rust_error_at (attr.get_locus (),
     458              :                      "the %<#[%s]%> attribute may only be applied to functions",
     459            2 :                      attr.get_path ().as_string ().c_str ());
     460              :     }
     461        30316 :   else if (attr.get_path () == Values::Attributes::REPR
     462           50 :            && item.get_item_kind () != AST::Item::Kind::Enum
     463           47 :            && item.get_item_kind () != AST::Item::Kind::Union
     464        15193 :            && item.get_item_kind () != AST::Item::Kind::Struct)
     465              :     {
     466            1 :       rust_error_at (attr.get_locus (),
     467              :                      "the %<#[%s]%> attribute may only be applied "
     468              :                      "to structs, enums and unions",
     469            2 :                      attr.get_path ().as_string ().c_str ());
     470              :     }
     471        15159 : }
     472              : 
     473         4771 : BuiltinAttributeChecker::BuiltinAttributeChecker () {}
     474              : 
     475              : void
     476         4771 : BuiltinAttributeChecker::go (AST::Crate &crate)
     477              : {
     478         4771 :   visit (crate);
     479         4771 : }
     480              : 
     481              : void
     482         4771 : BuiltinAttributeChecker::visit (AST::Crate &crate)
     483              : {
     484        16838 :   for (auto &attr : crate.get_inner_attrs ())
     485              :     {
     486        12067 :       check_inner_attribute (attr);
     487              :     }
     488              : 
     489         4771 :   AST::DefaultASTVisitor::visit (crate);
     490         4771 : }
     491              : 
     492              : void
     493        28987 : BuiltinAttributeChecker::visit (AST::Attribute &attribute)
     494              : {
     495        38122 :   lookup_handler (attribute.get_path ().as_string ()).map ([&] (auto handler) {
     496         9135 :     handler (attribute);
     497              :   });
     498        28987 :   AST::DefaultASTVisitor::visit (attribute);
     499        28987 : }
     500              : 
     501              : void
     502         1325 : BuiltinAttributeChecker::visit (AST::Module &module)
     503              : {
     504         1325 :   default_outer_attribute_check (module);
     505         1325 : }
     506              : 
     507              : void
     508           28 : BuiltinAttributeChecker::visit (AST::ExternCrate &extern_crate)
     509              : {
     510           28 :   default_outer_attribute_check (extern_crate);
     511           28 : }
     512              : 
     513              : void
     514          692 : BuiltinAttributeChecker::visit (AST::UseDeclaration &declaration)
     515              : {
     516          692 :   default_outer_attribute_check (declaration);
     517          692 : }
     518              : 
     519              : void
     520        19030 : BuiltinAttributeChecker::visit (AST::Function &function)
     521              : {
     522        19030 :   BuiltinAttrDefinition result;
     523        29150 :   for (auto &attribute : function.get_outer_attrs ())
     524              :     {
     525        10120 :       check_valid_attribute_for_item (attribute, function);
     526              : 
     527        10120 :       auto result = lookup_builtin (attribute);
     528        10120 :       if (!result)
     529            0 :         return;
     530              : 
     531        10120 :       if (result->name == Attrs::TARGET_FEATURE)
     532              :         {
     533            3 :           if (!function.get_qualifiers ().is_unsafe ())
     534              :             {
     535            1 :               rust_error_at (
     536              :                 attribute.get_locus (),
     537              :                 "the %<#[target_feature]%> attribute can only be applied "
     538              :                 "to %<unsafe%> functions");
     539              :             }
     540              :         }
     541        10117 :       else if (result->name == Attrs::NO_MANGLE)
     542              :         {
     543            2 :           check_no_mangle_function (attribute, function);
     544              :         }
     545        10120 :     }
     546              : 
     547        19030 :   AST::DefaultASTVisitor::visit (function);
     548        19030 : }
     549              : 
     550              : void
     551         1323 : BuiltinAttributeChecker::visit (AST::TypeAlias &alias)
     552              : {
     553         1323 :   default_outer_attribute_check (alias);
     554         1323 : }
     555              : 
     556              : void
     557         1668 : BuiltinAttributeChecker::visit (AST::StructStruct &struct_item)
     558              : {
     559         1668 :   default_outer_attribute_check (struct_item);
     560         1668 : }
     561              : 
     562              : void
     563          983 : BuiltinAttributeChecker::visit (AST::TupleStruct &tuple_struct)
     564              : {
     565          983 :   default_outer_attribute_check (tuple_struct);
     566          983 : }
     567              : 
     568              : void
     569          557 : BuiltinAttributeChecker::visit (AST::Enum &enumeration)
     570              : {
     571          557 :   default_outer_attribute_check (enumeration);
     572          557 : }
     573              : 
     574              : void
     575          111 : BuiltinAttributeChecker::visit (AST::Union &u)
     576              : {
     577          111 :   default_outer_attribute_check (u);
     578          111 : }
     579              : 
     580              : void
     581          594 : BuiltinAttributeChecker::visit (AST::ConstantItem &item)
     582              : {
     583          594 :   default_outer_attribute_check (item);
     584          594 : }
     585              : 
     586              : void
     587           64 : BuiltinAttributeChecker::visit (AST::StaticItem &item)
     588              : {
     589           72 :   for (auto &attr : item.get_outer_attrs ())
     590            8 :     check_valid_attribute_for_item (attr, item);
     591              : 
     592           64 :   AST::DefaultASTVisitor::visit (item);
     593           64 : }
     594              : 
     595              : void
     596         3980 : BuiltinAttributeChecker::visit (AST::Trait &trait)
     597              : {
     598         3980 :   default_outer_attribute_check (trait);
     599         3980 : }
     600              : 
     601              : void
     602          999 : BuiltinAttributeChecker::visit (AST::InherentImpl &impl)
     603              : {
     604          999 :   default_outer_attribute_check (impl);
     605          999 : }
     606              : 
     607              : void
     608         4812 : BuiltinAttributeChecker::visit (AST::TraitImpl &impl)
     609              : {
     610         4812 :   default_outer_attribute_check (impl);
     611         4812 : }
     612              : 
     613              : void
     614         1657 : BuiltinAttributeChecker::visit (AST::ExternBlock &block)
     615              : {
     616         1657 :   default_outer_attribute_check (block);
     617         1657 : }
     618              : 
     619              : } // namespace Analysis
     620              : } // 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.