Skip to content
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions gcc/rust/ast/rust-macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,10 @@ class MetaNameValueStr : public MetaItem
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
Expand Down
2 changes: 1 addition & 1 deletion gcc/rust/backend/rust-constexpr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3137,7 +3137,7 @@ eval_binary_expression (const constexpr_ctx *ctx, tree t, bool lval,
{
tree lmem = PTRMEM_CST_MEMBER (lhs);
tree rmem = PTRMEM_CST_MEMBER (rhs);
bool eq;
bool eq = false;
if (TREE_CODE (lmem) == TREE_CODE (rmem)
&& TREE_CODE (lmem) == FIELD_DECL
&& TREE_CODE (DECL_CONTEXT (lmem)) == UNION_TYPE
Expand Down
140 changes: 130 additions & 10 deletions gcc/rust/checks/errors/feature/rust-feature-gate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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 ())
Expand Down Expand Up @@ -146,10 +165,78 @@ FeatureGate::check_may_dangle_attribute (
}
}

void
FeatureGate::check_lang_item_attribute (
const std::vector<AST::Attribute> &attributes)
{
for (const AST::Attribute &attr : attributes)
{
const auto &str_path = attr.get_path ().as_string ();
bool is_lang_item = str_path == Values::Attributes::LANG
&& attr.has_attr_input ()
&& attr.get_attr_input ().get_attr_input_type ()
== AST::AttrInput::AttrInputType::LITERAL;

if (is_lang_item)
gate (Feature::Name::LANG_ITEMS, attr.get_locus (),
"lang items are subject to change");
}
}

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
Expand All @@ -158,6 +245,10 @@ FeatureGate::visit (AST::Function &function)
if (!function.is_external ())
check_rustc_attri (function.get_outer_attrs ());

check_lang_item_attribute (function.get_outer_attrs ());

note_stability_attribute (function.get_outer_attrs ());

AST::DefaultASTVisitor::visit (function);
}

Expand Down Expand Up @@ -186,6 +277,7 @@ FeatureGate::visit (AST::Trait &trait)
if (trait.is_auto ())
gate (Feature::Name::OPTIN_BUILTIN_TRAITS, trait.get_locus (),
"auto traits are experimental and possibly buggy");
check_lang_item_attribute (trait.get_outer_attrs ());
AST::DefaultASTVisitor::visit (trait);
}

Expand Down Expand Up @@ -243,4 +335,32 @@ FeatureGate::visit (AST::UseTreeGlob &use)
// #[feature(prelude_import)]
}

void
FeatureGate::visit (AST::StructStruct &struct_item)
{
check_lang_item_attribute (struct_item.get_outer_attrs ());
AST::DefaultASTVisitor::visit (struct_item);
}

void
FeatureGate::visit (AST::TraitItemType &trait_item_type)
{
check_lang_item_attribute (trait_item_type.get_outer_attrs ());
AST::DefaultASTVisitor::visit (trait_item_type);
}

void
FeatureGate::visit (AST::Enum &enum_item)
{
check_lang_item_attribute (enum_item.get_outer_attrs ());
AST::DefaultASTVisitor::visit (enum_item);
}

void
FeatureGate::visit (AST::EnumItem &enum_variant)
{
check_lang_item_attribute (enum_variant.get_outer_attrs ());
AST::DefaultASTVisitor::visit (enum_variant);
}

} // namespace Rust
19 changes: 18 additions & 1 deletion gcc/rust/checks/errors/feature/rust-feature-gate.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,30 @@ class FeatureGate : public AST::DefaultASTVisitor
void visit (AST::ExternBlock &block) override;
void visit (AST::MacroRulesDefinition &rules_def) override;
void visit (AST::RangePattern &pattern) override;
void visit (AST::StructStruct &struct_item) override;
void visit (AST::TraitItemType &trait_item_type) override;
void visit (AST::Enum &enum_item) override;
void visit (AST::EnumItem &enum_variant) override;

private:
void gate (Feature::Name name, location_t loc, const std::string &error_msg);
void check_rustc_attri (const std::vector<AST::Attribute> &attributes);
void
check_may_dangle_attribute (const std::vector<AST::Attribute> &attributes);
std::set<Feature::Name> valid_features;
void
check_lang_item_attribute (const std::vector<AST::Attribute> &attributes);
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
9 changes: 5 additions & 4 deletions gcc/rust/checks/errors/feature/rust-feature.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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>>
Expand Down
8 changes: 7 additions & 1 deletion gcc/rust/expand/rust-expand-visitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "rust-expand-visitor.h"
#include "rust-ast-fragment.h"
#include "rust-hir-map.h"
#include "rust-item.h"
#include "rust-proc-macro.h"
#include "rust-attributes.h"
Expand Down Expand Up @@ -48,7 +49,10 @@ static std::vector<std::unique_ptr<AST::Item>>
builtin_derive_item (AST::Item &item, const AST::Attribute &derive,
BuiltinMacro to_derive)
{
return AST::DeriveVisitor::derive (item, derive, to_derive);
auto items = AST::DeriveVisitor::derive (item, derive, to_derive);
for (auto &item : items)
Analysis::Mappings::get ().add_derived_node (item->get_node_id ());
return items;
}

static std::vector<std::unique_ptr<AST::Item>>
Expand All @@ -64,6 +68,8 @@ derive_item (AST::Item &item, AST::SimplePath &to_derive,
switch (node.get_kind ())
{
case AST::SingleASTNode::Kind::Item:
Analysis::Mappings::get ().add_derived_node (
node.get_item ()->get_node_id ());
result.push_back (node.take_item ());
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion gcc/rust/expand/rust-macro-expand.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ struct MacroExpander
*
* @param parser Parser to use for matching
* @param rep Repetition to try and match
* @param match_amount Reference in which to store the ammount of succesful
* @param match_amount Reference in which to store the amount of successful
* and valid matches
*
* @param lo_bound Lower bound of the matcher. When specified, the matcher
Expand Down
4 changes: 2 additions & 2 deletions gcc/rust/lex/rust-lex.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2640,8 +2640,8 @@ rust_input_source_test ()
{
// ASCII
std::string src = (const char *) u8"_abcde\tXYZ\v\f";
std::vector<uint32_t> expected
= {u'_', u'a', u'b', u'c', u'd', u'e', u'\t', u'X', u'Y', u'Z', u'\v', u'\f'};
std::vector<uint32_t> expected = {u'_', u'a', u'b', u'c', u'd', u'e',
u'\t', u'X', u'Y', u'Z', u'\v', u'\f'};
test_buffer_input_source (src, expected);

// BOM
Expand Down
Loading