forked from OSchip/llvm-project
[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:
parent
fc8ce08be3
commit
091b87bb9d
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue