Index: lib/IR/Attributes.cpp =================================================================== --- lib/IR/Attributes.cpp +++ lib/IR/Attributes.cpp @@ -543,17 +543,17 @@ AttributeSet AttributeSet::removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const { if (!hasAttribute(Kind)) return *this; - AttrBuilder B; - B.addAttribute(Kind); - return removeAttributes(C, B); + AttrBuilder B(*this); + B.removeAttribute(Kind); + return get(C, B); } AttributeSet AttributeSet::removeAttribute(LLVMContext &C, StringRef Kind) const { if (!hasAttribute(Kind)) return *this; - AttrBuilder B; - B.addAttribute(Kind); - return removeAttributes(C, B); + AttrBuilder B(*this); + B.removeAttribute(Kind); + return get(C, B); } AttributeSet AttributeSet::removeAttributes(LLVMContext &C, @@ -1098,17 +1098,37 @@ AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const { if (!hasAttribute(Index, Kind)) return *this; - AttrBuilder B; - B.addAttribute(Kind); - return removeAttributes(C, Index, B); + if (!pImpl) + return AttributeList(); + + Index = attrIdxToArrayIdx(Index); + SmallVector AttrSets(this->begin(), this->end()); + if (Index >= AttrSets.size()) + AttrSets.resize(Index + 1); + + AttrBuilder B(AttrSets[Index]); + B.removeAttribute(Kind); + AttrSets[Index] = AttributeSet::get(C, B); + + return getImpl(C, AttrSets); } AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const { if (!hasAttribute(Index, Kind)) return *this; - AttrBuilder B; - B.addAttribute(Kind); - return removeAttributes(C, Index, B); + if (!pImpl) + return AttributeList(); + + Index = attrIdxToArrayIdx(Index); + SmallVector AttrSets(this->begin(), this->end()); + if (Index >= AttrSets.size()) + AttrSets.resize(Index + 1); + + AttrBuilder B(AttrSets[Index]); + B.removeAttribute(Kind); + AttrSets[Index] = AttributeSet::get(C, B); + + return getImpl(C, AttrSets); } AttributeList @@ -1117,10 +1137,6 @@ if (!pImpl) return AttributeList(); - // 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(!AttrsToRemove.hasAlignmentAttr() && "Attempt to change alignment!"); - Index = attrIdxToArrayIdx(Index); SmallVector AttrSets(this->begin(), this->end()); if (Index >= AttrSets.size()) Index: unittests/IR/AttributesTest.cpp =================================================================== --- unittests/IR/AttributesTest.cpp +++ unittests/IR/AttributesTest.cpp @@ -63,6 +63,23 @@ EXPECT_TRUE(AL.hasFnAttribute(Attribute::NoReturn)); } +TEST(Attributes, RemoveAlign) { + LLVMContext C; + AttrBuilder B; + B.addAttribute(Attribute::getWithAlignment(C, 8)); + AttributeSet AS = AttributeSet::get(C, B); + EXPECT_TRUE(AS.getAlignment() == 8); + AS = AS.removeAttribute(C, Attribute::Alignment); + EXPECT_TRUE(AS.getAlignment() == 0); + AttributeList AL; + AL = AL.addParamAttributes(C, 0, B); + EXPECT_TRUE(AL.hasParamAttrs(0)); + EXPECT_TRUE(AL.hasParamAttr(0, Attribute::Alignment)); + EXPECT_TRUE(AL.getParamAlignment(0) == 8); + AL = AL.removeParamAttribute(C, 0, Attribute::Alignment); + EXPECT_FALSE(AL.hasParamAttr(0, Attribute::Alignment)); +} + TEST(Attributes, AddMatchingAlignAttr) { LLVMContext C; AttributeList AL;