]> granicus.if.org Git - clang/commitdiff
Implemented rewriting of protocol-qualified global variable types.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 11 Dec 2007 22:50:14 +0000 (22:50 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 11 Dec 2007 22:50:14 +0000 (22:50 +0000)
Re-implemented some of rewriting of protocol-qualified function
argument types to support it in its generality.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44886 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/RewriteTest.cpp
test/Sema/rewrite-protocol-type-1.m [new file with mode: 0644]

index cc10ab0d383958390ba4ccc7698c4ca3a29eaccc..237ed21f1d246099c4f113b663d95a371a506a8c 100644 (file)
@@ -273,6 +273,7 @@ void RewriteTest::HandleDeclInMainFile(Decl *D) {
   else if (ObjcClassDecl *CD = dyn_cast<ObjcClassDecl>(D))
     RewriteForwardClassDecl(CD);
   else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    RewriteObjcQualifiedInterfaceTypes(VD);
     if (VD->getInit())
       RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
   }
@@ -978,6 +979,17 @@ static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
   return false;
 }
 
+static void scanToNextArgument(const char *&argRef) {
+  int angle = 0;
+  while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
+    if (*argRef == '<')
+      angle++;
+    else if (*argRef == '>')
+      angle--;
+    argRef++;
+  }
+  assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
+}
 bool RewriteTest::needToScanForQualifiers(QualType T) {
   // FIXME: we don't currently represent "id <Protocol>" in the type system.
   if (T == Context->getObjcIdType())
@@ -992,20 +1004,29 @@ bool RewriteTest::needToScanForQualifiers(QualType T) {
 }
 
 void RewriteTest::RewriteObjcQualifiedInterfaceTypes(Decl *Dcl) {
-  
-  FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl);
-  if (!FD)
-    return;
-  // Check for ObjC 'id' and class types that have been adorned with protocol
-  // information (id<p>, C<p>*). The protocol references need to be rewritten!
-  const FunctionType *funcType = FD->getType()->getAsFunctionType();
-  assert(funcType && "missing function type");
-  const FunctionTypeProto *proto = dyn_cast<FunctionTypeProto>(funcType);
-  if (!proto)
+  SourceLocation Loc;
+  QualType Type;
+  const FunctionTypeProto *proto = 0;
+  if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
+    Loc = VD->getLocation();
+    Type = VD->getType();
+  }
+  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
+    Loc = FD->getLocation();
+    // Check for ObjC 'id' and class types that have been adorned with protocol
+    // information (id<p>, C<p>*). The protocol references need to be rewritten!
+    const FunctionType *funcType = FD->getType()->getAsFunctionType();
+    assert(funcType && "missing function type");
+    proto = dyn_cast<FunctionTypeProto>(funcType);
+    if (!proto)
+      return;
+    Type = proto->getResultType();
+  }
+  else
     return;
-  if (needToScanForQualifiers(proto->getResultType())) {
+  
+  if (needToScanForQualifiers(Type)) {
     // Since types are unique, we need to scan the buffer.
-    SourceLocation Loc = FD->getLocation();
     
     const char *endBuf = SM->getCharacterData(Loc);
     const char *startBuf = endBuf;
@@ -1021,26 +1042,34 @@ void RewriteTest::RewriteObjcQualifiedInterfaceTypes(Decl *Dcl) {
       Rewrite.InsertText(GreaterLoc, "*/", 2);
     }
   }
+  if (!proto)
+      return; // most likely, was a variable
   // Now check arguments.
+  const char *startBuf = SM->getCharacterData(Loc);
+  const char *startFuncBuf = startBuf;
   for (unsigned i = 0; i < proto->getNumArgs(); i++) {
     if (needToScanForQualifiers(proto->getArgType(i))) {
       // Since types are unique, we need to scan the buffer.
-      SourceLocation Loc = FD->getLocation();
       
-      const char *startBuf = SM->getCharacterData(Loc);
       const char *endBuf = startBuf;
-      while (*endBuf != ';')
-        endBuf++; // scan forward (from the decl location) for argument types.
+      // scan forward (from the decl location) for argument types.
+      scanToNextArgument(endBuf);
       const char *startRef = 0, *endRef = 0;
       if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
         // Get the locations of the startRef, endRef.
-        SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
-        SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
+        SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startFuncBuf);
+        SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startFuncBuf+1);
         // Comment out the protocol references.
         Rewrite.InsertText(LessLoc, "/*", 2);
         Rewrite.InsertText(GreaterLoc, "*/", 2);
       }
-    } 
+      startBuf = ++endBuf;
+    }
+    else {
+      while (*startBuf != ')' && *startBuf != ',')
+        startBuf++; // scan forward (from the decl location) for argument types.
+      startBuf++;
+    }
   }
 }
 
diff --git a/test/Sema/rewrite-protocol-type-1.m b/test/Sema/rewrite-protocol-type-1.m
new file mode 100644 (file)
index 0000000..93dfb2a
--- /dev/null
@@ -0,0 +1,24 @@
+// RUN: clang -rewrite-test %s | clang
+
+@protocol MyProto1 
+@end
+
+@protocol MyProto2
+@end
+
+@interface INTF @end
+
+INTF <MyProto1> *g1;
+
+INTF <MyProto1, MyProto2> *g2, *g3;
+
+INTF <MyProto1> * Func(INTF <MyProto1> *p2, INTF<MyProto1> *p3, INTF *p4, INTF<MyProto1> *p5)
+{
+       return p2;
+}
+
+INTF <MyProto1, MyProto2> * Func1(INTF *p2, INTF<MyProto1, MyProto2> *p3, INTF *p4, INTF<MyProto1> *p5)
+{
+       return p3;
+}
+