[libclang] When querying for the availability of an enumerator, pick up the availability from the enum declaration.
rdar://14789001.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192718 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 967750f..8e14d3f 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -5835,25 +5835,30 @@
}
extern "C" {
+
+static CXAvailabilityKind getCursorAvailabilityForDecl(const Decl *D) {
+ if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
+ return CXAvailability_Available;
+ switch (D->getAvailability()) {
+ case AR_Available:
+ case AR_NotYetIntroduced:
+ if (const EnumConstantDecl *EnumConst = dyn_cast<EnumConstantDecl>(D))
+ return getCursorAvailabilityForDecl(cast<Decl>(EnumConst->getDeclContext()));
+ return CXAvailability_Available;
+
+ case AR_Deprecated:
+ return CXAvailability_Deprecated;
+
+ case AR_Unavailable:
+ return CXAvailability_NotAvailable;
+ }
+}
+
enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
if (clang_isDeclaration(cursor.kind))
- if (const Decl *D = cxcursor::getCursorDecl(cursor)) {
- if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted())
- return CXAvailability_Available;
-
- switch (D->getAvailability()) {
- case AR_Available:
- case AR_NotYetIntroduced:
- return CXAvailability_Available;
-
- case AR_Deprecated:
- return CXAvailability_Deprecated;
-
- case AR_Unavailable:
- return CXAvailability_NotAvailable;
- }
- }
+ if (const Decl *D = cxcursor::getCursorDecl(cursor))
+ return getCursorAvailabilityForDecl(D);
return CXAvailability_Available;
}
@@ -5877,7 +5882,66 @@
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) {
+ bool HadAvailAttr = false;
+ int N = 0;
+ for (Decl::attr_iterator A = D->attr_begin(), AEnd = D->attr_end(); A != AEnd;
+ ++A) {
+ if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) {
+ HadAvailAttr = true;
+ if (always_deprecated)
+ *always_deprecated = 1;
+ if (deprecated_message)
+ *deprecated_message = cxstring::createDup(Deprecated->getMessage());
+ continue;
+ }
+
+ if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) {
+ HadAvailAttr = true;
+ if (always_unavailable)
+ *always_unavailable = 1;
+ if (unavailable_message) {
+ *unavailable_message = cxstring::createDup(Unavailable->getMessage());
+ }
+ continue;
+ }
+
+ if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(*A)) {
+ 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<EnumConstantDecl>(D))
+ return getCursorPlatformAvailabilityForDecl(
+ cast<Decl>(EnumConst->getDeclContext()),
+ always_deprecated,
+ deprecated_message,
+ always_unavailable,
+ unavailable_message,
+ availability,
+ availability_size);
+ return N;
+}
+
int clang_getCursorPlatformAvailability(CXCursor cursor,
int *always_deprecated,
CXString *deprecated_message,
@@ -5893,49 +5957,20 @@
*always_unavailable = 0;
if (unavailable_message)
*unavailable_message = cxstring::createEmpty();
-
+
if (!clang_isDeclaration(cursor.kind))
return 0;
-
+
const Decl *D = cxcursor::getCursorDecl(cursor);
if (!D)
return 0;
-
- int N = 0;
- for (Decl::attr_iterator A = D->attr_begin(), AEnd = D->attr_end(); A != AEnd;
- ++A) {
- if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) {
- if (always_deprecated)
- *always_deprecated = 1;
- if (deprecated_message)
- *deprecated_message = cxstring::createDup(Deprecated->getMessage());
- continue;
- }
-
- if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) {
- if (always_unavailable)
- *always_unavailable = 1;
- if (unavailable_message) {
- *unavailable_message = cxstring::createDup(Unavailable->getMessage());
- }
- continue;
- }
-
- if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(*A)) {
- 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;
- }
- }
-
- return N;
+
+ return getCursorPlatformAvailabilityForDecl(D, always_deprecated,
+ deprecated_message,
+ always_unavailable,
+ unavailable_message,
+ availability,
+ availability_size);
}
void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) {