================
@@ -16,33 +16,101 @@
 #include "clang/AST/Decl.h"
 #include "clang/Basic/TargetInfo.h"
 
-namespace clang {
+namespace {
+
+struct AvailabilitySet {
+  llvm::SmallVector<clang::AvailabilityInfo> Availabilities;
+  bool UnconditionallyDeprecated = false;
+  bool UnconditionallyUnavailable = false;
 
-AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *Decl) {
-  ASTContext &Context = Decl->getASTContext();
-  StringRef PlatformName = Context.getTargetInfo().getPlatformName();
-  AvailabilityInfo Availability;
+  void insert(clang::AvailabilityInfo &&Availability) {
+    auto *Found = getForPlatform(Availability.Domain);
+    if (Found)
+      Found->mergeWith(std::move(Availability));
+    else
+      Availabilities.emplace_back(std::move(Availability));
+  }
+
+  clang::AvailabilityInfo *getForPlatform(llvm::StringRef Domain) {
+    auto *It = llvm::find_if(Availabilities,
+                             [Domain](const clang::AvailabilityInfo &Info) {
+                               return Domain.compare(Info.Domain) == 0;
+                             });
+    return It == Availabilities.end() ? nullptr : It;
+  }
+};
 
+static void createInfoForDecl(const clang::Decl *Decl,
+                              AvailabilitySet &Availabilities) {
   // Collect availability attributes from all redeclarations.
   for (const auto *RD : Decl->redecls()) {
-    for (const auto *A : RD->specific_attrs<AvailabilityAttr>()) {
-      if (A->getPlatform()->getName() != PlatformName)
-        continue;
-      Availability = AvailabilityInfo(
+    for (const auto *A : RD->specific_attrs<clang::AvailabilityAttr>()) {
+      Availabilities.insert(clang::AvailabilityInfo(
           A->getPlatform()->getName(), A->getIntroduced(), A->getDeprecated(),
-          A->getObsoleted(), A->getUnavailable(), false, false);
-      break;
+          A->getObsoleted(), A->getUnavailable(), false, false));
     }
 
-    if (const auto *A = RD->getAttr<UnavailableAttr>())
+    if (const auto *A = RD->getAttr<clang::UnavailableAttr>())
       if (!A->isImplicit())
-        Availability.UnconditionallyUnavailable = true;
+        Availabilities.UnconditionallyUnavailable = true;
 
-    if (const auto *A = RD->getAttr<DeprecatedAttr>())
+    if (const auto *A = RD->getAttr<clang::DeprecatedAttr>())
       if (!A->isImplicit())
-        Availability.UnconditionallyDeprecated = true;
+        Availabilities.UnconditionallyDeprecated = true;
+  }
+}
+
+} // namespace
+
+namespace clang {
+
+void AvailabilityInfo::mergeWith(AvailabilityInfo Other) {
+  if (isDefault() && Other.isDefault())
+    return;
+
+  if (Domain.empty())
+    Domain = Other.Domain;
+
+  UnconditionallyUnavailable |= Other.UnconditionallyUnavailable;
+  UnconditionallyDeprecated |= Other.UnconditionallyDeprecated;
+  Unavailable |= Other.Unavailable;
+
+  Introduced = std::max(Introduced, Other.Introduced);
+
+  // Default VersionTuple is 0.0.0 so if both are non default let's pick the
+  // smallest version number, otherwise select the one that is non-zero if 
there
+  // is one.
+  if (!Deprecated.empty() && !Other.Deprecated.empty())
+    Deprecated = std::min(Deprecated, Other.Deprecated);
+  else
+    Deprecated = std::max(Deprecated, Other.Deprecated);
+
+  if (!Obsoleted.empty() && !Other.Obsoleted.empty())
+    Obsoleted = std::min(Obsoleted, Other.Obsoleted);
+  else
+    Obsoleted = std::max(Obsoleted, Other.Obsoleted);
+}
+
+AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *D) {
+  AvailabilitySet Availabilities;
+  createInfoForDecl(D, Availabilities);
+  // Traverse
----------------
cyndyishida wrote:

nit: I think this can be removed

https://github.com/llvm/llvm-project/pull/103040
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to