From patchwork Tue Dec 6 10:13:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arthur Cohen X-Patchwork-Id: 61522 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9476739DDDBD for ; Tue, 6 Dec 2022 10:21:39 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by sourceware.org (Postfix) with ESMTPS id A93C339730C1 for ; Tue, 6 Dec 2022 10:12:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A93C339730C1 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-wm1-x336.google.com with SMTP id h8-20020a1c2108000000b003d1efd60b65so439765wmh.0 for ; Tue, 06 Dec 2022 02:12:26 -0800 (PST) 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=2UmEcn6JHGXa5zW7vP0Gpu+lZ/Vi3t1iPVYRFlF31c4=; b=hrwKzrMCkNk0Zn5upEEr7h6Mr7PcfzWsYsV6o7aq9TPrSGRXp4maaJ2eFrWIDoNG2x ePxsp7WGW19tbwS+amHkin+8SXU81abu24WyANYNJf64xRzSF5RMsSU9INJz7h+kB1DH 67Ve69l6h3ku2vVJ3HZBjyzI1qPzJPyek6RfiECfpgNN+6NC6dlqqjcjdSCuBYwFVp1e OqelzFvO2dwc6xfpeowKpFXH9Ffb0oK7BMB1MTVbHemgMTtK7faXk8xErjldr5FSnMvW XUkQm3Dnp0/FHgrbDEkATjAhPwtCL4ExUk+frmWbFDVr9OrX10hZKK9R4eL82vPeSGU0 KMrg== 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=2UmEcn6JHGXa5zW7vP0Gpu+lZ/Vi3t1iPVYRFlF31c4=; b=gNorOYoDmCiknRXe1GtUARF0YmdvImngAAsYPAsJE35V48JuG8dKh7xU1wh6QI2Ium 5ROp8tDMa6CItwfX4AKwN8p+TzRPRXDNjAU+FShj3x0gezrS22q+YSMTwVqp6C7L30pp qNVsTuM5/gOs0g+hS4tr+6DwlXCKd6xNtHWxumm34dNTZV9owbSMaujTsmOcOC6W4Zp9 qzZxduYacbveaZx0m3Wyh0Nrp7+B+jwTJL/UFHMcZoFp1oki0r9FdSP/o3bDSZFPwta8 u5mBai3LUxyIM5qx71DnJLYaRmoHlWeLWPmaAAvjY0aNxJ8MeJ5Pw4O8ZGHGq9uVrEBG coPQ== X-Gm-Message-State: ANoB5plRj5aAMCAvCsveCLj13eMoJqgD8ru85XCI+Lfe1Hhl69VGyO7w ckROqh4iCaK5uEps1OqFBG3qhIpnJyH+E3pKWg== X-Google-Smtp-Source: AA0mqf6elD1vngwrBrLzpDZPAKW4UJCb7qUWWXyWRICSmJq6KQB3k5yrvZ1p6C+u7kKeWHlF3WD9xg== X-Received: by 2002:a05:600c:4e0a:b0:3d0:7b8c:2098 with SMTP id b10-20020a05600c4e0a00b003d07b8c2098mr16984852wmq.110.1670321545009; Tue, 06 Dec 2022 02:12:25 -0800 (PST) Received: from platypus.lan ([2001:861:5e4c:3bb0:6424:328a:1734:3249]) by smtp.googlemail.com with ESMTPSA id r10-20020a05600c458a00b003cfd4a50d5asm27052699wmo.34.2022.12.06.02.12.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Dec 2022 02:12:24 -0800 (PST) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, Arthur Cohen Subject: [PATCH Rust front-end v4 25/46] gccrs: Add attributes checker Date: Tue, 6 Dec 2022 11:13:57 +0100 Message-Id: <20221206101417.778807-26-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221206101417.778807-1-arthur.cohen@embecosm.com> References: <20221206101417.778807-1-arthur.cohen@embecosm.com> MIME-Version: 1.0 X-Spam-Status: No, score=-15.9 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=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: arthur.cohen@embecosm.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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