From 36ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 7 Dec 2007 18:47:10 +0000 Subject: [PATCH] Patch for rewriting of @protocol. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44681 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/RewriteTest.cpp | 56 +++++++++++++++++++++++++++++++--- test/Sema/protocol-rewrite-1.m | 48 +++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 test/Sema/protocol-rewrite-1.m diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp index 6b9c611c71..9c845a4473 100644 --- a/Driver/RewriteTest.cpp +++ b/Driver/RewriteTest.cpp @@ -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 \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(S)) return RewriteObjcThrowStmt(StmtThrow); + + if (ObjCProtocolExpr *ProtocolExp = dyn_cast(S)) + return RewriteObjCProtocolExpr(ProtocolExp); #if 0 if (ImplicitCastExpr *ICE = dyn_cast(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 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 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 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 index 0000000000..a9df2ec793 --- /dev/null +++ b/test/Sema/protocol-rewrite-1.m @@ -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 +@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 )view widget]; + } + return widget; +} +@end + +int main(void) { + id view; + MyWidget *w = [Container elementForView: view]; + + return 0; +} -- 2.40.0