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