[midend]修复replaceAllUsesWith中由于setOperand 间接调用 removeUse 或 addUse导致的迭代器失效问题
This commit is contained in:
@ -232,7 +232,7 @@ class Value {
|
||||
void replaceAllUsesWith(Value *value); ///< 将原来使用该value的使用者全变为使用给定参数value并修改相应use关系
|
||||
void removeUse(const std::shared_ptr<Use> &use) {
|
||||
assert(use != nullptr && "Use cannot be null");
|
||||
assert(use->getValue() != this && "Use does not belong to this Value");
|
||||
assert(use->getValue() == this && "Use being removed does NOT point to this Value!");
|
||||
auto it = std::find(uses.begin(), uses.end(), use);
|
||||
assert(it != uses.end() && "Use not found in Value's uses");
|
||||
uses.remove(use);
|
||||
|
||||
@ -118,13 +118,45 @@ ArrayType *ArrayType::get(Type *elementType, unsigned numElements) {
|
||||
return result.first->get();
|
||||
}
|
||||
|
||||
// void Value::replaceAllUsesWith(Value *value) {
|
||||
// for (auto &use : uses) {
|
||||
// auto user = use->getUser();
|
||||
// assert(user && "Use's user cannot be null");
|
||||
// user->setOperand(use->getIndex(), value);
|
||||
// }
|
||||
// uses.clear();
|
||||
// }
|
||||
void Value::replaceAllUsesWith(Value *value) {
|
||||
for (auto &use : uses) {
|
||||
use->getUser()->setOperand(use->getIndex(), value);
|
||||
}
|
||||
uses.clear();
|
||||
}
|
||||
// 1. 创建 uses 列表的副本进行迭代。
|
||||
// 这样做是为了避免在迭代过程中,由于 setOperand 间接调用 removeUse 或 addUse
|
||||
// 导致原列表被修改,从而引发迭代器失效问题。
|
||||
std::list<std::shared_ptr<Use>> uses_copy = uses;
|
||||
|
||||
for (auto &use_ptr : uses_copy) { // 遍历副本
|
||||
// 2. 检查 shared_ptr<Use> 本身是否为空。这是最常见的崩溃原因之一。
|
||||
if (use_ptr == nullptr) {
|
||||
std::cerr << "Warning: Encountered a null std::shared_ptr<Use> in Value::uses list. Skipping this entry." << std::endl;
|
||||
// 在一个健康的 IR 中,这种情况不应该发生。如果经常出现,说明你的 Use 创建或管理有问题。
|
||||
continue; // 跳过空的智能指针
|
||||
}
|
||||
|
||||
// 3. 检查 Use 对象内部的 User* 是否为空。
|
||||
User* user_val = use_ptr->getUser();
|
||||
if (user_val == nullptr) {
|
||||
std::cerr << "Warning: Use object (" << use_ptr.get() << ") has a null User* in replaceAllUsesWith. Skipping this entry. This indicates IR corruption." << std::endl;
|
||||
// 同样,在一个健康的 IR 中,Use 对象的 User* 不应该为空。
|
||||
continue; // 跳过用户指针为空的 Use 对象
|
||||
}
|
||||
|
||||
// 如果走到这里,use_ptr 和 user_val 都是有效的,可以安全调用 setOperand
|
||||
user_val->setOperand(use_ptr->getIndex(), value);
|
||||
}
|
||||
|
||||
// 4. 处理完所有 use 之后,清空原始的 uses 列表。
|
||||
// replaceAllUsesWith 的目的就是将所有使用关系从当前 Value 转移走,
|
||||
// 所以最后清空列表是正确的。
|
||||
uses.clear();
|
||||
}
|
||||
|
||||
// Implementations for static members
|
||||
|
||||
|
||||
Reference in New Issue
Block a user