From f908a87299d278164540f90b5b6e6cab7b14fb41 Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Tue, 30 Oct 2007 02:23:23 +0000 Subject: [PATCH] More support for rewriting ObjC intefaces. Still some edge cases to handle... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43493 91177308-0d34-0410-b5e6-96231b3b80d8 --- AST/Decl.cpp | 6 +++--- Driver/RewriteTest.cpp | 21 +++++++++++++++++++++ Parse/MinimalAction.cpp | 2 +- Parse/ParseDecl.cpp | 3 ++- Parse/ParseObjc.cpp | 24 ++++++++++++++++-------- Parse/ParseStmt.cpp | 3 ++- Sema/Sema.h | 5 +++-- Sema/SemaDecl.cpp | 27 +++++++++++++++++---------- include/clang/AST/DeclObjC.h | 14 +++++++------- include/clang/Parse/Action.h | 6 ++++-- include/clang/Parse/Parser.h | 3 ++- 11 files changed, 78 insertions(+), 36 deletions(-) diff --git a/AST/Decl.cpp b/AST/Decl.cpp index 804e9ccabf..106537f5e3 100644 --- a/AST/Decl.cpp +++ b/AST/Decl.cpp @@ -295,13 +295,13 @@ ObjcMethodDecl::~ObjcMethodDecl() { /// void ObjcInterfaceDecl::addInstanceVariablesToClass(ObjcIvarDecl **ivars, unsigned numIvars, - SourceLocation RB) { + SourceLocation RBrac) { NumIvars = numIvars; if (numIvars) { Ivars = new ObjcIvarDecl*[numIvars]; memcpy(Ivars, ivars, numIvars*sizeof(ObjcIvarDecl*)); } - RBracLoc = RB; + setLocEnd(RBrac); } /// ObjcAddInstanceVariablesToClassImpl - Checks for correctness of Instance @@ -335,7 +335,7 @@ void ObjcInterfaceDecl::addMethods(ObjcMethodDecl **insMethods, ClassMethods = new ObjcMethodDecl*[numClsMembers]; memcpy(ClassMethods, clsMethods, numClsMembers*sizeof(ObjcMethodDecl*)); } - EndLoc = endLoc; + AtEndLoc = endLoc; } /// addMethods - Insert instance and methods declarations into diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp index c76b9eeba9..8063574750 100644 --- a/Driver/RewriteTest.cpp +++ b/Driver/RewriteTest.cpp @@ -264,6 +264,27 @@ void RewriteTest::RewriteForwardClassDecl(ObjcClassDecl *ClassDecl) { } void RewriteTest::RewriteInterfaceDecl(ObjcInterfaceDecl *ClassDecl) { + + SourceLocation LocStart = ClassDecl->getLocStart(); + SourceLocation LocEnd = ClassDecl->getLocEnd(); + + const char *startBuf = SM->getCharacterData(LocStart); + const char *endBuf = SM->getCharacterData(LocEnd); + + // FIXME: need to consider empty class decls (no vars, methods)... + // @interface NSConstantString : NSSimpleCString + // @end + + if (*endBuf != '>' && *endBuf != '}') + // we have an identifier - scan ahead until the end of token. + endBuf = strchr(endBuf, ' '); // FIXME: implement correctly. + + std::string ResultStr; + SynthesizeObjcInternalStruct(ClassDecl, ResultStr); + + Rewrite.ReplaceText(LocStart, endBuf-startBuf+1, + ResultStr.c_str(), ResultStr.size()); + int nInstanceMethods = ClassDecl->getNumInstanceMethods(); ObjcMethodDecl **instanceMethods = ClassDecl->getInstanceMethods(); diff --git a/Parse/MinimalAction.cpp b/Parse/MinimalAction.cpp index b0dad9330c..d439141322 100644 --- a/Parse/MinimalAction.cpp +++ b/Parse/MinimalAction.cpp @@ -72,7 +72,7 @@ MinimalAction::ActOnStartClassInterface(SourceLocation AtInterafceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperName, SourceLocation SuperLoc, IdentifierInfo **ProtocolNames, unsigned NumProtocols, - AttributeList *AttrList) { + SourceLocation EndProtoLoc, AttributeList *AttrList) { TypeNameInfo *TI = new TypeNameInfo(1, ClassName->getFETokenInfo()); diff --git a/Parse/ParseDecl.cpp b/Parse/ParseDecl.cpp index 1e786da435..aeecdb7872 100644 --- a/Parse/ParseDecl.cpp +++ b/Parse/ParseDecl.cpp @@ -407,8 +407,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS) { DS.Range.setEnd(Tok.getLocation()); ConsumeToken(); // The identifier if (Tok.is(tok::less)) { + SourceLocation endProtoLoc; llvm::SmallVector ProtocolRefs; - ParseObjCProtocolReferences(ProtocolRefs); + ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc); llvm::SmallVector *ProtocolDecl = new llvm::SmallVector; DS.setProtocolQualifiers(ProtocolDecl); diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp index 0d44dcdd3a..0c0c165c2a 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -146,9 +146,10 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( return 0; } rparenLoc = ConsumeParen(); + SourceLocation endProtoLoc; // Next, we need to check for any protocol references. if (Tok.is(tok::less)) { - if (ParseObjCProtocolReferences(ProtocolRefs)) + if (ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc)) return 0; } if (attrList) // categories don't support attributes. @@ -183,14 +184,15 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration( } // Next, we need to check for any protocol references. llvm::SmallVector ProtocolRefs; + SourceLocation endProtoLoc; if (Tok.is(tok::less)) { - if (ParseObjCProtocolReferences(ProtocolRefs)) + if (ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc)) return 0; } DeclTy *ClsType = Actions.ActOnStartClassInterface( atLoc, nameId, nameLoc, superClassId, superClassLoc, &ProtocolRefs[0], - ProtocolRefs.size(), attrList); + ProtocolRefs.size(), endProtoLoc, attrList); if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(ClsType, atLoc); @@ -635,7 +637,8 @@ static bool CmpProtocolVals(const IdentifierInfo* const& lhs, /// '<' identifier-list '>' /// bool Parser::ParseObjCProtocolReferences( - llvm::SmallVectorImpl &ProtocolRefs) { + llvm::SmallVectorImpl &ProtocolRefs, SourceLocation &endLoc) +{ assert(Tok.is(tok::less) && "expected <"); ConsumeToken(); // the "<" @@ -661,9 +664,13 @@ bool Parser::ParseObjCProtocolReferences( // Make protocol names unique. ProtocolRefs.erase(std::unique(ProtocolRefs.begin(), ProtocolRefs.end()), ProtocolRefs.end()); - // Consume the '>'. - return ExpectAndConsume(tok::greater, diag::err_expected_greater); + if (Tok.is(tok::greater)) { + endLoc = ConsumeAnyToken(); + return false; + } + Diag(Tok, diag::err_expected_greater); + return true; } /// objc-class-instance-variables: @@ -811,15 +818,16 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) { &ProtocolRefs[0], ProtocolRefs.size()); // Last, and definitely not least, parse a protocol declaration. + SourceLocation endProtoLoc; if (Tok.is(tok::less)) { - if (ParseObjCProtocolReferences(ProtocolRefs)) + if (ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc)) return 0; } DeclTy *ProtoType = Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc, &ProtocolRefs[0], - ProtocolRefs.size()); + ProtocolRefs.size(), endProtoLoc); ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol); // The @ sign was already consumed by ParseObjCInterfaceDeclList(). diff --git a/Parse/ParseStmt.cpp b/Parse/ParseStmt.cpp index 9e18bbaebd..5e05f9a27d 100644 --- a/Parse/ParseStmt.cpp +++ b/Parse/ParseStmt.cpp @@ -235,9 +235,10 @@ Parser::StmtResult Parser::ParseIdentifierStatement(bool OnlyStatement) { IdentTok.getLocation(), PrevSpec, TypeRep); assert(!isInvalid && "First declspec can't be invalid!"); + SourceLocation endProtoLoc; if (Tok.is(tok::less)) { llvm::SmallVector ProtocolRefs; - ParseObjCProtocolReferences(ProtocolRefs); + ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc); llvm::SmallVector *ProtocolDecl = new llvm::SmallVector; DS.setProtocolQualifiers(ProtocolDecl); diff --git a/Sema/Sema.h b/Sema/Sema.h index dcf024ec0c..2d82ab1c50 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -472,7 +472,7 @@ public: IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperName, SourceLocation SuperLoc, IdentifierInfo **ProtocolNames, unsigned NumProtocols, - AttributeList *AttrList); + SourceLocation EndProtoLoc, AttributeList *AttrList); virtual DeclTy *ActOnCompatiblityAlias( SourceLocation AtCompatibilityAliasLoc, @@ -482,7 +482,8 @@ public: virtual DeclTy *ActOnStartProtocolInterface( SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, - IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs); + IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs, + SourceLocation EndProtoLoc); virtual DeclTy *ActOnStartCategoryInterface( SourceLocation AtInterfaceLoc, diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 1ec54d511c..be34dfb004 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -941,7 +941,7 @@ Sema::DeclTy *Sema::ActOnStartClassInterface( IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperName, SourceLocation SuperLoc, IdentifierInfo **ProtocolNames, unsigned NumProtocols, - AttributeList *AttrList) { + SourceLocation EndProtoLoc, AttributeList *AttrList) { assert(ClassName && "Missing class identifier"); // Check for another declaration kind with the same name. @@ -958,6 +958,7 @@ Sema::DeclTy *Sema::ActOnStartClassInterface( if (!IDecl->isForwardDecl()) Diag(AtInterfaceLoc, diag::err_duplicate_class_def, IDecl->getName()); else { + IDecl->setLocation(AtInterfaceLoc); IDecl->setForwardDecl(false); IDecl->AllocIntfRefProtocols(NumProtocols); } @@ -994,18 +995,23 @@ Sema::DeclTy *Sema::ActOnStartClassInterface( } } IDecl->setSuperClass(SuperClassEntry); + IDecl->setLocEnd(SuperLoc); + } else { // we have a root class. + IDecl->setLocEnd(ClassLoc); } /// Check then save referenced protocols - for (unsigned int i = 0; i != NumProtocols; i++) { - ObjcProtocolDecl* RefPDecl = ObjcProtocols[ProtocolNames[i]]; - if (!RefPDecl || RefPDecl->isForwardDecl()) - Diag(ClassLoc, diag::err_undef_protocolref, - ProtocolNames[i]->getName(), - ClassName->getName()); - IDecl->setIntfRefProtocols((int)i, RefPDecl); + if (NumProtocols) { + for (unsigned int i = 0; i != NumProtocols; i++) { + ObjcProtocolDecl* RefPDecl = ObjcProtocols[ProtocolNames[i]]; + if (!RefPDecl || RefPDecl->isForwardDecl()) + Diag(ClassLoc, diag::err_undef_protocolref, + ProtocolNames[i]->getName(), + ClassName->getName()); + IDecl->setIntfRefProtocols((int)i, RefPDecl); + } + IDecl->setLocEnd(EndProtoLoc); } - return IDecl; } @@ -1055,7 +1061,8 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias( Sema::DeclTy *Sema::ActOnStartProtocolInterface( SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, - IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs) { + IdentifierInfo **ProtoRefNames, unsigned NumProtoRefs, + SourceLocation EndProtoLoc) { assert(ProtocolName && "Missing protocol identifier"); ObjcProtocolDecl *PDecl = ObjcProtocols[ProtocolName]; if (PDecl) { diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index e5d6fb8a7c..dd6518cb49 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -74,8 +74,8 @@ class ObjcInterfaceDecl : public TypeDecl { bool ForwardDecl; // declared with @class. - SourceLocation RBracLoc; // marks the end of the instance variables. - SourceLocation EndLoc; // marks the end of the entire interface. + SourceLocation EndLoc; // marks the '>', '}', or identifier. + SourceLocation AtEndLoc; // marks the end of the entire interface. public: ObjcInterfaceDecl(SourceLocation atLoc, unsigned numRefProtos, IdentifierInfo *Id, bool FD = false) @@ -137,14 +137,14 @@ public: ObjcMethodDecl *lookupInstanceMethod(Selector &Sel); ObjcMethodDecl *lookupClassMethod(Selector &Sel); - // Location information, modeled after the Stmt API. For interfaces, - // which are fairly course grain, the end refers to the '}' token. + // Location information, modeled after the Stmt API. SourceLocation getLocStart() const { return getLocation(); } // '@'interface - SourceLocation getLocEnd() const { return RBracLoc; } + SourceLocation getLocEnd() const { return EndLoc; } + void setLocEnd(SourceLocation LE) { EndLoc = LE; }; // We also need to record the @end location. - SourceLocation getAtEndLoc() const { return EndLoc; } - + SourceLocation getAtEndLoc() const { return AtEndLoc; } + /// ImplicitInterfaceDecl - check that this is an implicitely declared /// ObjcInterfaceDecl node. This is for legacy objective-c @implementation /// declaration without an @interface declaration. diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index a80fb08184..1ea1643854 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -465,6 +465,7 @@ public: SourceLocation SuperLoc, IdentifierInfo **ProtocolNames, unsigned NumProtocols, + SourceLocation EndProtoLoc, AttributeList *AttrList) { return 0; } @@ -485,7 +486,8 @@ public: IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, IdentifierInfo **ProtoRefNames, - unsigned NumProtoRefs) { + unsigned NumProtoRefs, + SourceLocation EndProtoLoc) { return 0; } // ActOnStartCategoryInterface - this action is called immdiately after @@ -654,7 +656,7 @@ public: IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperName, SourceLocation SuperLoc, IdentifierInfo **ProtocolNames, unsigned NumProtocols, - AttributeList *AttrList); + SourceLocation EndProtoLoc, AttributeList *AttrList); }; } // end namespace clang diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 0ca6eaf096..3c4767be5b 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -260,7 +260,8 @@ private: AttributeList *prefixAttrs = 0); void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, SourceLocation atLoc); - bool ParseObjCProtocolReferences(llvm::SmallVectorImpl &); + bool ParseObjCProtocolReferences(llvm::SmallVectorImpl &, + SourceLocation &endProtoLoc); void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl, tok::ObjCKeywordKind contextKey); DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc); -- 2.40.0