Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -217,6 +217,12 @@ /// Cache of constants visited in search of ConstantExprs. SmallPtrSet ConstantExprVisited; + // Verify that this GlobalValue is only used in this module. + // This map is used to avoid visiting uses twice. We can arrive at a user + // twice, if they have multiple operands. In particular for very large + // constant expressions, we can arrive at a particular user many times. + SmallPtrSet GlobalValueVisited; + void checkAtomicMemAccessSize(const Module *M, Type *Ty, const Instruction *I); public: @@ -310,6 +316,10 @@ private: // Verification methods... void visitGlobalValue(const GlobalValue &GV); + bool doVisitGlobalValue(const GlobalValue &GV, const Value *V); + void forEachUserGlobalValue(const Value *User, + const GlobalValue &GV); + void visitGlobalVariable(const GlobalVariable &GV); void visitGlobalAlias(const GlobalAlias &GA); void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); @@ -462,17 +472,35 @@ InstVisitor::visit(I); } -// Helper to recursively iterate over indirect users. By -// returning false, the callback can ask to stop recursing -// further. -static void forEachUser(const Value *User, - SmallPtrSet &Visited, - llvm::function_ref Callback) { - if (!Visited.insert(User).second) +bool Verifier::doVisitGlobalValue(const GlobalValue &GV, const Value *V) { + if (const Instruction *I = dyn_cast(V)) { + if (!I->getParent() || !I->getParent()->getParent()) + CheckFailed("Global is referenced by parentless instruction!", &GV, + M, I); + else if (I->getParent()->getParent()->getParent() != M) + CheckFailed("Global is referenced in a different module!", &GV, + M, I, I->getParent()->getParent(), + I->getParent()->getParent()->getParent()); + return false; + } else if (const Function *F = dyn_cast(V)) { + if (F->getParent() != M) + CheckFailed("Global is used by function in a different module", &GV, + M, F, F->getParent()); + return false; + } + return true; +} + +// Helper to recursively iterate over indirect users of +// a global value. By returning false, doVisitGlobalValue +// can ask to stop recursing further. +void Verifier::forEachUserGlobalValue(const Value *User, + const GlobalValue &GV) { + if (!GlobalValueVisited.insert(User).second) return; for (const Value *TheNextUser : User->materialized_users()) - if (Callback(TheNextUser)) - forEachUser(TheNextUser, Visited, Callback); + if (doVisitGlobalValue(GV, TheNextUser)) + forEachUserGlobalValue(TheNextUser, GV); } void Verifier::visitGlobalValue(const GlobalValue &GV) { @@ -494,29 +522,7 @@ if (GV.isDeclarationForLinker()) Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV); - // Verify that this GlobalValue is only used in this module. - // This map is used to avoid visiting uses twice. We can arrive at a user - // twice, if they have multiple operands. In particular for very large - // constant expressions, we can arrive at a particular user many times. - SmallPtrSet Visited; - forEachUser(&GV, Visited, [&](const Value *V) -> bool { - if (const Instruction *I = dyn_cast(V)) { - if (!I->getParent() || !I->getParent()->getParent()) - CheckFailed("Global is referenced by parentless instruction!", &GV, - M, I); - else if (I->getParent()->getParent()->getParent() != M) - CheckFailed("Global is referenced in a different module!", &GV, - M, I, I->getParent()->getParent(), - I->getParent()->getParent()->getParent()); - return false; - } else if (const Function *F = dyn_cast(V)) { - if (F->getParent() != M) - CheckFailed("Global is used by function in a different module", &GV, - M, F, F->getParent()); - return false; - } - return true; - }); + forEachUser(&GV, GV); } void Verifier::visitGlobalVariable(const GlobalVariable &GV) {