From: mxlol233 <mxlol...@outlook.com> 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 <mxlol...@outlook.com> --- 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 +// <http://www.gnu.org/licenses/>. + +#include "rust-feature-gate.h" +#include "rust-feature.h" + +namespace Rust { + +void +FeatureGate::check (AST::Crate &crate) +{ + std::vector<Feature> 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<const AST::DelimTokenTree &> ( + attr.get_attr_input ()); + std::unique_ptr<AST::AttrInputMetaItemContainer> 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 +// <http://www.gnu.org/licenses/>. + +#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 +// <http://www.gnu.org/licenses/>. + +#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<CompileOptions::Edition>::none (), ""); + case Feature::Name::INTRINSICS: + return Feature (Feature::Name::INTRINSICS, Feature::State::ACCEPTED, + "intrinsics", "1.0.0", 0, + Optional<CompileOptions::Edition>::none (), ""); + case Feature::Name::RUSTC_ATTRS: + return Feature (Feature::Name::RUSTC_ATTRS, Feature::State::ACCEPTED, + "rustc_attrs", "1.0.0", 0, + Optional<CompileOptions::Edition>::none (), ""); + case Feature::Name::DECL_MACRO: + return Feature (Feature::Name::DECL_MACRO, Feature::State::ACCEPTED, + "decl_macro", "1.0.0", 0, + Optional<CompileOptions::Edition>::none (), ""); + default: + gcc_unreachable (); + } +} + +const std::map<std::string, Feature::Name> 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::Name> +Feature::as_name (const std::string &name) +{ + if (Feature::name_hash_map.count (name)) + return Optional<Feature::Name>::some (Feature::name_hash_map.at (name)); + return Optional<Feature::Name>::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 +// <http://www.gnu.org/licenses/>. + +#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<Name> 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<CompileOptions::Edition> &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<CompileOptions::Edition> edition; + std::string m_description; + + static const std::map<std::string, Name> 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