]> granicus.if.org Git - clang/commitdiff
More support for rewriting ObjC intefaces. Still some edge cases to handle...
authorSteve Naroff <snaroff@apple.com>
Tue, 30 Oct 2007 02:23:23 +0000 (02:23 +0000)
committerSteve Naroff <snaroff@apple.com>
Tue, 30 Oct 2007 02:23:23 +0000 (02:23 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43493 91177308-0d34-0410-b5e6-96231b3b80d8

AST/Decl.cpp
Driver/RewriteTest.cpp
Parse/MinimalAction.cpp
Parse/ParseDecl.cpp
Parse/ParseObjc.cpp
Parse/ParseStmt.cpp
Sema/Sema.h
Sema/SemaDecl.cpp
include/clang/AST/DeclObjC.h
include/clang/Parse/Action.h
include/clang/Parse/Parser.h

index 804e9ccabfef50113974c8cdda7462eb911c4b76..106537f5e3d63b169c39e08b73c8967768ab5675 100644 (file)
@@ -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
index c76b9eeba9bb2115e9781f3d8ac773d8c975a152..8063574750cd1cdc0ea2a34390fbb7ed7af98e4c 100644 (file)
@@ -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();
   
index b0dad9330c62407a1f40452f4b7a370d195270af..d4391413220a7ac6e0de8f14295ace43df549810 100644 (file)
@@ -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<TypeNameInfo>());
 
index 1e786da4359985957cf90cf77e6d8ebe22a1f7db..aeecdb787226035121b8f3bbf65cd534c47a9aac 100644 (file)
@@ -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<IdentifierInfo *, 8> ProtocolRefs;
-            ParseObjCProtocolReferences(ProtocolRefs);
+            ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc);
             llvm::SmallVector<DeclTy *, 8> *ProtocolDecl = 
                     new llvm::SmallVector<DeclTy *, 8>;
             DS.setProtocolQualifiers(ProtocolDecl);
index 0d44dcdd3a86ff52fa74040fba358c1c8e243f80..0c0c165c2a3b281be8340f65432aebc899b2e112 100644 (file)
@@ -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<IdentifierInfo *, 8> 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<IdentifierInfo*> &ProtocolRefs) {
+  llvm::SmallVectorImpl<IdentifierInfo*> &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().
index 9e18bbaebd31e47d87e556630847e72b1b60c1b9..5e05f9a27d2e83e883843e2fea6c4da833afdcfa 100644 (file)
@@ -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<IdentifierInfo *, 8> ProtocolRefs;
-      ParseObjCProtocolReferences(ProtocolRefs);
+      ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc);
       llvm::SmallVector<DeclTy *, 8> *ProtocolDecl = 
               new llvm::SmallVector<DeclTy *, 8>;
       DS.setProtocolQualifiers(ProtocolDecl);
index dcf024ec0c6078ca1f305e4ccd801b83eb3e6fcd..2d82ab1c50198b49f67227762cd7e9cfdf23b76f 100644 (file)
@@ -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,
index 1ec54d511cb4465028649becddec9f46dee2823f..be34dfb004a0aa6e001d548e4de73699e7831d26 100644 (file)
@@ -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) {
index e5d6fb8a7c41b09d65955c45ac383d764e75c43e..dd6518cb490b5fe70eb05d0c36beec4bab18f4ac 100644 (file)
@@ -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.
index a80fb081841dc4f9682ebad69192e4ba5e60a48e..1ea164385472135790e9a8633f00995098531826 100644 (file)
@@ -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
index 0ca6eaf096676c82cde784b468382e09f97eaff6..3c4767be5bf91c85afd8dbb4e63ce4a598752d9b 100644 (file)
@@ -260,7 +260,8 @@ private:
                                           AttributeList *prefixAttrs = 0);
   void ParseObjCClassInstanceVariables(DeclTy *interfaceDecl, 
                                        SourceLocation atLoc);
-  bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<IdentifierInfo*> &);
+  bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<IdentifierInfo*> &,
+                                   SourceLocation &endProtoLoc);
   void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
                                  tok::ObjCKeywordKind contextKey);
   DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc);