diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-06-09 03:03:02 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-06-09 03:03:02 +0000 |
commit | 135bf8ee69e2ae2daea4f713381995028c41e264 (patch) | |
tree | 686fba6b8104e66db2b7953053cbb4c6a16e9191 | |
parent | 70186fc9e0bd5e2b3de79058c9ddc57e87213d8d (diff) |
[libclang] When doing the cursor visitation make sure declarations
in the same line do not override getting a cursor for the previous declaration.
e.g:
int x, y;
@synthesize prop1, prop2;
pointing at 'x'/'prop1' would give 'y'/'prop2' because their source ranges overlap.
rdar://11361113
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158258 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/DeclObjC.h | 11 | ||||
-rw-r--r-- | test/Index/get-cursor.c | 6 | ||||
-rw-r--r-- | test/Index/get-cursor.m | 22 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 32 |
4 files changed, 70 insertions, 1 deletions
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 88b7b773a1..14c30dc8bf 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1983,6 +1983,17 @@ public: this->IvarLoc = IvarLoc; } + /// \brief For \@synthesize, returns true if an ivar name was explicitly + /// specified. + /// + /// \code + /// \@synthesize int a = b; // true + /// \@synthesize int a; // false + /// \endcode + bool isIvarNameSpecified() const { + return IvarLoc.isValid() && IvarLoc != getLocation(); + } + Expr *getGetterCXXConstructor() const { return GetterCXXConstructor; } diff --git a/test/Index/get-cursor.c b/test/Index/get-cursor.c index 23a4b5cb53..c0614af5dd 100644 --- a/test/Index/get-cursor.c +++ b/test/Index/get-cursor.c @@ -4,11 +4,17 @@ struct _MyS { struct _MyS ww; +int x, y; + // RUN: c-index-test -cursor-at=%s:1:9 \ // RUN: -cursor-at=%s:2:9 \ // RUN: -cursor-at=%s:5:9 \ +// RUN: -cursor-at=%s:7:5 \ +// RUN: -cursor-at=%s:7:8 \ // RUN: %s | FileCheck %s // CHECK: StructDecl=_MyS:1:8 (Definition) // CHECK: FieldDecl=foo:2:7 (Definition) // CHECK: TypeRef=struct _MyS:1:8 +// CHECK: VarDecl=x:7:5 +// CHECK: VarDecl=y:7:8 diff --git a/test/Index/get-cursor.m b/test/Index/get-cursor.m index 5ac3375988..32ac53fe3b 100644 --- a/test/Index/get-cursor.m +++ b/test/Index/get-cursor.m @@ -69,6 +69,21 @@ void foo3(Test3 *test3) { @class Forw1, Forw2, Forw3; +@interface Test5 { + id prop1; + id prop2; +} +@property (assign) id prop1; +@property (assign) id prop2; +@property (assign) id prop3; +@property (assign) id prop4; +@end + +@implementation Test5 +@synthesize prop1, prop2; +@dynamic prop3, prop4; +@end + // 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 // CHECK-PROP: ObjCPropertyDecl=foo2:5:27 @@ -102,3 +117,10 @@ void foo3(Test3 *test3) { // CHECK-SPELLRANGE: 70:8 ObjCClassRef=Forw1:70:8 Extent=[70:8 - 70:13] Spelling=Forw1 ([70:8 - 70:13]) // CHECK-SPELLRANGE: 70:15 ObjCClassRef=Forw2:70:15 Extent=[70:15 - 70:20] Spelling=Forw2 ([70:15 - 70:20]) // CHECK-SPELLRANGE: 70:22 ObjCClassRef=Forw3:70:22 Extent=[70:22 - 70:27] Spelling=Forw3 ([70:22 - 70:27]) + +// RUN: c-index-test -cursor-at=%s:83:15 -cursor-at=%s:83:21 \ +// RUN: -cursor-at=%s:84:12 -cursor-at=%s:84:20 %s | FileCheck -check-prefix=CHECK-MULTISYNTH %s +// CHECK-MULTISYNTH: 83:13 ObjCSynthesizeDecl=prop1:76:23 (Definition) Extent=[83:1 - 83:18] Spelling=prop1 ([83:13 - 83:18]) +// CHECK-MULTISYNTH: 83:20 ObjCSynthesizeDecl=prop2:77:23 (Definition) Extent=[83:1 - 83:25] Spelling=prop2 ([83:20 - 83:25]) +// CHECK-MULTISYNTH: 84:10 ObjCDynamicDecl=prop3:78:23 (Definition) Extent=[84:1 - 84:15] Spelling=prop3 ([84:10 - 84:15]) +// CHECK-MULTISYNTH: 84:17 ObjCDynamicDecl=prop4:79:23 (Definition) Extent=[84:1 - 84:22] Spelling=prop4 ([84:17 - 84:22]) diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 8eaf4ecf0c..9a17b35cd1 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1068,7 +1068,8 @@ bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { bool CursorVisitor::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD) { if (ObjCIvarDecl *Ivar = PD->getPropertyIvarDecl()) - return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU)); + if (PD->isIvarNameSpecified()) + return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU)); return false; } @@ -3613,12 +3614,15 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { struct GetCursorData { SourceLocation TokenBeginLoc; bool PointsAtMacroArgExpansion; + bool VisitedObjCPropertyImplDecl; + SourceLocation VisitedDeclaratorDeclStartLoc; CXCursor &BestCursor; GetCursorData(SourceManager &SM, SourceLocation tokenBegin, CXCursor &outputCursor) : TokenBeginLoc(tokenBegin), BestCursor(outputCursor) { PointsAtMacroArgExpansion = SM.isMacroArgExpansion(tokenBegin); + VisitedObjCPropertyImplDecl = false; } }; @@ -3658,6 +3662,32 @@ static enum CXChildVisitResult GetCursorVisitor(CXCursor cursor, !ID->isThisDeclarationADefinition()) return CXChildVisit_Break; } + + } else if (DeclaratorDecl *DD + = dyn_cast_or_null<DeclaratorDecl>(getCursorDecl(cursor))) { + SourceLocation StartLoc = DD->getSourceRange().getBegin(); + // Check that when we have multiple declarators in the same line, + // that later ones do not override the previous ones. + // If we have: + // int Foo, Bar; + // source ranges for both start at 'int', so 'Bar' will end up overriding + // 'Foo' even though the cursor location was at 'Foo'. + if (Data->VisitedDeclaratorDeclStartLoc == StartLoc) + return CXChildVisit_Break; + Data->VisitedDeclaratorDeclStartLoc = StartLoc; + + } else if (ObjCPropertyImplDecl *PropImp + = dyn_cast_or_null<ObjCPropertyImplDecl>(getCursorDecl(cursor))) { + (void)PropImp; + // Check that when we have multiple @synthesize in the same line, + // that later ones do not override the previous ones. + // If we have: + // @synthesize Foo, Bar; + // source ranges for both start at '@', so 'Bar' will end up overriding + // 'Foo' even though the cursor location was at 'Foo'. + if (Data->VisitedObjCPropertyImplDecl) + return CXChildVisit_Break; + Data->VisitedObjCPropertyImplDecl = true; } } |