X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FVMCore%2FAttributes.cpp;h=635ad1409ffa220825054dccc974c67a83241681;hp=e20fa6b43272c8ffdda6eb7d7d1ccf2ddc246c94;hb=c416795feaaa2052f7b46fa7a3f9b6ec3751b1eb;hpb=8e635dbc78996bc18cf13b4806706cf3529ea646 diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp index e20fa6b4327..635ad1409ff 100644 --- a/lib/VMCore/Attributes.cpp +++ b/lib/VMCore/Attributes.cpp @@ -29,10 +29,19 @@ using namespace llvm; Attributes::Attributes(uint64_t Val) : Attrs(Val) {} -Attributes::Attributes(Attribute::AttrConst Val) : Attrs(Val.v) {} +Attributes::Attributes(LLVMContext &C, AttrVal Val) + : Attrs(Attributes::get(Attributes::Builder().addAttribute(Val)).Attrs) {} Attributes::Attributes(AttributesImpl *A) : Attrs(A->Bits) {} +Attributes::Attributes(const Attributes &A) : Attrs(A.Attrs) {} + +// FIXME: This is temporary until we have implemented the uniquified version of +// AttributesImpl. +Attributes Attributes::get(Attributes::Builder &B) { + return Attributes(B.Bits); +} + Attributes Attributes::get(LLVMContext &Context, Attributes::Builder &B) { // If there are no attributes, return an empty Attributes class. if (B.Bits == 0) @@ -57,94 +66,17 @@ Attributes Attributes::get(LLVMContext &Context, Attributes::Builder &B) { return Attributes(PA); } +bool Attributes::hasAttribute(AttrVal Val) const { + return Attrs.hasAttribute(Val); +} + bool Attributes::hasAttributes(const Attributes &A) const { return Attrs.hasAttributes(A); } -bool Attributes::hasAddressSafetyAttr() const { - return Attrs.hasAttribute(Attribute::AddressSafety_i); -} -bool Attributes::hasAlignmentAttr() const { - return Attrs.hasAttribute(Attribute::Alignment_i); -} -bool Attributes::hasAlwaysInlineAttr() const { - return Attrs.hasAttribute(Attribute::AlwaysInline_i); -} -bool Attributes::hasByValAttr() const { - return Attrs.hasAttribute(Attribute::ByVal_i); -} -bool Attributes::hasInlineHintAttr() const { - return Attrs.hasAttribute(Attribute::InlineHint_i); -} -bool Attributes::hasInRegAttr() const { - return Attrs.hasAttribute(Attribute::InReg_i); -} -bool Attributes::hasNakedAttr() const { - return Attrs.hasAttribute(Attribute::Naked_i); -} -bool Attributes::hasNestAttr() const { - return Attrs.hasAttribute(Attribute::Nest_i); -} -bool Attributes::hasNoAliasAttr() const { - return Attrs.hasAttribute(Attribute::NoAlias_i); -} -bool Attributes::hasNoCaptureAttr() const { - return Attrs.hasAttribute(Attribute::NoCapture_i); -} -bool Attributes::hasNoImplicitFloatAttr() const { - return Attrs.hasAttribute(Attribute::NoImplicitFloat_i); -} -bool Attributes::hasNoInlineAttr() const { - return Attrs.hasAttribute(Attribute::NoInline_i); -} -bool Attributes::hasNonLazyBindAttr() const { - return Attrs.hasAttribute(Attribute::NonLazyBind_i); -} -bool Attributes::hasNoRedZoneAttr() const { - return Attrs.hasAttribute(Attribute::NoRedZone_i); -} -bool Attributes::hasNoReturnAttr() const { - return Attrs.hasAttribute(Attribute::NoReturn_i); -} -bool Attributes::hasNoUnwindAttr() const { - return Attrs.hasAttribute(Attribute::NoUnwind_i); -} -bool Attributes::hasOptimizeForSizeAttr() const { - return Attrs.hasAttribute(Attribute::OptimizeForSize_i); -} -bool Attributes::hasReadNoneAttr() const { - return Attrs.hasAttribute(Attribute::ReadNone_i); -} -bool Attributes::hasReadOnlyAttr() const { - return Attrs.hasAttribute(Attribute::ReadOnly_i); -} -bool Attributes::hasReturnsTwiceAttr() const { - return Attrs.hasAttribute(Attribute::ReturnsTwice_i); -} -bool Attributes::hasSExtAttr() const { - return Attrs.hasAttribute(Attribute::SExt_i); -} -bool Attributes::hasStackAlignmentAttr() const { - return Attrs.hasAttribute(Attribute::StackAlignment_i); -} -bool Attributes::hasStackProtectAttr() const { - return Attrs.hasAttribute(Attribute::StackProtect_i); -} -bool Attributes::hasStackProtectReqAttr() const { - return Attrs.hasAttribute(Attribute::StackProtectReq_i); -} -bool Attributes::hasStructRetAttr() const { - return Attrs.hasAttribute(Attribute::StructRet_i); -} -bool Attributes::hasUWTableAttr() const { - return Attrs.hasAttribute(Attribute::UWTable_i); -} -bool Attributes::hasZExtAttr() const { - return Attrs.hasAttribute(Attribute::ZExt_i); -} /// This returns the alignment field of an attribute as a byte alignment value. unsigned Attributes::getAlignment() const { - if (!hasAlignmentAttr()) + if (!hasAttribute(Attributes::Alignment)) return 0; return 1U << ((Attrs.getAlignment() >> 16) - 1); } @@ -152,7 +84,7 @@ unsigned Attributes::getAlignment() const { /// This returns the stack alignment field of an attribute as a byte alignment /// value. unsigned Attributes::getStackAlignment() const { - if (!hasStackAlignmentAttr()) + if (!hasAttribute(Attributes::StackAlignment)) return 0; return 1U << ((Attrs.getStackAlignment() >> 26) - 1); } @@ -161,26 +93,13 @@ bool Attributes::isEmptyOrSingleton() const { return Attrs.isEmptyOrSingleton(); } -Attributes Attributes::operator | (const Attributes &A) const { - return Attributes(Raw() | A.Raw()); -} Attributes Attributes::operator & (const Attributes &A) const { return Attributes(Raw() & A.Raw()); } -Attributes Attributes::operator ^ (const Attributes &A) const { - return Attributes(Raw() ^ A.Raw()); -} -Attributes &Attributes::operator |= (const Attributes &A) { - Attrs.Bits |= A.Raw(); - return *this; -} Attributes &Attributes::operator &= (const Attributes &A) { Attrs.Bits &= A.Raw(); return *this; } -Attributes Attributes::operator ~ () const { - return Attributes(~Raw()); -} uint64_t Attributes::Raw() const { return Attrs.Bits; @@ -189,82 +108,80 @@ uint64_t Attributes::Raw() const { Attributes Attributes::typeIncompatible(Type *Ty) { Attributes::Builder Incompatible; - if (!Ty->isIntegerTy()) { + if (!Ty->isIntegerTy()) // Attributes that only apply to integers. - Incompatible.addSExtAttr(); - Incompatible.addZExtAttr(); - } + Incompatible.addAttribute(Attributes::SExt) + .addAttribute(Attributes::ZExt); - if (!Ty->isPointerTy()) { + if (!Ty->isPointerTy()) // Attributes that only apply to pointers. - Incompatible.addByValAttr(); - Incompatible.addNestAttr(); - Incompatible.addNoAliasAttr(); - Incompatible.addNoCaptureAttr(); - Incompatible.addStructRetAttr(); - } + Incompatible.addAttribute(Attributes::ByVal) + .addAttribute(Attributes::Nest) + .addAttribute(Attributes::NoAlias) + .addAttribute(Attributes::NoCapture) + .addAttribute(Attributes::StructRet); return Attributes(Incompatible.Bits); // FIXME: Use Attributes::get(). } std::string Attributes::getAsString() const { std::string Result; - if (hasZExtAttr()) + if (hasAttribute(Attributes::ZExt)) Result += "zeroext "; - if (hasSExtAttr()) + if (hasAttribute(Attributes::SExt)) Result += "signext "; - if (hasNoReturnAttr()) + if (hasAttribute(Attributes::NoReturn)) Result += "noreturn "; - if (hasNoUnwindAttr()) + if (hasAttribute(Attributes::NoUnwind)) Result += "nounwind "; - if (hasUWTableAttr()) + if (hasAttribute(Attributes::UWTable)) Result += "uwtable "; - if (hasReturnsTwiceAttr()) + if (hasAttribute(Attributes::ReturnsTwice)) Result += "returns_twice "; - if (hasInRegAttr()) + if (hasAttribute(Attributes::InReg)) Result += "inreg "; - if (hasNoAliasAttr()) + if (hasAttribute(Attributes::NoAlias)) Result += "noalias "; - if (hasNoCaptureAttr()) + if (hasAttribute(Attributes::NoCapture)) Result += "nocapture "; - if (hasStructRetAttr()) + if (hasAttribute(Attributes::StructRet)) Result += "sret "; - if (hasByValAttr()) + if (hasAttribute(Attributes::ByVal)) Result += "byval "; - if (hasNestAttr()) + if (hasAttribute(Attributes::Nest)) Result += "nest "; - if (hasReadNoneAttr()) + if (hasAttribute(Attributes::ReadNone)) Result += "readnone "; - if (hasReadOnlyAttr()) + if (hasAttribute(Attributes::ReadOnly)) Result += "readonly "; - if (hasOptimizeForSizeAttr()) + if (hasAttribute(Attributes::OptimizeForSize)) Result += "optsize "; - if (hasNoInlineAttr()) + if (hasAttribute(Attributes::NoInline)) Result += "noinline "; - if (hasInlineHintAttr()) + if (hasAttribute(Attributes::InlineHint)) Result += "inlinehint "; - if (hasAlwaysInlineAttr()) + if (hasAttribute(Attributes::AlwaysInline)) Result += "alwaysinline "; - if (hasStackProtectAttr()) + if (hasAttribute(Attributes::StackProtect)) Result += "ssp "; - if (hasStackProtectReqAttr()) + if (hasAttribute(Attributes::StackProtectReq)) Result += "sspreq "; - if (hasNoRedZoneAttr()) + if (hasAttribute(Attributes::NoRedZone)) Result += "noredzone "; - if (hasNoImplicitFloatAttr()) + if (hasAttribute(Attributes::NoImplicitFloat)) Result += "noimplicitfloat "; - if (hasNakedAttr()) + if (hasAttribute(Attributes::Naked)) Result += "naked "; - if (hasNonLazyBindAttr()) + if (hasAttribute(Attributes::NonLazyBind)) Result += "nonlazybind "; - if (hasAddressSafetyAttr()) + if (hasAttribute(Attributes::AddressSafety)) Result += "address_safety "; - if (hasStackAlignmentAttr()) { + if (hasAttribute(Attributes::StackAlignment)) { Result += "alignstack("; Result += utostr(getStackAlignment()); Result += ") "; } - if (hasAlignmentAttr()) { + if (hasAttribute(Attributes::Alignment)) { Result += "align "; Result += utostr(getAlignment()); Result += " "; @@ -279,178 +196,117 @@ std::string Attributes::getAsString() const { // Attributes::Builder Implementation //===----------------------------------------------------------------------===// -void Attributes::Builder::addAddressSafetyAttr() { - Bits |= Attribute::AddressSafety_i; -} -void Attributes::Builder::addAlwaysInlineAttr() { - Bits |= Attribute::AlwaysInline_i; -} -void Attributes::Builder::addByValAttr() { - Bits |= Attribute::ByVal_i; -} -void Attributes::Builder::addInlineHintAttr() { - Bits |= Attribute::InlineHint_i; -} -void Attributes::Builder::addInRegAttr() { - Bits |= Attribute::InReg_i; -} -void Attributes::Builder::addNakedAttr() { - Bits |= Attribute::Naked_i; -} -void Attributes::Builder::addNestAttr() { - Bits |= Attribute::Nest_i; -} -void Attributes::Builder::addNoAliasAttr() { - Bits |= Attribute::NoAlias_i; -} -void Attributes::Builder::addNoCaptureAttr() { - Bits |= Attribute::NoCapture_i; -} -void Attributes::Builder::addNoImplicitFloatAttr() { - Bits |= Attribute::NoImplicitFloat_i; -} -void Attributes::Builder::addNoInlineAttr() { - Bits |= Attribute::NoInline_i; -} -void Attributes::Builder::addNonLazyBindAttr() { - Bits |= Attribute::NonLazyBind_i; -} -void Attributes::Builder::addNoRedZoneAttr() { - Bits |= Attribute::NoRedZone_i; -} -void Attributes::Builder::addNoReturnAttr() { - Bits |= Attribute::NoReturn_i; -} -void Attributes::Builder::addNoUnwindAttr() { - Bits |= Attribute::NoUnwind_i; -} -void Attributes::Builder::addOptimizeForSizeAttr() { - Bits |= Attribute::OptimizeForSize_i; -} -void Attributes::Builder::addReadNoneAttr() { - Bits |= Attribute::ReadNone_i; -} -void Attributes::Builder::addReadOnlyAttr() { - Bits |= Attribute::ReadOnly_i; -} -void Attributes::Builder::addReturnsTwiceAttr() { - Bits |= Attribute::ReturnsTwice_i; -} -void Attributes::Builder::addSExtAttr() { - Bits |= Attribute::SExt_i; -} -void Attributes::Builder::addStackProtectAttr() { - Bits |= Attribute::StackProtect_i; -} -void Attributes::Builder::addStackProtectReqAttr() { - Bits |= Attribute::StackProtectReq_i; -} -void Attributes::Builder::addStructRetAttr() { - Bits |= Attribute::StructRet_i; -} -void Attributes::Builder::addUWTableAttr() { - Bits |= Attribute::UWTable_i; +Attributes::Builder &Attributes::Builder:: +addAttribute(Attributes::AttrVal Val) { + Bits |= AttributesImpl::getAttrMask(Val); + return *this; } -void Attributes::Builder::addZExtAttr() { - Bits |= Attribute::ZExt_i; + +Attributes::Builder &Attributes::Builder::addRawValue(uint64_t Val) { + Bits |= Val; + return *this; } -void Attributes::Builder::addAlignmentAttr(unsigned Align) { - if (Align == 0) return; +Attributes::Builder &Attributes::Builder::addAlignmentAttr(unsigned Align) { + if (Align == 0) return *this; assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); assert(Align <= 0x40000000 && "Alignment too large."); Bits |= (Log2_32(Align) + 1) << 16; + return *this; } -void Attributes::Builder::addStackAlignmentAttr(unsigned Align) { +Attributes::Builder &Attributes::Builder::addStackAlignmentAttr(unsigned Align){ // Default alignment, allow the target to define how to align it. - if (Align == 0) return; + if (Align == 0) return *this; assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); assert(Align <= 0x100 && "Alignment too large."); Bits |= (Log2_32(Align) + 1) << 26; + return *this; } -void Attributes::Builder::removeAddressSafetyAttr() { - Bits &= ~Attribute::AddressSafety_i; -} -void Attributes::Builder::removeAlwaysInlineAttr() { - Bits &= ~Attribute::AlwaysInline_i; -} -void Attributes::Builder::removeByValAttr() { - Bits &= ~Attribute::ByVal_i; -} -void Attributes::Builder::removeInlineHintAttr() { - Bits &= ~Attribute::InlineHint_i; -} -void Attributes::Builder::removeInRegAttr() { - Bits &= ~Attribute::InReg_i; -} -void Attributes::Builder::removeNakedAttr() { - Bits &= ~Attribute::Naked_i; -} -void Attributes::Builder::removeNestAttr() { - Bits &= ~Attribute::Nest_i; -} -void Attributes::Builder::removeNoAliasAttr() { - Bits &= ~Attribute::NoAlias_i; -} -void Attributes::Builder::removeNoCaptureAttr() { - Bits &= ~Attribute::NoCapture_i; -} -void Attributes::Builder::removeNoImplicitFloatAttr() { - Bits &= ~Attribute::NoImplicitFloat_i; -} -void Attributes::Builder::removeNoInlineAttr() { - Bits &= ~Attribute::NoInline_i; -} -void Attributes::Builder::removeNonLazyBindAttr() { - Bits &= ~Attribute::NonLazyBind_i; -} -void Attributes::Builder::removeNoRedZoneAttr() { - Bits &= ~Attribute::NoRedZone_i; -} -void Attributes::Builder::removeNoReturnAttr() { - Bits &= ~Attribute::NoReturn_i; -} -void Attributes::Builder::removeNoUnwindAttr() { - Bits &= ~Attribute::NoUnwind_i; -} -void Attributes::Builder::removeOptimizeForSizeAttr() { - Bits &= ~Attribute::OptimizeForSize_i; -} -void Attributes::Builder::removeReadNoneAttr() { - Bits &= ~Attribute::ReadNone_i; +Attributes::Builder &Attributes::Builder:: +removeAttribute(Attributes::AttrVal Val) { + Bits &= ~AttributesImpl::getAttrMask(Val); + return *this; } -void Attributes::Builder::removeReadOnlyAttr() { - Bits &= ~Attribute::ReadOnly_i; + +Attributes::Builder &Attributes::Builder::addAttributes(const Attributes &A) { + Bits |= A.Raw(); + return *this; } -void Attributes::Builder::removeReturnsTwiceAttr() { - Bits &= ~Attribute::ReturnsTwice_i; + +Attributes::Builder &Attributes::Builder::removeAttributes(const Attributes &A){ + Bits &= ~A.Raw(); + return *this; } -void Attributes::Builder::removeSExtAttr() { - Bits &= ~Attribute::SExt_i; + +bool Attributes::Builder::hasAttribute(Attributes::AttrVal A) const { + return Bits & AttributesImpl::getAttrMask(A); } -void Attributes::Builder::removeStackProtectAttr() { - Bits &= ~Attribute::StackProtect_i; + +bool Attributes::Builder::hasAttributes() const { + return Bits != 0; } -void Attributes::Builder::removeStackProtectReqAttr() { - Bits &= ~Attribute::StackProtectReq_i; +bool Attributes::Builder::hasAttributes(const Attributes &A) const { + return Bits & A.Raw(); } -void Attributes::Builder::removeStructRetAttr() { - Bits &= ~Attribute::StructRet_i; +bool Attributes::Builder::hasAlignmentAttr() const { + return Bits & AttributesImpl::getAttrMask(Attributes::Alignment); } -void Attributes::Builder::removeUWTableAttr() { - Bits &= ~Attribute::UWTable_i; + +uint64_t Attributes::Builder::getAlignment() const { + if (!hasAlignmentAttr()) + return 0; + return 1U << + (((Bits & AttributesImpl::getAttrMask(Attributes::Alignment)) >> 16) - 1); } -void Attributes::Builder::removeZExtAttr() { - Bits &= ~Attribute::ZExt_i; + +uint64_t Attributes::Builder::getStackAlignment() const { + if (!hasAlignmentAttr()) + return 0; + return 1U << + (((Bits & AttributesImpl::getAttrMask(Attributes::StackAlignment))>>26)-1); } //===----------------------------------------------------------------------===// // AttributeImpl Definition //===----------------------------------------------------------------------===// +uint64_t AttributesImpl::getAttrMask(uint64_t Val) { + switch (Val) { + case Attributes::None: return 0; + case Attributes::ZExt: return 1 << 0; + case Attributes::SExt: return 1 << 1; + case Attributes::NoReturn: return 1 << 2; + case Attributes::InReg: return 1 << 3; + case Attributes::StructRet: return 1 << 4; + case Attributes::NoUnwind: return 1 << 5; + case Attributes::NoAlias: return 1 << 6; + case Attributes::ByVal: return 1 << 7; + case Attributes::Nest: return 1 << 8; + case Attributes::ReadNone: return 1 << 9; + case Attributes::ReadOnly: return 1 << 10; + case Attributes::NoInline: return 1 << 11; + case Attributes::AlwaysInline: return 1 << 12; + case Attributes::OptimizeForSize: return 1 << 13; + case Attributes::StackProtect: return 1 << 14; + case Attributes::StackProtectReq: return 1 << 15; + case Attributes::Alignment: return 31 << 16; + case Attributes::NoCapture: return 1 << 21; + case Attributes::NoRedZone: return 1 << 22; + case Attributes::NoImplicitFloat: return 1 << 23; + case Attributes::Naked: return 1 << 24; + case Attributes::InlineHint: return 1 << 25; + case Attributes::StackAlignment: return 7 << 26; + case Attributes::ReturnsTwice: return 1 << 29; + case Attributes::UWTable: return 1 << 30; + case Attributes::NonLazyBind: return 1U << 31; + case Attributes::AddressSafety: return 1ULL << 32; + } + llvm_unreachable("Unsupported attribute type"); +} + bool AttributesImpl::hasAttribute(uint64_t A) const { - return (Bits & A) != 0; + return (Bits & getAttrMask(A)) != 0; } bool AttributesImpl::hasAttributes() const { @@ -462,11 +318,11 @@ bool AttributesImpl::hasAttributes(const Attributes &A) const { } uint64_t AttributesImpl::getAlignment() const { - return Bits & Attribute::Alignment_i; + return Bits & getAttrMask(Attributes::Alignment); } uint64_t AttributesImpl::getStackAlignment() const { - return Bits & Attribute::StackAlignment_i; + return Bits & getAttrMask(Attributes::StackAlignment); } bool AttributesImpl::isEmptyOrSingleton() const { @@ -624,18 +480,28 @@ Attributes AttrListPtr::getAttributes(unsigned Idx) const { /// hasAttrSomewhere - Return true if the specified attribute is set for at /// least one parameter or for the return value. -bool AttrListPtr::hasAttrSomewhere(Attributes Attr) const { +bool AttrListPtr::hasAttrSomewhere(Attributes::AttrVal Attr) const { if (AttrList == 0) return false; - + const SmallVector &Attrs = AttrList->Attrs; for (unsigned i = 0, e = Attrs.size(); i != e; ++i) - if (Attrs[i].Attrs.hasAttributes(Attr)) + if (Attrs[i].Attrs.hasAttribute(Attr)) return true; return false; } +unsigned AttrListPtr::getNumAttrs() const { + return AttrList ? AttrList->Attrs.size() : 0; +} + +Attributes &AttrListPtr::getAttributesAtIndex(unsigned i) const { + assert(AttrList && "Trying to get an attribute from an empty list!"); + assert(i < AttrList->Attrs.size() && "Index out of range!"); + return AttrList->Attrs[i].Attrs; +} -AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const { +AttrListPtr AttrListPtr::addAttr(LLVMContext &C, unsigned Idx, + Attributes Attrs) const { Attributes OldAttrs = getAttributes(Idx); #ifndef NDEBUG // FIXME it is not obvious how this should work for alignment. @@ -646,8 +512,9 @@ AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const { "Attempt to change alignment!"); #endif - Attributes NewAttrs = OldAttrs | Attrs; - if (NewAttrs == OldAttrs) + Attributes::Builder NewAttrs = + Attributes::Builder(OldAttrs).addAttributes(Attrs); + if (NewAttrs == Attributes::Builder(OldAttrs)) return *this; SmallVector NewAttrList; @@ -662,7 +529,9 @@ AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const { // If there are attributes already at this index, merge them in. if (i != e && OldAttrList[i].Index == Idx) { - Attrs |= OldAttrList[i].Attrs; + Attrs = + Attributes::get(C, Attributes::Builder(Attrs). + addAttributes(OldAttrList[i].Attrs)); ++i; } @@ -676,17 +545,20 @@ AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const { return get(NewAttrList); } -AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const { +AttrListPtr AttrListPtr::removeAttr(LLVMContext &C, unsigned Idx, + Attributes Attrs) const { #ifndef NDEBUG // FIXME it is not obvious how this should work for alignment. // For now, say we can't pass in alignment, which no current use does. - assert(!Attrs.hasAlignmentAttr() && "Attempt to exclude alignment!"); + assert(!Attrs.hasAttribute(Attributes::Alignment) && + "Attempt to exclude alignment!"); #endif if (AttrList == 0) return AttrListPtr(); Attributes OldAttrs = getAttributes(Idx); - Attributes NewAttrs = OldAttrs & ~Attrs; - if (NewAttrs == OldAttrs) + Attributes::Builder NewAttrs = + Attributes::Builder(OldAttrs).removeAttributes(Attrs); + if (NewAttrs == Attributes::Builder(OldAttrs)) return *this; SmallVector NewAttrList; @@ -699,7 +571,8 @@ AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const { // If there are attributes already at this index, merge them in. assert(OldAttrList[i].Index == Idx && "Attribute isn't set?"); - Attrs = OldAttrList[i].Attrs & ~Attrs; + Attrs = Attributes::get(C, Attributes::Builder(OldAttrList[i].Attrs). + removeAttributes(Attrs)); ++i; if (Attrs) // If any attributes left for this parameter, add them. NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));