[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

llvm-svn: 158258
This commit is contained in:
Argyrios Kyrtzidis 2012-06-09 03:03:02 +00:00
parent fc8ce08be3
commit 091b87bb9d
4 changed files with 70 additions and 1 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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])

View File

@ -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;
}
}