[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-12 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added a comment.

Recommitted in r305221.


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-12 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added a comment.

Thanks, I'll recommit today.


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-11 Thread Ronald Wampler via Phabricator via cfe-commits
rdwampler updated this revision to Diff 102150.
rdwampler added a comment.

I was able to build and test this on a linux box. The issue was the whitespace 
surrounding the regex.

On Linux, `(unavailable)` is not present. I.e,
`FunctionDecl=foo:3:6  (ios, introduced=3.2, deprecated=4.1)  (macos, 
introduced=10.4, deprecated=10.5, obsoleted=10.7)`
vs on macOS
`FunctionDecl=foo:3:6 (unavailable)  (ios, introduced=3.2, deprecated=4.1) 
(unavailable)  (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)`

I changed it to just match any characters between the function declaration and 
the availabilities.

Sorry for the noise.


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
@@ -7216,15 +7216,11 @@
   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 &AvailabilityAttrs) {
   bool HadAvailAttr = false;
-  int N = 0;
   for (auto A : D->attrs()) {
 if (DeprecatedAttr *Deprecated = dyn_cast(A)) {
   HadAvailAttr = true;
@@ -7236,7 +7232,7 @@
   }
   continue;
 }
-
+
 if (UnavailableAttr *Unavailable = dyn_cast(A)) {
   HadAvailAttr = true;
   if (always_unavailable)
@@ -7247,38 +7243,71 @@
   }
   continue;
 }
-
+
 if (AvailabilityAttr *Avail = dyn_cast(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 (!HadAvailAttr)
 if (const EnumConstantDecl *EnumConst = dyn_cast(D))
   return getCursorPlatformAvailabilityForDecl(
-cast(EnumConst->getDeclContext()),
-  always_deprecated,
-  deprecated_message,
-  always_unavailable,
-  unavailable_message,
-  availability,
-  availability_size);
-  
-  return N;
+  cast(EnumConst->getDeclContext()), always_deprecated,
+  deprecated_message, always_unavailable, unavailable_message,
+  AvailabilityAttrs);
+
+  if (AvailabilityAttrs.empty())
+return;
+
+  std::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+[](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+  return LHS->getPlatform() > RHS->getPlatform();
+});
+  ASTContext &Ctx = D->getASTContext();
+  auto It = std::unique(
+  AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+  [&Ctx](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+if (LHS->getPlatform() != RHS->getPlatform())
+  return false;
+
+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()))
+  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

[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-09 Thread Ronald Wampler via Phabricator via cfe-commits
rdwampler added a comment.

Alex, I will look into it. Thanks!


Repository:
  rL LLVM

https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-09 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added a comment.

Ronald, I had to revert the commit as the `availability.c` test was failing on 
Linux (e.g. 
http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/builds/12532).
 Can you please look into that? I think you might have to got back to the 
`CHECK-1` and `CHECK-2` thing


Repository:
  rL LLVM

https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-09 Thread Alex Lorenz via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL305117: [libclang] Merge multiple availability clauses when 
getting the platform's (authored by arphaman).

Changed prior to commit:
  https://reviews.llvm.org/D33478?vs=102050&id=102074#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D33478

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

Index: cfe/trunk/test/Index/availability.c
===
--- cfe/trunk/test/Index/availability.c
+++ cfe/trunk/test/Index/availability.c
@@ -8,13 +8,15 @@
 
 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)));
 
-// 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-2: (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
+void bar(void) __attribute__((availability(macosx,introduced=10.4))) __attribute__((availability(macosx,obsoleted=10.6))) __attribute__((availability(ios,introduced=3.2))) __attribute__((availability(macosx,deprecated=10.5,message="use foobar")));
 
-// 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)
+void bar2(void) __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7))) __attribute__((availability(ios,introduced=3.2,deprecated=10.0))) __attribute__((availability(macosx,introduced=10.4,deprecated=10.5,obsoleted=10.7))) __attribute__((availability(ios,introduced=3.2,deprecated=10.0)));
+
+// RUN: c-index-test -test-load-source all %s | FileCheck %s
+// CHECK: FunctionDecl=foo:3:6 {{.*}} (ios, introduced=3.2, deprecated=4.1) (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
+// CHECK: EnumConstantDecl=old_enum:6:3 (Definition) (deprecated)
+// CHECK: EnumConstantDecl=old_enum_plat:10:3 {{.*}} (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
+// CHECK: FunctionDecl=bar:13:6 {{.*}} (ios, introduced=3.2) (macos, introduced=10.4, deprecated=10.5, obsoleted=10.6, message="use foobar")
+// CHECK: FunctionDecl=bar2:15:6 {{.*}} (ios, introduced=3.2, deprecated=10.0) (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
Index: cfe/trunk/tools/libclang/CIndex.cpp
===
--- cfe/trunk/tools/libclang/CIndex.cpp
+++ cfe/trunk/tools/libclang/CIndex.cpp
@@ -7216,15 +7216,11 @@
   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 &AvailabilityAttrs) {
   bool HadAvailAttr = false;
-  int N = 0;
   for (auto A : D->attrs()) {
 if (DeprecatedAttr *Deprecated = dyn_cast(A)) {
   HadAvailAttr = true;
@@ -7236,7 +7232,7 @@
   }
   continue;
 }
-
+
 if (UnavailableAttr *Unavailable = dyn_cast(A)) {
   HadAvailAttr = true;
   if (always_unavailable)
@@ -7247,38 +7243,71 @@
   }
   continue;
 }
-
+
 if (AvailabilityAttr *Avail = dyn_cast(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 (!HadAvailAttr)
 if (const EnumConstantDecl *EnumConst = dyn_cast(D))
   return getCursorPlatformAvailabilityForDecl(
-cast(EnumConst->getDeclContext()),
-  always_deprecated,
-  deprecated_message,
-  always_unavailable,
-

[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-09 Thread Ronald Wampler via Phabricator via cfe-commits
rdwampler marked 2 inline comments as done.
rdwampler added a comment.

I don't have commit access, but I would grateful if you can commit it.


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-09 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added a comment.

Do you have commit access or shall I commit it on your behalf?


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-09 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman accepted this revision.
arphaman added a comment.
This revision is now accepted and ready to land.

LGTM


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-09 Thread Ronald Wampler via Phabricator via cfe-commits
rdwampler updated this revision to Diff 102050.
rdwampler added a comment.

Remove an unnecessary check when determining a mismatch of availabilities
Simplify invocation of FileCheck in availability.c


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,11 @@
   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 &AvailabilityAttrs) {
   bool HadAvailAttr = false;
-  int N = 0;
   for (auto A : D->attrs()) {
 if (DeprecatedAttr *Deprecated = dyn_cast(A)) {
   HadAvailAttr = true;
@@ -7220,7 +7216,7 @@
   }
   continue;
 }
-
+
 if (UnavailableAttr *Unavailable = dyn_cast(A)) {
   HadAvailAttr = true;
   if (always_unavailable)
@@ -7231,38 +7227,71 @@
   }
   continue;
 }
-
+
 if (AvailabilityAttr *Avail = dyn_cast(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 (!HadAvailAttr)
 if (const EnumConstantDecl *EnumConst = dyn_cast(D))
   return getCursorPlatformAvailabilityForDecl(
-cast(EnumConst->getDeclContext()),
-  always_deprecated,
-  deprecated_message,
-  always_unavailable,
-  unavailable_message,
-  availability,
-  availability_size);
-  
-  return N;
+  cast(EnumConst->getDeclContext()), always_deprecated,
+  deprecated_message, always_unavailable, unavailable_message,
+  AvailabilityAttrs);
+
+  if (AvailabilityAttrs.empty())
+return;
+
+  std::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+[](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+  return LHS->getPlatform() > RHS->getPlatform();
+});
+  ASTContext &Ctx = D->getASTContext();
+  auto It = std::unique(
+  AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+  [&Ctx](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+if (LHS->getPlatform() != RHS->getPlatform())
+  return false;
+
+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()))
+  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());
+  if (LHS->getRep

[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-08 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added inline comments.



Comment at: test/Index/availability.c:20
 // CHECK-2: (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
 
 // CHECK-2: EnumConstantDecl=old_enum:6:3 (Definition) (deprecated)

rdwampler wrote:
> Can we run `FileCheck` once now? I believe the `CHECK-1` and `CHECK-2` were 
> added since there were no particular order for the availabilities. With this 
> patch the order is guarantee to be stable.
Sure, if the test passes we can use one `FileCheck` invocation. We can also use 
`CHECK-DAG:` to check for strings without obeying a specific order. 


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-07 Thread Ronald Wampler via Phabricator via cfe-commits
rdwampler marked an inline comment as done.
rdwampler added inline comments.



Comment at: test/Index/availability.c:20
 // CHECK-2: (macos, introduced=10.4, deprecated=10.5, obsoleted=10.7)
 
 // CHECK-2: EnumConstantDecl=old_enum:6:3 (Definition) (deprecated)

Can we run `FileCheck` once now? I believe the `CHECK-1` and `CHECK-2` were 
added since there were no particular order for the availabilities. With this 
patch the order is guarantee to be stable.



Comment at: tools/libclang/CIndex.cpp:7268
+(!LHS->getObsoleted().empty() && !RHS->getObsoleted().empty()) ||
+(!LHS->getMessage().empty() && !RHS->getMessage().empty()))
+  return false;

arphaman wrote:
> I think that we don't really need the `(!LHS->getMessage().empty() && 
> !RHS->getMessage().empty())` check here since message has to be either in a 
> deprecated or obsoleted clause, so we should already handle that with 
> previous checks.
Agreed.


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-07 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added a comment.

This looks better, it's almost ready. A couple of small requests:




Comment at: tools/libclang/CIndex.cpp:7262
+LHS->getMessage() == RHS->getMessage() &&
+LHS->getReplacement() == RHS->getReplacement())
+  return true;

We should also have a test that verifies that we merge identical availabilities.



Comment at: tools/libclang/CIndex.cpp:7268
+(!LHS->getObsoleted().empty() && !RHS->getObsoleted().empty()) ||
+(!LHS->getMessage().empty() && !RHS->getMessage().empty()))
+  return false;

I think that we don't really need the `(!LHS->getMessage().empty() && 
!RHS->getMessage().empty())` check here since message has to be either in a 
deprecated or obsoleted clause, so we should already handle that with previous 
checks.


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-07 Thread Ronald Wampler via Phabricator via cfe-commits
rdwampler updated this revision to Diff 101787.
rdwampler marked 6 inline comments as done.
rdwampler added a comment.

This should resolve the bug (a conditional was inverted) in the last revision 
along with the other changes requested.


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,11 @@
   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 &AvailabilityAttrs) {
   bool HadAvailAttr = false;
-  int N = 0;
   for (auto A : D->attrs()) {
 if (DeprecatedAttr *Deprecated = dyn_cast(A)) {
   HadAvailAttr = true;
@@ -7220,7 +7216,7 @@
   }
   continue;
 }
-
+
 if (UnavailableAttr *Unavailable = dyn_cast(A)) {
   HadAvailAttr = true;
   if (always_unavailable)
@@ -7231,38 +7227,72 @@
   }
   continue;
 }
-
+
 if (AvailabilityAttr *Avail = dyn_cast(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 (!HadAvailAttr)
 if (const EnumConstantDecl *EnumConst = dyn_cast(D))
   return getCursorPlatformAvailabilityForDecl(
-cast(EnumConst->getDeclContext()),
-  always_deprecated,
-  deprecated_message,
-  always_unavailable,
-  unavailable_message,
-  availability,
-  availability_size);
-  
-  return N;
+  cast(EnumConst->getDeclContext()), always_deprecated,
+  deprecated_message, always_unavailable, unavailable_message,
+  AvailabilityAttrs);
+
+  if (AvailabilityAttrs.empty())
+return;
+
+  std::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+[](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+  return LHS->getPlatform() > RHS->getPlatform();
+});
+  ASTContext &Ctx = D->getASTContext();
+  auto It = std::unique(
+  AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+  [&Ctx](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+if (LHS->getPlatform() != RHS->getPlatform())
+  return false;
+
+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());
+

[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-06 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added a comment.

It seems that there's a slight bug in the patch:

If I print the output of the following code using `c-index-test 
-test-load-source all`:

  void bar2(void)
  __attribute__((availability(macosx, introduced=10.4)))
  __attribute__((availability(macosx, deprecated=10.5, message="use x")));

I see availability that includes a deprecation message: `FunctionDecl=bar2:15:6 
(deprecated)  (macos, introduced=10.4, deprecated=10.5, message="use x")`.
However, if I look at the output of the following code:

  void bar2(void)
  __attribute__((availability(macosx, deprecated=10.5, message="use x")))
  __attribute__((availability(macosx, introduced=10.4)));

I get something that doesn't include the message: `FunctionDecl=bar2:15:6 
(deprecated)  (macos, introduced=10.4, deprecated=10.5)`.




Comment at: test/Index/availability.c:13
+
+void bar(void) __attribute__((availability(macosx,introduced=10.4))) 
__attribute__((availability(ios,introduced=3.2))) 
__attribute__((availability(macosx,deprecated=10.5,message="use foobar")));
 

Please add a test for merge of the `obsoleted` clause as well.



Comment at: tools/libclang/CIndex.cpp:7239
 if (const EnumConstantDecl *EnumConst = dyn_cast(D))
-  return getCursorPlatformAvailabilityForDecl(
-
cast(EnumConst->getDeclContext()),
-  always_deprecated,
-  deprecated_message,
-  always_unavailable,
-  unavailable_message,
-  availability,
-  availability_size);
-  
-  return N;
+  getCursorPlatformAvailabilityForDecl(
+  cast(EnumConst->getDeclContext()), always_deprecated,

You should be able to keep the `return` here, since you will `sort` and 
`unique` the attributes in this call to `getCursorPlatformAvailabilityForDecl`.



Comment at: tools/libclang/CIndex.cpp:7255
+  [&Ctx](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+if (LHS->getPlatform() == RHS->getPlatform()) {
+  if (LHS->getIntroduced() == RHS->getIntroduced() &&

Please invert this `if` and `return false` early instead of leaving it at the 
end of the lambda.


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-06 Thread Ronald Wampler via Phabricator via cfe-commits
rdwampler updated this revision to Diff 101569.
rdwampler added a comment.

Rearrange `if` statements in `getCursorPlatformAvailabilityForDecl` to return 
early if we do not need to merge availability attributes.
Use ranged for loop.


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,11 @@
   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 &AvailabilityAttrs) {
   bool HadAvailAttr = false;
-  int N = 0;
   for (auto A : D->attrs()) {
 if (DeprecatedAttr *Deprecated = dyn_cast(A)) {
   HadAvailAttr = true;
@@ -7220,7 +7216,7 @@
   }
   continue;
 }
-
+
 if (UnavailableAttr *Unavailable = dyn_cast(A)) {
   HadAvailAttr = true;
   if (always_unavailable)
@@ -7231,38 +7227,72 @@
   }
   continue;
 }
-
+
 if (AvailabilityAttr *Avail = dyn_cast(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 (!HadAvailAttr)
 if (const EnumConstantDecl *EnumConst = dyn_cast(D))
-  return getCursorPlatformAvailabilityForDecl(
-cast(EnumConst->getDeclContext()),
-  always_deprecated,
-  deprecated_message,
-  always_unavailable,
-  unavailable_message,
-  availability,
-  availability_size);
-  
-  return N;
+  getCursorPlatformAvailabilityForDecl(
+  cast(EnumConst->getDeclContext()), always_deprecated,
+  deprecated_message, always_unavailable, unavailable_message,
+  AvailabilityAttrs);
+
+  if (AvailabilityAttrs.empty())
+return;
+
+  std::sort(AvailabilityAttrs.begin(), AvailabilityAttrs.end(),
+[](AvailabilityAttr *LHS, AvailabilityAttr *RHS) {
+  return LHS->getPlatform() > RHS->getPlatform();
+});
+  ASTContext &Ctx = D->getASTContext();
+  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->

[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-05 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added inline comments.



Comment at: tools/libclang/CIndex.cpp:7322
+
+  for (int I = 0, E = AvailabilityAttrs.size(); I < E && I < availability_size;
+   ++I) {

rdwampler wrote:
> arphaman wrote:
> > You can use a ranged for loop here if you use `take_front`, e.g.
> > 
> > ```
> > for (const auto *Avail : AvailabilityAttrs.take_front(availability_size))
> > ```
> I would need to covert this to an `ArrayRef`, I believe. Also, I would need 
> to check `availability_size` is in bounds. Would something like the following 
> be preferred:
> ```
> int N = 0;
> for (const auto *Avail : AvailabilityAttrs) {
>   if (N < availability_size) {
> // populate availability
> N++;
>   }
> }
> ```
Right, sorry I forgot about the `N`.
I think that you can use 
`llvm::enumerate(llvm::makeArrayRef(AvailabilityAttrs).take_front(availability_size))`
 to get rid of `N` as well, as you can the index and the attribute pointer from 
the loop variable.
Btw, The `take_front(N)` will ensure that you will only iterate either over the 
first N attributes or all of the attributes if `N > AvailabilityAttrs.size()`, 
so you won't need to check `N` in the loop.


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-02 Thread Ronald Wampler via Phabricator via cfe-commits
rdwampler added inline comments.



Comment at: tools/libclang/CIndex.cpp:7322
+
+  for (int I = 0, E = AvailabilityAttrs.size(); I < E && I < availability_size;
+   ++I) {

arphaman wrote:
> You can use a ranged for loop here if you use `take_front`, e.g.
> 
> ```
> for (const auto *Avail : AvailabilityAttrs.take_front(availability_size))
> ```
I would need to covert this to an `ArrayRef`, I believe. Also, I would need to 
check `availability_size` is in bounds. Would something like the following be 
preferred:
```
int N = 0;
for (const auto *Avail : AvailabilityAttrs) {
  if (N < availability_size) {
// populate availability
N++;
  }
}
```


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-06-02 Thread Alex Lorenz via Phabricator via cfe-commits
arphaman added inline comments.



Comment at: tools/libclang/CIndex.cpp:7287
+
   if (!HadAvailAttr)
 if (const EnumConstantDecl *EnumConst = dyn_cast(D))

I think that you can move this `if` before the new `if`, and convert the new 
`if` to be an `if (AvailabilityAttrs.empty())` that returns early. Then you can 
do the merging outside of the `if` at the end of the function.



Comment at: tools/libclang/CIndex.cpp:7322
+
+  for (int I = 0, E = AvailabilityAttrs.size(); I < E && I < availability_size;
+   ++I) {

You can use a ranged for loop here if you use `take_front`, e.g.

```
for (const auto *Avail : AvailabilityAttrs.take_front(availability_size))
```


https://reviews.llvm.org/D33478



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33478: [libclang] When getting platform availabilities, merge multiple declarations if possible

2017-05-23 Thread Ronald Wampler via Phabricator via cfe-commits
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 &AvailabilityAttrs) {
   bool HadAvailAttr = false;
-  int N = 0;
+  ASTContext &Ctx = D->getASTContext();
   for (auto A : D->attrs()) {
 if (DeprecatedAttr *Deprecated = dyn_cast(A)) {
   HadAvailAttr = true;
@@ -7220,7 +7217,7 @@
   }
   continue;
 }
-
+
 if (UnavailableAttr *Unavailable = dyn_cast(A)) {
   HadAvailAttr = true;
   if (always_unavailable)
@@ -7231,38 +7228,71 @@
   }
   continue;
 }
-
+
 if (AvailabilityAttr *Avail = dyn_cast(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(D))
-  return getCursorPlatformAvailabilityForDecl(
-cast(EnumConst->getDeclContext()),
-  always_deprecated,
-  deprecated_message,
-  always_unavailable,
-  unavailable_message,
-  availability,
-  availability_size);
-  
-  return N