diff --git a/llvm/include/llvm/Support/TypeSize.h b/llvm/include/llvm/Support/TypeSize.h index ada98d809fc23..08ab7c9024f75 100644 --- a/llvm/include/llvm/Support/TypeSize.h +++ b/llvm/include/llvm/Support/TypeSize.h @@ -100,14 +100,22 @@ template class FixedOrScalableQuantity { : Quantity(Quantity), Scalable(Scalable) {} friend constexpr LeafTy &operator+=(LeafTy &LHS, const LeafTy &RHS) { - assert(LHS.Scalable == RHS.Scalable && "Incompatible types"); + assert((LHS.Quantity == 0 || RHS.Quantity == 0 || + LHS.Scalable == RHS.Scalable) && + "Incompatible types"); LHS.Quantity += RHS.Quantity; + if (!RHS.isZero()) + LHS.Scalable = RHS.Scalable; return LHS; } friend constexpr LeafTy &operator-=(LeafTy &LHS, const LeafTy &RHS) { - assert(LHS.Scalable == RHS.Scalable && "Incompatible types"); + assert((LHS.Quantity == 0 || RHS.Quantity == 0 || + LHS.Scalable == RHS.Scalable) && + "Incompatible types"); LHS.Quantity -= RHS.Quantity; + if (!RHS.isZero()) + LHS.Scalable = RHS.Scalable; return LHS; } @@ -315,6 +323,8 @@ class TypeSize : public details::FixedOrScalableQuantity { : FixedOrScalableQuantity(V) {} public: + constexpr TypeSize() : FixedOrScalableQuantity(0, false) {} + constexpr TypeSize(ScalarTy Quantity, bool Scalable) : FixedOrScalableQuantity(Quantity, Scalable) {} diff --git a/llvm/unittests/Support/TypeSizeTest.cpp b/llvm/unittests/Support/TypeSizeTest.cpp index 33169a3d8b198..503dc5d99b182 100644 --- a/llvm/unittests/Support/TypeSizeTest.cpp +++ b/llvm/unittests/Support/TypeSizeTest.cpp @@ -81,6 +81,27 @@ static_assert(INT64_C(2) * TSFixed32 == TypeSize::getFixed(64)); static_assert(UINT64_C(2) * TSFixed32 == TypeSize::getFixed(64)); static_assert(alignTo(TypeSize::getFixed(7), 8) == TypeSize::getFixed(8)); +static_assert(TypeSize() == TypeSize::getFixed(0)); +static_assert(TypeSize::getFixed(0) != TypeSize::getScalable(0)); +static_assert(TypeSize::getFixed(0).isZero()); +static_assert(TypeSize::getScalable(0).isZero()); +static_assert(TypeSize::getFixed(0) == + (TypeSize::getFixed(4) - TypeSize::getFixed(4))); +static_assert(TypeSize::getScalable(0) == + (TypeSize::getScalable(4) - TypeSize::getScalable(4))); +static_assert(TypeSize::getFixed(0) + TypeSize::getScalable(8) == + TypeSize::getScalable(8)); +static_assert(TypeSize::getScalable(8) + TypeSize::getFixed(0) == + TypeSize::getScalable(8)); +static_assert(TypeSize::getFixed(8) + TypeSize::getScalable(0) == + TypeSize::getFixed(8)); +static_assert(TypeSize::getScalable(0) + TypeSize::getFixed(8) == + TypeSize::getFixed(8)); +static_assert(TypeSize::getScalable(8) - TypeSize::getFixed(0) == + TypeSize::getScalable(8)); +static_assert(TypeSize::getFixed(8) - TypeSize::getScalable(0) == + TypeSize::getFixed(8)); + TEST(TypeSize, FailIncompatibleTypes) { EXPECT_DEBUG_DEATH(TypeSize::getFixed(8) + TypeSize::getScalable(8), "Incompatible types");