summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2015-12-19 20:03:23 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2015-12-19 20:03:23 +0000
commitfdb838f3f8a8b6896bbbd5285555874eb3b748eb (patch)
treebb327efea5430802f5c35627328bdffe7a062dd1 /include
parent25b4ccf2a65d754b09169602e88e12637d7068b7 (diff)
Assert that we have all use/users in the getters.
An error that is pretty easy to make is to use the lazy bitcode reader and then do something like if (V.use_empty()) The problem is that uses in unmaterialized functions are not accounted for. This patch adds asserts that all uses are known. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256105 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/llvm/IR/Module.h2
-rw-r--r--include/llvm/IR/Value.h77
2 files changed, 66 insertions, 13 deletions
diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h
index bf1447e48af..942f68543cb 100644
--- a/include/llvm/IR/Module.h
+++ b/include/llvm/IR/Module.h
@@ -439,6 +439,7 @@ public:
void setMaterializer(GVMaterializer *GVM);
/// Retrieves the GVMaterializer, if any, for this Module.
GVMaterializer *getMaterializer() const { return Materializer.get(); }
+ bool isMaterialized() const { return !getMaterializer(); }
/// Make sure the GlobalValue is fully read. If the module is corrupt, this
/// returns true and fills in the optional string with information about the
@@ -446,7 +447,6 @@ public:
std::error_code materialize(GlobalValue *GV);
/// Make sure all GlobalValues in this Module are fully read and clear the
- /// Materializer. If the module is corrupt, this DOES NOT clear the old
/// Materializer.
std::error_code materializeAll();
diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h
index be9f14a78de..bb7ff278fde 100644
--- a/include/llvm/IR/Value.h
+++ b/include/llvm/IR/Value.h
@@ -273,38 +273,91 @@ public:
//----------------------------------------------------------------------
// Methods for handling the chain of uses of this Value.
//
- bool use_empty() const { return UseList == nullptr; }
+ // Materializing a function can introduce new uses, so these methods come in
+ // two variants:
+ // The methods that start with materialized_ check the uses that are
+ // currently known given which functions are materialized. Be very careful
+ // when using them since you might not get all uses.
+ // The methods that don't start with materialized_ assert that modules is
+ // fully materialized.
+#ifdef NDEBUG
+ void assertModuleIsMaterialized() const {}
+#else
+ void assertModuleIsMaterialized() const;
+#endif
+
+ bool use_empty() const {
+ assertModuleIsMaterialized();
+ return UseList == nullptr;
+ }
typedef use_iterator_impl<Use> use_iterator;
typedef use_iterator_impl<const Use> const_use_iterator;
- use_iterator use_begin() { return use_iterator(UseList); }
- const_use_iterator use_begin() const { return const_use_iterator(UseList); }
+ use_iterator materialized_use_begin() { return use_iterator(UseList); }
+ const_use_iterator materialized_use_begin() const {
+ return const_use_iterator(UseList);
+ }
+ use_iterator use_begin() {
+ assertModuleIsMaterialized();
+ return materialized_use_begin();
+ }
+ const_use_iterator use_begin() const {
+ assertModuleIsMaterialized();
+ return materialized_use_begin();
+ }
use_iterator use_end() { return use_iterator(); }
const_use_iterator use_end() const { return const_use_iterator(); }
+ iterator_range<use_iterator> materialized_uses() {
+ return make_range(materialized_use_begin(), use_end());
+ }
+ iterator_range<const_use_iterator> materialized_uses() const {
+ return make_range(materialized_use_begin(), use_end());
+ }
iterator_range<use_iterator> uses() {
- return make_range(use_begin(), use_end());
+ assertModuleIsMaterialized();
+ return materialized_uses();
}
iterator_range<const_use_iterator> uses() const {
- return make_range(use_begin(), use_end());
+ assertModuleIsMaterialized();
+ return materialized_uses();
}
- bool user_empty() const { return UseList == nullptr; }
+ bool user_empty() const {
+ assertModuleIsMaterialized();
+ return UseList == nullptr;
+ }
typedef user_iterator_impl<User> user_iterator;
typedef user_iterator_impl<const User> const_user_iterator;
- user_iterator user_begin() { return user_iterator(UseList); }
- const_user_iterator user_begin() const {
+ user_iterator materialized_user_begin() { return user_iterator(UseList); }
+ const_user_iterator materialized_user_begin() const {
return const_user_iterator(UseList);
}
+ user_iterator user_begin() {
+ assertModuleIsMaterialized();
+ return materialized_user_begin();
+ }
+ const_user_iterator user_begin() const {
+ assertModuleIsMaterialized();
+ return materialized_user_begin();
+ }
user_iterator user_end() { return user_iterator(); }
const_user_iterator user_end() const { return const_user_iterator(); }
- User *user_back() { return *user_begin(); }
- const User *user_back() const { return *user_begin(); }
+ User *user_back() {
+ assertModuleIsMaterialized();
+ return *materialized_user_begin();
+ }
+ const User *user_back() const {
+ assertModuleIsMaterialized();
+ return *materialized_user_begin();
+ }
iterator_range<user_iterator> users() {
- return make_range(user_begin(), user_end());
+ assertModuleIsMaterialized();
+ return make_range(materialized_user_begin(), user_end());
}
iterator_range<const_user_iterator> users() const {
- return make_range(user_begin(), user_end());
+ assertModuleIsMaterialized();
+ return make_range(materialized_user_begin(), user_end());
}
/// \brief Return true if there is exactly one user of this value.