rdwampler created this revision.

https://reviews.llvm.org/D33478

Files:
  test/Index/availability.c
  tools/libclang/CIndex.cpp

Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -7200,15 +7200,12 @@
   return Out;
 }
 
-static int getCursorPlatformAvailabilityForDecl(const Decl *D,
-                                                int *always_deprecated,
-                                                CXString *deprecated_message,
-                                                int *always_unavailable,
-                                                CXString *unavailable_message,
-                                           CXPlatformAvailability *availability,
-                                                int availability_size) {
+static void getCursorPlatformAvailabilityForDecl(
+    const Decl *D, int *always_deprecated, CXString *deprecated_message,
+    int *always_unavailable, CXString *unavailable_message,
+    SmallVectorImpl<AvailabilityAttr *> &AvailabilityAttrs) {
   bool HadAvailAttr = false;
-  int N = 0;
+  ASTContext &Ctx = D->getASTContext();
   for (auto A : D->attrs()) {
     if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(A)) {
       HadAvailAttr = true;
@@ -7220,7 +7217,7 @@
       }
       continue;
     }
-    
+
     if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(A)) {
       HadAvailAttr = true;
       if (always_unavailable)
@@ -7231,38 +7228,71 @@
       }
       continue;
     }
-    
+
     if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(A)) {
+      AvailabilityAttrs.push_back(Avail);
       HadAvailAttr = true;
-      if (N < availability_size) {
-        availability[N].Platform
-          = cxstring::createDup(Avail->getPlatform()->getName());
-        availability[N].Introduced = convertVersion(Avail->getIntroduced());
-        availability[N].Deprecated = convertVersion(Avail->getDeprecated());
-        availability[N].Obsoleted = convertVersion(Avail->getObsoleted());
-        availability[N].Unavailable = Avail->getUnavailable();
-        availability[N].Message = cxstring::createDup(Avail->getMessage());
-      }
-      ++N;
     }
   }
 
+  if (!AvailabilityAttrs.empty()) {
+    std::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+              [](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+                return LHS->getPlatform() > RHS->getPlatform();
+              });
+    auto It = std::unique(
+        AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+        [&Ctx](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+          if (LHS->getPlatform() == RHS->getPlatform()) {
+            if (LHS->getIntroduced() == RHS->getIntroduced() &&
+                LHS->getDeprecated() == RHS->getDeprecated() &&
+                LHS->getObsoleted() == RHS->getObsoleted() &&
+                LHS->getMessage() == RHS->getMessage() &&
+                LHS->getReplacement() == RHS->getReplacement())
+              return true;
+
+            if ((!LHS->getIntroduced().empty() &&
+                 !RHS->getIntroduced().empty()) ||
+                (!LHS->getDeprecated().empty() &&
+                 !RHS->getDeprecated().empty()) ||
+                (!LHS->getObsoleted().empty() &&
+                 !RHS->getObsoleted().empty()) ||
+                (!LHS->getMessage().empty() && !RHS->getMessage().empty()))
+              return false;
+
+            if (LHS->getIntroduced().empty() && !RHS->getIntroduced().empty())
+              LHS->setIntroduced(Ctx, RHS->getIntroduced());
+
+            if (LHS->getDeprecated().empty() && !RHS->getDeprecated().empty()) {
+              LHS->setDeprecated(Ctx, RHS->getDeprecated());
+              if (!LHS->getMessage().empty())
+                LHS->setMessage(Ctx, RHS->getMessage());
+              if (!LHS->getReplacement().empty())
+                LHS->setReplacement(Ctx, RHS->getReplacement());
+            }
+
+            if (LHS->getObsoleted().empty() && !RHS->getObsoleted().empty()) {
+              LHS->setObsoleted(Ctx, RHS->getObsoleted());
+              if (!LHS->getMessage().empty())
+                LHS->setMessage(Ctx, RHS->getMessage());
+            }
+
+            return true;
+          }
+          return false;
+        });
+    AvailabilityAttrs.erase(It, AvailabilityAttrs.end());
+  }
+
   if (!HadAvailAttr)
     if (const EnumConstantDecl *EnumConst = dyn_cast<EnumConstantDecl>(D))
-      return getCursorPlatformAvailabilityForDecl(
-                                        cast<Decl>(EnumConst->getDeclContext()),
-                                                  always_deprecated,
-                                                  deprecated_message,
-                                                  always_unavailable,
-                                                  unavailable_message,
-                                                  availability,
-                                                  availability_size);
-  
-  return N;
+      getCursorPlatformAvailabilityForDecl(
+          cast<Decl>(EnumConst->getDeclContext()), always_deprecated,
+          deprecated_message, always_unavailable, unavailable_message,
+          AvailabilityAttrs);
 }
 
-int clang_getCursorPlatformAvailability(CXCursor cursor,
-                                        int *always_deprecated,
+int clang_getCursorPlatformAvailability(CXCursor cursor, int *always_deprecated,
                                         CXString *deprecated_message,
                                         int *always_unavailable,
                                         CXString *unavailable_message,
@@ -7284,14 +7314,29 @@
   if (!D)
     return 0;
 
-  return getCursorPlatformAvailabilityForDecl(D, always_deprecated,
-                                              deprecated_message,
-                                              always_unavailable,
-                                              unavailable_message,
-                                              availability,
-                                              availability_size);
+  SmallVector<AvailabilityAttr *, 8> AvailabilityAttrs;
+  getCursorPlatformAvailabilityForDecl(D, always_deprecated, deprecated_message,
+                                       always_unavailable, unavailable_message,
+                                       AvailabilityAttrs);
+
+  for (int I = 0, E = AvailabilityAttrs.size(); I < E && I < availability_size;
+       ++I) {
+    availability[I].Platform =
+        cxstring::createDup(AvailabilityAttrs[I]->getPlatform()->getName());
+    availability[I].Introduced =
+        convertVersion(AvailabilityAttrs[I]->getIntroduced());
+    availability[I].Deprecated =
+        convertVersion(AvailabilityAttrs[I]->getDeprecated());
+    availability[I].Obsoleted =
+        convertVersion(AvailabilityAttrs[I]->getObsoleted());
+    availability[I].Unavailable = AvailabilityAttrs[I]->getUnavailable();
+    availability[I].Message =
+        cxstring::createDup(AvailabilityAttrs[I]->getMessage());
+  }
+
+  return AvailabilityAttrs.size();
 }
-  
+
 void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) {
   clang_disposeString(availability->Platform);
   clang_disposeString(availability->Message);
Index: test/Index/availability.c
===================================================================
--- test/Index/availability.c
+++ test/Index/availability.c
@@ -8,13 +8,16 @@
 
 enum {
   old_enum_plat
-} __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7)
+} __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7)));
+
+void bar(void) __attribute__((availability(macosx,introduced=10.4))) __attribute__((availability(ios,introduced=3.2))) __attribute__((availability(macosx,deprecated=10.5,message="use foobar")));
 
 // RUN: c-index-test -test-load-source all %s > %t
 // RUN: FileCheck -check-prefix=CHECK-1 %s < %t
 // RUN: FileCheck -check-prefix=CHECK-2 %s < %t
-// CHECK-1: (ios, introduced=3.2, deprecated=4.1) 
+// CHECK-1: (ios, introduced=3.2, deprecated=4.1)
 // CHECK-2: (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
 
 // CHECK-2: EnumConstantDecl=old_enum:6:3 (Definition) (deprecated)
 // CHECK-2: EnumConstantDecl=old_enum_plat:10:3 {{.*}} (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
+// CHECK-2: FunctionDecl=bar:13:6 (deprecated) (ios, introduced=3.2) (macos, introduced=10.4, deprecated=10.5, message="use foobar")
\ No newline at end of file
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to