]> granicus.if.org Git - clang/commitdiff
Patch for rewriting of @protocol.
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 7 Dec 2007 18:47:10 +0000 (18:47 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 7 Dec 2007 18:47:10 +0000 (18:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44681 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 6b9c611c714caabca9925165619f67a262956c49..9c845a4473369ed5e12e5ae03b7130a3da6ae43e 100644 (file)
@@ -50,6 +50,7 @@ namespace {
     FunctionDecl *GetMetaClassFunctionDecl;
     FunctionDecl *SelGetUidFunctionDecl;
     FunctionDecl *CFStringFunctionDecl;
+    FunctionDecl *GetProtocolFunctionDecl;
       
     // ObjC string constant support.
     FileVarDecl *ConstantStringClassReference;
@@ -73,6 +74,7 @@ namespace {
       GetMetaClassFunctionDecl = 0;
       SelGetUidFunctionDecl = 0;
       CFStringFunctionDecl = 0;
+      GetProtocolFunctionDecl = 0;
       ConstantStringClassReference = 0;
       NSStringRecord = 0;
       CurMethodDecl = 0;
@@ -89,10 +91,15 @@ namespace {
       // declaring objc_selector outside the parameter list removes a silly
       // scope related warning...
       const char *s = "struct objc_selector; struct objc_class;\n"
-                                         "#ifndef OBJC_SUPER\n"
-                                         "struct objc_super { struct objc_object *o; struct objc_object *superClass; };\n"
-                                         "#define OBJC_SUPER\n"
-                                         "#endif\n"
+                      "#ifndef OBJC_SUPER\n"
+                      "struct objc_super { struct objc_object *o; "
+                      "struct objc_object *superClass; };\n"
+                      "#define OBJC_SUPER\n"
+                      "#endif\n"
+                      "#ifndef _REWRITER_typedef_Protocol\n"
+                      "typedef struct objc_object Protocol;\n"
+                      "#define _REWRITER_typedef_Protocol\n"
+                      "#endif\n"
                       "extern struct objc_object *objc_msgSend"
                       "(struct objc_object *, struct objc_selector *, ...);\n"
                       "extern struct objc_object *objc_msgSendSuper"
@@ -113,6 +120,7 @@ namespace {
                       "extern struct objc_object *objc_exception_extract(void *);\n"
                       "extern int objc_exception_match"
                       "(struct objc_class *, struct objc_object *, ...);\n"
+                      "extern Protocol *objc_getProtocol(const char *);\n"
                       "#include <objc/objc.h>\n";
 
       Rewrite.InsertText(SourceLocation::getFileLoc(mainFileID, 0), 
@@ -152,6 +160,7 @@ namespace {
     Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
     Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
     Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
+    Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
     Stmt *RewriteObjcTryStmt(ObjcAtTryStmt *S);
     Stmt *RewriteObjcCatchStmt(ObjcAtCatchStmt *S);
     Stmt *RewriteObjcFinallyStmt(ObjcAtFinallyStmt *S);
@@ -167,6 +176,7 @@ namespace {
     void SynthGetMetaClassFunctionDecl();
     void SynthCFStringFunctionDecl();
     void SynthSelGetUidFunctionDecl();
+    void SynthGetProtocolFunctionDecl();
       
     // Metadata emission.
     void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl,
@@ -708,6 +718,9 @@ Stmt *RewriteTest::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
 
   if (ObjcAtThrowStmt *StmtThrow = dyn_cast<ObjcAtThrowStmt>(S))
     return RewriteObjcThrowStmt(StmtThrow);
+  
+  if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
+    return RewriteObjCProtocolExpr(ProtocolExp);
 #if 0
   if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
     CastExpr *Replacement = new CastExpr(ICE->getType(), ICE->getSubExpr(), SourceLocation());
@@ -1036,6 +1049,20 @@ void RewriteTest::SynthSelGetUidFunctionDecl() {
                                            FunctionDecl::Extern, false, 0);
 }
 
+// SynthGetProtocolFunctionDecl - Protocol objc_getProtocol(const char *proto);
+void RewriteTest::SynthGetProtocolFunctionDecl() {
+  IdentifierInfo *SelGetProtoIdent = &Context->Idents.get("objc_getProtocol");
+  llvm::SmallVector<QualType, 16> ArgTys;
+  ArgTys.push_back(Context->getPointerType(
+    Context->CharTy.getQualifiedType(QualType::Const)));
+  QualType getFuncType = Context->getFunctionType(Context->getObjcProtoType(),
+                                                  &ArgTys[0], ArgTys.size(),
+                                                  false /*isVariadic*/);
+  GetProtocolFunctionDecl = new FunctionDecl(SourceLocation(), 
+                                             SelGetProtoIdent, getFuncType,
+                                             FunctionDecl::Extern, false, 0);
+}
+
 void RewriteTest::RewriteFunctionDecl(FunctionDecl *FD) {
   // declared in <objc/objc.h>
   if (strcmp(FD->getName(), "sel_registerName") == 0) {
@@ -1555,6 +1582,27 @@ Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
   return CE;
 }
 
+/// RewriteObjCProtocolExpr - Rewrite a protocol expression into
+/// call to objc_getProtocol("proto-name").
+Stmt *RewriteTest::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
+  if (!GetProtocolFunctionDecl)
+    SynthGetProtocolFunctionDecl();
+  // Create a call to objc_getProtocol("ProtocolName").
+  llvm::SmallVector<Expr*, 8> ProtoExprs;
+  QualType argType = Context->getPointerType(Context->CharTy);
+  ProtoExprs.push_back(new StringLiteral(Exp->getProtocol()->getName(),
+                                       strlen(Exp->getProtocol()->getName()),
+                                       false, argType, SourceLocation(),
+                                       SourceLocation()));
+  CallExpr *ProtoExp = SynthesizeCallToFunctionDecl(GetProtocolFunctionDecl,
+                                                    &ProtoExprs[0], 
+                                                    ProtoExprs.size());
+  Rewrite.ReplaceStmt(Exp, ProtoExp);
+  delete Exp;
+  return ProtoExp;
+  
+}
+
 /// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
 /// an objective-c class with ivars.
 void RewriteTest::SynthesizeObjcInternalStruct(ObjcInterfaceDecl *CDecl,
diff --git a/test/Sema/protocol-rewrite-1.m b/test/Sema/protocol-rewrite-1.m
new file mode 100644 (file)
index 0000000..a9df2ec
--- /dev/null
@@ -0,0 +1,48 @@
+// RUN: clang -rewrite-test %s
+
+typedef struct MyWidget {
+  int a;
+} MyWidget;
+
+MyWidget gWidget = { 17 };
+
+@protocol MyProto
+- (MyWidget *)widget;
+@end
+
+@interface Foo 
+@end
+
+@interface Bar: Foo <MyProto>
+@end
+
+@interface Container 
++ (MyWidget *)elementForView:(Foo *)view;
+@end
+
+@implementation Foo
+@end
+
+@implementation Bar
+- (MyWidget *)widget {
+  return &gWidget;
+}
+@end
+
+@implementation Container
++ (MyWidget *)elementForView:(Foo *)view
+{
+  MyWidget *widget = (void*)0;
+  if (@protocol(MyProto)) {
+    widget = [(id <MyProto>)view widget];
+  }
+  return widget;
+}
+@end
+
+int main(void) {
+  id view;
+  MyWidget *w = [Container elementForView: view];
+
+  return 0;
+}