Skip to content

Commit 12adbc3

Browse files
powerboat9P-E-P
authored andcommitted
Improve feature handling
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]>
1 parent 13dafe5 commit 12adbc3

File tree

5 files changed

+103
-16
lines changed

5 files changed

+103
-16
lines changed

gcc/rust/ast/rust-macro.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,10 @@ class MetaNameValueStr : public MetaItem
993993
return ident.as_string () + " = \"" + str + "\"";
994994
}
995995

996+
const Identifier &get_name () const { return ident; }
997+
998+
const std::string &get_value () const { return str; }
999+
9961000
void accept_vis (ASTVisitor &vis) override;
9971001

9981002
// HACK: used to simplify parsing - creates a copy of this

gcc/rust/checks/errors/feature/rust-feature-gate.cc

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ FeatureGate::check (AST::Crate &crate)
3434
void
3535
FeatureGate::visit (AST::Crate &crate)
3636
{
37-
valid_features.clear ();
37+
valid_lang_features.clear ();
38+
valid_lib_features.clear ();
39+
40+
// avoid clearing defined features (?)
3841

3942
for (const auto &attr : crate.inner_attrs)
4043
{
@@ -58,29 +61,45 @@ FeatureGate::visit (AST::Crate &crate)
5861
for (const auto &item : meta_item->get_items ())
5962
{
6063
const auto &name_str = item->as_string ();
61-
auto tname = Feature::as_name (name_str);
62-
if (tname.has_value ())
63-
{
64-
auto name = tname.value ();
65-
valid_features.insert (name);
66-
}
6764

65+
// TODO: detect duplicates
66+
if (auto tname = Feature::as_name (name_str))
67+
valid_lang_features.insert (tname.value ());
6868
else
69-
rust_error_at (item->get_locus (), ErrorCode::E0635,
70-
"unknown feature %qs", name_str.c_str ());
69+
valid_lib_features.emplace (name_str, item->get_locus ());
7170
}
7271
}
7372
}
7473
}
7574

7675
AST::DefaultASTVisitor::visit (crate);
76+
77+
for (auto &ent : valid_lib_features)
78+
{
79+
const std::string &feature = ent.first;
80+
location_t locus = ent.second;
81+
82+
// rustc treats these as valid,
83+
// but apparently has special handling for them
84+
if (feature == "libc" || feature == "test")
85+
continue;
86+
87+
if (defined_lib_features.find (feature) != defined_lib_features.end ())
88+
{
89+
// TODO: emit warning if stable
90+
continue;
91+
}
92+
93+
rust_error_at (locus, ErrorCode::E0635, "unknown feature %qs",
94+
feature.c_str ());
95+
}
7796
}
7897

7998
void
8099
FeatureGate::gate (Feature::Name name, location_t loc,
81100
const std::string &error_msg)
82101
{
83-
if (!valid_features.count (name))
102+
if (!valid_lang_features.count (name))
84103
{
85104
auto &feature = Feature::lookup (name);
86105
if (auto issue = feature.issue ())
@@ -164,10 +183,60 @@ FeatureGate::check_lang_item_attribute (
164183
}
165184
}
166185

186+
void
187+
FeatureGate::note_stability_attribute (
188+
const std::vector<AST::Attribute> &attributes)
189+
{
190+
for (const AST::Attribute &attr : attributes)
191+
{
192+
std::string attr_name = attr.get_path ().as_string ();
193+
194+
Stability stability;
195+
196+
if (attr_name == Values::Attributes::STABLE)
197+
stability = Stability::STABLE;
198+
else if (attr_name == Values::Attributes::UNSTABLE)
199+
stability = Stability::UNSTABLE;
200+
else if (attr_name == Values::Attributes::RUSTC_CONST_STABLE)
201+
stability = Stability::STABLE;
202+
else if (attr_name == Values::Attributes::RUSTC_CONST_UNSTABLE)
203+
stability = Stability::UNSTABLE;
204+
else
205+
continue;
206+
207+
if (attr.empty_input ())
208+
// TODO: error?
209+
continue;
210+
211+
auto &attr_input = attr.get_attr_input ();
212+
if (attr_input.get_attr_input_type ()
213+
!= AST::AttrInput::AttrInputType::TOKEN_TREE)
214+
// TODO: error?
215+
continue;
216+
217+
std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
218+
static_cast<const AST::DelimTokenTree &> (attr_input)
219+
.parse_to_meta_item ());
220+
221+
for (auto &item : meta_item->get_items ())
222+
{
223+
// TODO: more thorough error checking?
224+
// ~only the standard libraries should ever exercise this
225+
if (item->is_key_value_pair ())
226+
{
227+
auto &pair = static_cast<const AST::MetaNameValueStr &> (*item);
228+
if (pair.get_name ().as_string () == "feature")
229+
defined_lib_features.emplace (pair.get_value (), stability);
230+
}
231+
}
232+
}
233+
}
234+
167235
void
168236
FeatureGate::visit (AST::MacroRulesDefinition &rules_def)
169237
{
170238
check_rustc_attri (rules_def.get_outer_attrs ());
239+
note_stability_attribute (rules_def.get_outer_attrs ());
171240
}
172241

173242
void
@@ -178,6 +247,8 @@ FeatureGate::visit (AST::Function &function)
178247

179248
check_lang_item_attribute (function.get_outer_attrs ());
180249

250+
note_stability_attribute (function.get_outer_attrs ());
251+
181252
AST::DefaultASTVisitor::visit (function);
182253
}
183254

gcc/rust/checks/errors/feature/rust-feature-gate.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,18 @@ class FeatureGate : public AST::DefaultASTVisitor
5959
check_may_dangle_attribute (const std::vector<AST::Attribute> &attributes);
6060
void
6161
check_lang_item_attribute (const std::vector<AST::Attribute> &attributes);
62-
std::set<Feature::Name> valid_features;
62+
void note_stability_attribute (const std::vector<AST::Attribute> &attributes);
63+
64+
std::set<Feature::Name> valid_lang_features;
65+
std::map<std::string, location_t> valid_lib_features;
66+
67+
enum class Stability
68+
{
69+
STABLE,
70+
UNSTABLE,
71+
};
72+
73+
std::map<std::string, Stability> defined_lib_features;
6374
};
6475
} // namespace Rust
6576
#endif

gcc/rust/checks/errors/feature/rust-feature.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,11 @@ const std::map<std::string, Feature::Name> Feature::name_hash_map = {
7777
tl::optional<Feature::Name>
7878
Feature::as_name (const std::string &name)
7979
{
80-
if (Feature::name_hash_map.count (name))
81-
return Feature::name_hash_map.at (name);
82-
83-
return tl::nullopt;
80+
auto it = Feature::name_hash_map.find (name);
81+
if (it == Feature::name_hash_map.end ())
82+
return tl::nullopt;
83+
else
84+
return it->second;
8485
}
8586

8687
tl::optional<std::reference_wrapper<const Feature>>

gcc/testsuite/rust/core/core.exp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ set saved-dg-do-what-default ${dg-do-what-default}
3030
set dg-do-what-default "compile"
3131
set individual_timeout 600
3232
dg-additional-files [lsort [glob -nocomplain $srcdir/../../libgrust/rustc-lib/*]]
33-
dg-runtest $srcdir/../../libgrust/rustc-lib/core/src/lib.rs "-frust-edition=2018 -frust-crate=core -frust-compile-until=astvalidation -w" ""
33+
dg-runtest $srcdir/../../libgrust/rustc-lib/core/src/lib.rs "-frust-edition=2018 -frust-crate=core -frust-compile-until=nameresolution -w" ""
3434
set dg-do-what-default ${saved-dg-do-what-default}
3535

3636
# All done.

0 commit comments

Comments
 (0)