Index: include/clang-c/Index.h =================================================================== --- include/clang-c/Index.h +++ include/clang-c/Index.h @@ -3437,6 +3437,16 @@ CINDEX_LINKAGE CXType clang_Type_getNamedType(CXType T); /** + * \brief Determine if a typedef is 'transparent' + * + * A typedef is considered 'transparent' if it shares a name and spelling + * location with its underlying type, as is the case with the NS_ENUM macro + * + * \returns non-zero if transparent and zero otherwise. + */ +CINDEX_LINKAGE unsigned clang_Type_isTransparentTypedef(CXType T); + +/** * \brief List the possible error codes for \c clang_Type_getSizeOf, * \c clang_Type_getAlignOf, \c clang_Type_getOffsetOf and * \c clang_Cursor_getOffsetOf. Index: include/clang/AST/Decl.h =================================================================== --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -2699,6 +2699,10 @@ /// this typedef declaration. TagDecl *getAnonDeclWithTypedefName(bool AnyRedecl = false) const; + /// Determines if this typedef shares a name and spelling location with its + /// underlying type, as is the case with the NS_ENUM macro + bool isTransparent() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { Index: include/clang/Index/USRGeneration.h =================================================================== --- include/clang/Index/USRGeneration.h +++ include/clang/Index/USRGeneration.h @@ -30,10 +30,10 @@ bool generateUSRForDecl(const Decl *D, SmallVectorImpl &Buf); /// \brief Generate a USR fragment for an Objective-C class. -void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS); +void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, StringRef ExtSymbolDefinedIn = ""); /// \brief Generate a USR fragment for an Objective-C class category. -void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS); +void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS, StringRef ExtSymDefinedIn = ""); /// \brief Generate a USR fragment for an Objective-C instance variable. The /// complete USR can be created by concatenating the USR for the @@ -48,7 +48,7 @@ void generateUSRForObjCProperty(StringRef Prop, bool isClassProp, raw_ostream &OS); /// \brief Generate a USR fragment for an Objective-C protocol. -void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS); +void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, StringRef ExtSymDefinedIn = ""); /// \brief Generate a USR for a macro, including the USR prefix. /// Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -4223,6 +4223,19 @@ return nullptr; } +bool TypedefNameDecl::isTransparent() const { + if (auto *TT = getTypeSourceInfo()->getType()->getAs()) { + if (auto *TD = TT->getDecl()) { + if (TD->getName() != getName()) + return false; + SourceManager &SM = getASTContext().getSourceManager(); + if (SM.getSpellingLoc(getLocation()) == SM.getSpellingLoc(TD->getLocation())) + return true; + } + } + return false; +} + TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(), nullptr, nullptr); Index: lib/Index/IndexDecl.cpp =================================================================== --- lib/Index/IndexDecl.cpp +++ lib/Index/IndexDecl.cpp @@ -14,6 +14,16 @@ using namespace clang; using namespace index; +#define TRY_DECL(CALL_EXPR) \ + switch(CALL_EXPR) { \ + case Action::ABORT: \ + return false; \ + case Action::SKIP: \ + return true; \ + case Action::CONTINUE: \ + break; \ + } + #define TRY_TO(CALL_EXPR) \ do { \ if (!CALL_EXPR) \ @@ -101,8 +111,7 @@ SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic; if (D->isImplicit()) Roles |= (SymbolRoleSet)SymbolRole::Implicit; - if (!IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)) - return false; + TRY_DECL(IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)); IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); bool hasIBActionAndFirst = D->hasAttr(); for (const auto *I : D->parameters()) { @@ -134,8 +143,7 @@ } } - if (!IndexCtx.handleDecl(D, Roles, Relations)) - return false; + TRY_DECL(IndexCtx.handleDecl(D, Roles, Relations)); handleDeclarator(D); if (const CXXConstructorDecl *Ctor = dyn_cast(D)) { @@ -161,16 +169,14 @@ } bool VisitVarDecl(const VarDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(IndexCtx.handleDecl(D)); handleDeclarator(D); IndexCtx.indexBody(D->getInit(), D); return true; } bool VisitFieldDecl(const FieldDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(IndexCtx.handleDecl(D)); handleDeclarator(D); if (D->isBitField()) IndexCtx.indexBody(D->getBitWidth(), D); @@ -184,8 +190,7 @@ // handled in VisitObjCPropertyImplDecl return true; } - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(IndexCtx.handleDecl(D)); handleDeclarator(D); return true; } @@ -196,15 +201,13 @@ } bool VisitEnumConstantDecl(const EnumConstantDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(IndexCtx.handleDecl(D)); IndexCtx.indexBody(D->getInitExpr(), D); return true; } bool VisitTypedefNameDecl(const TypedefNameDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(IndexCtx.handleDecl(D)); IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); return true; } @@ -231,20 +234,25 @@ I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { SourceLocation Loc = *LI; ObjCProtocolDecl *PD = *I; - TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, - SymbolRoleSet(), - SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); + TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, SymbolRoleSet(), + SymbolRelation{ + (unsigned)SymbolRole::RelationBaseOf, + ContD + })); } return true; } bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { if (D->isThisDeclarationADefinition()) { - TRY_TO(IndexCtx.handleDecl(D)); + TRY_DECL(IndexCtx.handleDecl(D)); if (auto *SuperD = D->getSuperClass()) { TRY_TO(IndexCtx.handleReference(SuperD, D->getSuperClassLoc(), D, D, - SymbolRoleSet(), - SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); + SymbolRoleSet(), + SymbolRelation{ + (unsigned)SymbolRole::RelationBaseOf, + D + })); } TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); TRY_TO(IndexCtx.indexDeclContext(D)); @@ -257,7 +265,7 @@ bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { if (D->isThisDeclarationADefinition()) { - TRY_TO(IndexCtx.handleDecl(D)); + TRY_DECL(IndexCtx.handleDecl(D)); TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); TRY_TO(IndexCtx.indexDeclContext(D)); } else { @@ -275,8 +283,7 @@ if (Class->isImplicitInterfaceDecl()) IndexCtx.handleDecl(Class); - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(IndexCtx.handleDecl(D)); // Visit implicit @synthesize property implementations first as their // location is reported at the name of the @implementation block. This @@ -305,7 +312,7 @@ SourceLocation CategoryLoc = D->getCategoryNameLoc(); if (!CategoryLoc.isValid()) CategoryLoc = D->getLocation(); - TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); + TRY_DECL(IndexCtx.handleDecl(D, CategoryLoc)); TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); TRY_TO(IndexCtx.indexDeclContext(D)); return true; @@ -322,8 +329,7 @@ SourceLocation CategoryLoc = D->getCategoryNameLoc(); if (!CategoryLoc.isValid()) CategoryLoc = D->getLocation(); - if (!IndexCtx.handleDecl(D, CategoryLoc)) - return false; + TRY_DECL(IndexCtx.handleDecl(D, CategoryLoc)); IndexCtx.indexDeclContext(D); return true; } @@ -345,8 +351,7 @@ if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) handleObjCMethod(MD, D); - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(IndexCtx.handleDecl(D)); if (IBOutletCollectionAttr *attr = D->getAttr()) IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, D->getLexicalDeclContext(), false, true); @@ -367,8 +372,7 @@ Loc = Container->getLocation(); Roles |= (SymbolRoleSet)SymbolRole::Implicit; } - if (!IndexCtx.handleDecl(D, Loc, Roles, Relations)) - return false; + TRY_DECL(IndexCtx.handleDecl(D, Loc, Roles, Relations)); if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) return true; @@ -402,8 +406,7 @@ } else if (D->getLocation() == IvarLoc) { IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; } - if(!IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)) - return false; + TRY_DECL(IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)); } else { IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, D->getDeclContext(), SymbolRoleSet()); @@ -413,8 +416,7 @@ } bool VisitNamespaceDecl(const NamespaceDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(IndexCtx.handleDecl(D)); IndexCtx.indexDeclContext(D); return true; } Index: lib/Index/IndexTypeSourceInfo.cpp =================================================================== --- lib/Index/IndexTypeSourceInfo.cpp +++ lib/Index/IndexTypeSourceInfo.cpp @@ -41,9 +41,14 @@ bool shouldWalkTypesOfTypeLocs() const { return false; } bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { - return IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(), - Parent, ParentDC, SymbolRoleSet(), - Relations); + TypedefNameDecl *ND = TL.getTypedefNameDecl(); + if (ND->isTransparent()) { + TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl(); + return IndexCtx.handleReference(Underlying, TL.getNameLoc(), Parent, + ParentDC, SymbolRoleSet(), Relations); + } + return IndexCtx.handleReference(ND, TL.getNameLoc(), Parent, + ParentDC, SymbolRoleSet(), Relations); } #define TRY_TO(CALL_EXPR) \ @@ -194,7 +199,7 @@ if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D)) return; - if (handleDecl(D)) { + if (handleDecl(D) == Action::CONTINUE) { if (D->isThisDeclarationADefinition()) { indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); if (auto CXXRD = dyn_cast(D)) { Index: lib/Index/IndexingContext.h =================================================================== --- lib/Index/IndexingContext.h +++ lib/Index/IndexingContext.h @@ -33,6 +33,11 @@ namespace index { class IndexDataConsumer; + enum class Action { + CONTINUE, + SKIP, // continue but skip any children + ABORT, + }; class IndexingContext { IndexingOptions IndexOpts; @@ -60,10 +65,10 @@ static bool isTemplateImplicitInstantiation(const Decl *D); - bool handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(), + Action handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(), ArrayRef Relations = None); - bool handleDecl(const Decl *D, SourceLocation Loc, + Action handleDecl(const Decl *D, SourceLocation Loc, SymbolRoleSet Roles = SymbolRoleSet(), ArrayRef Relations = None, const DeclContext *DC = nullptr); Index: lib/Index/IndexingContext.cpp =================================================================== --- lib/Index/IndexingContext.cpp +++ lib/Index/IndexingContext.cpp @@ -17,20 +17,30 @@ using namespace clang; using namespace index; +static bool isGeneratedDecl(const Decl *D) { + if (!D->hasAttr()) + return false; + return D->getAttr()->getGeneratedDeclaration(); +} + bool IndexingContext::shouldIndexFunctionLocalSymbols() const { return IndexOpts.IndexFunctionLocals; } -bool IndexingContext::handleDecl(const Decl *D, +Action IndexingContext::handleDecl(const Decl *D, SymbolRoleSet Roles, ArrayRef Relations) { return handleDecl(D, D->getLocation(), Roles, Relations); } -bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc, +Action IndexingContext::handleDecl(const Decl *D, SourceLocation Loc, SymbolRoleSet Roles, ArrayRef Relations, const DeclContext *DC) { + + if (isGeneratedDecl(D)) + return Action::SKIP; + if (!DC) DC = D->getDeclContext(); @@ -38,9 +48,10 @@ if (isa(D)) { D = cast(D)->getPropertyDecl(); } - return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast(DC), - Roles, Relations, - nullptr, OrigD, DC); + if (handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast(DC), Roles, + Relations, nullptr, OrigD, DC)) + return Action::CONTINUE; + return Action::ABORT; } bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, Index: lib/Index/USRGeneration.cpp =================================================================== --- lib/Index/USRGeneration.cpp +++ lib/Index/USRGeneration.cpp @@ -46,6 +46,12 @@ return false; } +static StringRef GetExternalSourceContainer(const NamedDecl *D) { + if (!D || !D->hasAttr()) + return StringRef(); + return D->getAttr()->getDefinedIn(); +} + namespace { class USRGenerator : public ConstDeclVisitor { SmallVectorImpl &Buf; @@ -116,6 +122,8 @@ return D->getParentFunctionOrMethod() != nullptr; } + void GenExtSymbolContainer(const NamedDecl *D); + /// Generate the string component containing the location of the /// declaration. bool GenLoc(const Decl *D, bool IncludeOffset); @@ -127,13 +135,13 @@ /// itself. /// Generate a USR for an Objective-C class. - void GenObjCClass(StringRef cls) { - generateUSRForObjCClass(cls, Out); + void GenObjCClass(StringRef cls, StringRef ext) { + generateUSRForObjCClass(cls, Out, ext); } /// Generate a USR for an Objective-C class category. - void GenObjCCategory(StringRef cls, StringRef cat) { - generateUSRForObjCCategory(cls, cat, Out); + void GenObjCCategory(StringRef cls, StringRef cat, StringRef ext) { + generateUSRForObjCCategory(cls, cat, Out, ext); } /// Generate a USR fragment for an Objective-C property. @@ -142,8 +150,8 @@ } /// Generate a USR for an Objective-C protocol. - void GenObjCProtocol(StringRef prot) { - generateUSRForObjCProtocol(prot, Out); + void GenObjCProtocol(StringRef prot, StringRef ext) { + generateUSRForObjCProtocol(prot, Out, ext); } void VisitType(QualType T); @@ -204,7 +212,11 @@ if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) return; + const unsigned StartSize = Buf.size(); VisitDeclContext(D->getDeclContext()); + if (Buf.size() == StartSize) + GenExtSymbolContainer(D); + bool IsTemplate = false; if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { IsTemplate = true; @@ -382,7 +394,7 @@ llvm_unreachable("Invalid ObjC container."); case Decl::ObjCInterface: case Decl::ObjCImplementation: - GenObjCClass(D->getName()); + GenObjCClass(D->getName(), GetExternalSourceContainer(D)); break; case Decl::ObjCCategory: { const ObjCCategoryDecl *CD = cast(D); @@ -402,7 +414,7 @@ GenLoc(CD, /*IncludeOffset=*/true); } else - GenObjCCategory(ID->getName(), CD->getName()); + GenObjCCategory(ID->getName(), CD->getName(), GetExternalSourceContainer(ID)); break; } @@ -417,12 +429,14 @@ IgnoreResults = true; return; } - GenObjCCategory(ID->getName(), CD->getName()); + GenObjCCategory(ID->getName(), CD->getName(), GetExternalSourceContainer(ID)); break; } - case Decl::ObjCProtocol: - GenObjCProtocol(cast(D)->getName()); + case Decl::ObjCProtocol: { + const ObjCProtocolDecl *PD = cast(D); + GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD)); break; + } } } @@ -452,6 +466,8 @@ ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) return; + GenExtSymbolContainer(D); + D = D->getCanonicalDecl(); VisitDeclContext(D->getDeclContext()); @@ -544,6 +560,12 @@ GenLoc(D, /*IncludeOffset=*/true); } +void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) { + StringRef Container = GetExternalSourceContainer(D); + if (!Container.empty()) + Out << "@M@" << Container; +} + bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { if (generatedLoc) return IgnoreResults; @@ -866,12 +888,16 @@ // USR generation functions. //===----------------------------------------------------------------------===// -void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) { +void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, StringRef ExtSymDefinedIn) { + if (!ExtSymDefinedIn.empty()) + OS << "@M@" << ExtSymDefinedIn; OS << "objc(cs)" << Cls; } void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat, - raw_ostream &OS) { + raw_ostream &OS, StringRef ExtSymDefinedIn) { + if (!ExtSymDefinedIn.empty()) + OS << "@M@" << ExtSymDefinedIn; OS << "objc(cy)" << Cls << '@' << Cat; } @@ -890,7 +916,9 @@ OS << (isClassProp ? "(cpy)" : "(py)") << Prop; } -void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) { +void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, StringRef ExtSymDefinedIn) { + if (!ExtSymDefinedIn.empty()) + OS << "@M@" << ExtSymDefinedIn; OS << "objc(pl)" << Prot; } Index: test/Index/Core/index-source.m =================================================================== --- test/Index/Core/index-source.m +++ test/Index/Core/index-source.m @@ -301,3 +301,68 @@ // CHECK: [[@LINE-1]]:3 | field/ObjC | _foo | c:objc(cs)I7@_foo | | Ref,Writ,RelCont | rel: 1 } @end + +__attribute__((external_source_symbol(language="Swift", defined_in="some_module", generated_declaration))) +@interface I8 +// CHECK-NOT: [[@LINE-1]]:12 | class/ObjC | I8 | {{.*}} | {{.*}} | Decl | rel: 0 +-(void)method; +// CHECK-NOT: [[@LINE-1]]:8 | instance-method/ObjC | method | {{.*}} | -[I8 method] | Decl,Dyn,RelChild | rel: 1 +@end + +__attribute__((external_source_symbol(language="Swift", defined_in="some_module"))) +@interface I9 +// CHECK: [[@LINE-1]]:12 | class/ObjC | I9 | {{.*}} | {{.*}} | Decl | rel: 0 +-(void)method; +// CHECK: [[@LINE-1]]:8 | instance-method/ObjC | method | {{.*}} | -[I9 method] | Decl,Dyn,RelChild | rel: 1 +@end + + + +typedef enum SomeEnum : int SomeEnum __attribute__((external_source_symbol(language="Swift", defined_in="some_module", generated_declaration))); +// CHECK-NOT: [[@LINE-1]]:29 | type-alias/C | SomeEnum | {{.*}} | {{.*}} | Def | rel: 0 +enum __attribute__((external_source_symbol(language="Swift", defined_in="some_module", generated_declaration))) SomeEnum : int { +// CHECK-NOT: [[@LINE-1]]:90 | enum/C | SomeEnum | {{.*}} | {{.*}} | Def | rel: 0 + SomeEnumFirst = 0, + // CHECK-NOT: [[@LINE-1]]:3 | enumerator/C | SomeEnumFirst | {{.*}} | Def | Def,RelChild | rel: 1 + SomeEnumSecond = 1, + SomeEnumThird = 2, +}; + +SomeEnum someT; +// CHECK: [[@LINE-1]]:1 | type-alias/C | SomeEnum | {{.*}} | {{.*}} | Ref,RelCont | rel: 1 +enum SomeEnum someE; +// CHECK: [[@LINE-1]]:6 | enum/C | SomeEnum | {{.*}} | {{.*}} | Ref,RelCont | rel: 1 + +#define NS_ENUM(_name, _type) enum _name:_type _name; enum _name : _type + +typedef NS_ENUM(AnotherEnum, int) { + AnotherEnumFirst = 0, + AnotherEnumSecond = 1, + AnotherEnumThird = 2, +}; + +AnotherEnum anotherT; +// CHECK: [[@LINE-1]]:1 | enum/C | AnotherEnum | {{.*}} | {{.*}} | Ref,RelCont | rel: 1 +enum AnotherEnum anotherE; +// CHECK: [[@LINE-1]]:6 | enum/C | AnotherEnum | {{.*}} | {{.*}} | Ref,RelCont | rel: 1 + +#define TRANSPARENT(_name) struct _name _name; struct _name +#define OPAQUE(_name) struct _name *_name; struct _name + +typedef TRANSPARENT(AStruct) { + int x; +}; + +AStruct aStructT; +// CHECK: [[@LINE-1]]:1 | struct/C | AStruct | {{.*}} | {{.*}} | Ref,RelCont | rel: 1 +struct AStruct aStructS; +// CHECK: [[@LINE-1]]:8 | struct/C | AStruct | {{.*}} | {{.*}} | Ref,RelCont | rel: 1 + +typedef OPAQUE(Separate) { + int x; +}; + +Separate separateT; +// CHECK: [[@LINE-1]]:1 | type-alias/C | Separate | {{.*}} | {{.*}} | Ref,RelCont | rel: 1 +struct Separate separateE; +// CHECK: [[@LINE-1]]:8 | struct/C | Separate | {{.*}} | {{.*}} | Ref,RelCont | rel: 1 Index: test/Index/get-cursor.c =================================================================== --- test/Index/get-cursor.c +++ test/Index/get-cursor.c @@ -30,4 +30,4 @@ // CHECK: TypeRef=struct _MyS:1:8 // CHECK: VarDecl=x:7:5 // CHECK: VarDecl=y:7:8 -// CHECK: 17:7 MemberRefExpr=field:11:9 \ No newline at end of file +// CHECK: 17:7 MemberRefExpr=field:11:9 Index: test/Index/get-cursor.m =================================================================== --- test/Index/get-cursor.m +++ test/Index/get-cursor.m @@ -129,6 +129,32 @@ } @end +#define NS_ENUM(_name, _type) enum _name : _type _name; enum _name : _type +typedef NS_ENUM(TestTransparent, int) { + TestTransparentFirst = 0, + TestTransparentSecond = 1, +}; +typedef enum TestTransparent NotTransparent; + +TestTransparent transparentTypedef; +enum TestTransparent transparentUnderlying; +NotTransparent opaqueTypedef; + +#define MY_ENUM(_name, _type) enum _name : _type _name##_t; enum _name : _type +typedef MY_ENUM(TokenPaste, int) { + TokenPasteFirst = 0, +}; +TokenPaste_t opaqueTypedef2; + +#define MY_TYPE(_name) struct _name _name; struct _name +typedef MY_TYPE(SomeT) { int x; }; +SomeT someVar; + +#define MY_TYPE2(_name) struct _name *_name; struct _name +typedef MY_TYPE2(SomeT2) { int x; }; +SomeT2 someVar2; + + // RUN: c-index-test -cursor-at=%s:4:28 -cursor-at=%s:5:28 %s | FileCheck -check-prefix=CHECK-PROP %s // CHECK-PROP: ObjCPropertyDecl=foo1:4:26 @@ -193,3 +219,11 @@ // RUN: c-index-test -cursor-at=%s:127:8 %s | FileCheck -check-prefix=CHECK-RECEIVER-WITH-NULLABILITY %s // RUN: c-index-test -cursor-at=%s:128:8 %s | FileCheck -check-prefix=CHECK-RECEIVER-WITH-NULLABILITY %s // CHECK-RECEIVER-WITH-NULLABILITY: Receiver-type=ObjCId + +// RUN: c-index-test -cursor-at=%s:139:1 -cursor-at=%s:140:6 -cursor-at=%s:141:1 -cursor-at=%s:147:1 -cursor-at=%s:151:1 -cursor-at=%s:155:1 %s | FileCheck -check-prefix=CHECK-TRANSPARENT %s +// CHECK-TRANSPARENT: 139:1 TypeRef=TestTransparent:133:17 (Transparent: enum TestTransparent) Extent=[139:1 - 139:16] Spelling=TestTransparent ([139:1 - 139:16]) +// CHECK-TRANSPARENT: 140:6 TypeRef=enum TestTransparent:133:17 Extent=[140:6 - 140:21] Spelling=enum TestTransparent ([140:6 - 140:21]) +// CHECK-TRANSPARENT: 141:1 TypeRef=NotTransparent:137:30 Extent=[141:1 - 141:15] Spelling=NotTransparent ([141:1 - 141:15]) +// CHECK-TRANSPARENT: 147:1 TypeRef=TokenPaste_t:144:9 Extent=[147:1 - 147:13] Spelling=TokenPaste_t ([147:1 - 147:13]) +// CHECK-TRANSPARENT: 151:1 TypeRef=SomeT:150:17 (Transparent: struct SomeT) Extent=[151:1 - 151:6] Spelling=SomeT ([151:1 - 151:6]) +// CHECK-TRANSPARENT: 155:1 TypeRef=SomeT2:154:18 Extent=[155:1 - 155:7] Spelling=SomeT2 ([155:1 - 155:7]) Index: test/Index/usrs.m =================================================================== --- test/Index/usrs.m +++ test/Index/usrs.m @@ -100,6 +100,24 @@ #define MACRO3(X) 123, X #define MACRO3(X) 789, X +void fromSwift() __attribute__((external_source_symbol(language="Swift", defined_in="s_module", generated_declaration))); + +enum WeekDays : int { + MONDAY, + TUESDAY, + WED +} __attribute__((external_source_symbol(language="Swift", defined_in="s_module", generated_declaration))); + +__attribute__((external_source_symbol(language="Swift", defined_in="s_module"))) +@interface IFromSwift +- (void)method; +@end + +__attribute__((external_source_symbol(language="Swift", defined_in="outer_module"))) +@interface IFromSwift2 +- (void)method __attribute__((external_source_symbol(language="Swift", defined_in="inner_module"))); +@end + // RUN: c-index-test -test-load-source-usrs all -target x86_64-apple-macosx10.7 %s -isystem %S/Inputs | FileCheck %s // CHECK: usrs-system.h c:@macro@MACRO_FROM_SYSTEM_HEADER_1 Extent=[1:9 - 1:40] // CHECK: usrs.m c:usrs.m@1265@macro@MACRO1 Extent=[94:9 - 94:19] @@ -169,6 +187,15 @@ // CHECK: usrs.m c:objc(cs)CWithExt2(py)pro_ext Extent=[88:1 - 88:30] // CHECK: usrs.m c:objc(cs)CWithExt2(im)pro_ext Extent=[88:23 - 88:30] // CHECK: usrs.m c:objc(cs)CWithExt2(im)setPro_ext: Extent=[88:23 - 88:30] +// CHECK: usrs.m c:@M@s_module@F@fromSwift Extent=[103:1 - 103:121] +// CHECK: usrs.m c:@M@s_module@E@WeekDays Extent=[105:1 - 109:2] +// CHECK: usrs.m c:@M@s_module@E@WeekDays@MONDAY Extent=[106:3 - 106:9] +// CHECK: usrs.m c:@M@s_module@E@WeekDays@TUESDAY Extent=[107:3 - 107:10] +// CHECK: usrs.m c:@M@s_module@E@WeekDays@WED Extent=[108:3 - 108:6] +// CHECK: usrs.m c:@M@s_moduleobjc(cs)IFromSwift Extent=[112:1 - 114:5] +// CHECK: usrs.m c:@M@s_moduleobjc(cs)IFromSwift(im)method Extent=[113:1 - 113:16] +// CHECK: usrs.m c:@M@outer_moduleobjc(cs)IFromSwift2 Extent=[117:1 - 119:5] +// CHECK: usrs.m c:@M@outer_moduleobjc(cs)IFromSwift2(im)method Extent=[118:1 - 118:101] // RUN: c-index-test -test-load-source all %s -isystem %S/Inputs | FileCheck -check-prefix=CHECK-source %s // CHECK-source: usrs-system.h:1:9: macro definition=MACRO_FROM_SYSTEM_HEADER_1 Extent=[1:9 - 1:40] @@ -306,3 +333,17 @@ // CHECK-source: usrs.m:89:7: ObjCInstanceMethodDecl=methodWithFn::89:7 Extent=[89:1 - 89:41] // CHECK-source: usrs.m:89:38: ParmDecl=fn:89:38 (Definition) Extent=[89:21 - 89:40] // CHECK-source: usrs.m:89:35: ParmDecl=p:89:35 (Definition) Extent=[89:30 - 89:36] +// CHECK-source: usrs.m:103:6: FunctionDecl=fromSwift:103:6 Extent=[103:1 - 103:121] +// CHECK-source: usrs.m:103:33: UnexposedAttr= Extent=[103:33 - 103:119] +// CHECK-source: usrs.m:105:6: EnumDecl=WeekDays:105:6 (Definition) Extent=[105:1 - 109:2] +// CHECK-source: usrs.m:109:18: UnexposedAttr= Extent=[109:18 - 109:104] +// CHECK-source: usrs.m:106:3: EnumConstantDecl=MONDAY:106:3 (Definition) Extent=[106:3 - 106:9] +// CHECK-source: usrs.m:107:3: EnumConstantDecl=TUESDAY:107:3 (Definition) Extent=[107:3 - 107:10] +// CHECK-source: usrs.m:108:3: EnumConstantDecl=WED:108:3 (Definition) Extent=[108:3 - 108:6] +// CHECK-source: usrs.m:112:12: ObjCInterfaceDecl=IFromSwift:112:12 Extent=[112:1 - 114:5] +// CHECK-source: usrs.m:111:16: UnexposedAttr= Extent=[111:16 - 111:79] +// CHECK-source: usrs.m:113:9: ObjCInstanceMethodDecl=method:113:9 Extent=[113:1 - 113:16] +// CHECK-source: usrs.m:117:12: ObjCInterfaceDecl=IFromSwift2:117:12 Extent=[117:1 - 119:5] +// CHECK-source: usrs.m:116:16: UnexposedAttr= Extent=[116:16 - 116:83] +// CHECK-source: usrs.m:118:9: ObjCInstanceMethodDecl=method:118:9 Extent=[118:1 - 118:101] +// CHECK-source: usrs.m:118:31: UnexposedAttr= Extent=[118:31 - 118:98] 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 @@ -710,6 +710,15 @@ clang_getSpellingLocation(Loc, 0, &line, &column, 0); printf(":%d:%d", line, column); } + + if (clang_getCursorKind(Referenced) == CXCursor_TypedefDecl) { + CXType T = clang_getCursorType(Referenced); + if (clang_Type_isTransparentTypedef(T)) { + CXType Underlying = clang_getTypedefDeclUnderlyingType(Referenced); + CXString S = clang_getTypeSpelling(Underlying); + printf(" (Transparent: %s)", clang_getCString(S)); + } + } } if (clang_isCursorDefinition(Cursor)) Index: tools/libclang/CXType.cpp =================================================================== --- tools/libclang/CXType.cpp +++ tools/libclang/CXType.cpp @@ -1039,3 +1039,13 @@ return MakeCXType(QualType(), GetTU(CT)); } + +unsigned clang_Type_isTransparentTypedef(CXType TT){ + QualType T = GetQualType(TT); + const Type *TP = T.getTypePtrOrNull(); + if (!TP || TP->getTypeClass() != Type::Typedef) + return false; + + TypedefNameDecl *D = cast(TP)->getDecl(); + return D && D->isTransparent(); +} Index: tools/libclang/libclang.exports =================================================================== --- tools/libclang/libclang.exports +++ tools/libclang/libclang.exports @@ -88,6 +88,7 @@ clang_Type_getCXXRefQualifier clang_Type_visitFields clang_Type_getNamedType +clang_Type_isTransparentTypedef clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString