Patch for rewriting of @protocol.

llvm-svn: 44681
This commit is contained in:
Fariborz Jahanian 2007-12-07 18:47:10 +00:00
parent bfd373a53e
commit 33c0e815f3
2 changed files with 100 additions and 4 deletions

View 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;
@ -90,9 +92,14 @@ namespace {
// 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"
"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,

View File

@ -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;
}