From a4ffd85a6684e42f900aad5459e58ad91bb88755 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 17 Nov 2010 01:03:52 +0000 Subject: [PATCH] For an Objective-C @synthesize statement, e.g., @synthesize foo = _foo; keep track of the location of the ivar ("_foo"). Teach libclang to visit the ivar as a member reference. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119447 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclObjC.h | 32 ++++++++++++++++++++++------- include/clang/Sema/Sema.h | 3 ++- lib/AST/DeclObjC.cpp | 13 +++++++++--- lib/Parse/ParseObjc.cpp | 7 ++++--- lib/Sema/SemaObjCProperty.cpp | 8 +++++--- lib/Serialization/ASTReaderDecl.cpp | 8 +++++--- lib/Serialization/ASTWriterDecl.cpp | 1 + test/Index/annotate-tokens.m | 7 ++++++- tools/libclang/CIndex.cpp | 8 ++++++++ 9 files changed, 66 insertions(+), 21 deletions(-) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index e913f551a5..621fa9d4c0 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -1455,6 +1455,15 @@ public: }; private: SourceLocation AtLoc; // location of @synthesize or @dynamic + + /// \brief For @synthesize, the location of the ivar, if it was written in + /// the source code. + /// + /// \code + /// @synthesize int a = b + /// \endcode + SourceLocation IvarLoc; + /// Property declaration being implemented ObjCPropertyDecl *PropertyDecl; @@ -1471,9 +1480,10 @@ private: ObjCPropertyImplDecl(DeclContext *DC, SourceLocation atLoc, SourceLocation L, ObjCPropertyDecl *property, Kind PK, - ObjCIvarDecl *ivarDecl) + ObjCIvarDecl *ivarDecl, + SourceLocation ivarLoc) : Decl(ObjCPropertyImpl, DC, L), AtLoc(atLoc), - PropertyDecl(property), PropertyIvarDecl(ivarDecl), + IvarLoc(ivarLoc), PropertyDecl(property), PropertyIvarDecl(ivarDecl), GetterCXXConstructor(0), SetterCXXAssignment(0) { assert (PK == Dynamic || PropertyIvarDecl); } @@ -1483,11 +1493,11 @@ public: SourceLocation atLoc, SourceLocation L, ObjCPropertyDecl *property, Kind PK, - ObjCIvarDecl *ivarDecl); + ObjCIvarDecl *ivarDecl, + SourceLocation ivarLoc); - virtual SourceRange getSourceRange() const { - return SourceRange(AtLoc, getLocation()); - } + virtual SourceRange getSourceRange() const; + SourceLocation getLocStart() const { return AtLoc; } void setAtLoc(SourceLocation Loc) { AtLoc = Loc; } @@ -1503,7 +1513,13 @@ public: ObjCIvarDecl *getPropertyIvarDecl() const { return PropertyIvarDecl; } - void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { PropertyIvarDecl = Ivar; } + SourceLocation getPropertyIvarDeclLoc() const { return IvarLoc; } + + void setPropertyIvarDecl(ObjCIvarDecl *Ivar, + SourceLocation IvarLoc) { + PropertyIvarDecl = Ivar; + this->IvarLoc = IvarLoc; + } Expr *getGetterCXXConstructor() const { return GetterCXXConstructor; @@ -1522,6 +1538,8 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCPropertyImplDecl *D) { return true; } static bool classofKind(Decl::Kind K) { return K == ObjCPropertyImpl; } + + friend class ASTDeclReader; }; } // end namespace clang diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 38b4f8b2ab..61e263065a 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3781,7 +3781,8 @@ public: SourceLocation PropertyLoc, bool ImplKind,Decl *ClassImplDecl, IdentifierInfo *PropertyId, - IdentifierInfo *PropertyIvar); + IdentifierInfo *PropertyIvar, + SourceLocation PropertyIvarLoc); struct ObjCArgInfo { IdentifierInfo *Name; diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 817f7073af..5e57cf87b9 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -896,7 +896,6 @@ ObjCPropertyDecl *ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, return new (C) ObjCPropertyDecl(DC, L, Id, AtLoc, T); } - //===----------------------------------------------------------------------===// // ObjCPropertyImplDecl //===----------------------------------------------------------------------===// @@ -907,8 +906,16 @@ ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C, SourceLocation L, ObjCPropertyDecl *property, Kind PK, - ObjCIvarDecl *ivar) { - return new (C) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar); + ObjCIvarDecl *ivar, + SourceLocation ivarLoc) { + return new (C) ObjCPropertyImplDecl(DC, atLoc, L, property, PK, ivar, + ivarLoc); } +SourceRange ObjCPropertyImplDecl::getSourceRange() const { + SourceLocation EndLoc = getLocation(); + if (IvarLoc.isValid()) + EndLoc = IvarLoc; + return SourceRange(AtLoc, EndLoc); +} diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index d18efac5e2..c01bea9cb5 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -1431,6 +1431,7 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { IdentifierInfo *propertyIvar = 0; IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name + SourceLocation propertyIvarLoc; if (Tok.is(tok::equal)) { // property '=' ivar-name ConsumeToken(); // consume '=' @@ -1446,10 +1447,10 @@ Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) { break; } propertyIvar = Tok.getIdentifierInfo(); - ConsumeToken(); // consume ivar-name + propertyIvarLoc = ConsumeToken(); // consume ivar-name } Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, true, ObjCImpDecl, - propertyId, propertyIvar); + propertyId, propertyIvar, propertyIvarLoc); if (Tok.isNot(tok::comma)) break; ConsumeToken(); // consume ',' @@ -1489,7 +1490,7 @@ Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) { IdentifierInfo *propertyId = Tok.getIdentifierInfo(); SourceLocation propertyLoc = ConsumeToken(); // consume property name Actions.ActOnPropertyImplDecl(getCurScope(), atLoc, propertyLoc, false, ObjCImpDecl, - propertyId, 0); + propertyId, 0, SourceLocation()); if (Tok.isNot(tok::comma)) break; diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index fe2de27c6c..65002f3ea0 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -318,7 +318,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, bool Synthesize, Decl *ClassCatImpDecl, IdentifierInfo *PropertyId, - IdentifierInfo *PropertyIvar) { + IdentifierInfo *PropertyIvar, + SourceLocation PropertyIvarLoc) { ObjCContainerDecl *ClassImpDecl = cast_or_null(ClassCatImpDecl); // Make sure we have a context for the property implementation declaration. @@ -474,7 +475,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, (Synthesize ? ObjCPropertyImplDecl::Synthesize : ObjCPropertyImplDecl::Dynamic), - Ivar); + Ivar, PropertyIvarLoc); if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { getterMethod->createImplicitParams(Context, IDecl); if (getLangOptions().CPlusPlus && Synthesize && @@ -997,7 +998,8 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, // to help users. ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), true,IMPDecl, - Prop->getIdentifier(), Prop->getIdentifier()); + Prop->getIdentifier(), Prop->getIdentifier(), + SourceLocation()); } } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index e49447063e..9f5d0c11d1 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -616,8 +616,9 @@ void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { D->setAtLoc(ReadSourceLocation(Record, Idx)); D->setPropertyDecl( cast_or_null(Reader.GetDecl(Record[Idx++]))); - D->setPropertyIvarDecl( - cast_or_null(Reader.GetDecl(Record[Idx++]))); + D->PropertyIvarDecl = + cast_or_null(Reader.GetDecl(Record[Idx++])); + D->IvarLoc = ReadSourceLocation(Record, Idx); D->setGetterCXXConstructor(Reader.ReadExpr(F)); D->setSetterCXXAssignment(Reader.ReadExpr(F)); } @@ -1467,7 +1468,8 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { case DECL_OBJC_PROPERTY_IMPL: D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, - ObjCPropertyImplDecl::Dynamic, 0); + ObjCPropertyImplDecl::Dynamic, 0, + SourceLocation()); break; case DECL_FIELD: D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0, diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 609a04432b..f7bb23764d 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -511,6 +511,7 @@ void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { Writer.AddSourceLocation(D->getLocStart(), Record); Writer.AddDeclRef(D->getPropertyDecl(), Record); Writer.AddDeclRef(D->getPropertyIvarDecl(), Record); + Writer.AddSourceLocation(D->getPropertyIvarDeclLoc(), Record); Writer.AddStmt(D->getGetterCXXConstructor()); Writer.AddStmt(D->getSetterCXXAssignment()); Code = serialization::DECL_OBJC_PROPERTY_IMPL; diff --git a/test/Index/annotate-tokens.m b/test/Index/annotate-tokens.m index f2933c6588..07e6020c74 100644 --- a/test/Index/annotate-tokens.m +++ b/test/Index/annotate-tokens.m @@ -479,4 +479,9 @@ static Rdar8595462_A * Rdar8595462_staticVar; // CHECK: Punctuation: "*" [111:26 - 111:27] ObjCPropertyDecl=foo2:111:27 // CHECK: Identifier: "foo2" [111:27 - 111:31] ObjCPropertyDecl=foo2:111:27 -// FIXME: Very poor handling of @synthesized +// CHECK: Punctuation: "@" [115:1 - 115:2] UnexposedDecl=foo:110:33 (Definition) +// CHECK: Keyword: "synthesize" [115:2 - 115:12] UnexposedDecl=foo:110:33 (Definition) +// CHECK: Identifier: "foo" [115:13 - 115:16] UnexposedDecl=foo:110:33 (Definition) +// CHECK: Punctuation: "=" [115:17 - 115:18] UnexposedDecl=foo:110:33 (Definition) +// CHECK: Identifier: "_foo" [115:19 - 115:23] MemberRef=_foo:107:8 +// CHECK: Punctuation: ";" [115:23 - 115:24] ObjCImplementationDecl=Rdar8595386:114:1 (Definition) diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index f4e355707c..17e2c7c5c7 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -293,6 +293,7 @@ public: // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations. bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D); bool VisitObjCClassDecl(ObjCClassDecl *D); + bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD); bool VisitLinkageSpecDecl(LinkageSpecDecl *D); bool VisitNamespaceDecl(NamespaceDecl *D); bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D); @@ -1044,6 +1045,13 @@ bool CursorVisitor::VisitObjCClassDecl(ObjCClassDecl *D) { return false; } +bool CursorVisitor::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD) { + if (ObjCIvarDecl *Ivar = PD->getPropertyIvarDecl()) + return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU)); + + return false; +} + bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) { return VisitDeclContext(D); } -- 2.40.0