mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-12 13:38:21 +00:00
Fix http://llvm.org/PR5160, to let CallbackVHs modify other ValueHandles on the
same Value without breaking things. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83861 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -11,6 +11,7 @@
|
||||
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
@ -327,4 +328,84 @@ TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) {
|
||||
BitcastUser->getOperand(0));
|
||||
}
|
||||
|
||||
TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) {
|
||||
// When a CallbackVH modifies other ValueHandles in its callbacks,
|
||||
// that shouldn't interfere with non-modified ValueHandles receiving
|
||||
// their appropriate callbacks.
|
||||
//
|
||||
// We create the active CallbackVH in the middle of a palindromic
|
||||
// arrangement of other VHs so that the bad behavior would be
|
||||
// triggered in whichever order callbacks run.
|
||||
|
||||
class DestroyingVH : public CallbackVH {
|
||||
public:
|
||||
OwningPtr<WeakVH> ToClear[2];
|
||||
DestroyingVH(Value *V) {
|
||||
ToClear[0].reset(new WeakVH(V));
|
||||
setValPtr(V);
|
||||
ToClear[1].reset(new WeakVH(V));
|
||||
}
|
||||
virtual void deleted() {
|
||||
ToClear[0].reset();
|
||||
ToClear[1].reset();
|
||||
CallbackVH::deleted();
|
||||
}
|
||||
virtual void allUsesReplacedWith(Value *) {
|
||||
ToClear[0].reset();
|
||||
ToClear[1].reset();
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
WeakVH ShouldBeVisited1(BitcastV.get());
|
||||
DestroyingVH C(BitcastV.get());
|
||||
WeakVH ShouldBeVisited2(BitcastV.get());
|
||||
|
||||
BitcastV->replaceAllUsesWith(ConstantV);
|
||||
EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1));
|
||||
EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2));
|
||||
}
|
||||
|
||||
{
|
||||
WeakVH ShouldBeVisited1(BitcastV.get());
|
||||
DestroyingVH C(BitcastV.get());
|
||||
WeakVH ShouldBeVisited2(BitcastV.get());
|
||||
|
||||
BitcastV.reset();
|
||||
EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited1));
|
||||
EXPECT_EQ(NULL, static_cast<Value*>(ShouldBeVisited2));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ValueHandle, AssertingVHCheckedLast) {
|
||||
// If a CallbackVH exists to clear out a group of AssertingVHs on
|
||||
// Value deletion, the CallbackVH should get a chance to do so
|
||||
// before the AssertingVHs assert.
|
||||
|
||||
class ClearingVH : public CallbackVH {
|
||||
public:
|
||||
AssertingVH<Value> *ToClear[2];
|
||||
ClearingVH(Value *V,
|
||||
AssertingVH<Value> &A0, AssertingVH<Value> &A1)
|
||||
: CallbackVH(V) {
|
||||
ToClear[0] = &A0;
|
||||
ToClear[1] = &A1;
|
||||
}
|
||||
|
||||
virtual void deleted() {
|
||||
*ToClear[0] = 0;
|
||||
*ToClear[1] = 0;
|
||||
CallbackVH::deleted();
|
||||
}
|
||||
};
|
||||
|
||||
AssertingVH<Value> A1, A2;
|
||||
A1 = BitcastV.get();
|
||||
ClearingVH C(BitcastV.get(), A1, A2);
|
||||
A2 = BitcastV.get();
|
||||
// C.deleted() should run first, clearing the two AssertingVHs,
|
||||
// which should prevent them from asserting.
|
||||
BitcastV.reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user