forked from OSchip/llvm-project
[Verifier] Iteratively traverse all indirect users.
The recursive implementation can run into stack overflows, e.g. like in PR52844. The order the users are visited changes, but for the current use case this only impacts the order error messages are emitted.
This commit is contained in:
parent
5fd328c45f
commit
5d68dc184e
|
@ -602,17 +602,22 @@ void Verifier::visit(Instruction &I) {
|
|||
InstVisitor<Verifier>::visit(I);
|
||||
}
|
||||
|
||||
// Helper to recursively iterate over indirect users. By
|
||||
// returning false, the callback can ask to stop recursing
|
||||
// further.
|
||||
// Helper to iterate over indirect users. By returning false, the callback can ask to stop traversing further.
|
||||
static void forEachUser(const Value *User,
|
||||
SmallPtrSet<const Value *, 32> &Visited,
|
||||
llvm::function_ref<bool(const Value *)> Callback) {
|
||||
if (!Visited.insert(User).second)
|
||||
return;
|
||||
for (const Value *TheNextUser : User->materialized_users())
|
||||
if (Callback(TheNextUser))
|
||||
forEachUser(TheNextUser, Visited, Callback);
|
||||
|
||||
SmallVector<const Value *> WorkList;
|
||||
append_range(WorkList, User->materialized_users());
|
||||
while (!WorkList.empty()) {
|
||||
const Value *Cur = WorkList.pop_back_val();
|
||||
if (!Visited.insert(Cur).second)
|
||||
continue;
|
||||
if (Callback(Cur))
|
||||
append_range(WorkList, Cur->materialized_users());
|
||||
}
|
||||
}
|
||||
|
||||
void Verifier::visitGlobalValue(const GlobalValue &GV) {
|
||||
|
|
|
@ -136,17 +136,17 @@ TEST(VerifierTest, CrossModuleRef) {
|
|||
raw_string_ostream ErrorOS(Error);
|
||||
EXPECT_TRUE(verifyModule(M2, &ErrorOS));
|
||||
EXPECT_TRUE(StringRef(ErrorOS.str())
|
||||
.equals("Global is used by function in a different module\n"
|
||||
"i32 ()* @foo2\n"
|
||||
"; ModuleID = 'M2'\n"
|
||||
"i32 ()* @foo3\n"
|
||||
"; ModuleID = 'M3'\n"
|
||||
"Global is referenced in a different module!\n"
|
||||
.equals("Global is referenced in a different module!\n"
|
||||
"i32 ()* @foo2\n"
|
||||
"; ModuleID = 'M2'\n"
|
||||
" %call = call i32 @foo2()\n"
|
||||
"i32 ()* @foo1\n"
|
||||
"; ModuleID = 'M1'\n"));
|
||||
"; ModuleID = 'M1'\n"
|
||||
"Global is used by function in a different module\n"
|
||||
"i32 ()* @foo2\n"
|
||||
"; ModuleID = 'M2'\n"
|
||||
"i32 ()* @foo3\n"
|
||||
"; ModuleID = 'M3'\n"));
|
||||
|
||||
Error.clear();
|
||||
EXPECT_TRUE(verifyModule(M1, &ErrorOS));
|
||||
|
|
Loading…
Reference in New Issue