1118: Add reachability visitor to Enum variants r=CohenArthur a=CohenArthur

This visits all of an enum's variants and their fields if present. To do that properly, this adds a new `EnumItemKind` enum which allows static casting when visiting each variant of the enum (kept as an `EnumItem` class which is derived three times)

Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
This commit is contained in:
bors[bot] 2022-04-16 09:37:42 +00:00 committed by GitHub
commit e76b639955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 6 deletions

View File

@ -3108,6 +3108,22 @@ EnumItem::as_string () const
{
std::string str = Item::as_string ();
str += variant_name;
str += " ";
switch (get_enum_item_kind ())
{
case Named:
str += "[Named variant]";
break;
case Tuple:
str += "[Tuple variant]";
break;
case Struct:
str += "[Struct variant]";
break;
case Discriminant:
str += "[Discriminant variant]";
break;
}
return str;
}

View File

@ -1588,7 +1588,7 @@ public:
std::string as_string () const;
Analysis::NodeMapping get_mappings () { return mappings; }
Analysis::NodeMapping get_mappings () const { return mappings; }
Location get_locus () const { return locus; }
@ -1644,12 +1644,19 @@ protected:
class EnumItem : public Item
{
Identifier variant_name;
Location locus;
public:
virtual ~EnumItem () {}
enum EnumItemKind
{
Named,
Tuple,
Struct,
Discriminant,
};
EnumItem (Analysis::NodeMapping mappings, Identifier variant_name,
AST::AttrVec outer_attrs, Location locus)
: Item (std::move (mappings), std::move (outer_attrs)),
@ -1663,6 +1670,7 @@ public:
}
virtual std::string as_string () const override;
virtual EnumItemKind get_enum_item_kind () const { return Named; };
// not pure virtual as not abstract
void accept_vis (HIRFullVisitor &vis) override;
@ -1687,6 +1695,11 @@ public:
// Returns whether tuple enum item has tuple fields.
bool has_tuple_fields () const { return !tuple_fields.empty (); }
EnumItemKind get_enum_item_kind () const override
{
return EnumItemKind::Tuple;
}
EnumItemTuple (Analysis::NodeMapping mappings, Identifier variant_name,
std::vector<TupleField> tuple_fields, AST::AttrVec outer_attrs,
Location locus)
@ -1720,6 +1733,11 @@ public:
// Returns whether struct enum item has struct fields.
bool has_struct_fields () const { return !struct_fields.empty (); }
EnumItemKind get_enum_item_kind () const override
{
return EnumItemKind::Struct;
}
EnumItemStruct (Analysis::NodeMapping mappings, Identifier variant_name,
std::vector<StructField> struct_fields,
AST::AttrVec outer_attrs, Location locus)
@ -1777,6 +1795,11 @@ public:
EnumItemDiscriminant (EnumItemDiscriminant &&other) = default;
EnumItemDiscriminant &operator= (EnumItemDiscriminant &&other) = default;
EnumItemKind get_enum_item_kind () const override
{
return EnumItemKind::Discriminant;
}
std::string as_string () const override;
void accept_vis (HIRFullVisitor &vis) override;

View File

@ -69,6 +69,9 @@ ReachabilityVisitor::visit_generic_predicates (
void
ReachabilityVisitor::visit (HIR::Module &mod)
{
auto reach = get_reachability_level (mod.get_visibility ());
reach = ctx.update_reachability (mod.get_mappings (), reach);
for (auto &item : mod.get_items ())
{
// FIXME: Is that what we want to do? Yes? Only visit the items with
@ -83,11 +86,17 @@ ReachabilityVisitor::visit (HIR::Module &mod)
void
ReachabilityVisitor::visit (HIR::ExternCrate &crate)
{}
{
auto reach = get_reachability_level (crate.get_visibility ());
reach = ctx.update_reachability (crate.get_mappings (), reach);
}
void
ReachabilityVisitor::visit (HIR::UseDeclaration &use_decl)
{}
{
auto reach = get_reachability_level (use_decl.get_visibility ());
reach = ctx.update_reachability (use_decl.get_mappings (), reach);
}
void
ReachabilityVisitor::visit (HIR::Function &func)
@ -141,6 +150,38 @@ ReachabilityVisitor::visit (HIR::Enum &enum_item)
enum_reach = ctx.update_reachability (enum_item.get_mappings (), enum_reach);
visit_generic_predicates (enum_item.get_generic_params (), enum_reach);
for (const auto &variant : enum_item.get_variants ())
{
auto variant_reach
= ctx.update_reachability (variant->get_mappings (), enum_reach);
switch (variant->get_enum_item_kind ())
{
case HIR::EnumItem::Tuple: {
// Should we update the fields only if they are public? Similarly to
// what we do in the ReachabilityVisitor for HIR::TupleStruct?
auto tuple_variant
= static_cast<HIR::EnumItemTuple *> (variant.get ());
for (const auto &field : tuple_variant->get_tuple_fields ())
ctx.update_reachability (field.get_mappings (), variant_reach);
break;
}
case HIR::EnumItem::Struct: {
// Should we update the fields only if they are public? Similarly to
// what we do in the ReachabilityVisitor for HIR::StructStruct?
auto struct_variant
= static_cast<HIR::EnumItemStruct *> (variant.get ());
for (const auto &field : struct_variant->get_struct_fields ())
ctx.update_reachability (field.get_mappings (), variant_reach);
break;
}
// Nothing nested to visit in that case
case HIR::EnumItem::Named:
case HIR::EnumItem::Discriminant:
break;
}
}
}
void
@ -155,11 +196,17 @@ ReachabilityVisitor::visit (HIR::Union &union_item)
void
ReachabilityVisitor::visit (HIR::ConstantItem &const_item)
{}
{
auto reach = get_reachability_level (const_item.get_visibility ());
reach = ctx.update_reachability (const_item.get_mappings (), reach);
}
void
ReachabilityVisitor::visit (HIR::StaticItem &static_item)
{}
{
auto reach = get_reachability_level (static_item.get_visibility ());
reach = ctx.update_reachability (static_item.get_mappings (), reach);
}
void
ReachabilityVisitor::visit (HIR::Trait &trait)