From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by sourceware.org (Postfix) with ESMTPS id 9B1A8384A804 for ; Wed, 26 Oct 2022 08:15:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9B1A8384A804 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wr1-x436.google.com with SMTP id v1so25019886wrt.11 for ; Wed, 26 Oct 2022 01:15:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=uDid4f2C2KOVdLcv3CBItO71bdKJAEKYJX5z63BDTIE=; b=EbcBpW3FRXMvNeZdY7+Nb+WKvGASDa5k+4iKzL7r1NV0S38slnSlqBiCS3g7x4MBSJ dehUT1nRZ+tNUuzgGGs3cd0PrDW5yIHv5yl/9pOlS918oq+7MswSinc/ACK3uHA0b/pn h1BalhTbDlYt2kW5IkkAVSxQ0d7Pg0WsHYB3Zdp3xi6oiDLQBfI/0jo1JhSSwYzIt/34 k6G/yFg7BuqZMQ9ZHHt1qOFLB63Il98Eero2KgoasJEp0ugaccxyEBzcHakkU8eEV/Qz cJp7sv9B3lR8gjxiCvVilRMzAA39Xxc9Zt9AF8ckPtbHgWWiGC5L0e8mlC7wtKMjiVUM 7XzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=uDid4f2C2KOVdLcv3CBItO71bdKJAEKYJX5z63BDTIE=; b=yIsLRDVMCqMwsGdm0Yobbrcey35vfVc2BXolAd16bMvn6XtwN80NNknLBKX2DoOeXi 4BplEHptXbra4qFzQG+O5kIISPRq72J68P2q2YsMvzROmFXK24pNy5a6KfJittPVxV+h tHANjc1t1K1Gd/4oPRPeYBtxgw40Spbp7jPgbG6H23RjNXhL2uv9P1oWV6IEx16CFzP3 IVPN7LPz+32lQiofi/r/WyseJoa3TvG3nNjLinV0eED7fULWqLTEaNpNFR5X8sX0iVvL IPKZQ2/ndb00DMNlPfJIw3HUE60lgQos2UlWqt/lbGHUfGHhE9RmlQgAJli+gxOBH7MW 1qvQ== X-Gm-Message-State: ACrzQf2lSBxw4/Iyg3NjiSu0xkslDYceYF4E93aCrPJCk1uNYLTqvy+E Y6W0EjPPhL0v8od54+Zyl8Np X-Google-Smtp-Source: AMsMyM5xlnXxYUWQurMk5fR6V4nHzWqRRJgtPMQjYSW8Aa7OpoB/oi2w1WflOn6dCSGoBDoRqmWxCw== X-Received: by 2002:a5d:4688:0:b0:236:8e4d:5cb3 with SMTP id u8-20020a5d4688000000b002368e4d5cb3mr768539wrq.710.1666772152932; Wed, 26 Oct 2022 01:15:52 -0700 (PDT) Received: from platypus.lan ([2001:861:5e4c:3bb0:6424:328a:1734:3249]) by smtp.googlemail.com with ESMTPSA id q16-20020a05600c46d000b003c6f426467fsm1134310wmo.40.2022.10.26.01.15.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 01:15:52 -0700 (PDT) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org Subject: [PATCH Rust front-end v3 25/46] gccrs: Add attributes checker Date: Wed, 26 Oct 2022 10:17:50 +0200 Message-Id: <20221026081811.602573-26-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20221026081811.602573-1-arthur.cohen@embecosm.com> References: <20221026081811.602573-1-arthur.cohen@embecosm.com> Reply-To: arthur.cohen@embecosm.com MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-13.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Arthur Cohen 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 | 839 +++++++++++++++++++++++++++++++ gcc/rust/util/rust-attributes.h | 270 ++++++++++ 2 files changed, 1109 insertions(+) create mode 100644 gcc/rust/util/rust-attributes.cc create mode 100644 gcc/rust/util/rust-attributes.h 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 +// . + +#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 ( + 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 (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 ¶m) +{} + +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 ¯o_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 +// . + +#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 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 ¶m); + 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 ¯o_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 -- 2.37.2