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