r298392 - [index/AST] Determine if a typedef shares a name and spelling location with its underlying tag type
Argyrios Kyrtzidis via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 21 09:56:03 PDT 2017
Author: akirtzidis
Date: Tue Mar 21 11:56:02 2017
New Revision: 298392
URL: http://llvm.org/viewvc/llvm-project?rev=298392&view=rev
Log:
[index/AST] Determine if a typedef shares a name and spelling location with its underlying tag type
In such a case, as when using the NS_ENUM macro, for indexing purposes treat the typedef as 'transparent',
meaning we treat its references as symbols of the underlying tag symbol.
Also provide a libclang API to check for such typedefs.
Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/Index/IndexDecl.cpp
cfe/trunk/lib/Index/IndexTypeSourceInfo.cpp
cfe/trunk/test/Index/Core/index-source.m
cfe/trunk/test/Index/get-cursor.m
cfe/trunk/tools/c-index-test/c-index-test.c
cfe/trunk/tools/libclang/CXType.cpp
cfe/trunk/tools/libclang/libclang.exports
Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Tue Mar 21 11:56:02 2017
@@ -3437,6 +3437,16 @@ CINDEX_LINKAGE long long clang_getArrayS
CINDEX_LINKAGE CXType clang_Type_getNamedType(CXType T);
/**
+ * \brief Determine if a typedef is 'transparent' tag.
+ *
+ * A typedef is considered 'transparent' if it shares a name and spelling
+ * location with its underlying tag type, as is the case with the NS_ENUM macro.
+ *
+ * \returns non-zero if transparent and zero otherwise.
+ */
+CINDEX_LINKAGE unsigned clang_Type_isTransparentTagTypedef(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.
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Mar 21 11:56:02 2017
@@ -2641,12 +2641,17 @@ class TypedefNameDecl : public TypeDecl,
typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo;
llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo;
+ // FIXME: This can be packed into the bitfields in Decl.
+ /// If 0, we have not computed IsTransparentTag.
+ /// Otherwise, IsTransparentTag is (CacheIsTransparentTag >> 1).
+ mutable unsigned CacheIsTransparentTag : 2;
+
protected:
TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, TypeSourceInfo *TInfo)
: TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C),
- MaybeModedTInfo(TInfo) {}
+ MaybeModedTInfo(TInfo), CacheIsTransparentTag(0) {}
typedef Redeclarable<TypedefNameDecl> redeclarable_base;
TypedefNameDecl *getNextRedeclarationImpl() override {
@@ -2699,11 +2704,22 @@ public:
/// this typedef declaration.
TagDecl *getAnonDeclWithTypedefName(bool AnyRedecl = false) const;
+ /// Determines if this typedef shares a name and spelling location with its
+ /// underlying tag type, as is the case with the NS_ENUM macro.
+ bool isTransparentTag() const {
+ if (CacheIsTransparentTag)
+ return CacheIsTransparentTag & 0x2;
+ return isTransparentTagSlow();
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
return K >= firstTypedefName && K <= lastTypedefName;
}
+
+private:
+ bool isTransparentTagSlow() const;
};
/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef'
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Mar 21 11:56:02 2017
@@ -4242,6 +4242,30 @@ TagDecl *TypedefNameDecl::getAnonDeclWit
return nullptr;
}
+bool TypedefNameDecl::isTransparentTagSlow() const {
+ auto determineIsTransparent = [&]() {
+ if (auto *TT = getUnderlyingType()->getAs<TagType>()) {
+ if (auto *TD = TT->getDecl()) {
+ if (TD->getName() != getName())
+ return false;
+ SourceLocation TTLoc = getLocation();
+ SourceLocation TDLoc = TD->getLocation();
+ if (!TTLoc.isMacroID() || !TDLoc.isMacroID())
+ return false;
+ SourceManager &SM = getASTContext().getSourceManager();
+ return SM.getSpellingLoc(TTLoc) == SM.getSpellingLoc(TDLoc);
+ }
+ }
+ return false;
+ };
+
+ bool isTransparent = determineIsTransparent();
+ CacheIsTransparentTag = 1;
+ if (isTransparent)
+ CacheIsTransparentTag |= 0x2;
+ return isTransparent;
+}
+
TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr);
Modified: cfe/trunk/lib/Index/IndexDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Index/IndexDecl.cpp?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/lib/Index/IndexDecl.cpp (original)
+++ cfe/trunk/lib/Index/IndexDecl.cpp Tue Mar 21 11:56:02 2017
@@ -231,8 +231,9 @@ public:
}
bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
- if (!IndexCtx.handleDecl(D))
- return false;
+ if (!D->isTransparentTag())
+ if (!IndexCtx.handleDecl(D))
+ return false;
IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
return true;
}
Modified: cfe/trunk/lib/Index/IndexTypeSourceInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Index/IndexTypeSourceInfo.cpp?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/lib/Index/IndexTypeSourceInfo.cpp (original)
+++ cfe/trunk/lib/Index/IndexTypeSourceInfo.cpp Tue Mar 21 11:56:02 2017
@@ -47,9 +47,15 @@ public:
} while (0)
bool VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ SourceLocation Loc = TL.getNameLoc();
+ TypedefNameDecl *ND = TL.getTypedefNameDecl();
+ if (ND->isTransparentTag()) {
+ TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl();
+ return IndexCtx.handleReference(Underlying, Loc, Parent,
+ ParentDC, SymbolRoleSet(), Relations);
+ }
if (IsBase) {
- SourceLocation Loc = TL.getNameLoc();
- TRY_TO(IndexCtx.handleReference(TL.getTypedefNameDecl(), Loc,
+ TRY_TO(IndexCtx.handleReference(ND, Loc,
Parent, ParentDC, SymbolRoleSet()));
if (auto *CD = TL.getType()->getAsCXXRecordDecl()) {
TRY_TO(IndexCtx.handleReference(CD, Loc, Parent, ParentDC,
@@ -57,7 +63,7 @@ public:
Relations));
}
} else {
- TRY_TO(IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(),
+ TRY_TO(IndexCtx.handleReference(ND, Loc,
Parent, ParentDC, SymbolRoleSet(),
Relations));
}
Modified: cfe/trunk/test/Index/Core/index-source.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/Core/index-source.m?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/test/Index/Core/index-source.m (original)
+++ cfe/trunk/test/Index/Core/index-source.m Tue Mar 21 11:56:02 2017
@@ -348,3 +348,39 @@ typedef MyGenCls<Base *><MyEnumerating>
// CHECK: [[@LINE-1]]:3 | field/ObjC | _foo | c:objc(cs)I7 at _foo | <no-cgname> | Ref,Writ,RelCont | rel: 1
}
@end
+
+#define NS_ENUM(_name, _type) enum _name:_type _name; enum _name : _type
+
+typedef NS_ENUM(AnotherEnum, int) {
+// CHECK-NOT: [[@LINE-1]]:17 | type-alias/C | AnotherEnum |
+// CHECK: [[@LINE-2]]:17 | enum/C | AnotherEnum | [[AnotherEnum_USR:.*]] | {{.*}} | Ref,RelCont | rel: 1
+ AnotherEnumFirst = 0,
+ AnotherEnumSecond = 1,
+ AnotherEnumThird = 2,
+};
+
+AnotherEnum anotherT;
+// CHECK: [[@LINE-1]]:1 | enum/C | AnotherEnum | [[AnotherEnum_USR]] | {{.*}} | Ref,RelCont | rel: 1
+enum AnotherEnum anotherE;
+// CHECK: [[@LINE-1]]:6 | enum/C | AnotherEnum | [[AnotherEnum_USR]] | {{.*}} | 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
Modified: cfe/trunk/test/Index/get-cursor.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/get-cursor.m?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/test/Index/get-cursor.m (original)
+++ cfe/trunk/test/Index/get-cursor.m Tue Mar 21 11:56:02 2017
@@ -129,6 +129,31 @@ void foo3(Test3 *test3) {
}
@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 +218,11 @@ void foo3(Test3 *test3) {
// 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])
Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Tue Mar 21 11:56:02 2017
@@ -710,6 +710,15 @@ static void PrintCursor(CXCursor Cursor,
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_isTransparentTagTypedef(T)) {
+ CXType Underlying = clang_getTypedefDeclUnderlyingType(Referenced);
+ CXString S = clang_getTypeSpelling(Underlying);
+ printf(" (Transparent: %s)", clang_getCString(S));
+ }
+ }
}
if (clang_isCursorDefinition(Cursor))
Modified: cfe/trunk/tools/libclang/CXType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXType.cpp?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXType.cpp (original)
+++ cfe/trunk/tools/libclang/CXType.cpp Tue Mar 21 11:56:02 2017
@@ -1039,3 +1039,12 @@ CXType clang_Type_getNamedType(CXType CT
return MakeCXType(QualType(), GetTU(CT));
}
+
+unsigned clang_Type_isTransparentTagTypedef(CXType TT){
+ QualType T = GetQualType(TT);
+ if (auto *TT = dyn_cast_or_null<TypedefType>(T.getTypePtrOrNull())) {
+ if (auto *D = TT->getDecl())
+ return D->isTransparentTag();
+ }
+ return false;
+}
Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=298392&r1=298391&r2=298392&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Tue Mar 21 11:56:02 2017
@@ -88,6 +88,7 @@ clang_Type_getTemplateArgumentAsType
clang_Type_getCXXRefQualifier
clang_Type_visitFields
clang_Type_getNamedType
+clang_Type_isTransparentTagTypedef
clang_VerbatimBlockLineComment_getText
clang_VerbatimLineComment_getText
clang_HTMLTagComment_getAsString
More information about the cfe-commits
mailing list