summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2022-08-23 16:27:23 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2022-12-13 14:00:05 +0100
commit2e7fc8780e0d5009bc8edd116378a25dea8cb1fa (patch)
tree42385a3fd9a961a9295df6daadd9e4f21f474430
parent9a4fee5f57c1ba6844407f81a6a40c30bc2735d4 (diff)
gccrs: Add attributes checker
The attribute checker is responsible for checking the validity of various attributes including built-in ones. It is currently unfinished and will receive some modifications, as well as become the host of some existing code in the compiler which needs to be refactored. One of its responsibilities is to make sure that arguments given to built-in attributes are correct, or contain the correct type of information. This visitor also checks that an attribute is allowed to be used in the current particular context. gcc/rust/ * util/rust-attributes.cc: New. * util/rust-attributes.h: New.
-rw-r--r--gcc/rust/util/rust-attributes.cc839
-rw-r--r--gcc/rust/util/rust-attributes.h270
2 files changed, 1109 insertions, 0 deletions
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
new file mode 100644
index 00000000000..b73e9534414
--- /dev/null
+++ b/gcc/rust/util/rust-attributes.cc
@@ -0,0 +1,839 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-system.h"
+#include "rust-attributes.h"
+#include "rust-ast.h"
+#include "rust-ast-full.h"
+#include "rust-diagnostics.h"
+
+namespace Rust {
+namespace Analysis {
+
+// https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248
+static const BuiltinAttrDefinition __definitions[] = {
+ {"inline", CODE_GENERATION},
+ {"cold", CODE_GENERATION},
+ {"cfg", EXPANSION},
+ {"cfg_attr", EXPANSION},
+ {"deprecated", STATIC_ANALYSIS},
+ {"allow", STATIC_ANALYSIS},
+ {"doc", HIR_LOWERING},
+ {"must_use", STATIC_ANALYSIS},
+ {"lang", HIR_LOWERING},
+ {"link_section", CODE_GENERATION},
+ {"no_mangle", CODE_GENERATION},
+ {"repr", CODE_GENERATION},
+ {"path", EXPANSION},
+};
+
+BuiltinAttributeMappings *
+BuiltinAttributeMappings::get ()
+{
+ static BuiltinAttributeMappings *instance = nullptr;
+ if (instance == nullptr)
+ instance = new BuiltinAttributeMappings ();
+
+ return instance;
+}
+
+const BuiltinAttrDefinition &
+BuiltinAttributeMappings::lookup_builtin (const std::string &attr_name) const
+{
+ auto it = mappings.find (attr_name);
+ if (it == mappings.end ())
+ return BuiltinAttrDefinition::error_node ();
+
+ return it->second;
+}
+
+BuiltinAttributeMappings::BuiltinAttributeMappings ()
+{
+ size_t ndefinitions = sizeof (__definitions) / sizeof (BuiltinAttrDefinition);
+ for (size_t i = 0; i < ndefinitions; i++)
+ {
+ const BuiltinAttrDefinition &def = __definitions[i];
+ mappings.insert ({def.name, def});
+ }
+}
+
+AttributeChecker::AttributeChecker () {}
+
+void
+AttributeChecker::go (AST::Crate &crate)
+{
+ check_attributes (crate.get_inner_attrs ());
+
+ for (auto &item : crate.items)
+ item->accept_vis (*this);
+}
+
+static bool
+is_builtin (const AST::Attribute &attribute, BuiltinAttrDefinition &builtin)
+{
+ auto &segments = attribute.get_path ().get_segments ();
+
+ // Builtin attributes always have a single segment. This avoids us creating
+ // strings all over the place and performing a linear search in the builtins
+ // map
+ if (segments.size () != 1)
+ return false;
+
+ builtin = BuiltinAttributeMappings::get ()->lookup_builtin (
+ segments.at (0).get_segment_name ());
+
+ return !builtin.is_error ();
+}
+
+/**
+ * Check that the string given to #[doc(alias = ...)] or #[doc(alias(...))] is
+ * valid.
+ *
+ * This means no whitespace characters other than spaces and no quoting
+ * characters.
+ */
+static void
+check_doc_alias (const std::string &alias_input, const Location &locus)
+{
+ // FIXME: The locus here is for the whole attribute. Can we get the locus
+ // of the alias input instead?
+ for (auto c : alias_input)
+ if ((ISSPACE (c) && c != ' ') || c == '\'' || c == '\"')
+ {
+ auto to_print = std::string (1, c);
+ switch (c)
+ {
+ case '\n':
+ to_print = "\\n";
+ break;
+ case '\t':
+ to_print = "\\t";
+ break;
+ default:
+ break;
+ }
+ rust_error_at (locus,
+ "invalid character used in %<#[doc(alias)]%> input: %qs",
+ to_print.c_str ());
+ }
+
+ if (alias_input.empty ())
+ return;
+
+ if (alias_input.front () == ' ' || alias_input.back () == ' ')
+ rust_error_at (locus,
+ "%<#[doc(alias)]%> input cannot start or end with a space");
+}
+
+static void
+check_doc_attribute (const AST::Attribute &attribute)
+{
+ if (!attribute.has_attr_input ())
+ {
+ rust_error_at (
+ attribute.get_locus (),
+ // FIXME: Improve error message here. Rustc has a very good one
+ "%<#[doc]%> cannot be an empty attribute");
+ return;
+ }
+
+ switch (attribute.get_attr_input ().get_attr_input_type ())
+ {
+ case AST::AttrInput::LITERAL:
+ case AST::AttrInput::META_ITEM:
+ break;
+ // FIXME: Handle them as well
+
+ case AST::AttrInput::TOKEN_TREE: {
+ // FIXME: This doesn't check for #[doc(alias(...))]
+ const auto &option = static_cast<const AST::DelimTokenTree &> (
+ attribute.get_attr_input ());
+ auto *meta_item = option.parse_to_meta_item ();
+
+ for (auto &item : meta_item->get_items ())
+ {
+ if (item->is_key_value_pair ())
+ {
+ auto name_value
+ = static_cast<AST::MetaNameValueStr *> (item.get ())
+ ->get_name_value_pair ();
+
+ // FIXME: Check for other stuff than #[doc(alias = ...)]
+ if (name_value.first == "alias")
+ check_doc_alias (name_value.second, attribute.get_locus ());
+ }
+ }
+ break;
+ }
+ }
+}
+
+void
+AttributeChecker::check_attribute (const AST::Attribute &attribute)
+{
+ BuiltinAttrDefinition result;
+
+ // This checker does not check non-builtin attributes
+ if (!is_builtin (attribute, result))
+ return;
+
+ // TODO: Add checks here for each builtin attribute
+ // TODO: Have an enum of builtins as well, switching on strings is annoying
+ // and costly
+ if (result.name == "doc")
+ check_doc_attribute (attribute);
+}
+
+void
+AttributeChecker::check_attributes (const AST::AttrVec &attributes)
+{
+ for (auto &attr : attributes)
+ check_attribute (attr);
+}
+
+void
+AttributeChecker::visit (AST::Token &tok)
+{}
+
+void
+AttributeChecker::visit (AST::DelimTokenTree &delim_tok_tree)
+{}
+
+void
+AttributeChecker::visit (AST::AttrInputMetaItemContainer &input)
+{}
+
+void
+AttributeChecker::visit (AST::IdentifierExpr &ident_expr)
+{}
+
+void
+AttributeChecker::visit (AST::Lifetime &lifetime)
+{}
+
+void
+AttributeChecker::visit (AST::LifetimeParam &lifetime_param)
+{}
+
+void
+AttributeChecker::visit (AST::ConstGenericParam &const_param)
+{}
+
+// rust-path.h
+void
+AttributeChecker::visit (AST::PathInExpression &path)
+{}
+
+void
+AttributeChecker::visit (AST::TypePathSegment &segment)
+{}
+
+void
+AttributeChecker::visit (AST::TypePathSegmentGeneric &segment)
+{}
+
+void
+AttributeChecker::visit (AST::TypePathSegmentFunction &segment)
+{}
+
+void
+AttributeChecker::visit (AST::TypePath &path)
+{}
+
+void
+AttributeChecker::visit (AST::QualifiedPathInExpression &path)
+{}
+
+void
+AttributeChecker::visit (AST::QualifiedPathInType &path)
+{}
+
+// rust-expr.h
+void
+AttributeChecker::visit (AST::LiteralExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::AttrInputLiteral &attr_input)
+{}
+
+void
+AttributeChecker::visit (AST::MetaItemLitExpr &meta_item)
+{}
+
+void
+AttributeChecker::visit (AST::MetaItemPathLit &meta_item)
+{}
+
+void
+AttributeChecker::visit (AST::BorrowExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::DereferenceExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ErrorPropagationExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::NegationExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ArithmeticOrLogicalExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ComparisonExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::LazyBooleanExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::TypeCastExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::AssignmentExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::CompoundAssignmentExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::GroupedExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ArrayElemsValues &elems)
+{}
+
+void
+AttributeChecker::visit (AST::ArrayElemsCopied &elems)
+{}
+
+void
+AttributeChecker::visit (AST::ArrayExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ArrayIndexExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::TupleExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::TupleIndexExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::StructExprStruct &expr)
+{}
+
+void
+AttributeChecker::visit (AST::StructExprFieldIdentifier &field)
+{}
+
+void
+AttributeChecker::visit (AST::StructExprFieldIdentifierValue &field)
+{}
+
+void
+AttributeChecker::visit (AST::StructExprFieldIndexValue &field)
+{}
+
+void
+AttributeChecker::visit (AST::StructExprStructFields &expr)
+{}
+
+void
+AttributeChecker::visit (AST::StructExprStructBase &expr)
+{}
+
+void
+AttributeChecker::visit (AST::CallExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::MethodCallExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::FieldAccessExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ClosureExprInner &expr)
+{}
+
+void
+AttributeChecker::visit (AST::BlockExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ClosureExprInnerTyped &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ContinueExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::BreakExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::RangeFromToExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::RangeFromExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::RangeToExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::RangeFullExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::RangeFromToInclExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::RangeToInclExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ReturnExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::UnsafeBlockExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::LoopExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::WhileLoopExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::WhileLetLoopExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::ForLoopExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::IfExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::IfExprConseqElse &expr)
+{}
+
+void
+AttributeChecker::visit (AST::IfExprConseqIf &expr)
+{}
+
+void
+AttributeChecker::visit (AST::IfExprConseqIfLet &expr)
+{}
+
+void
+AttributeChecker::visit (AST::IfLetExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::IfLetExprConseqElse &expr)
+{}
+
+void
+AttributeChecker::visit (AST::IfLetExprConseqIf &expr)
+{}
+
+void
+AttributeChecker::visit (AST::IfLetExprConseqIfLet &expr)
+{}
+
+void
+AttributeChecker::visit (AST::MatchExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::AwaitExpr &expr)
+{}
+
+void
+AttributeChecker::visit (AST::AsyncBlockExpr &expr)
+{}
+
+// rust-item.h
+void
+AttributeChecker::visit (AST::TypeParam &param)
+{}
+
+void
+AttributeChecker::visit (AST::LifetimeWhereClauseItem &item)
+{}
+
+void
+AttributeChecker::visit (AST::TypeBoundWhereClauseItem &item)
+{}
+
+void
+AttributeChecker::visit (AST::Method &method)
+{}
+
+void
+AttributeChecker::visit (AST::Module &module)
+{}
+
+void
+AttributeChecker::visit (AST::ExternCrate &crate)
+{}
+
+void
+AttributeChecker::visit (AST::UseTreeGlob &use_tree)
+{}
+
+void
+AttributeChecker::visit (AST::UseTreeList &use_tree)
+{}
+
+void
+AttributeChecker::visit (AST::UseTreeRebind &use_tree)
+{}
+
+void
+AttributeChecker::visit (AST::UseDeclaration &use_decl)
+{}
+
+void
+AttributeChecker::visit (AST::Function &function)
+{}
+
+void
+AttributeChecker::visit (AST::TypeAlias &type_alias)
+{}
+
+void
+AttributeChecker::visit (AST::StructStruct &struct_item)
+{
+ check_attributes (struct_item.get_outer_attrs ());
+}
+
+void
+AttributeChecker::visit (AST::TupleStruct &tuple_struct)
+{}
+
+void
+AttributeChecker::visit (AST::EnumItem &item)
+{}
+
+void
+AttributeChecker::visit (AST::EnumItemTuple &item)
+{}
+
+void
+AttributeChecker::visit (AST::EnumItemStruct &item)
+{}
+
+void
+AttributeChecker::visit (AST::EnumItemDiscriminant &item)
+{}
+
+void
+AttributeChecker::visit (AST::Enum &enum_item)
+{}
+
+void
+AttributeChecker::visit (AST::Union &union_item)
+{}
+
+void
+AttributeChecker::visit (AST::ConstantItem &const_item)
+{}
+
+void
+AttributeChecker::visit (AST::StaticItem &static_item)
+{}
+
+void
+AttributeChecker::visit (AST::TraitItemFunc &item)
+{}
+
+void
+AttributeChecker::visit (AST::TraitItemMethod &item)
+{}
+
+void
+AttributeChecker::visit (AST::TraitItemConst &item)
+{}
+
+void
+AttributeChecker::visit (AST::TraitItemType &item)
+{}
+
+void
+AttributeChecker::visit (AST::Trait &trait)
+{}
+
+void
+AttributeChecker::visit (AST::InherentImpl &impl)
+{}
+
+void
+AttributeChecker::visit (AST::TraitImpl &impl)
+{}
+
+void
+AttributeChecker::visit (AST::ExternalStaticItem &item)
+{}
+
+void
+AttributeChecker::visit (AST::ExternalFunctionItem &item)
+{}
+
+void
+AttributeChecker::visit (AST::ExternBlock &block)
+{}
+
+// rust-macro.h
+void
+AttributeChecker::visit (AST::MacroMatchFragment &match)
+{}
+
+void
+AttributeChecker::visit (AST::MacroMatchRepetition &match)
+{}
+
+void
+AttributeChecker::visit (AST::MacroMatcher &matcher)
+{}
+
+void
+AttributeChecker::visit (AST::MacroRulesDefinition &rules_def)
+{}
+
+void
+AttributeChecker::visit (AST::MacroInvocation &macro_invoc)
+{}
+
+void
+AttributeChecker::visit (AST::MetaItemPath &meta_item)
+{}
+
+void
+AttributeChecker::visit (AST::MetaItemSeq &meta_item)
+{}
+
+void
+AttributeChecker::visit (AST::MetaWord &meta_item)
+{}
+
+void
+AttributeChecker::visit (AST::MetaNameValueStr &meta_item)
+{}
+
+void
+AttributeChecker::visit (AST::MetaListPaths &meta_item)
+{}
+
+void
+AttributeChecker::visit (AST::MetaListNameValueStr &meta_item)
+{}
+
+// rust-pattern.h
+void
+AttributeChecker::visit (AST::LiteralPattern &pattern)
+{}
+
+void
+AttributeChecker::visit (AST::IdentifierPattern &pattern)
+{}
+
+void
+AttributeChecker::visit (AST::WildcardPattern &pattern)
+{}
+
+// void AttributeChecker::visit(RangePatternBound& bound){}
+
+void
+AttributeChecker::visit (AST::RangePatternBoundLiteral &bound)
+{}
+
+void
+AttributeChecker::visit (AST::RangePatternBoundPath &bound)
+{}
+
+void
+AttributeChecker::visit (AST::RangePatternBoundQualPath &bound)
+{}
+
+void
+AttributeChecker::visit (AST::RangePattern &pattern)
+{}
+
+void
+AttributeChecker::visit (AST::ReferencePattern &pattern)
+{}
+
+// void AttributeChecker::visit(StructPatternField& field){}
+
+void
+AttributeChecker::visit (AST::StructPatternFieldTuplePat &field)
+{}
+
+void
+AttributeChecker::visit (AST::StructPatternFieldIdentPat &field)
+{}
+
+void
+AttributeChecker::visit (AST::StructPatternFieldIdent &field)
+{}
+
+void
+AttributeChecker::visit (AST::StructPattern &pattern)
+{}
+
+// void AttributeChecker::visit(TupleStructItems& tuple_items){}
+
+void
+AttributeChecker::visit (AST::TupleStructItemsNoRange &tuple_items)
+{}
+
+void
+AttributeChecker::visit (AST::TupleStructItemsRange &tuple_items)
+{}
+
+void
+AttributeChecker::visit (AST::TupleStructPattern &pattern)
+{}
+
+// void AttributeChecker::visit(TuplePatternItems& tuple_items){}
+
+void
+AttributeChecker::visit (AST::TuplePatternItemsMultiple &tuple_items)
+{}
+
+void
+AttributeChecker::visit (AST::TuplePatternItemsRanged &tuple_items)
+{}
+
+void
+AttributeChecker::visit (AST::TuplePattern &pattern)
+{}
+
+void
+AttributeChecker::visit (AST::GroupedPattern &pattern)
+{}
+
+void
+AttributeChecker::visit (AST::SlicePattern &pattern)
+{}
+
+// rust-stmt.h
+void
+AttributeChecker::visit (AST::EmptyStmt &stmt)
+{}
+
+void
+AttributeChecker::visit (AST::LetStmt &stmt)
+{}
+
+void
+AttributeChecker::visit (AST::ExprStmtWithoutBlock &stmt)
+{}
+
+void
+AttributeChecker::visit (AST::ExprStmtWithBlock &stmt)
+{}
+
+// rust-type.h
+void
+AttributeChecker::visit (AST::TraitBound &bound)
+{}
+
+void
+AttributeChecker::visit (AST::ImplTraitType &type)
+{}
+
+void
+AttributeChecker::visit (AST::TraitObjectType &type)
+{}
+
+void
+AttributeChecker::visit (AST::ParenthesisedType &type)
+{}
+
+void
+AttributeChecker::visit (AST::ImplTraitTypeOneBound &type)
+{}
+
+void
+AttributeChecker::visit (AST::TraitObjectTypeOneBound &type)
+{}
+
+void
+AttributeChecker::visit (AST::TupleType &type)
+{}
+
+void
+AttributeChecker::visit (AST::NeverType &type)
+{}
+
+void
+AttributeChecker::visit (AST::RawPointerType &type)
+{}
+
+void
+AttributeChecker::visit (AST::ReferenceType &type)
+{}
+
+void
+AttributeChecker::visit (AST::ArrayType &type)
+{}
+
+void
+AttributeChecker::visit (AST::SliceType &type)
+{}
+
+void
+AttributeChecker::visit (AST::InferredType &type)
+{}
+
+void
+AttributeChecker::visit (AST::BareFunctionType &type)
+{}
+
+} // namespace Analysis
+} // namespace Rust
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
new file mode 100644
index 00000000000..3ac93ff5908
--- /dev/null
+++ b/gcc/rust/util/rust-attributes.h
@@ -0,0 +1,270 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-ast.h"
+#include "rust-system.h"
+#include "rust-ast-visitor.h"
+
+namespace Rust {
+namespace Analysis {
+
+enum CompilerPass
+{
+ UNKNOWN,
+
+ EXPANSION,
+ NAME_RESOLUTION,
+ HIR_LOWERING,
+ TYPE_CHECK,
+ STATIC_ANALYSIS,
+ CODE_GENERATION
+};
+
+struct BuiltinAttrDefinition
+{
+ std::string name;
+ CompilerPass handler;
+
+ static BuiltinAttrDefinition get_error ()
+ {
+ return BuiltinAttrDefinition{"", UNKNOWN};
+ }
+
+ static BuiltinAttrDefinition &error_node ()
+ {
+ static BuiltinAttrDefinition error_node = get_error ();
+ return error_node;
+ }
+
+ bool is_error () const { return name.empty (); }
+};
+
+class BuiltinAttributeMappings
+{
+public:
+ static BuiltinAttributeMappings *get ();
+
+ const BuiltinAttrDefinition &
+ lookup_builtin (const std::string &attr_name) const;
+
+private:
+ BuiltinAttributeMappings ();
+
+ std::map<std::string, const BuiltinAttrDefinition> mappings;
+};
+
+/**
+ * Checks the validity of various attributes. The goal of this visitor is to
+ * make sure that attributes are applied in allowed contexts, for example to
+ * make sure that #[inline] is only applied to functions and closures, as well
+ * as checking the "arguments" or input given to these attributes, making sure
+ * it is appropriate and valid.
+ */
+class AttributeChecker : public AST::ASTVisitor
+{
+public:
+ AttributeChecker ();
+
+ /**
+ * Check all the attributes of all the items of a crate
+ */
+ void go (AST::Crate &crate);
+
+private:
+ /* Check the validity of a given attribute */
+ void check_attribute (const AST::Attribute &attribute);
+
+ /* Check the validity of all given attributes */
+ void check_attributes (const AST::AttrVec &attributes);
+
+ // rust-ast.h
+ void visit (AST::Token &tok);
+ void visit (AST::DelimTokenTree &delim_tok_tree);
+ void visit (AST::AttrInputMetaItemContainer &input);
+ void visit (AST::IdentifierExpr &ident_expr);
+ void visit (AST::Lifetime &lifetime);
+ void visit (AST::LifetimeParam &lifetime_param);
+ void visit (AST::ConstGenericParam &const_param);
+
+ // rust-path.h
+ void visit (AST::PathInExpression &path);
+ void visit (AST::TypePathSegment &segment);
+ void visit (AST::TypePathSegmentGeneric &segment);
+ void visit (AST::TypePathSegmentFunction &segment);
+ void visit (AST::TypePath &path);
+ void visit (AST::QualifiedPathInExpression &path);
+ void visit (AST::QualifiedPathInType &path);
+
+ // rust-expr.h
+ void visit (AST::LiteralExpr &expr);
+ void visit (AST::AttrInputLiteral &attr_input);
+ void visit (AST::MetaItemLitExpr &meta_item);
+ void visit (AST::MetaItemPathLit &meta_item);
+ void visit (AST::BorrowExpr &expr);
+ void visit (AST::DereferenceExpr &expr);
+ void visit (AST::ErrorPropagationExpr &expr);
+ void visit (AST::NegationExpr &expr);
+ void visit (AST::ArithmeticOrLogicalExpr &expr);
+ void visit (AST::ComparisonExpr &expr);
+ void visit (AST::LazyBooleanExpr &expr);
+ void visit (AST::TypeCastExpr &expr);
+ void visit (AST::AssignmentExpr &expr);
+ void visit (AST::CompoundAssignmentExpr &expr);
+ void visit (AST::GroupedExpr &expr);
+ void visit (AST::ArrayElemsValues &elems);
+ void visit (AST::ArrayElemsCopied &elems);
+ void visit (AST::ArrayExpr &expr);
+ void visit (AST::ArrayIndexExpr &expr);
+ void visit (AST::TupleExpr &expr);
+ void visit (AST::TupleIndexExpr &expr);
+ void visit (AST::StructExprStruct &expr);
+ void visit (AST::StructExprFieldIdentifier &field);
+ void visit (AST::StructExprFieldIdentifierValue &field);
+ void visit (AST::StructExprFieldIndexValue &field);
+ void visit (AST::StructExprStructFields &expr);
+ void visit (AST::StructExprStructBase &expr);
+ void visit (AST::CallExpr &expr);
+ void visit (AST::MethodCallExpr &expr);
+ void visit (AST::FieldAccessExpr &expr);
+ void visit (AST::ClosureExprInner &expr);
+ void visit (AST::BlockExpr &expr);
+ void visit (AST::ClosureExprInnerTyped &expr);
+ void visit (AST::ContinueExpr &expr);
+ void visit (AST::BreakExpr &expr);
+ void visit (AST::RangeFromToExpr &expr);
+ void visit (AST::RangeFromExpr &expr);
+ void visit (AST::RangeToExpr &expr);
+ void visit (AST::RangeFullExpr &expr);
+ void visit (AST::RangeFromToInclExpr &expr);
+ void visit (AST::RangeToInclExpr &expr);
+ void visit (AST::ReturnExpr &expr);
+ void visit (AST::UnsafeBlockExpr &expr);
+ void visit (AST::LoopExpr &expr);
+ void visit (AST::WhileLoopExpr &expr);
+ void visit (AST::WhileLetLoopExpr &expr);
+ void visit (AST::ForLoopExpr &expr);
+ void visit (AST::IfExpr &expr);
+ void visit (AST::IfExprConseqElse &expr);
+ void visit (AST::IfExprConseqIf &expr);
+ void visit (AST::IfExprConseqIfLet &expr);
+ void visit (AST::IfLetExpr &expr);
+ void visit (AST::IfLetExprConseqElse &expr);
+ void visit (AST::IfLetExprConseqIf &expr);
+ void visit (AST::IfLetExprConseqIfLet &expr);
+ void visit (AST::MatchExpr &expr);
+ void visit (AST::AwaitExpr &expr);
+ void visit (AST::AsyncBlockExpr &expr);
+
+ // rust-item.h
+ void visit (AST::TypeParam &param);
+ void visit (AST::LifetimeWhereClauseItem &item);
+ void visit (AST::TypeBoundWhereClauseItem &item);
+ void visit (AST::Method &method);
+ void visit (AST::Module &module);
+ void visit (AST::ExternCrate &crate);
+ void visit (AST::UseTreeGlob &use_tree);
+ void visit (AST::UseTreeList &use_tree);
+ void visit (AST::UseTreeRebind &use_tree);
+ void visit (AST::UseDeclaration &use_decl);
+ void visit (AST::Function &function);
+ void visit (AST::TypeAlias &type_alias);
+ void visit (AST::StructStruct &struct_item);
+ void visit (AST::TupleStruct &tuple_struct);
+ void visit (AST::EnumItem &item);
+ void visit (AST::EnumItemTuple &item);
+ void visit (AST::EnumItemStruct &item);
+ void visit (AST::EnumItemDiscriminant &item);
+ void visit (AST::Enum &enum_item);
+ void visit (AST::Union &union_item);
+ void visit (AST::ConstantItem &const_item);
+ void visit (AST::StaticItem &static_item);
+ void visit (AST::TraitItemFunc &item);
+ void visit (AST::TraitItemMethod &item);
+ void visit (AST::TraitItemConst &item);
+ void visit (AST::TraitItemType &item);
+ void visit (AST::Trait &trait);
+ void visit (AST::InherentImpl &impl);
+ void visit (AST::TraitImpl &impl);
+ void visit (AST::ExternalStaticItem &item);
+ void visit (AST::ExternalFunctionItem &item);
+ void visit (AST::ExternBlock &block);
+
+ // rust-macro.h
+ void visit (AST::MacroMatchFragment &match);
+ void visit (AST::MacroMatchRepetition &match);
+ void visit (AST::MacroMatcher &matcher);
+ void visit (AST::MacroRulesDefinition &rules_def);
+ void visit (AST::MacroInvocation &macro_invoc);
+ void visit (AST::MetaItemPath &meta_item);
+ void visit (AST::MetaItemSeq &meta_item);
+ void visit (AST::MetaWord &meta_item);
+ void visit (AST::MetaNameValueStr &meta_item);
+ void visit (AST::MetaListPaths &meta_item);
+ void visit (AST::MetaListNameValueStr &meta_item);
+
+ // rust-pattern.h
+ void visit (AST::LiteralPattern &pattern);
+ void visit (AST::IdentifierPattern &pattern);
+ void visit (AST::WildcardPattern &pattern);
+ // void visit(RangePatternBound& bound);
+ void visit (AST::RangePatternBoundLiteral &bound);
+ void visit (AST::RangePatternBoundPath &bound);
+ void visit (AST::RangePatternBoundQualPath &bound);
+ void visit (AST::RangePattern &pattern);
+ void visit (AST::ReferencePattern &pattern);
+ // void visit(StructPatternField& field);
+ void visit (AST::StructPatternFieldTuplePat &field);
+ void visit (AST::StructPatternFieldIdentPat &field);
+ void visit (AST::StructPatternFieldIdent &field);
+ void visit (AST::StructPattern &pattern);
+ // void visit(TupleStructItems& tuple_items);
+ void visit (AST::TupleStructItemsNoRange &tuple_items);
+ void visit (AST::TupleStructItemsRange &tuple_items);
+ void visit (AST::TupleStructPattern &pattern);
+ // void visit(TuplePatternItems& tuple_items);
+ void visit (AST::TuplePatternItemsMultiple &tuple_items);
+ void visit (AST::TuplePatternItemsRanged &tuple_items);
+ void visit (AST::TuplePattern &pattern);
+ void visit (AST::GroupedPattern &pattern);
+ void visit (AST::SlicePattern &pattern);
+
+ // rust-stmt.h
+ void visit (AST::EmptyStmt &stmt);
+ void visit (AST::LetStmt &stmt);
+ void visit (AST::ExprStmtWithoutBlock &stmt);
+ void visit (AST::ExprStmtWithBlock &stmt);
+
+ // rust-type.h
+ void visit (AST::TraitBound &bound);
+ void visit (AST::ImplTraitType &type);
+ void visit (AST::TraitObjectType &type);
+ void visit (AST::ParenthesisedType &type);
+ void visit (AST::ImplTraitTypeOneBound &type);
+ void visit (AST::TraitObjectTypeOneBound &type);
+ void visit (AST::TupleType &type);
+ void visit (AST::NeverType &type);
+ void visit (AST::RawPointerType &type);
+ void visit (AST::ReferenceType &type);
+ void visit (AST::ArrayType &type);
+ void visit (AST::SliceType &type);
+ void visit (AST::InferredType &type);
+ void visit (AST::BareFunctionType &type);
+};
+
+} // namespace Analysis
+} // namespace Rust