[PATCH] D50318: Support Swift in platform availability attribute
michaelwu added a comment. Review ping Repository: rC Clang https://reviews.llvm.org/D50318 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51281: [libclang] Return the proper pointee type for 'auto' deduced to pointer
michaelwu added a comment. It shouldn't be too hard to make a test using `c-index-test`. `-test-print-type` will print out the pointee type if it's valid. Comment at: tools/libclang/CXType.cpp:448 break; +case Type::Auto: + TP = cast(TP)->getDeducedType().getTypePtrOrNull(); Seems like this might make sense for `Type::DeducedTemplateSpecialization` too. https://reviews.llvm.org/D51281 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D51281: [libclang] Return the proper pointee type for 'auto' deduced to pointer
michaelwu accepted this revision. michaelwu added a comment. This revision is now accepted and ready to land. LGTM https://reviews.llvm.org/D51281 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49634: [libclang] Add support for getting property setter and getter names
michaelwu created this revision. This allows libclang to access the actual names of property setters and getters without needing to go through the indexer API. Usually default names are used, but the property can specify a different name. Repository: rC Clang https://reviews.llvm.org/D49634 Files: include/clang-c/Index.h test/Index/property-getter-setter.m tools/c-index-test/c-index-test.c tools/libclang/CIndex.cpp tools/libclang/libclang.exports Index: tools/libclang/libclang.exports === --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -31,6 +31,8 @@ clang_Cursor_getNumArguments clang_Cursor_getObjCDeclQualifiers clang_Cursor_getObjCPropertyAttributes +clang_Cursor_getObjCPropertyGetterName +clang_Cursor_getObjCPropertySetterName clang_Cursor_getObjCSelectorIndex clang_Cursor_getOffsetOfField clang_Cursor_getSpellingNameRange Index: tools/libclang/CIndex.cpp === --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -7913,6 +7913,30 @@ return Result; } +CXString clang_Cursor_getObjCPropertyGetterName(CXCursor C) { + if (C.kind != CXCursor_ObjCPropertyDecl) +return cxstring::createNull(); + + const ObjCPropertyDecl *PD = dyn_cast(getCursorDecl(C)); + Selector sel = PD->getGetterName(); + if (sel.isNull()) +return cxstring::createNull(); + + return cxstring::createDup(sel.getAsString()); +} + +CXString clang_Cursor_getObjCPropertySetterName(CXCursor C) { + if (C.kind != CXCursor_ObjCPropertyDecl) +return cxstring::createNull(); + + const ObjCPropertyDecl *PD = dyn_cast(getCursorDecl(C)); + Selector sel = PD->getSetterName(); + if (sel.isNull()) +return cxstring::createNull(); + + return cxstring::createDup(sel.getAsString()); +} + unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C) { if (!clang_isDeclaration(C.kind)) return CXObjCDeclQualifier_None; Index: tools/c-index-test/c-index-test.c === --- tools/c-index-test/c-index-test.c +++ tools/c-index-test/c-index-test.c @@ -1103,6 +1103,34 @@ } } +if (Cursor.kind == CXCursor_ObjCPropertyDecl) { + CXString Name = clang_Cursor_getObjCPropertyGetterName(Cursor); + CXString Spelling = clang_getCursorSpelling(Cursor); + const char *CName = clang_getCString(Name); + const char *CSpelling = clang_getCString(Spelling); + if (CName && strcmp(CName, CSpelling)) { +printf(" (getter=%s)", CName); + } + clang_disposeString(Spelling); + clang_disposeString(Name); +} + +if (Cursor.kind == CXCursor_ObjCPropertyDecl) { + CXString Name = clang_Cursor_getObjCPropertySetterName(Cursor); + CXString Spelling = clang_getCursorSpelling(Cursor); + const char *CName = clang_getCString(Name); + const char *CSpelling = clang_getCString(Spelling); + char *DefaultSetter = malloc(strlen(CSpelling) + 5); + sprintf(DefaultSetter, "set%s:", CSpelling); + DefaultSetter[3] &= ~(1 << 5); // Make uppercase + if (CName && strcmp(CName, DefaultSetter)) { +printf(" (setter=%s)", CName); + } + free(DefaultSetter); + clang_disposeString(Spelling); + clang_disposeString(Name); +} + { unsigned QT = clang_Cursor_getObjCDeclQualifiers(Cursor); if (QT != CXObjCDeclQualifier_None) { Index: test/Index/property-getter-setter.m === --- /dev/null +++ test/Index/property-getter-setter.m @@ -0,0 +1,10 @@ +@interface Foo +@property (assign,readwrite,getter=b,setter=c:) id a; +@property (assign,readonly,getter=e) id d; +@property (assign,readwrite) id f; +@end + +// RUN: c-index-test -test-print-type-declaration +// CHECK: ObjCPropertyDecl=a:2:52 [getter,assign,readwrite,setter,] (getter=b) (setter=c:) [typedeclaration=id] [typekind=ObjCId] +// CHECK: ObjCPropertyDecl=d:3:41 [readonly,getter,assign,] (getter=e) [typedeclaration=id] [typekind=ObjCId] +// CHECK: ObjCPropertyDecl=f:4:33 [assign,readwrite,] [typedeclaration=id] [typekind=ObjCId] Index: include/clang-c/Index.h === --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -4449,6 +4449,18 @@ CINDEX_LINKAGE unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C, unsigned reserved); +/** + * Given a cursor that represents a property declaration, return the + * name of the method that implements the getter. + */ +CINDEX_LINKAGE CXString clang_Cursor_getObjCPropertyGetterName(CXCursor C); + +/** + * Given a cursor that represents a property declaration, return the + * name of the method that implements the setter, if any. + */ +CINDEX_LINKAGE CXString clang_Cursor_getObjCPropertySetterName(CXCursor C); + /**
[PATCH] D49635: [libclang 8/8] Add support for the flag_enum attribute
michaelwu created this revision. This adds support to libclang for reading the flag_enum attribute. This also bumps CINDEX_VERSION_MINOR for this patch series. Repository: rC Clang https://reviews.llvm.org/D49635 Files: include/clang-c/Index.h test/Index/attributes.c tools/libclang/CIndex.cpp tools/libclang/CXCursor.cpp Index: tools/libclang/CXCursor.cpp === --- tools/libclang/CXCursor.cpp +++ tools/libclang/CXCursor.cpp @@ -78,6 +78,7 @@ case attr::ObjCDesignatedInitializer: return CXCursor_ObjCDesignatedInitializer; case attr::ObjCRuntimeVisible: return CXCursor_ObjCRuntimeVisible; case attr::ObjCBoxable: return CXCursor_ObjCBoxable; +case attr::FlagEnum: return CXCursor_FlagEnum; } return CXCursor_UnexposedAttr; Index: tools/libclang/CIndex.cpp === --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -5313,6 +5313,8 @@ return cxstring::createRef("attribute(objc_runtime_visible)"); case CXCursor_ObjCBoxable: return cxstring::createRef("attribute(objc_boxable)"); + case CXCursor_FlagEnum: +return cxstring::createRef("attribute(flag_enum)"); case CXCursor_PreprocessingDirective: return cxstring::createRef("preprocessing directive"); case CXCursor_MacroDefinition: Index: test/Index/attributes.c === --- test/Index/attributes.c +++ test/Index/attributes.c @@ -8,6 +8,10 @@ void const_fn() __attribute__((const)); void noduplicate_fn() __attribute__((noduplicate)); +enum __attribute((flag_enum)) FlagEnum { + Foo +}; + // CHECK: attributes.c:3:32: StructDecl=Test2:3:32 (Definition) Extent=[3:1 - 5:2] // CHECK: attributes.c:3:23: attribute(packed)=packed Extent=[3:23 - 3:29] // CHECK: attributes.c:4:8: FieldDecl=a:4:8 (Definition) Extent=[4:3 - 4:9] [access=public] @@ -18,3 +22,5 @@ // CHECK: attributes.c:8:32: attribute(const)= Extent=[8:32 - 8:37] // CHECK: attributes.c:9:6: FunctionDecl=noduplicate_fn:9:6 Extent=[9:1 - 9:51] // CHECK: attributes.c:9:38: attribute(noduplicate)= Extent=[9:38 - 9:49] +// CHECK: attributes.c:11:31: EnumDecl=FlagEnum:11:31 (Definition) Extent=[11:1 - 13:2] +// CHECK: attributes.c:11:19: attribute(flag_enum)= Extent=[11:19 - 11:28] Index: include/clang-c/Index.h === --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 49 +#define CINDEX_VERSION_MINOR 50 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 1) \ @@ -2586,7 +2586,8 @@ CXCursor_ObjCDesignatedInitializer = 434, CXCursor_ObjCRuntimeVisible= 435, CXCursor_ObjCBoxable = 436, - CXCursor_LastAttr = CXCursor_ObjCBoxable, + CXCursor_FlagEnum = 437, + CXCursor_LastAttr = CXCursor_FlagEnum, /* Preprocessing */ CXCursor_PreprocessingDirective= 500, Index: tools/libclang/CXCursor.cpp === --- tools/libclang/CXCursor.cpp +++ tools/libclang/CXCursor.cpp @@ -78,6 +78,7 @@ case attr::ObjCDesignatedInitializer: return CXCursor_ObjCDesignatedInitializer; case attr::ObjCRuntimeVisible: return CXCursor_ObjCRuntimeVisible; case attr::ObjCBoxable: return CXCursor_ObjCBoxable; +case attr::FlagEnum: return CXCursor_FlagEnum; } return CXCursor_UnexposedAttr; Index: tools/libclang/CIndex.cpp === --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -5313,6 +5313,8 @@ return cxstring::createRef("attribute(objc_runtime_visible)"); case CXCursor_ObjCBoxable: return cxstring::createRef("attribute(objc_boxable)"); + case CXCursor_FlagEnum: +return cxstring::createRef("attribute(flag_enum)"); case CXCursor_PreprocessingDirective: return cxstring::createRef("preprocessing directive"); case CXCursor_MacroDefinition: Index: test/Index/attributes.c === --- test/Index/attributes.c +++ test/Index/attributes.c @@ -8,6 +8,10 @@ void const_fn() __attribute__((const)); void noduplicate_fn() __attribute__((noduplicate)); +enum __attribute((flag_enum)) FlagEnum { + Foo +}; + // CHECK: attributes.c:3:32: StructDecl=Test2:3:32 (Definition) Extent=[3:1 - 5:2] // CHECK: attributes.c:3:23: attribute(packed)=packed Extent=[3:23 - 3:29] // CHECK: attributes.c:4:8: FieldDecl=a:4:8 (Definition) Extent=[4:3 - 4:9] [access=public] @@ -18,3 +22,5 @@ // CHECK: attributes.c:8:32: attribute(const)= Extent=[8:32 - 8:37] // CHECK: attributes.c:9:6:
[PATCH] D49634: [libclang 7/8] Add support for getting property setter and getter names
michaelwu updated this revision to Diff 156691. michaelwu added a comment. Fix test https://reviews.llvm.org/D49634 Files: include/clang-c/Index.h test/Index/property-getter-setter.m tools/c-index-test/c-index-test.c tools/libclang/CIndex.cpp tools/libclang/libclang.exports Index: tools/libclang/libclang.exports === --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -31,6 +31,8 @@ clang_Cursor_getNumArguments clang_Cursor_getObjCDeclQualifiers clang_Cursor_getObjCPropertyAttributes +clang_Cursor_getObjCPropertyGetterName +clang_Cursor_getObjCPropertySetterName clang_Cursor_getObjCSelectorIndex clang_Cursor_getOffsetOfField clang_Cursor_getSpellingNameRange Index: tools/libclang/CIndex.cpp === --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -7913,6 +7913,30 @@ return Result; } +CXString clang_Cursor_getObjCPropertyGetterName(CXCursor C) { + if (C.kind != CXCursor_ObjCPropertyDecl) +return cxstring::createNull(); + + const ObjCPropertyDecl *PD = dyn_cast(getCursorDecl(C)); + Selector sel = PD->getGetterName(); + if (sel.isNull()) +return cxstring::createNull(); + + return cxstring::createDup(sel.getAsString()); +} + +CXString clang_Cursor_getObjCPropertySetterName(CXCursor C) { + if (C.kind != CXCursor_ObjCPropertyDecl) +return cxstring::createNull(); + + const ObjCPropertyDecl *PD = dyn_cast(getCursorDecl(C)); + Selector sel = PD->getSetterName(); + if (sel.isNull()) +return cxstring::createNull(); + + return cxstring::createDup(sel.getAsString()); +} + unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C) { if (!clang_isDeclaration(C.kind)) return CXObjCDeclQualifier_None; Index: tools/c-index-test/c-index-test.c === --- tools/c-index-test/c-index-test.c +++ tools/c-index-test/c-index-test.c @@ -1103,6 +1103,34 @@ } } +if (Cursor.kind == CXCursor_ObjCPropertyDecl) { + CXString Name = clang_Cursor_getObjCPropertyGetterName(Cursor); + CXString Spelling = clang_getCursorSpelling(Cursor); + const char *CName = clang_getCString(Name); + const char *CSpelling = clang_getCString(Spelling); + if (CName && strcmp(CName, CSpelling)) { +printf(" (getter=%s)", CName); + } + clang_disposeString(Spelling); + clang_disposeString(Name); +} + +if (Cursor.kind == CXCursor_ObjCPropertyDecl) { + CXString Name = clang_Cursor_getObjCPropertySetterName(Cursor); + CXString Spelling = clang_getCursorSpelling(Cursor); + const char *CName = clang_getCString(Name); + const char *CSpelling = clang_getCString(Spelling); + char *DefaultSetter = malloc(strlen(CSpelling) + 5); + sprintf(DefaultSetter, "set%s:", CSpelling); + DefaultSetter[3] &= ~(1 << 5); // Make uppercase + if (CName && strcmp(CName, DefaultSetter)) { +printf(" (setter=%s)", CName); + } + free(DefaultSetter); + clang_disposeString(Spelling); + clang_disposeString(Name); +} + { unsigned QT = clang_Cursor_getObjCDeclQualifiers(Cursor); if (QT != CXObjCDeclQualifier_None) { Index: test/Index/property-getter-setter.m === --- /dev/null +++ test/Index/property-getter-setter.m @@ -0,0 +1,10 @@ +@interface Foo +@property (assign,readwrite,getter=b,setter=c:) id a; +@property (assign,readonly,getter=e) id d; +@property (assign,readwrite) id f; +@end + +// RUN: c-index-test -test-print-type-declaration %s | FileCheck %s +// CHECK: ObjCPropertyDecl=a:2:52 [getter,assign,readwrite,setter,] (getter=b) (setter=c:) [typedeclaration=id] [typekind=ObjCId] +// CHECK: ObjCPropertyDecl=d:3:41 [readonly,getter,assign,] (getter=e) [typedeclaration=id] [typekind=ObjCId] +// CHECK: ObjCPropertyDecl=f:4:33 [assign,readwrite,] [typedeclaration=id] [typekind=ObjCId] Index: include/clang-c/Index.h === --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -4449,6 +4449,18 @@ CINDEX_LINKAGE unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C, unsigned reserved); +/** + * Given a cursor that represents a property declaration, return the + * name of the method that implements the getter. + */ +CINDEX_LINKAGE CXString clang_Cursor_getObjCPropertyGetterName(CXCursor C); + +/** + * Given a cursor that represents a property declaration, return the + * name of the method that implements the setter, if any. + */ +CINDEX_LINKAGE CXString clang_Cursor_getObjCPropertySetterName(CXCursor C); + /** * 'Qualifiers' written next to the return and parameter types in * Objective-C method declarations. ___ cfe-commits
[PATCH] D49063: [libclang 1/8] Add support for ObjCObjectType
michaelwu updated this revision to Diff 156692. michaelwu added a comment. `clang_Type_getNumObjCTypeArgs` and `clang_Type_getNumObjCProtocolRefs` now return unsigned. I've bumped `CINDEX_VERSION_MINOR` in https://reviews.llvm.org/D49635 , which is the last in this patch series. https://reviews.llvm.org/D49063 Files: include/clang-c/Index.h test/Index/objc-typeargs-protocols.m test/Index/print-type.m tools/c-index-test/c-index-test.c tools/libclang/CXType.cpp tools/libclang/libclang.exports Index: tools/libclang/libclang.exports === --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -98,6 +98,11 @@ clang_Type_visitFields clang_Type_getNamedType clang_Type_isTransparentTagTypedef +clang_Type_getObjCObjectBaseType +clang_Type_getNumObjCProtocolRefs +clang_Type_getObjCProtocolDecl +clang_Type_getNumObjCTypeArgs +clang_Type_getObjCTypeArg clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString Index: tools/libclang/CXType.cpp === --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -98,6 +98,7 @@ TKCASE(Enum); TKCASE(Typedef); TKCASE(ObjCInterface); +TKCASE(ObjCObject); TKCASE(ObjCObjectPointer); TKCASE(FunctionNoProto); TKCASE(FunctionProto); @@ -575,6 +576,7 @@ TKIND(Enum); TKIND(Typedef); TKIND(ObjCInterface); +TKIND(ObjCObject); TKIND(ObjCObjectPointer); TKIND(FunctionNoProto); TKIND(FunctionProto); @@ -1098,6 +1100,74 @@ return MakeCXType(QT.getValueOr(QualType()), GetTU(CT)); } +CXType clang_Type_getObjCObjectBaseType(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return MakeCXType(QualType(), GetTU(CT)); + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return MakeCXType(QualType(), GetTU(CT)); + + return MakeCXType(OT->getBaseType(), GetTU(CT)); +} + +unsigned clang_Type_getNumObjCProtocolRefs(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return 0; + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return 0; + + return OT->getNumProtocols(); +} + +CXCursor clang_Type_getObjCProtocolDecl(CXType CT, unsigned i) { + QualType T = GetQualType(CT); + if (T.isNull()) +return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); + + const ObjCProtocolDecl *PD = OT->getProtocol(i); + if (!PD) +return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); + + return cxcursor::MakeCXCursor(PD, GetTU(CT)); +} + +unsigned clang_Type_getNumObjCTypeArgs(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return 0; + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return 0; + + return OT->getTypeArgs().size(); +} + +CXType clang_Type_getObjCTypeArg(CXType CT, unsigned i) { + QualType T = GetQualType(CT); + if (T.isNull()) +return MakeCXType(QualType(), GetTU(CT)); + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return MakeCXType(QualType(), GetTU(CT)); + + const ArrayRef TA = OT->getTypeArgs(); + if ((size_t)i >= TA.size()) +return MakeCXType(QualType(), GetTU(CT)); + + return MakeCXType(TA[i], GetTU(CT)); +} + unsigned clang_Type_visitFields(CXType PT, CXFieldVisitor visitor, CXClientData client_data){ Index: tools/c-index-test/c-index-test.c === --- tools/c-index-test/c-index-test.c +++ tools/c-index-test/c-index-test.c @@ -1500,6 +1500,7 @@ CXClientData d) { if (!clang_isInvalid(clang_getCursorKind(cursor))) { CXType T = clang_getCursorType(cursor); +CXType PT = clang_getPointeeType(T); enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T); PrintCursor(cursor, NULL); PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]"); @@ -1545,11 +1546,45 @@ printf("]"); } } +/* Print ObjC base types, type arguments, and protocol list if available. */ +{ + CXType BT = clang_Type_getObjCObjectBaseType(PT); + if (BT.kind != CXType_Invalid) { +PrintTypeAndTypeKind(BT, " [basetype=%s] [basekind=%s]"); + } +} +{ + unsigned NumTypeArgs = clang_Type_getNumObjCTypeArgs(PT); + if (NumTypeArgs > 0) { +unsigned i; +printf(" [typeargs="); +for (i = 0; i < NumTypeArgs; ++i) { + CXType TA = clang_Type_getObjCTypeArg(PT, i); + if (TA.kind != CXType_Invalid) { +PrintTypeAndTypeKind(TA, " [%s] [%s]"); + } +} +printf("]"); + } +} +{ + unsigned NumProtocols = clang_Type_getNumObjCProtocolRefs(PT); + if (NumProtoco
[PATCH] D49127: [libclang 5/8] Add support for ObjC attributes without args
michaelwu added a comment. Some of the CHECKs in the test will be reordered to pass, but it's still the same test. Repository: rC Clang https://reviews.llvm.org/D49127 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49634: [libclang 7/8] Add support for getting property setter and getter names
michaelwu added a comment. The patch will be adjusted slightly to replace a // comment with a /* */ comment. Repository: rC Clang https://reviews.llvm.org/D49634 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49635: [libclang 8/8] Add support for the flag_enum attribute
michaelwu added a comment. Thanks for the reviews! Repository: rC Clang https://reviews.llvm.org/D49635 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D50318: Support Swift in platform availability attribute
michaelwu created this revision. michaelwu added reviewers: manmanren, friss, doug.gregor. This adds support for Swift platform availability attributes. It's largely a port of the changes made to https://github.com/apple/swift-clang/ for Swift availability attributes. Specifically, https://github.com/apple/swift-clang/commit/84b5a21c31cb5b0d7d958a478bc01964939b6952 and https://github.com/apple/swift-clang/commit/e5b87f265aede41c8381094bbf54e2715c8293b0 . The implementation of attribute_availability_swift is a little different and additional tests in test/Index/availability.c were added. Repository: rC Clang https://reviews.llvm.org/D50318 Files: include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/Features.def lib/Parse/ParseDecl.cpp lib/Sema/SemaDeclAttr.cpp test/Index/availability.c test/Sema/attr-availability-swift.c Index: test/Sema/attr-availability-swift.c === --- /dev/null +++ test/Sema/attr-availability-swift.c @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -ast-dump %s | FileCheck %s +// + +#if !__has_feature(attribute_availability_with_message) +# error "Missing __has_feature" +#endif + +#if __has_feature(attribute_availability_swift) +# warning "okay" +// expected-warning@-1{{okay}} +#else +# error "Missing __has_feature" +#endif + +extern int noSwiftGlobal1 __attribute__((availability(swift, unavailable))); +// CHECK: AvailabilityAttr {{.*}}swift 0 0 0 Unavailable "" "" +extern int noSwiftGlobal1 __attribute__((availability(macosx, introduced=10.1))); // okay +// CHECK: AvailabilityAttr {{.*}}macos 10.1 0 0 "" "" +// CHECK: AvailabilityAttr {{.*}}Inherited swift 0 0 0 Unavailable "" "" +extern int noSwiftGlobal1 __attribute__((availability(swift, unavailable, message="and this one has a message"))); // okay +// CHECK: AvailabilityAttr {{.*}}swift 0 0 0 Unavailable "and this one has a message" "" +// CHECK: AvailabilityAttr {{.*}}Inherited macos 10.1 0 0 "" "" +extern int noSwiftGlobal2 __attribute__((availability(swift, introduced=5))); // expected-warning{{only 'unavailable' and 'deprecated' are supported for Swift availability}} +// CHECK: VarDecl +// CHECK-NOT: AvailabilityAttr +extern int noSwiftGlobal3 __attribute__((availability(swift, deprecated, message="t"))); +// CHECK: VarDecl +// CHECK: AvailabilityAttr {{.*}}swift 0 1 0 "t" "" Index: test/Index/availability.c === --- test/Index/availability.c +++ test/Index/availability.c @@ -14,9 +14,14 @@ 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))); +void foo2(void) __attribute__((availability(swift,unavailable))); +void foo3(void) __attribute__((availability(swift,deprecated))); + // 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) +// CHECK: FunctionDecl=foo2:17:6{{.*}}(swift, unavailable) +// CHECK: FunctionDecl=foo3:18:6{{.*}}(swift, deprecated=1) Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -2365,6 +2365,15 @@ if (const auto *SE = dyn_cast_or_null(AL.getReplacementExpr())) Replacement = SE->getString(); + if (II->getName() == "swift") { +if (Introduced.isValid() || Obsoleted.isValid() || +(!IsUnavailable && !Deprecated.isValid())) { + S.Diag(AL.getLoc(), + diag::warn_availability_swift_unavailable_deprecated_only); + return; +} + } + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, AL.getRange(), II, false/*Implicit*/, Introduced.Version, Index: lib/Parse/ParseDecl.cpp === --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -1001,6 +1001,21 @@ continue; } +if (Keyword == Ident_deprecated && Platform->Ident
[PATCH] D50318: Support Swift in platform availability attribute
michaelwu updated this revision to Diff 173607. michaelwu added a comment. Thanks for the review! All requested changes have been made, and I also had to fix a test due to https://reviews.llvm.org/D50214 https://reviews.llvm.org/D50318 Files: include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/Features.def lib/Parse/ParseDecl.cpp lib/Sema/SemaDeclAttr.cpp test/Index/availability.c test/Sema/attr-availability-swift.c Index: test/Sema/attr-availability-swift.c === --- test/Sema/attr-availability-swift.c +++ test/Sema/attr-availability-swift.c @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -fblocks -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 -fsyntax-only -ast-dump %s | FileCheck %s +// + +#if !__has_feature(attribute_availability_with_message) +# error "Missing __has_feature" +#endif + +#if __has_feature(attribute_availability_swift) +# warning "okay" +// expected-warning@-1{{okay}} +#else +# error "Missing __has_feature" +#endif + +extern int noSwiftGlobal1 __attribute__((availability(swift, unavailable))); +// CHECK: AvailabilityAttr {{.*}}swift 0 0 0 Unavailable "" "" +extern int noSwiftGlobal1 __attribute__((availability(macosx, introduced=10.1))); // okay +// CHECK: AvailabilityAttr {{.*}}Inherited swift 0 0 0 Unavailable "" "" +// CHECK: AvailabilityAttr {{.*}}macos 10.1 0 0 "" "" +extern int noSwiftGlobal1 __attribute__((availability(swift, unavailable, message="and this one has a message"))); // okay +// CHECK: AvailabilityAttr {{.*}}Inherited macos 10.1 0 0 "" "" +// CHECK: AvailabilityAttr {{.*}}swift 0 0 0 Unavailable "and this one has a message" "" +extern int noSwiftGlobal2 __attribute__((availability(swift, introduced=5))); // expected-warning{{only 'unavailable' and 'deprecated' are supported for Swift availability}} +// CHECK: VarDecl +// CHECK-NOT: AvailabilityAttr +extern int noSwiftGlobal3 __attribute__((availability(swift, deprecated, message="t"))); +// CHECK: VarDecl +// CHECK: AvailabilityAttr {{.*}}swift 0 1 0 "t" "" Index: test/Index/availability.c === --- test/Index/availability.c +++ test/Index/availability.c @@ -14,9 +14,14 @@ 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))); +void foo2(void) __attribute__((availability(swift,unavailable))); +void foo3(void) __attribute__((availability(swift,deprecated))); + // 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) +// CHECK: FunctionDecl=foo2:17:6{{.*}}(swift, unavailable) +// CHECK: FunctionDecl=foo3:18:6{{.*}}(swift, deprecated=1) Index: lib/Sema/SemaDeclAttr.cpp === --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -2410,6 +2410,15 @@ if (const auto *SE = dyn_cast_or_null(AL.getReplacementExpr())) Replacement = SE->getString(); + if (II->isStr("swift")) { +if (Introduced.isValid() || Obsoleted.isValid() || +(!IsUnavailable && !Deprecated.isValid())) { + S.Diag(AL.getLoc(), + diag::warn_availability_swift_unavailable_deprecated_only); + return; +} + } + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, AL.getRange(), II, false/*Implicit*/, Introduced.Version, Index: lib/Parse/ParseDecl.cpp === --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -1001,6 +1001,21 @@ continue; } +if (Keyword == Ident_deprecated && Platform->Ident && +Platform->Ident->isStr("swift")) { + // For swift, we deprecate for all versions. + if (Changes[Deprecated].KeywordLoc.isValid()) { +Diag(KeywordLoc, diag::err_availability_redundant) + << Keyword + << SourceRange(Changes[Deprecated].KeywordLoc); + } + + Changes[Deprecated].KeywordLoc = KeywordLoc; + // Use a fake version here. +
[PATCH] D49063: [libclang] Add support for ObjCObjectType
michaelwu created this revision. This patch adds support to the clang-c API for identifying ObjCObjects in CXTypes, enumerating type args and protocols on ObjCObjectTypes, and retrieving the base type of ObjCObjectTypes. Currently only ObjCInterfaceTypes are exposed, which do not have type args or protocols. Repository: rC Clang https://reviews.llvm.org/D49063 Files: include/clang-c/Index.h test/Index/objc-typeargs-protocols.m test/Index/print-type.m tools/c-index-test/c-index-test.c tools/libclang/CXType.cpp tools/libclang/libclang.exports Index: tools/libclang/libclang.exports === --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -98,6 +98,11 @@ clang_Type_visitFields clang_Type_getNamedType clang_Type_isTransparentTagTypedef +clang_Type_getObjCObjectBaseType +clang_Type_getNumObjCProtocolRefs +clang_Type_getObjCProtocolDecl +clang_Type_getNumObjCTypeArgs +clang_Type_getObjCTypeArg clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString Index: tools/libclang/CXType.cpp === --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -98,6 +98,7 @@ TKCASE(Enum); TKCASE(Typedef); TKCASE(ObjCInterface); +TKCASE(ObjCObject); TKCASE(ObjCObjectPointer); TKCASE(FunctionNoProto); TKCASE(FunctionProto); @@ -575,6 +576,7 @@ TKIND(Enum); TKIND(Typedef); TKIND(ObjCInterface); +TKIND(ObjCObject); TKIND(ObjCObjectPointer); TKIND(FunctionNoProto); TKIND(FunctionProto); @@ -1098,6 +1100,74 @@ return MakeCXType(QT.getValueOr(QualType()), GetTU(CT)); } +CXType clang_Type_getObjCObjectBaseType(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return MakeCXType(QualType(), GetTU(CT)); + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return MakeCXType(QualType(), GetTU(CT)); + + return MakeCXType(OT->getBaseType(), GetTU(CT)); +} + +int clang_Type_getNumObjCProtocolRefs(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return -1; + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return -1; + + return OT->getNumProtocols(); +} + +CXCursor clang_Type_getObjCProtocolDecl(CXType CT, unsigned i) { + QualType T = GetQualType(CT); + if (T.isNull()) +return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); + + const ObjCProtocolDecl *PD = OT->getProtocol(i); + if (!PD) +return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); + + return cxcursor::MakeCXCursor(PD, GetTU(CT)); +} + +int clang_Type_getNumObjCTypeArgs(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return -1; + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return -1; + + return OT->getTypeArgs().size(); +} + +CXType clang_Type_getObjCTypeArg(CXType CT, unsigned i) { + QualType T = GetQualType(CT); + if (T.isNull()) +return MakeCXType(QualType(), GetTU(CT)); + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return MakeCXType(QualType(), GetTU(CT)); + + const ArrayRef TA = OT->getTypeArgs(); + if ((size_t)i >= TA.size()) +return MakeCXType(QualType(), GetTU(CT)); + + return MakeCXType(TA[i], GetTU(CT)); +} + unsigned clang_Type_visitFields(CXType PT, CXFieldVisitor visitor, CXClientData client_data){ Index: tools/c-index-test/c-index-test.c === --- tools/c-index-test/c-index-test.c +++ tools/c-index-test/c-index-test.c @@ -1500,6 +1500,7 @@ CXClientData d) { if (!clang_isInvalid(clang_getCursorKind(cursor))) { CXType T = clang_getCursorType(cursor); +CXType PT = clang_getPointeeType(T); enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T); PrintCursor(cursor, NULL); PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]"); @@ -1545,11 +1546,45 @@ printf("]"); } } +/* Print ObjC base types, type arguments, and protocol list if available. */ +{ + CXType BT = clang_Type_getObjCObjectBaseType(PT); + if (BT.kind != CXType_Invalid) { +PrintTypeAndTypeKind(BT, " [basetype=%s] [basekind=%s]"); + } +} +{ + int NumTypeArgs = clang_Type_getNumObjCTypeArgs(PT); + if (NumTypeArgs > 0) { +int i; + printf(" [typeargs="); + for (i = 0; i < NumTypeArgs; ++i) { + CXType TA = clang_Type_getObjCTypeArg(PT, i); + if (TA.kind != CXType_Invalid) { +PrintTypeAndTypeKind(TA, " [%s] [%s]"); + } + } + printf("]"); + } +} +{ + int NumProtocols = clang_Type_getNumObjCProtocolRefs(PT); + if (NumProtocols > 0) { +
[PATCH] D49063: [libclang] Add support for ObjCObjectType
michaelwu updated this revision to Diff 154540. michaelwu added a comment. Replaced tabs with spaces. https://reviews.llvm.org/D49063 Files: include/clang-c/Index.h test/Index/objc-typeargs-protocols.m test/Index/print-type.m tools/c-index-test/c-index-test.c tools/libclang/CXType.cpp tools/libclang/libclang.exports Index: tools/libclang/libclang.exports === --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -98,6 +98,11 @@ clang_Type_visitFields clang_Type_getNamedType clang_Type_isTransparentTagTypedef +clang_Type_getObjCObjectBaseType +clang_Type_getNumObjCProtocolRefs +clang_Type_getObjCProtocolDecl +clang_Type_getNumObjCTypeArgs +clang_Type_getObjCTypeArg clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString Index: tools/libclang/CXType.cpp === --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -98,6 +98,7 @@ TKCASE(Enum); TKCASE(Typedef); TKCASE(ObjCInterface); +TKCASE(ObjCObject); TKCASE(ObjCObjectPointer); TKCASE(FunctionNoProto); TKCASE(FunctionProto); @@ -575,6 +576,7 @@ TKIND(Enum); TKIND(Typedef); TKIND(ObjCInterface); +TKIND(ObjCObject); TKIND(ObjCObjectPointer); TKIND(FunctionNoProto); TKIND(FunctionProto); @@ -1098,6 +1100,74 @@ return MakeCXType(QT.getValueOr(QualType()), GetTU(CT)); } +CXType clang_Type_getObjCObjectBaseType(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return MakeCXType(QualType(), GetTU(CT)); + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return MakeCXType(QualType(), GetTU(CT)); + + return MakeCXType(OT->getBaseType(), GetTU(CT)); +} + +int clang_Type_getNumObjCProtocolRefs(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return -1; + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return -1; + + return OT->getNumProtocols(); +} + +CXCursor clang_Type_getObjCProtocolDecl(CXType CT, unsigned i) { + QualType T = GetQualType(CT); + if (T.isNull()) +return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); + + const ObjCProtocolDecl *PD = OT->getProtocol(i); + if (!PD) +return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); + + return cxcursor::MakeCXCursor(PD, GetTU(CT)); +} + +int clang_Type_getNumObjCTypeArgs(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return -1; + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return -1; + + return OT->getTypeArgs().size(); +} + +CXType clang_Type_getObjCTypeArg(CXType CT, unsigned i) { + QualType T = GetQualType(CT); + if (T.isNull()) +return MakeCXType(QualType(), GetTU(CT)); + + const ObjCObjectType *OT = dyn_cast(T); + if (!OT) +return MakeCXType(QualType(), GetTU(CT)); + + const ArrayRef TA = OT->getTypeArgs(); + if ((size_t)i >= TA.size()) +return MakeCXType(QualType(), GetTU(CT)); + + return MakeCXType(TA[i], GetTU(CT)); +} + unsigned clang_Type_visitFields(CXType PT, CXFieldVisitor visitor, CXClientData client_data){ Index: tools/c-index-test/c-index-test.c === --- tools/c-index-test/c-index-test.c +++ tools/c-index-test/c-index-test.c @@ -1500,6 +1500,7 @@ CXClientData d) { if (!clang_isInvalid(clang_getCursorKind(cursor))) { CXType T = clang_getCursorType(cursor); +CXType PT = clang_getPointeeType(T); enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T); PrintCursor(cursor, NULL); PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]"); @@ -1545,11 +1546,45 @@ printf("]"); } } +/* Print ObjC base types, type arguments, and protocol list if available. */ +{ + CXType BT = clang_Type_getObjCObjectBaseType(PT); + if (BT.kind != CXType_Invalid) { +PrintTypeAndTypeKind(BT, " [basetype=%s] [basekind=%s]"); + } +} +{ + int NumTypeArgs = clang_Type_getNumObjCTypeArgs(PT); + if (NumTypeArgs > 0) { +int i; +printf(" [typeargs="); +for (i = 0; i < NumTypeArgs; ++i) { + CXType TA = clang_Type_getObjCTypeArg(PT, i); + if (TA.kind != CXType_Invalid) { +PrintTypeAndTypeKind(TA, " [%s] [%s]"); + } +} +printf("]"); + } +} +{ + int NumProtocols = clang_Type_getNumObjCProtocolRefs(PT); + if (NumProtocols > 0) { +int i; +printf(" [protocols="); +for (i = 0; i < NumProtocols; ++i) { + CXCursor P = clang_Type_getObjCProtocolDecl(PT, i); + if (!clang_isInvalid(cl
[PATCH] D49066: [libclang] Add support for ObjCTypeParam
michaelwu created this revision. This patch adds support to the libclang API for identifying ObjCTypeParams in CXTypes. This patch depends on https://reviews.llvm.org/D49063 since both patches add new values to CXTypeKind. Repository: rC Clang https://reviews.llvm.org/D49066 Files: include/clang-c/Index.h test/Index/print-type.m tools/libclang/CXType.cpp Index: tools/libclang/CXType.cpp === --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -100,6 +100,7 @@ TKCASE(ObjCInterface); TKCASE(ObjCObject); TKCASE(ObjCObjectPointer); +TKCASE(ObjCTypeParam); TKCASE(FunctionNoProto); TKCASE(FunctionProto); TKCASE(ConstantArray); @@ -578,6 +579,7 @@ TKIND(ObjCInterface); TKIND(ObjCObject); TKIND(ObjCObjectPointer); +TKIND(ObjCTypeParam); TKIND(FunctionNoProto); TKIND(FunctionProto); TKIND(ConstantArray); Index: test/Index/print-type.m === --- test/Index/print-type.m +++ test/Index/print-type.m @@ -7,6 +7,10 @@ @property (class) int classProp; @end +@interface Bar : Foo +-(SomeType)generic; +@end + // RUN: c-index-test -test-print-type %s | FileCheck %s // CHECK: ObjCPropertyDecl=x:2:25 [readonly,] [type=id] [typekind=ObjCId] [canonicaltype=id] [canonicaltypekind=ObjCObjectPointer] [isPOD=1] // CHECK: ObjCInstanceMethodDecl=mymethod:3:8 [type=] [typekind=Invalid] [resulttype=int] [resulttypekind=Int] [isPOD=0] @@ -17,3 +21,4 @@ // CHECK: ParmDecl=j:5:49 (Definition) [Out,] [type=short *] [typekind=Pointer] [isPOD=1] [pointeetype=short] [pointeekind=Short] // CHECK: ParmDecl=p:6:36 (Definition) [type=__kindof Foo *] [typekind=ObjCObjectPointer] [canonicaltype=__kindof Foo *] [canonicaltypekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [isPOD=1] [pointeetype=Foo] [pointeekind=ObjCInterface] // CHECK: ObjCPropertyDecl=classProp:7:23 [class,] [type=int] [typekind=Int] [isPOD=1] +// CHECK: ObjCInstanceMethodDecl=generic:11:12 [type=] [typekind=Invalid] [resulttype=SomeType] [resulttypekind=ObjCTypeParam] [isPOD=0] Index: include/clang-c/Index.h === --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -3268,7 +3268,8 @@ CXType_OCLQueue = 159, CXType_OCLReserveID = 160, - CXType_ObjCObject = 161 + CXType_ObjCObject = 161, + CXType_ObjCTypeParam = 162 }; /** Index: tools/libclang/CXType.cpp === --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -100,6 +100,7 @@ TKCASE(ObjCInterface); TKCASE(ObjCObject); TKCASE(ObjCObjectPointer); +TKCASE(ObjCTypeParam); TKCASE(FunctionNoProto); TKCASE(FunctionProto); TKCASE(ConstantArray); @@ -578,6 +579,7 @@ TKIND(ObjCInterface); TKIND(ObjCObject); TKIND(ObjCObjectPointer); +TKIND(ObjCTypeParam); TKIND(FunctionNoProto); TKIND(FunctionProto); TKIND(ConstantArray); Index: test/Index/print-type.m === --- test/Index/print-type.m +++ test/Index/print-type.m @@ -7,6 +7,10 @@ @property (class) int classProp; @end +@interface Bar : Foo +-(SomeType)generic; +@end + // RUN: c-index-test -test-print-type %s | FileCheck %s // CHECK: ObjCPropertyDecl=x:2:25 [readonly,] [type=id] [typekind=ObjCId] [canonicaltype=id] [canonicaltypekind=ObjCObjectPointer] [isPOD=1] // CHECK: ObjCInstanceMethodDecl=mymethod:3:8 [type=] [typekind=Invalid] [resulttype=int] [resulttypekind=Int] [isPOD=0] @@ -17,3 +21,4 @@ // CHECK: ParmDecl=j:5:49 (Definition) [Out,] [type=short *] [typekind=Pointer] [isPOD=1] [pointeetype=short] [pointeekind=Short] // CHECK: ParmDecl=p:6:36 (Definition) [type=__kindof Foo *] [typekind=ObjCObjectPointer] [canonicaltype=__kindof Foo *] [canonicaltypekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [isPOD=1] [pointeetype=Foo] [pointeekind=ObjCInterface] // CHECK: ObjCPropertyDecl=classProp:7:23 [class,] [type=int] [typekind=Int] [isPOD=1] +// CHECK: ObjCInstanceMethodDecl=generic:11:12 [type=] [typekind=Invalid] [resulttype=SomeType] [resulttypekind=ObjCTypeParam] [isPOD=0] Index: include/clang-c/Index.h === --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -3268,7 +3268,8 @@ CXType_OCLQueue = 159, CXType_OCLReserveID = 160, - CXType_ObjCObject = 161 + CXType_ObjCObject = 161, + CXType_ObjCTypeParam = 162 }; /** ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49081: [libclang] Add support for AttributedType
michaelwu created this revision. This patch adds support to the libclang API for identifying AttributedTypes in CXTypes and reading the modified type that the type points to. Currently AttributedTypes are skipped. This patch continues to skip AttributedTypes by default, but adds a parsing option to CXTranslationUnit to include AttributedTypes. This patch depends on https://reviews.llvm.org/D49066 since it also adds a CXType. Testing will be added in another patch which depends on this one. Repository: rC Clang https://reviews.llvm.org/D49081 Files: include/clang-c/Index.h tools/libclang/CXType.cpp tools/libclang/libclang.exports Index: tools/libclang/libclang.exports === --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -103,6 +103,7 @@ clang_Type_getObjCProtocolDecl clang_Type_getNumObjCTypeArgs clang_Type_getObjCTypeArg +clang_Type_getModifiedType clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString Index: tools/libclang/CXType.cpp === --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -112,6 +112,7 @@ TKCASE(Auto); TKCASE(Elaborated); TKCASE(Pipe); +TKCASE(Attributed); default: return CXType_Unexposed; } @@ -125,7 +126,9 @@ if (TU && !T.isNull()) { // Handle attributed types as the original type if (auto *ATT = T->getAs()) { - return MakeCXType(ATT->getModifiedType(), TU); + if (!(TU->ParsingOptions & CXTranslationUnit_IncludeAttributedTypes)) { +return MakeCXType(ATT->getModifiedType(), TU); + } } // Handle paren types as the original type if (auto *PTT = T->getAs()) { @@ -591,6 +594,7 @@ TKIND(Auto); TKIND(Elaborated); TKIND(Pipe); +TKIND(Attributed); #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) TKIND(Id); #include "clang/Basic/OpenCLImageTypes.def" #undef IMAGE_TYPE @@ -996,6 +1000,17 @@ return CXTypeLayoutError_InvalidFieldName; } +CXType clang_Type_getModifiedType(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return MakeCXType(QualType(), GetTU(CT)); + + if (auto *ATT = T->getAs()) +return MakeCXType(ATT->getModifiedType(), GetTU(CT)); + + return MakeCXType(QualType(), GetTU(CT)); +} + long long clang_Cursor_getOffsetOfField(CXCursor C) { if (clang_isDeclaration(C.kind)) { // we need to validate the parent type Index: include/clang-c/Index.h === --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -1332,7 +1332,12 @@ * * The function bodies of the main file are not skipped. */ - CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 0x800 + CXTranslationUnit_LimitSkipFunctionBodiesToPreamble = 0x800, + + /** + * Used to indicate that attributed types should be included in CXType. + */ + CXTranslationUnit_IncludeAttributedTypes = 0x1000 }; /** @@ -3269,7 +3274,8 @@ CXType_OCLReserveID = 160, CXType_ObjCObject = 161, - CXType_ObjCTypeParam = 162 + CXType_ObjCTypeParam = 162, + CXType_Attributed = 163 }; /** @@ -3818,6 +3824,13 @@ */ CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S); +/** + * Return the type that was modified by this attributed type. + * + * If the type is not an attributed type, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getModifiedType(CXType T); + /** * Return the offset of the field represented by the Cursor. * ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49082: [libclang] Add the clang_Type_getNullability() API
michaelwu created this revision. This patch adds a clang-c API for querying the nullability of an AttributedType. The test here also tests https://reviews.llvm.org/D49081 Repository: rC Clang https://reviews.llvm.org/D49082 Files: include/clang-c/Index.h test/Index/nullability.c tools/c-index-test/c-index-test.c tools/libclang/CXType.cpp tools/libclang/libclang.exports Index: tools/libclang/libclang.exports === --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -104,6 +104,7 @@ clang_Type_getNumObjCTypeArgs clang_Type_getObjCTypeArg clang_Type_getModifiedType +clang_Type_getNullability clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString Index: tools/libclang/CXType.cpp === --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -1240,3 +1240,22 @@ } return false; } + +enum CXTypeNullabilityKind clang_Type_getNullability(CXType CT) { + QualType T = GetQualType(CT); + if (T.isNull()) +return CXTypeNullability_Invalid; + + ASTContext &Ctx = cxtu::getASTUnit(GetTU(CT))->getASTContext(); + if (auto nullability = T->getNullability(Ctx)) { +switch (*nullability) { + case NullabilityKind::NonNull: +return CXTypeNullability_NonNull; + case NullabilityKind::Nullable: +return CXTypeNullability_Nullable; + case NullabilityKind::Unspecified: +return CXTypeNullability_Unspecified; +} + } + return CXTypeNullability_Invalid; +} Index: tools/c-index-test/c-index-test.c === --- tools/c-index-test/c-index-test.c +++ tools/c-index-test/c-index-test.c @@ -84,6 +84,8 @@ options |= CXTranslationUnit_KeepGoing; if (getenv("CINDEXTEST_LIMIT_SKIP_FUNCTION_BODIES_TO_PREAMBLE")) options |= CXTranslationUnit_LimitSkipFunctionBodiesToPreamble; + if (getenv("CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES")) +options |= CXTranslationUnit_IncludeAttributedTypes; return options; } @@ -1496,14 +1498,31 @@ } } +static void PrintNullabilityKind(CXType T, const char *Format) { + enum CXTypeNullabilityKind N = clang_Type_getNullability(T); + + const char *nullability = 0; + switch (N) { +case CXTypeNullability_NonNull: nullability = "nonnull"; break; +case CXTypeNullability_Nullable: nullability = "nullable"; break; +case CXTypeNullability_Unspecified: nullability = "unspecified"; break; +case CXTypeNullability_Invalid: break; + } + + if (nullability) { +printf(Format, nullability); + } +} + static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p, CXClientData d) { if (!clang_isInvalid(clang_getCursorKind(cursor))) { CXType T = clang_getCursorType(cursor); CXType PT = clang_getPointeeType(T); enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T); PrintCursor(cursor, NULL); PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]"); +PrintNullabilityKind(T, " [nullability=%s]"); if (clang_isConstQualifiedType(T)) printf(" const"); if (clang_isVolatileQualifiedType(T)) @@ -1524,12 +1543,20 @@ PrintTypeTemplateArgs(CT, " [canonicaltemplateargs/%d="); } } +/* Print the modified type if it exists. */ +{ + CXType MT = clang_Type_getModifiedType(T); + if (MT.kind != CXType_Invalid) { +PrintTypeAndTypeKind(MT, " [modifiedtype=%s] [modifiedtypekind=%s]"); + } +} /* Print the return type if it exists. */ { CXType RT = clang_getCursorResultType(cursor); if (RT.kind != CXType_Invalid) { PrintTypeAndTypeKind(RT, " [resulttype=%s] [resulttypekind=%s]"); } + PrintNullabilityKind(RT, " [resultnullability=%s]"); } /* Print the argument types if they exist. */ { @@ -1541,6 +1568,7 @@ CXType T = clang_getCursorType(clang_Cursor_getArgument(cursor, i)); if (T.kind != CXType_Invalid) { PrintTypeAndTypeKind(T, " [%s] [%s]"); +PrintNullabilityKind(T, " [%s]"); } } printf("]"); Index: test/Index/nullability.c === --- /dev/null +++ test/Index/nullability.c @@ -0,0 +1,10 @@ +int *a; +int * _Nonnull b; +int * _Nullable c; +int * _Null_unspecified d; + +// RUN: env CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES=1 c-index-test -test-print-type %s | FileCheck %s +// CHECK: VarDecl=a:1:6 [type=int *] [typekind=Pointer] [isPOD=1] [pointeetype=int] [pointeekind=Int] +// CHECK: VarDecl=b:2:16 [type=int * _Nonnull] [typekind=Attributed] [nullability=nonnull] [canonicaltype=int *] [canonicaltypekind=Pointer] [modifiedtype=int *] [modifiedtypekind=Pointer] [isPOD=1] +// CHECK: VarDecl=c:3:17 [type=int * _Nullable] [typekind=Attribute
[PATCH] D49127: [libclang] Add support for ObjC attributes without args
michaelwu created this revision. This adds support to libclang for identifying ObjC related attributes that don't take arguments. All attributes but NSObject and NSConsumed are tested. Repository: rC Clang https://reviews.llvm.org/D49127 Files: include/clang-c/Index.h test/Index/index-attrs.m tools/libclang/CIndex.cpp tools/libclang/CXCursor.cpp Index: tools/libclang/CXCursor.cpp === --- tools/libclang/CXCursor.cpp +++ tools/libclang/CXCursor.cpp @@ -61,6 +61,23 @@ case attr::Visibility: return CXCursor_VisibilityAttr; case attr::DLLExport: return CXCursor_DLLExport; case attr::DLLImport: return CXCursor_DLLImport; +case attr::NSReturnsRetained: return CXCursor_NSReturnsRetained; +case attr::NSReturnsNotRetained: return CXCursor_NSReturnsNotRetained; +case attr::NSReturnsAutoreleased: return CXCursor_NSReturnsAutoreleased; +case attr::NSConsumesSelf: return CXCursor_NSConsumesSelf; +case attr::NSConsumed: return CXCursor_NSConsumed; +case attr::ObjCException: return CXCursor_ObjCException; +case attr::ObjCNSObject: return CXCursor_ObjCNSObject; +case attr::ObjCIndependentClass: return CXCursor_ObjCIndependentClass; +case attr::ObjCPreciseLifetime: return CXCursor_ObjCPreciseLifetime; +case attr::ObjCReturnsInnerPointer: return CXCursor_ObjCReturnsInnerPointer; +case attr::ObjCRequiresSuper: return CXCursor_ObjCRequiresSuper; +case attr::ObjCRootClass: return CXCursor_ObjCRootClass; +case attr::ObjCSubclassingRestricted: return CXCursor_ObjCSubclassingRestricted; +case attr::ObjCExplicitProtocolImpl: return CXCursor_ObjCExplicitProtocolImpl; +case attr::ObjCDesignatedInitializer: return CXCursor_ObjCDesignatedInitializer; +case attr::ObjCRuntimeVisible: return CXCursor_ObjCRuntimeVisible; +case attr::ObjCBoxable: return CXCursor_ObjCBoxable; } return CXCursor_UnexposedAttr; Index: tools/libclang/CIndex.cpp === --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -5276,6 +5276,40 @@ return cxstring::createRef("attribute(dllexport)"); case CXCursor_DLLImport: return cxstring::createRef("attribute(dllimport)"); + case CXCursor_NSReturnsRetained: +return cxstring::createRef("attribute(ns_returns_retained)"); + case CXCursor_NSReturnsNotRetained: +return cxstring::createRef("attribute(ns_returns_not_retained)"); + case CXCursor_NSReturnsAutoreleased: +return cxstring::createRef("attribute(ns_returns_autoreleased)"); + case CXCursor_NSConsumesSelf: +return cxstring::createRef("attribute(ns_consumes_self)"); + case CXCursor_NSConsumed: +return cxstring::createRef("attribute(ns_consumed)"); + case CXCursor_ObjCException: +return cxstring::createRef("attribute(objc_exception)"); + case CXCursor_ObjCNSObject: +return cxstring::createRef("attribute(NSObject)"); + case CXCursor_ObjCIndependentClass: +return cxstring::createRef("attribute(objc_independent_class)"); + case CXCursor_ObjCPreciseLifetime: +return cxstring::createRef("attribute(objc_precise_lifetime)"); + case CXCursor_ObjCReturnsInnerPointer: +return cxstring::createRef("attribute(objc_returns_inner_pointer)"); + case CXCursor_ObjCRequiresSuper: +return cxstring::createRef("attribute(objc_requires_super)"); + case CXCursor_ObjCRootClass: +return cxstring::createRef("attribute(objc_root_class)"); + case CXCursor_ObjCSubclassingRestricted: +return cxstring::createRef("attribute(objc_subclassing_restricted)"); + case CXCursor_ObjCExplicitProtocolImpl: +return cxstring::createRef("attribute(objc_protocol_requires_explicit_implementation)"); + case CXCursor_ObjCDesignatedInitializer: +return cxstring::createRef("attribute(objc_designated_initializer)"); + case CXCursor_ObjCRuntimeVisible: +return cxstring::createRef("attribute(objc_runtime_visible)"); + case CXCursor_ObjCBoxable: +return cxstring::createRef("attribute(objc_boxable)"); case CXCursor_PreprocessingDirective: return cxstring::createRef("preprocessing directive"); case CXCursor_MacroDefinition: Index: test/Index/index-attrs.m === --- test/Index/index-attrs.m +++ test/Index/index-attrs.m @@ -9,9 +9,48 @@ @property (assign) id prop __attribute__((annotate("anno"))); @end +__attribute__((objc_protocol_requires_explicit_implementation)) +@protocol P +@end + +typedef id __attribute__((objc_independent_class)) T2; +id __attribute__((objc_precise_lifetime)) x; +struct __attribute__((objc_boxable)) S { + int x; +}; + +__attribute__((objc_exception)) +__attribute__((objc_root_class)) +__attribute__((objc_subclassing_restricted)) +__attribute__((objc_runtime_visible)) +@interface J +-(id)a __attribute__((ns_returns_retained)); +-(id)b __attribute__((ns_returns_not_retained)); +-(id)c __attribu
[PATCH] D49063: [libclang] Add support for ObjCObjectType
michaelwu added inline comments. Comment at: include/clang-c/Index.h:35 #define CINDEX_VERSION_MAJOR 0 #define CINDEX_VERSION_MINOR 49 yvvan wrote: > Please, increment the minor version (you are adding new functions) This is one in a series of patches that add features to libclang - would you be ok with incrementing at the end of the series? Comment at: include/clang-c/Index.h:3644 + */ +CINDEX_LINKAGE int clang_Type_getNumObjCProtocolRefs(CXType T); + yvvan wrote: > Other similar calls usually return unsigned int because they can't be below > zero. I was mimicking `clang_Type_getNumTemplateArguments` for this, which appears to be the most similar API. It uses 0 to n for the number of template arguments and -1 to indicate that it was called on the wrong type. If you're ok with the inconsistency, I'll make this unsigned. I also prefer having this unsigned. https://reviews.llvm.org/D49063 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits