[cfe-commits] r104055 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaObjCProperty.cpp test/Index/properties-class-extensions.m tools/libclang/CIndex.cpp
Ted Kremenek
kremenek at apple.com
Tue May 18 14:09:07 PDT 2010
Author: kremenek
Date: Tue May 18 16:09:07 2010
New Revision: 104055
URL: http://llvm.org/viewvc/llvm-project?rev=104055&view=rev
Log:
Teach CursorVisitor about duplicate ObjCPropertyDecls that can arise because of a current
design limitation in how we handle Objective-C class extensions. This was causing the CursorVisitor
to essentially visit an @property twice (once in the @interface, the other in the class extension).
Fixes <rdar://problem/7410145>.
Added:
cfe/trunk/test/Index/properties-class-extensions.m
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaObjCProperty.cpp
cfe/trunk/tools/libclang/CIndex.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=104055&r1=104054&r2=104055&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue May 18 16:09:07 2010
@@ -1597,7 +1597,8 @@
const bool isAssign,
const bool isReadWrite,
const unsigned Attributes, QualType T,
- tok::ObjCKeywordKind MethodImplKind);
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC = 0);
/// AtomicPropertySetterGetterRules - This routine enforces the rule (via
/// warning) when atomic property has one but not the other user-declared
Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=104055&r1=104054&r2=104055&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Tue May 18 16:09:07 2010
@@ -121,7 +121,7 @@
ObjCPropertyDecl *PDecl =
CreatePropertyDecl(S, CCPrimary, AtLoc,
FD, GetterSel, SetterSel, isAssign, isReadWrite,
- Attributes, T, MethodImplKind);
+ Attributes, T, MethodImplKind, DC);
// A case of continuation class adding a new property in the class. This
// is not what it was meant for. However, gcc supports it and so should we.
@@ -191,7 +191,8 @@
const bool isReadWrite,
const unsigned Attributes,
QualType T,
- tok::ObjCKeywordKind MethodImplKind){
+ tok::ObjCKeywordKind MethodImplKind,
+ DeclContext *lexicalDC){
IdentifierInfo *PropertyId = FD.D.getIdentifier();
@@ -222,8 +223,11 @@
Diag(prevDecl->getLocation(), diag::note_property_declare);
PDecl->setInvalidDecl();
}
- else
+ else {
DC->addDecl(PDecl);
+ if (lexicalDC)
+ PDecl->setLexicalDeclContext(lexicalDC);
+ }
if (T->isArrayType() || T->isFunctionType()) {
Diag(AtLoc, diag::err_property_type) << T;
@@ -1064,6 +1068,11 @@
ObjCMethodDecl::Optional :
ObjCMethodDecl::Required);
CD->addDecl(GetterMethod);
+ // FIXME: Eventually this shouldn't be needed, as the lexical context
+ // and the real context should be the same.
+ if (DeclContext *lexicalDC = property->getLexicalDeclContext())
+ GetterMethod->setLexicalDeclContext(lexicalDC);
+
} else
// A user declared getter will be synthesize when @synthesize of
// the property with the same name is seen in the @implementation
@@ -1097,6 +1106,10 @@
0);
SetterMethod->setMethodParams(Context, &Argument, 1, 1);
CD->addDecl(SetterMethod);
+ // FIXME: Eventually this shouldn't be needed, as the lexical context
+ // and the real context should be the same.
+ if (DeclContext *lexicalDC = property->getLexicalDeclContext())
+ SetterMethod->setLexicalDeclContext(lexicalDC);
} else
// A user declared setter will be synthesize when @synthesize of
// the property with the same name is seen in the @implementation
Added: cfe/trunk/test/Index/properties-class-extensions.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/properties-class-extensions.m?rev=104055&view=auto
==============================================================================
--- cfe/trunk/test/Index/properties-class-extensions.m (added)
+++ cfe/trunk/test/Index/properties-class-extensions.m Tue May 18 16:09:07 2010
@@ -0,0 +1,28 @@
+// Test that @properties within class extensions are visited by
+// clang_visitChildren only in the class extension, not the original
+// @interface (where we have a duplicate declaration - to be removed).
+ at interface Foo {} @end
+ at interface Foo (Cat)
+ @property int a;
+ at end
+ at interface Foo ()
+ @property int b;
+ - (void) bar;
+ at end
+
+// RUN: c-index-test -test-load-source local %s | FileCheck %s
+// CHECK: properties-class-extensions.m:4:12: ObjCInterfaceDecl=Foo:4:12 Extent=[4:1 - 4:23]
+// CHECK: properties-class-extensions.m:5:12: ObjCCategoryDecl=Cat:5:12 Extent=[5:1 - 7:5]
+// CHECK: properties-class-extensions.m:5:12: ObjCClassRef=Foo:4:12 Extent=[5:12 - 5:15]
+// CHECK: properties-class-extensions.m:6:17: ObjCPropertyDecl=a:6:17 Extent=[6:17 - 6:18]
+// CHECK: properties-class-extensions.m:6:17: ObjCInstanceMethodDecl=a:6:17 Extent=[6:17 - 6:18]
+// CHECK: properties-class-extensions.m:6:17: ObjCInstanceMethodDecl=setA::6:17 Extent=[6:17 - 6:18]
+// CHECK: properties-class-extensions.m:6:17: ParmDecl=a:6:17 (Definition) Extent=[6:17 - 6:18]
+// CHECK: properties-class-extensions.m:8:12: ObjCCategoryDecl=:8:12 Extent=[8:1 - 11:5]
+// CHECK: properties-class-extensions.m:8:12: ObjCClassRef=Foo:4:12 Extent=[8:12 - 8:15]
+// CHECK: properties-class-extensions.m:9:17: ObjCPropertyDecl=b:9:17 Extent=[9:17 - 9:18]
+// CHECK: properties-class-extensions.m:9:17: ObjCInstanceMethodDecl=b:9:17 Extent=[9:17 - 9:18]
+// CHECK: properties-class-extensions.m:9:17: ObjCInstanceMethodDecl=setB::9:17 Extent=[9:17 - 9:18]
+// CHECK: properties-class-extensions.m:9:17: ParmDecl=b:9:17 (Definition) Extent=[9:17 - 9:18]
+// CHECK: properties-class-extensions.m:10:3: ObjCInstanceMethodDecl=bar:10:3 Extent=[10:3 - 10:16]
+
Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=104055&r1=104054&r2=104055&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue May 18 16:09:07 2010
@@ -297,6 +297,7 @@
bool VisitObjCContainerDecl(ObjCContainerDecl *D);
bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
+ bool VisitObjCPropertyDecl(ObjCPropertyDecl *PD);
bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
bool VisitObjCImplDecl(ObjCImplDecl *D);
bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
@@ -528,7 +529,11 @@
for (DeclContext::decl_iterator
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
- CXCursor Cursor = MakeCXCursor(*I, TU);
+ Decl *D = *I;
+ if (D->getLexicalDeclContext() != DC)
+ continue;
+
+ CXCursor Cursor = MakeCXCursor(D, TU);
if (RegionOfInterest.isValid()) {
SourceRange Range =
@@ -666,6 +671,40 @@
return VisitObjCContainerDecl(PID);
}
+bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) {
+ // FIXME: This implements a workaround with @property declarations also being
+ // installed in the DeclContext for the @interface. Eventually this code
+ // should be removed.
+ ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(PD->getDeclContext());
+ if (!CDecl || !CDecl->IsClassExtension())
+ return false;
+
+ ObjCInterfaceDecl *ID = CDecl->getClassInterface();
+ if (!ID)
+ return false;
+
+ IdentifierInfo *PropertyId = PD->getIdentifier();
+ ObjCPropertyDecl *prevDecl =
+ ObjCPropertyDecl::findPropertyDecl(cast<DeclContext>(ID), PropertyId);
+
+ if (!prevDecl)
+ return false;
+
+ // Visit synthesized methods since they will be skipped when visiting
+ // the @interface.
+ if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl())
+ if (MD->isSynthesized())
+ if (Visit(MakeCXCursor(MD, TU)))
+ return true;
+
+ if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl())
+ if (MD->isSynthesized())
+ if (Visit(MakeCXCursor(MD, TU)))
+ return true;
+
+ return false;
+}
+
bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
// Issue callbacks for super class.
if (D->getSuperClass() &&
@@ -2480,8 +2519,14 @@
// Adjust the annotated range based specific declarations.
const enum CXCursorKind cursorK = clang_getCursorKind(cursor);
if (cursorK >= CXCursor_FirstDecl && cursorK <= CXCursor_LastDecl) {
- if (const DeclaratorDecl *DD =
- dyn_cast<DeclaratorDecl>(cxcursor::getCursorDecl(cursor))) {
+ Decl *D = cxcursor::getCursorDecl(cursor);
+ // Don't visit synthesized ObjC methods, since they have no syntatic
+ // representation in the source.
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ if (MD->isSynthesized())
+ return CXChildVisit_Continue;
+ }
+ if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
if (TypeSourceInfo *TI = DD->getTypeSourceInfo()) {
TypeLoc TL = TI->getTypeLoc();
SourceLocation TLoc = TL.getFullSourceRange().getBegin();
More information about the cfe-commits
mailing list