From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by sourceware.org (Postfix) with ESMTPS id 3CFCE3853556 for ; Wed, 5 Apr 2023 14:05:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3CFCE3853556 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-x42c.google.com with SMTP id m2so36336240wrh.6 for ; Wed, 05 Apr 2023 07:05:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; t=1680703552; 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=45DNQu9fBFY6qFaUoOeFel8jIU22OK+1TD92XMz9Rj4=; b=RojwQ+uHK2udovy+5Yxiu3q9KCMVeTtui4aEegMB7xbd8+fl48Ou6/91g7ZcVJfGou oScI9Wln/fovUbTAUHvtN3Kgc+6fEiKe/Cg+2hhodAgfuDvXTBFalXuBdwJVNAe5K/hk lh/4SqxF2ghLkAYkQqLniaPtEmbUxKQ/9SUndNY1w+WEq6O2A6yT21/p1ApXTDExSGe8 emLAWEkv/h39Z7i0UdvP+wn1UL/5R+yghD11iKAPHsrp/JT1BEtGPCT/casL/7NS63BK 3LCIktjOO9tbSOG+SKMSJw0kyaJZnaWBx7b71VmzWYl8+1CUVOkWibI3UN1d2BmsuwEd wWdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680703552; 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=45DNQu9fBFY6qFaUoOeFel8jIU22OK+1TD92XMz9Rj4=; b=UflycqgGGSPBJlGZX7t81AVjsfFqcXZLiJzPPed+0g7FCNnhLEzq+x8hn2XfaNnUBi OzK0V+AHpu0G3AliRQQZc6gFKLJQl2Y1c/JRfZ6B8L221MpjFGqbV6Ma77wb8lTvNenZ fVyP5/hX90HjbLFspSOGFXbEanXhX6HUnIezjk1L2swMh02JHWJ5XREs72+y2vRut8II AAD8LL72MKZgGv8o4F/XUB0cgM6bo6rzNhem6FBpCVwDlRUZuuExPDVQsQkNlyQs5c1V nZjvitGDVWmjTo3SeC6o6+J9aJEm1UbajURqjm18PlaPlXNEMIZBJavOvHZUYgVWzxwH PMJA== X-Gm-Message-State: AAQBX9d8ufRlkd4lkNO1Rh9H91gFaUXD/+0V04tJDPssfyAoLevWAOkc pns6U6TbdkVFgJ3fCLOLeGVh9I5A3/jx+I7ApQ== X-Google-Smtp-Source: AKy350bRqxqdEKqMVcSqnN63ZNPyhOMKyWL6BqCsRrPI4TgKu5NCiDa5Z07nsJBJNu7fhXJT3uhpGg== X-Received: by 2002:adf:fdd0:0:b0:2ce:a862:551 with SMTP id i16-20020adffdd0000000b002cea8620551mr4388550wrs.58.1680703551698; Wed, 05 Apr 2023 07:05:51 -0700 (PDT) Received: from platypus.localdomain ([62.23.166.218]) by smtp.gmail.com with ESMTPSA id ay8-20020a05600c1e0800b003edddae1068sm2330150wmb.9.2023.04.05.07.05.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 05 Apr 2023 07:05:51 -0700 (PDT) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org, mxlol233 Subject: [committed 33/88] gccrs: Add support for feature check. Date: Wed, 5 Apr 2023 16:03:17 +0200 Message-Id: <20230405140411.3016563-34-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: <20230405140411.3016563-1-arthur.cohen@embecosm.com> References: <20230405140411.3016563-1-arthur.cohen@embecosm.com> Reply-To: arthur.cohen@embecosm.com MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-14.3 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,T_FILL_THIS_FORM_SHORT 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: mxlol233 This commit implements a very basic feature checking module. gcc/rust/ChangeLog: * Make-lang.in: Add object files: `rust-feature.o` and `rust-feature-gate.o` * checks/errors/rust-feature-gate.cc: New file. * checks/errors/rust-feature-gate.h: New file. * checks/errors/rust-feature.cc: New file. * checks/errors/rust-feature.h: New file. * rust-session-manager.cc: Add FeatureGate check. gcc/testsuite/ChangeLog: * rust/compile/feature.rs: New test. Signed-off-by: Xiao Ma --- gcc/rust/Make-lang.in | 2 + gcc/rust/checks/errors/rust-feature-gate.cc | 63 +++++++ gcc/rust/checks/errors/rust-feature-gate.h | 191 ++++++++++++++++++++ gcc/rust/checks/errors/rust-feature.cc | 66 +++++++ gcc/rust/checks/errors/rust-feature.h | 76 ++++++++ gcc/rust/rust-session-manager.cc | 4 + gcc/testsuite/rust/compile/feature.rs | 4 + 7 files changed, 406 insertions(+) create mode 100644 gcc/rust/checks/errors/rust-feature-gate.cc create mode 100644 gcc/rust/checks/errors/rust-feature-gate.h create mode 100644 gcc/rust/checks/errors/rust-feature.cc create mode 100644 gcc/rust/checks/errors/rust-feature.h create mode 100644 gcc/testsuite/rust/compile/feature.rs diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 87f3ba66eba..a0c5757592e 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -161,6 +161,8 @@ GRS_OBJS = \ rust/rust-import-archive.o \ rust/rust-extern-crate.o \ rust/rust-builtins.o \ + rust/rust-feature.o \ + rust/rust-feature-gate.o \ $(END) # removed object files from here diff --git a/gcc/rust/checks/errors/rust-feature-gate.cc b/gcc/rust/checks/errors/rust-feature-gate.cc new file mode 100644 index 00000000000..cd26f8a17f5 --- /dev/null +++ b/gcc/rust/checks/errors/rust-feature-gate.cc @@ -0,0 +1,63 @@ +// 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-feature-gate.h" +#include "rust-feature.h" + +namespace Rust { + +void +FeatureGate::check (AST::Crate &crate) +{ + std::vector valid_features; + for (const auto &attr : crate.inner_attrs) + { + if (attr.get_path ().as_string () == "feature") + { + const auto &attr_input = attr.get_attr_input (); + auto type = attr_input.get_attr_input_type (); + if (type == AST::AttrInput::AttrInputType::TOKEN_TREE) + { + const auto &option = static_cast ( + attr.get_attr_input ()); + std::unique_ptr meta_item ( + option.parse_to_meta_item ()); + for (const auto &item : meta_item->get_items ()) + { + const auto &name = item->as_string (); + auto tname = Feature::as_name (name); + if (!tname.is_none ()) + valid_features.push_back (Feature::create (tname.get ())); + else + rust_error_at (item->get_locus (), "unknown feature '%s'", + name.c_str ()); + } + } + } + } + valid_features.shrink_to_fit (); + + // TODO (mxlol233): add the real feature gate stuff. + auto &items = crate.items; + for (auto it = items.begin (); it != items.end (); it++) + { + auto &item = *it; + item->accept_vis (*this); + } +} +} // namespace Rust \ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-feature-gate.h b/gcc/rust/checks/errors/rust-feature-gate.h new file mode 100644 index 00000000000..080c15ccd23 --- /dev/null +++ b/gcc/rust/checks/errors/rust-feature-gate.h @@ -0,0 +1,191 @@ +// 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 +// . + +#ifndef RUST_FEATURE_GATE_H +#define RUST_FEATURE_GATE_H + +#include "rust-ast-visitor.h" +#include "rust-ast-full.h" + +namespace Rust { + +struct Feature; + +class FeatureGate : public AST::ASTVisitor +{ +public: + FeatureGate () {} + + void check (AST::Crate &crate); + + void visit (AST::Token &tok) override {} + void visit (AST::DelimTokenTree &delim_tok_tree) override {} + void visit (AST::AttrInputMetaItemContainer &input) override {} + void visit (AST::IdentifierExpr &ident_expr) override {} + void visit (AST::Lifetime &lifetime) override {} + void visit (AST::LifetimeParam &lifetime_param) override {} + void visit (AST::ConstGenericParam &const_param) override {} + void visit (AST::PathInExpression &path) override {} + void visit (AST::TypePathSegment &segment) override {} + void visit (AST::TypePathSegmentGeneric &segment) override {} + void visit (AST::TypePathSegmentFunction &segment) override {} + void visit (AST::TypePath &path) override {} + void visit (AST::QualifiedPathInExpression &path) override {} + void visit (AST::QualifiedPathInType &path) override {} + void visit (AST::LiteralExpr &expr) override {} + void visit (AST::AttrInputLiteral &attr_input) override {} + void visit (AST::MetaItemLitExpr &meta_item) override {} + void visit (AST::MetaItemPathLit &meta_item) override {} + void visit (AST::BorrowExpr &expr) override {} + void visit (AST::DereferenceExpr &expr) override {} + void visit (AST::ErrorPropagationExpr &expr) override {} + void visit (AST::NegationExpr &expr) override {} + void visit (AST::ArithmeticOrLogicalExpr &expr) override {} + void visit (AST::ComparisonExpr &expr) override {} + void visit (AST::LazyBooleanExpr &expr) override {} + void visit (AST::TypeCastExpr &expr) override {} + void visit (AST::AssignmentExpr &expr) override {} + void visit (AST::CompoundAssignmentExpr &expr) override {} + void visit (AST::GroupedExpr &expr) override {} + void visit (AST::ArrayElemsValues &elems) override {} + void visit (AST::ArrayElemsCopied &elems) override {} + void visit (AST::ArrayExpr &expr) override {} + void visit (AST::ArrayIndexExpr &expr) override {} + void visit (AST::TupleExpr &expr) override {} + void visit (AST::TupleIndexExpr &expr) override {} + void visit (AST::StructExprStruct &expr) override {} + void visit (AST::StructExprFieldIdentifier &field) override {} + void visit (AST::StructExprFieldIdentifierValue &field) override {} + void visit (AST::StructExprFieldIndexValue &field) override {} + void visit (AST::StructExprStructFields &expr) override {} + void visit (AST::StructExprStructBase &expr) override {} + void visit (AST::CallExpr &expr) override {} + void visit (AST::MethodCallExpr &expr) override {} + void visit (AST::FieldAccessExpr &expr) override {} + void visit (AST::ClosureExprInner &expr) override {} + void visit (AST::BlockExpr &expr) override {} + void visit (AST::ClosureExprInnerTyped &expr) override {} + void visit (AST::ContinueExpr &expr) override {} + void visit (AST::BreakExpr &expr) override {} + void visit (AST::RangeFromToExpr &expr) override {} + void visit (AST::RangeFromExpr &expr) override {} + void visit (AST::RangeToExpr &expr) override {} + void visit (AST::RangeFullExpr &expr) override {} + void visit (AST::RangeFromToInclExpr &expr) override {} + void visit (AST::RangeToInclExpr &expr) override {} + void visit (AST::ReturnExpr &expr) override {} + void visit (AST::UnsafeBlockExpr &expr) override {} + void visit (AST::LoopExpr &expr) override {} + void visit (AST::WhileLoopExpr &expr) override {} + void visit (AST::WhileLetLoopExpr &expr) override {} + void visit (AST::ForLoopExpr &expr) override {} + void visit (AST::IfExpr &expr) override {} + void visit (AST::IfExprConseqElse &expr) override {} + void visit (AST::IfExprConseqIf &expr) override {} + void visit (AST::IfExprConseqIfLet &expr) override {} + void visit (AST::IfLetExpr &expr) override {} + void visit (AST::IfLetExprConseqElse &expr) override {} + void visit (AST::IfLetExprConseqIf &expr) override {} + void visit (AST::IfLetExprConseqIfLet &expr) override {} + void visit (AST::MatchExpr &expr) override {} + void visit (AST::AwaitExpr &expr) override {} + void visit (AST::AsyncBlockExpr &expr) override {} + void visit (AST::TypeParam ¶m) override {} + void visit (AST::LifetimeWhereClauseItem &item) override {} + void visit (AST::TypeBoundWhereClauseItem &item) override {} + void visit (AST::Method &method) override {} + void visit (AST::Module &module) override {} + void visit (AST::ExternCrate &crate) override {} + void visit (AST::UseTreeGlob &use_tree) override {} + void visit (AST::UseTreeList &use_tree) override {} + void visit (AST::UseTreeRebind &use_tree) override {} + void visit (AST::UseDeclaration &use_decl) override {} + void visit (AST::Function &function) override {} + void visit (AST::TypeAlias &type_alias) override {} + void visit (AST::StructStruct &struct_item) override {} + void visit (AST::TupleStruct &tuple_struct) override {} + void visit (AST::EnumItem &item) override {} + void visit (AST::EnumItemTuple &item) override {} + void visit (AST::EnumItemStruct &item) override {} + void visit (AST::EnumItemDiscriminant &item) override {} + void visit (AST::Enum &enum_item) override {} + void visit (AST::Union &union_item) override {} + void visit (AST::ConstantItem &const_item) override {} + void visit (AST::StaticItem &static_item) override {} + void visit (AST::TraitItemFunc &item) override {} + void visit (AST::TraitItemMethod &item) override {} + void visit (AST::TraitItemConst &item) override {} + void visit (AST::TraitItemType &item) override {} + void visit (AST::Trait &trait) override {} + void visit (AST::InherentImpl &impl) override {} + void visit (AST::TraitImpl &impl) override {} + void visit (AST::ExternalStaticItem &item) override {} + void visit (AST::ExternalFunctionItem &item) override {} + void visit (AST::ExternBlock &block) override {} + void visit (AST::MacroMatchFragment &match) override {} + void visit (AST::MacroMatchRepetition &match) override {} + void visit (AST::MacroMatcher &matcher) override {} + void visit (AST::MacroRulesDefinition &rules_def) override {} + void visit (AST::MacroInvocation ¯o_invoc) override {} + void visit (AST::MetaItemPath &meta_item) override {} + void visit (AST::MetaItemSeq &meta_item) override {} + void visit (AST::MetaWord &meta_item) override {} + void visit (AST::MetaNameValueStr &meta_item) override {} + void visit (AST::MetaListPaths &meta_item) override {} + void visit (AST::MetaListNameValueStr &meta_item) override {} + void visit (AST::LiteralPattern &pattern) override {} + void visit (AST::IdentifierPattern &pattern) override {} + void visit (AST::WildcardPattern &pattern) override {} + void visit (AST::RangePatternBoundLiteral &bound) override {} + void visit (AST::RangePatternBoundPath &bound) override {} + void visit (AST::RangePatternBoundQualPath &bound) override {} + void visit (AST::RangePattern &pattern) override {} + void visit (AST::ReferencePattern &pattern) override {} + void visit (AST::StructPatternFieldTuplePat &field) override {} + void visit (AST::StructPatternFieldIdentPat &field) override {} + void visit (AST::StructPatternFieldIdent &field) override {} + void visit (AST::StructPattern &pattern) override {} + void visit (AST::TupleStructItemsNoRange &tuple_items) override {} + void visit (AST::TupleStructItemsRange &tuple_items) override {} + void visit (AST::TupleStructPattern &pattern) override {} + void visit (AST::TuplePatternItemsMultiple &tuple_items) override {} + void visit (AST::TuplePatternItemsRanged &tuple_items) override {} + void visit (AST::TuplePattern &pattern) override {} + void visit (AST::GroupedPattern &pattern) override {} + void visit (AST::SlicePattern &pattern) override {} + void visit (AST::EmptyStmt &stmt) override {} + void visit (AST::LetStmt &stmt) override {} + void visit (AST::ExprStmtWithoutBlock &stmt) override {} + void visit (AST::ExprStmtWithBlock &stmt) override {} + void visit (AST::TraitBound &bound) override {} + void visit (AST::ImplTraitType &type) override {} + void visit (AST::TraitObjectType &type) override {} + void visit (AST::ParenthesisedType &type) override {} + void visit (AST::ImplTraitTypeOneBound &type) override {} + void visit (AST::TraitObjectTypeOneBound &type) override {} + void visit (AST::TupleType &type) override {} + void visit (AST::NeverType &type) override {} + void visit (AST::RawPointerType &type) override {} + void visit (AST::ReferenceType &type) override {} + void visit (AST::ArrayType &type) override {} + void visit (AST::SliceType &type) override {} + void visit (AST::InferredType &type) override {} + void visit (AST::BareFunctionType &type) override {} +}; +} // namespace Rust +#endif \ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-feature.cc b/gcc/rust/checks/errors/rust-feature.cc new file mode 100644 index 00000000000..b87b4ca38ef --- /dev/null +++ b/gcc/rust/checks/errors/rust-feature.cc @@ -0,0 +1,66 @@ +// 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-feature.h" +#include "rust-session-manager.h" + +namespace Rust { + +Feature +Feature::create (Feature::Name name) +{ + switch (name) + { + case Feature::Name::ASSOCIATED_TYPE_BOUNDS: + return Feature (Feature::Name::ASSOCIATED_TYPE_BOUNDS, + Feature::State::ACCEPTED, "associated_type_bounds", + "1.34.0", 52662, + Optional::none (), ""); + case Feature::Name::INTRINSICS: + return Feature (Feature::Name::INTRINSICS, Feature::State::ACCEPTED, + "intrinsics", "1.0.0", 0, + Optional::none (), ""); + case Feature::Name::RUSTC_ATTRS: + return Feature (Feature::Name::RUSTC_ATTRS, Feature::State::ACCEPTED, + "rustc_attrs", "1.0.0", 0, + Optional::none (), ""); + case Feature::Name::DECL_MACRO: + return Feature (Feature::Name::DECL_MACRO, Feature::State::ACCEPTED, + "decl_macro", "1.0.0", 0, + Optional::none (), ""); + default: + gcc_unreachable (); + } +} + +const std::map Feature::name_hash_map = { + {"associated_type_bounds", Feature::Name::ASSOCIATED_TYPE_BOUNDS}, + {"intrinsics", Feature::Name::INTRINSICS}, + {"rustc_attrs", Feature::Name::RUSTC_ATTRS}, + {"decl_macro", Feature::Name::DECL_MACRO}, +}; + +Optional +Feature::as_name (const std::string &name) +{ + if (Feature::name_hash_map.count (name)) + return Optional::some (Feature::name_hash_map.at (name)); + return Optional::none (); +} + +} // namespace Rust \ No newline at end of file diff --git a/gcc/rust/checks/errors/rust-feature.h b/gcc/rust/checks/errors/rust-feature.h new file mode 100644 index 00000000000..bf93b090af5 --- /dev/null +++ b/gcc/rust/checks/errors/rust-feature.h @@ -0,0 +1,76 @@ +// 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 +// . + +#ifndef RUST_FEATURE_H +#define RUST_FEATURE_H + +#include "rust-session-manager.h" +#include "rust-optional.h" + +namespace Rust { + +class Feature +{ +public: + enum class State + { + ACCEPTED, + ACTIVE, + REMOVED, + STABILIZED, + }; + + enum class Name + { + ASSOCIATED_TYPE_BOUNDS, + INTRINSICS, + RUSTC_ATTRS, + DECL_MACRO, + }; + + const std::string &as_string () { return m_name_str; } + Name name () { return m_name; } + const std::string &description () { return m_description; } + State state () { return m_state; } + + static Optional as_name (const std::string &name); + static Feature create (Name name); + +private: + Feature (Name name, State state, const char *name_str, + const char *rustc_since, uint64_t issue_number, + const Optional &edition, + const char *description) + : m_state (state), m_name (name), m_name_str (name_str), + m_rustc_since (rustc_since), issue (issue_number), edition (edition), + m_description (description) + {} + + State m_state; + Name m_name; + std::string m_name_str; + std::string m_rustc_since; + uint64_t issue; + Optional edition; + std::string m_description; + + static const std::map name_hash_map; +}; + +} // namespace Rust +#endif \ No newline at end of file diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 70b058ff992..28ac2ba4a53 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -27,6 +27,7 @@ #include "rust-hir-type-check.h" #include "rust-privacy-check.h" #include "rust-const-checker.h" +#include "rust-feature-gate.h" #include "rust-tycheck-dump.h" #include "rust-compile.h" #include "rust-cfg-parser.h" @@ -558,6 +559,9 @@ Session::compile_crate (const char *filename) rust_debug ("END POST-EXPANSION AST DUMP"); } + // feature gating + FeatureGate ().check (parsed_crate); + if (last_step == CompileOptions::CompileStep::NameResolution) return; diff --git a/gcc/testsuite/rust/compile/feature.rs b/gcc/testsuite/rust/compile/feature.rs new file mode 100644 index 00000000000..305d112b7c4 --- /dev/null +++ b/gcc/testsuite/rust/compile/feature.rs @@ -0,0 +1,4 @@ +#![feature(AA)] //{ dg-error "unknown feature 'AA'" } + + +fn main(){} \ No newline at end of file -- 2.40.0