I have just tried the following nesting:
using mlir::Value;
using mlir::Attribute;
PointerIntPair<PointerUnion<Value, Attribute>, 1, bool> data;
This seems to overlap the discriminant bit of PointerUnion with the single bit requested for PointerIntPair. The following then does not assert:
// getInt() returns the discriminant
data.setPointer(Value{});
assert(data.getInt() == 0);
data.setPointer(Attribute{});
assert(data.getInt() == 1);
// setInt() swaps the apparent type in the union
data.setPointer(Value{});
assert(isa<Value>(data.getPointer()));
data.setInt(1);
assert(isa<Attribute>(data.getPointer()));
Is this intended behavior or a bug? (Running this on x86_64.) A comment on PointerIntPair suggests that nesting these is actually intended to work (from llvm/ADR/PointerIntPair.h):
/// Note that PointerIntPair always puts the IntVal part in the highest bits
/// possible. For example, PointerIntPair<void*, 1, bool> will put the bit for
/// the bool into bit #2, not bit #0, which allows the low two bits to be used
/// for something else. For example, this allows:
/// PointerIntPair<PointerIntPair<void*, 1, bool>, 1, bool>
/// ... and the two bools will land in different bits.
template <typename PointerTy, unsigned IntBits, typename IntType = unsigned,
typename PtrTraits = PointerLikeTypeTraits<PointerTy>,
typename Info = PointerIntPairInfo<PointerTy, IntBits, PtrTraits>>
class PointerIntPair {