From: Owen Avery <[email protected]>
This fixes a false positive with undefined features, improves the
implementation of Feature::as_name, and configures the testsuite to
check further stages of libcore compilation.
gcc/rust/ChangeLog:
* ast/rust-macro.h (MetaNameValueStr::get_name): New function.
(MetaNameValueStr::get_value): Likewise.
* checks/errors/feature/rust-feature-gate.cc
(FeatureGate::visit): Tweak unknown feature detection.
(FeatureGate::gate): Handle field rename.
(FeatureGate::note_stability_attribute): New function
definition.
* checks/errors/feature/rust-feature-gate.h
(FeatureGate::note_stability_attribute): New function
declaration.
(FeatureGate::Stability): New enum class.
(FeatureGate::valid_features): Rename field to...
(FeatureGate::valid_lang_features): ...here.
(FeatureGate::valid_lib_features): New field.
(FeatureGate::defined_lib_features): Likewise.
* checks/errors/feature/rust-feature.cc (Feature::as_name):
Improve implementation.
gcc/testsuite/ChangeLog:
* rust/core/core.exp: Change -frust-compile-until=astvalidation
to -frust-compile-until=nameresolution.
Signed-off-by: Owen Avery <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/12adbc3130dd2352e628a3ee992645d05b3ff046
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4319
gcc/rust/ast/rust-macro.h | 4 +
.../errors/feature/rust-feature-gate.cc | 91 +++++++++++++++++--
.../checks/errors/feature/rust-feature-gate.h | 13 ++-
.../checks/errors/feature/rust-feature.cc | 9 +-
gcc/testsuite/rust/core/core.exp | 2 +-
5 files changed, 103 insertions(+), 16 deletions(-)
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 416507501..71de8f022 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -993,6 +993,10 @@ public:
return ident.as_string () + " = \"" + str + "\"";
}
+ const Identifier &get_name () const { return ident; }
+
+ const std::string &get_value () const { return str; }
+
void accept_vis (ASTVisitor &vis) override;
// HACK: used to simplify parsing - creates a copy of this
diff --git a/gcc/rust/checks/errors/feature/rust-feature-gate.cc
b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
index 448fa18f2..9df822b7e 100644
--- a/gcc/rust/checks/errors/feature/rust-feature-gate.cc
+++ b/gcc/rust/checks/errors/feature/rust-feature-gate.cc
@@ -34,7 +34,10 @@ FeatureGate::check (AST::Crate &crate)
void
FeatureGate::visit (AST::Crate &crate)
{
- valid_features.clear ();
+ valid_lang_features.clear ();
+ valid_lib_features.clear ();
+
+ // avoid clearing defined features (?)
for (const auto &attr : crate.inner_attrs)
{
@@ -58,29 +61,45 @@ FeatureGate::visit (AST::Crate &crate)
for (const auto &item : meta_item->get_items ())
{
const auto &name_str = item->as_string ();
- auto tname = Feature::as_name (name_str);
- if (tname.has_value ())
- {
- auto name = tname.value ();
- valid_features.insert (name);
- }
+ // TODO: detect duplicates
+ if (auto tname = Feature::as_name (name_str))
+ valid_lang_features.insert (tname.value ());
else
- rust_error_at (item->get_locus (), ErrorCode::E0635,
- "unknown feature %qs", name_str.c_str ());
+ valid_lib_features.emplace (name_str, item->get_locus ());
}
}
}
}
AST::DefaultASTVisitor::visit (crate);
+
+ for (auto &ent : valid_lib_features)
+ {
+ const std::string &feature = ent.first;
+ location_t locus = ent.second;
+
+ // rustc treats these as valid,
+ // but apparently has special handling for them
+ if (feature == "libc" || feature == "test")
+ continue;
+
+ if (defined_lib_features.find (feature) != defined_lib_features.end ())
+ {
+ // TODO: emit warning if stable
+ continue;
+ }
+
+ rust_error_at (locus, ErrorCode::E0635, "unknown feature %qs",
+ feature.c_str ());
+ }
}
void
FeatureGate::gate (Feature::Name name, location_t loc,
const std::string &error_msg)
{
- if (!valid_features.count (name))
+ if (!valid_lang_features.count (name))
{
auto &feature = Feature::lookup (name);
if (auto issue = feature.issue ())
@@ -164,10 +183,60 @@ FeatureGate::check_lang_item_attribute (
}
}
+void
+FeatureGate::note_stability_attribute (
+ const std::vector<AST::Attribute> &attributes)
+{
+ for (const AST::Attribute &attr : attributes)
+ {
+ std::string attr_name = attr.get_path ().as_string ();
+
+ Stability stability;
+
+ if (attr_name == Values::Attributes::STABLE)
+ stability = Stability::STABLE;
+ else if (attr_name == Values::Attributes::UNSTABLE)
+ stability = Stability::UNSTABLE;
+ else if (attr_name == Values::Attributes::RUSTC_CONST_STABLE)
+ stability = Stability::STABLE;
+ else if (attr_name == Values::Attributes::RUSTC_CONST_UNSTABLE)
+ stability = Stability::UNSTABLE;
+ else
+ continue;
+
+ if (attr.empty_input ())
+ // TODO: error?
+ continue;
+
+ auto &attr_input = attr.get_attr_input ();
+ if (attr_input.get_attr_input_type ()
+ != AST::AttrInput::AttrInputType::TOKEN_TREE)
+ // TODO: error?
+ continue;
+
+ std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
+ static_cast<const AST::DelimTokenTree &> (attr_input)
+ .parse_to_meta_item ());
+
+ for (auto &item : meta_item->get_items ())
+ {
+ // TODO: more thorough error checking?
+ // ~only the standard libraries should ever exercise this
+ if (item->is_key_value_pair ())
+ {
+ auto &pair = static_cast<const AST::MetaNameValueStr &> (*item);
+ if (pair.get_name ().as_string () == "feature")
+ defined_lib_features.emplace (pair.get_value (), stability);
+ }
+ }
+ }
+}
+
void
FeatureGate::visit (AST::MacroRulesDefinition &rules_def)
{
check_rustc_attri (rules_def.get_outer_attrs ());
+ note_stability_attribute (rules_def.get_outer_attrs ());
}
void
@@ -178,6 +247,8 @@ FeatureGate::visit (AST::Function &function)
check_lang_item_attribute (function.get_outer_attrs ());
+ note_stability_attribute (function.get_outer_attrs ());
+
AST::DefaultASTVisitor::visit (function);
}
diff --git a/gcc/rust/checks/errors/feature/rust-feature-gate.h
b/gcc/rust/checks/errors/feature/rust-feature-gate.h
index c8ab66b75..8ff491c10 100644
--- a/gcc/rust/checks/errors/feature/rust-feature-gate.h
+++ b/gcc/rust/checks/errors/feature/rust-feature-gate.h
@@ -59,7 +59,18 @@ private:
check_may_dangle_attribute (const std::vector<AST::Attribute> &attributes);
void
check_lang_item_attribute (const std::vector<AST::Attribute> &attributes);
- std::set<Feature::Name> valid_features;
+ void note_stability_attribute (const std::vector<AST::Attribute>
&attributes);
+
+ std::set<Feature::Name> valid_lang_features;
+ std::map<std::string, location_t> valid_lib_features;
+
+ enum class Stability
+ {
+ STABLE,
+ UNSTABLE,
+ };
+
+ std::map<std::string, Stability> defined_lib_features;
};
} // namespace Rust
#endif
diff --git a/gcc/rust/checks/errors/feature/rust-feature.cc
b/gcc/rust/checks/errors/feature/rust-feature.cc
index 7fc5cb047..1a967aa70 100644
--- a/gcc/rust/checks/errors/feature/rust-feature.cc
+++ b/gcc/rust/checks/errors/feature/rust-feature.cc
@@ -77,10 +77,11 @@ const std::map<std::string, Feature::Name>
Feature::name_hash_map = {
tl::optional<Feature::Name>
Feature::as_name (const std::string &name)
{
- if (Feature::name_hash_map.count (name))
- return Feature::name_hash_map.at (name);
-
- return tl::nullopt;
+ auto it = Feature::name_hash_map.find (name);
+ if (it == Feature::name_hash_map.end ())
+ return tl::nullopt;
+ else
+ return it->second;
}
tl::optional<std::reference_wrapper<const Feature>>
diff --git a/gcc/testsuite/rust/core/core.exp b/gcc/testsuite/rust/core/core.exp
index 330c6d5ba..45bdbb599 100644
--- a/gcc/testsuite/rust/core/core.exp
+++ b/gcc/testsuite/rust/core/core.exp
@@ -30,7 +30,7 @@ set saved-dg-do-what-default ${dg-do-what-default}
set dg-do-what-default "compile"
set individual_timeout 600
dg-additional-files [lsort [glob -nocomplain
$srcdir/../../libgrust/rustc-lib/*]]
-dg-runtest $srcdir/../../libgrust/rustc-lib/core/src/lib.rs
"-frust-edition=2018 -frust-crate=core -frust-compile-until=astvalidation -w" ""
+dg-runtest $srcdir/../../libgrust/rustc-lib/core/src/lib.rs
"-frust-edition=2018 -frust-crate=core -frust-compile-until=nameresolution -w"
""
set dg-do-what-default ${saved-dg-do-what-default}
# All done.
base-commit: 13dafe56a3d167b9900c985e5d1cc34d67c58de0
--
2.51.2