diff --git a/gcc/rust/privacy/rust-privacy-ctx.cc b/gcc/rust/privacy/rust-privacy-ctx.cc index e876e7855c7..3a44ce0cc0e 100644 --- a/gcc/rust/privacy/rust-privacy-ctx.cc +++ b/gcc/rust/privacy/rust-privacy-ctx.cc @@ -17,19 +17,75 @@ // . #include "rust-privacy-ctx.h" +#include "selftest.h" namespace Rust { namespace Privacy { -void -PrivacyContext::insert_reachability (const Analysis::NodeMapping &mapping, +static ReachLevel +insert_if_higher (ReachLevel new_level, + std::unordered_map::iterator &existing) +{ + if (new_level > existing->second) + existing->second = new_level; + + return existing->second; +} + +ReachLevel +PrivacyContext::update_reachability (const Analysis::NodeMapping &mapping, ReachLevel reach) -{} +{ + auto existing_reach = reachability_map.find (mapping.get_hirid ()); + if (existing_reach != reachability_map.end ()) + return insert_if_higher (reach, existing_reach); + + reachability_map.insert ({mapping.get_hirid (), reach}); + return reach; +} const ReachLevel * PrivacyContext::lookup_reachability (const Analysis::NodeMapping &mapping) { - return nullptr; -} + auto existing_reach = reachability_map.find (mapping.get_hirid ()); + if (existing_reach == reachability_map.end ()) + return nullptr; + return &existing_reach->second; +} } // namespace Privacy } // namespace Rust + +#if CHECKING_P +namespace selftest { +static void +update_reachability_test (void) +{ + auto ctx = Rust::Privacy::PrivacyContext (); + // Bogus values for the mappings + auto mapping = Rust::Analysis::NodeMapping (15, 15, 15, 15); + + auto new_level + = ctx.update_reachability (mapping, Rust::Privacy::ReachLevel::Unreachable); + + ASSERT_EQ (new_level, Rust::Privacy::ReachLevel::Unreachable); + + ASSERT_TRUE (ctx.lookup_reachability (mapping)); + ASSERT_EQ (*ctx.lookup_reachability (mapping), + Rust::Privacy::ReachLevel::Unreachable); + + new_level + = ctx.update_reachability (mapping, Rust::Privacy::ReachLevel::Reachable); + + ASSERT_EQ (new_level, Rust::Privacy::ReachLevel::Reachable); + ASSERT_TRUE (ctx.lookup_reachability (mapping)); + ASSERT_EQ (*ctx.lookup_reachability (mapping), + Rust::Privacy::ReachLevel::Reachable); +} + +void +rust_privacy_ctx_test (void) +{ + update_reachability_test (); +} +} // namespace selftest +#endif // !CHECKING_P diff --git a/gcc/rust/privacy/rust-privacy-ctx.h b/gcc/rust/privacy/rust-privacy-ctx.h index 2a11b56f3ca..7626df300e7 100644 --- a/gcc/rust/privacy/rust-privacy-ctx.h +++ b/gcc/rust/privacy/rust-privacy-ctx.h @@ -16,6 +16,9 @@ // along with GCC; see the file COPYING3. If not see // . +#ifndef RUST_PRIVACY_CTX_H +#define RUST_PRIVACY_CTX_H + #include "rust-hir-map.h" #include "rust-privacy-check.h" @@ -36,13 +39,19 @@ class PrivacyContext { public: /** - * Insert a new resolved visibility for a given node + * Insert a new resolved visibility for a given node. If the node is already + * present in the reachability map, then its visibility will only be updated + * if the given visibility is higher. * * @param mappings Mappings of the node to store the reach level for * @param reach Level of reachability for the given node + * + * @return The new reachability level for this node. If this was the first + * time inserting this node, then return `reach`. Otherwise, return `reach` or + * the existing reach level if it was higher. */ - void insert_reachability (const Analysis::NodeMapping &mapping, - ReachLevel reach); + ReachLevel update_reachability (const Analysis::NodeMapping &mapping, + ReachLevel reach); /** * Lookup the visibility of an already declared Node @@ -59,3 +68,12 @@ private: }; } // namespace Privacy } // namespace Rust + +#if CHECKING_P +namespace selftest { +void +rust_privacy_ctx_test (void); +} +#endif // !CHECKING_P + +#endif // !RUST_PRIVACY_CTX_H diff --git a/gcc/rust/privacy/rust-reachability.cc b/gcc/rust/privacy/rust-reachability.cc index 5cab439739c..1876222e1b4 100644 --- a/gcc/rust/privacy/rust-reachability.cc +++ b/gcc/rust/privacy/rust-reachability.cc @@ -63,14 +63,14 @@ ReachabilityVisitor::visit (HIR::StructStruct &struct_item) if (struct_item.get_visibility ().get_vis_type () == HIR::Visibility::NONE) struct_reach = ReachLevel::Reachable; - // FIXME: Here we want to update only if the visibility is higher - ctx.insert_reachability (struct_item.get_mappings (), struct_reach); + struct_reach + = ctx.update_reachability (struct_item.get_mappings (), struct_reach); // FIXME: We need to also visit the fields as they might have their own set // of reachability levels for (auto &field : struct_item.get_fields ()) - ctx.insert_reachability (field.get_mappings (), struct_reach); + ctx.update_reachability (field.get_mappings (), struct_reach); // FIXME: How do we get the constructor from `struct_item`? We need to update // its visibility as well. Probably by keeping a reference to the TypeCtx? diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index 5ecd79b154f..c7469412392 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -32,8 +32,10 @@ #include "convert.h" #include "langhooks.h" #include "langhooks-def.h" + #include "selftest.h" #include "rust-cfg-parser.h" +#include "rust-privacy-ctx.h" #include // note: header files must be in this order or else forward declarations don't @@ -455,6 +457,7 @@ run_rust_tests () // Call tests for the rust frontend here simple_assert (); rust_cfg_parser_test (); + rust_privacy_ctx_test (); } } // namespace selftest