diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2015-12-19 20:03:23 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2015-12-19 20:03:23 +0000 |
commit | fdb838f3f8a8b6896bbbd5285555874eb3b748eb (patch) | |
tree | bb327efea5430802f5c35627328bdffe7a062dd1 /include | |
parent | 25b4ccf2a65d754b09169602e88e12637d7068b7 (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.h | 2 | ||||
-rw-r--r-- | include/llvm/IR/Value.h | 77 |
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. |