+AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
+ if (Bytes == 0) return *this;
+
+ Attrs[Attribute::Dereferenceable] = true;
+ DerefBytes = Bytes;
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) {
+ if (Bytes == 0)
+ return *this;
+
+ Attrs[Attribute::DereferenceableOrNull] = true;
+ DerefOrNullBytes = Bytes;
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
+ // FIXME: What if both have alignments, but they don't match?!
+ if (!Alignment)
+ Alignment = B.Alignment;
+
+ if (!StackAlignment)
+ StackAlignment = B.StackAlignment;
+
+ if (!DerefBytes)
+ DerefBytes = B.DerefBytes;
+
+ if (!DerefOrNullBytes)
+ DerefOrNullBytes = B.DerefOrNullBytes;
+
+ Attrs |= B.Attrs;
+
+ for (auto I : B.td_attrs())
+ TargetDepAttrs[I.first] = I.second;
+
+ return *this;
+}
+
+AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
+ // FIXME: What if both have alignments, but they don't match?!
+ if (B.Alignment)
+ Alignment = 0;
+
+ if (B.StackAlignment)
+ StackAlignment = 0;
+
+ if (B.DerefBytes)
+ DerefBytes = 0;
+
+ if (B.DerefOrNullBytes)
+ DerefOrNullBytes = 0;
+
+ Attrs &= ~B.Attrs;
+
+ for (auto I : B.td_attrs())
+ TargetDepAttrs.erase(I.first);
+
+ return *this;
+}
+
+bool AttrBuilder::overlaps(const AttrBuilder &B) const {
+ // First check if any of the target independent attributes overlap.
+ if ((Attrs & B.Attrs).any())
+ return true;
+
+ // Then check if any target dependent ones do.
+ for (auto I : td_attrs())
+ if (B.contains(I.first))
+ return true;
+
+ return false;
+}
+
+bool AttrBuilder::contains(StringRef A) const {
+ return TargetDepAttrs.find(A) != TargetDepAttrs.end();