From 23fc3ff7fe9405797d5961f7792540d3f487a287 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Thu, 7 Apr 2022 11:48:22 +0200 Subject: [PATCH] privacy: ctx: Add proper implementations for insert_reachability() and lookup_reachability() Inserting reach levels in the reachability_map should only be done if the existing reach level is lower than the provided one. If the node is not yet present in the reachability map, insert it no matter what --- gcc/rust/privacy/rust-privacy-ctx.cc | 66 +++++++++++++++++++++++++-- gcc/rust/privacy/rust-privacy-ctx.h | 24 ++++++++-- gcc/rust/privacy/rust-reachability.cc | 6 +-- gcc/rust/rust-lang.cc | 3 ++ 4 files changed, 88 insertions(+), 11 deletions(-) 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