================
@@ -451,6 +452,119 @@ class StmtComparer {
 };
 } // namespace
 
+namespace {
+enum class AttrComparisonKind { Equal, NotEqual };
+
+/// Represents the result of comparing the attribute sets on two decls. If the
+/// sets are incompatible, A1/A2 point to the offending attributes.
+struct AttrComparisonResult {
+  AttrComparisonKind Kind = AttrComparisonKind::Equal;
+  const Attr *A1 = nullptr, *A2 = nullptr;
+};
+} // namespace
+
+static AttrComparisonResult
+areAvailabilityAttrsEqual(const AvailabilityAttr *A1,
+                          const AvailabilityAttr *A2) {
+  if (A1->getPlatform() == A2->getPlatform() &&
+      A1->getIntroduced() == A2->getIntroduced() &&
+      A1->getDeprecated() == A2->getDeprecated() &&
+      A1->getObsoleted() == A2->getObsoleted() &&
+      A1->getUnavailable() == A2->getUnavailable() &&
+      A1->getMessage() == A2->getMessage() &&
+      A1->getReplacement() == A2->getReplacement() &&
+      A1->getStrict() == A2->getStrict() &&
+      A1->getPriority() == A2->getPriority() &&
+      A1->getEnvironment() == A2->getEnvironment())
+    return {AttrComparisonKind::Equal};
+  return {AttrComparisonKind::NotEqual, A1, A2};
+}
+
+static AttrComparisonResult
+areEnumExtensibilityAttrsEqual(const EnumExtensibilityAttr *A1,
+                               const EnumExtensibilityAttr *A2) {
+  if (A1->getExtensibility() == A2->getExtensibility())
+    return {AttrComparisonKind::Equal};
+  return {AttrComparisonKind::NotEqual, A1, A2};
+}
+
+static AttrComparisonResult areAttrsEqual(const Attr *A1, const Attr *A2) {
+  auto Kind1 = A1->getKind(), Kind2 = A2->getKind();
+  if (Kind1 != Kind2)
+    return {AttrComparisonKind::NotEqual, A1, A2};
+
+  switch (Kind1) {
+  case attr::Availability:
+    return areAvailabilityAttrsEqual(cast<AvailabilityAttr>(A1),
+                                     cast<AvailabilityAttr>(A2));
+  case attr::EnumExtensibility:
+    return areEnumExtensibilityAttrsEqual(cast<EnumExtensibilityAttr>(A1),
+                                          cast<EnumExtensibilityAttr>(A2));
+  case attr::Unused:
+    return {AttrComparisonKind::Equal};
+  default:
+    llvm_unreachable("unexpected attr kind");
+  }
+}
+
+static bool compareAttrKind(const Attr *A1, const Attr *A2) {
+  return A1->getKind() < A2->getKind();
+}
+
+namespace {
+using AttrSet = std::multiset<const Attr *, decltype(&compareAttrKind)>;
----------------
AaronBallman wrote:

Would a `SmallPtrSet` make more sense?

https://github.com/llvm/llvm-project/pull/168769
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to