[cfe-commits] r44168 - /cfe/trunk/Driver/RewriteTest.cpp
Steve Naroff
snaroff at apple.com
Thu Nov 15 02:28:21 PST 2007
Author: snaroff
Date: Thu Nov 15 04:28:18 2007
New Revision: 44168
URL: http://llvm.org/viewvc/llvm-project?rev=44168&view=rev
Log:
Rewrite for messaging 'super'.
The code gen. results in some spurious warnings...a cast is forthcoming.
Modified:
cfe/trunk/Driver/RewriteTest.cpp
Modified: cfe/trunk/Driver/RewriteTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteTest.cpp?rev=44168&r1=44167&r2=44168&view=diff
==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Thu Nov 15 04:28:18 2007
@@ -20,6 +20,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "clang/Lex/Lexer.h"
+#include <sstream>
using namespace clang;
using llvm::utostr;
@@ -37,6 +38,7 @@
llvm::DenseMap<ObjcMethodDecl*, std::string> MethodInternalNames;
FunctionDecl *MsgSendFunctionDecl;
+ FunctionDecl *MsgSendSuperFunctionDecl;
FunctionDecl *GetClassFunctionDecl;
FunctionDecl *SelGetUidFunctionDecl;
FunctionDecl *CFStringFunctionDecl;
@@ -45,6 +47,10 @@
FileVarDecl *ConstantStringClassReference;
RecordDecl *NSStringRecord;
+ // Needed for super.
+ ObjcMethodDecl *CurMethodDecl;
+ RecordDecl *SuperStructDecl;
+
static const int OBJC_ABI_VERSION =7 ;
public:
void Initialize(ASTContext &context, unsigned mainFileID) {
@@ -52,17 +58,24 @@
SM = &Context->SourceMgr;
MainFileID = mainFileID;
MsgSendFunctionDecl = 0;
+ MsgSendSuperFunctionDecl = 0;
GetClassFunctionDecl = 0;
SelGetUidFunctionDecl = 0;
CFStringFunctionDecl = 0;
ConstantStringClassReference = 0;
NSStringRecord = 0;
+ CurMethodDecl = 0;
+ SuperStructDecl = 0;
+
Rewrite.setSourceMgr(Context->SourceMgr);
// declaring objc_selector outside the parameter list removes a silly
// scope related warning...
const char *s = "struct objc_selector; struct objc_class;\n"
"extern struct objc_object *objc_msgSend"
"(struct objc_object *, struct objc_selector *, ...);\n"
+ "struct objc_super { struct objc_object *receiver; struct objc_class *super; };\n"
+ "extern struct objc_object *objc_msgSendSuper"
+ "(struct objc_super *, struct objc_selector *, ...);\n"
"extern struct objc_object *objc_getClass"
"(const char *);\n"
"extern void objc_exception_throw(struct objc_object *);\n"
@@ -99,6 +112,8 @@
void RewriteObjcQualifiedInterfaceTypes(
const FunctionTypeProto *proto, FunctionDecl *FD);
bool needToScanForQualifiers(QualType T);
+ ObjcInterfaceDecl *isSuperReceiver(Expr *recExpr);
+ QualType getSuperStructType();
// Expression Rewriting.
Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
@@ -114,6 +129,7 @@
CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
Expr **args, unsigned nargs);
void SynthMsgSendFunctionDecl();
+ void SynthMsgSendSuperFunctionDecl();
void SynthGetClassFunctionDecl();
void SynthCFStringFunctionDecl();
@@ -197,8 +213,12 @@
FD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
if (ObjcMethodDecl *MD = dyn_cast<ObjcMethodDecl>(D)) {
- if (Stmt *Body = MD->getBody())
+ if (Stmt *Body = MD->getBody()) {
+ //Body->dump();
+ CurMethodDecl = MD;
MD->setBody(RewriteFunctionBodyOrGlobalInitializer(Body));
+ CurMethodDecl = 0;
+ }
}
if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
ClassImplementation.push_back(CI);
@@ -631,7 +651,20 @@
if (ObjcAtThrowStmt *StmtThrow = dyn_cast<ObjcAtThrowStmt>(S))
return RewriteObjcThrowStmt(StmtThrow);
-
+#if 0
+ if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
+ CastExpr *Replacement = new CastExpr(ICE->getType(), ICE->getSubExpr(), SourceLocation());
+ // Get the new text.
+ std::ostringstream Buf;
+ Replacement->printPretty(Buf);
+ const std::string &Str = Buf.str();
+
+ printf("CAST = %s\n", &Str[0]);
+ Rewrite.InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size());
+ delete S;
+ return Replacement;
+ }
+#endif
// Return this stmt unmodified.
return S;
}
@@ -954,6 +987,26 @@
FunctionDecl::Extern, false, 0);
}
+// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
+void RewriteTest::SynthMsgSendSuperFunctionDecl() {
+ IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
+ llvm::SmallVector<QualType, 16> ArgTys;
+ RecordDecl *RD = new RecordDecl(Decl::Struct, SourceLocation(),
+ &Context->Idents.get("objc_super"), 0);
+ QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
+ assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
+ ArgTys.push_back(argT);
+ argT = Context->getObjcSelType();
+ assert(!argT.isNull() && "Can't find 'SEL' type");
+ ArgTys.push_back(argT);
+ QualType msgSendType = Context->getFunctionType(Context->getObjcIdType(),
+ &ArgTys[0], ArgTys.size(),
+ true /*isVariadic*/);
+ MsgSendSuperFunctionDecl = new FunctionDecl(SourceLocation(),
+ msgSendIdent, msgSendType,
+ FunctionDecl::Extern, false, 0);
+}
+
// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
void RewriteTest::SynthGetClassFunctionDecl() {
IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
@@ -1038,13 +1091,62 @@
#endif
}
+ObjcInterfaceDecl *RewriteTest::isSuperReceiver(Expr *recExpr) {
+ if (CurMethodDecl) { // check if we are sending a message to 'super'
+ if (CastExpr *CE = dyn_cast<CastExpr>(recExpr)) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) {
+ if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ if (!strcmp(PVD->getName(), "self")) {
+ if (const PointerType *PT = CE->getType()->getAsPointerType()) {
+ if (ObjcInterfaceType *IT =
+ dyn_cast<ObjcInterfaceType>(PT->getPointeeType())) {
+ if (IT->getDecl() ==
+ CurMethodDecl->getClassInterface()->getSuperClass())
+ return IT->getDecl();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
+QualType RewriteTest::getSuperStructType() {
+ if (!SuperStructDecl) {
+ SuperStructDecl = new RecordDecl(Decl::Struct, SourceLocation(),
+ &Context->Idents.get("objc_super"), 0);
+ QualType FieldTypes[2];
+
+ // struct objc_object *receiver;
+ FieldTypes[0] = Context->getObjcIdType();
+ // struct objc_class *super;
+ FieldTypes[1] = Context->getObjcClassType();
+ // Create fields
+ FieldDecl *FieldDecls[2];
+
+ for (unsigned i = 0; i < 2; ++i)
+ FieldDecls[i] = new FieldDecl(SourceLocation(), 0, FieldTypes[i]);
+
+ SuperStructDecl->defineBody(FieldDecls, 4);
+ }
+ return Context->getTagDeclType(SuperStructDecl);
+}
+
Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
if (!MsgSendFunctionDecl)
SynthMsgSendFunctionDecl();
+ if (!MsgSendSuperFunctionDecl)
+ SynthMsgSendSuperFunctionDecl();
if (!GetClassFunctionDecl)
SynthGetClassFunctionDecl();
+ // default to objc_msgSend().
+ FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
+
// Synthesize a call to objc_msgSend().
llvm::SmallVector<Expr*, 8> MsgExprs;
IdentifierInfo *clsName = Exp->getClassName();
@@ -1062,9 +1164,40 @@
MsgExprs.push_back(Cls);
} else { // instance message.
Expr *recExpr = Exp->getReceiver();
-
- recExpr = new CastExpr(Context->getObjcIdType(), recExpr, SourceLocation());
- MsgExprs.push_back(recExpr);
+
+ if (ObjcInterfaceDecl *ID = isSuperReceiver(recExpr)) {
+ MsgSendFlavor = MsgSendSuperFunctionDecl;
+ assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
+
+ llvm::SmallVector<Expr*, 4> InitExprs;
+
+ InitExprs.push_back(recExpr); // set the 'receiver'.
+
+ llvm::SmallVector<Expr*, 8> ClsExprs;
+ QualType argType = Context->getPointerType(Context->CharTy);
+ ClsExprs.push_back(new StringLiteral(ID->getIdentifier()->getName(),
+ ID->getIdentifier()->getLength(),
+ false, argType, SourceLocation(),
+ SourceLocation()));
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
+ &ClsExprs[0], ClsExprs.size());
+ InitExprs.push_back(Cls); // set 'super class', using objc_getClass().
+ // struct objc_super
+ QualType superType = getSuperStructType();
+ // (struct objc_super) { <exprs from above> }
+ InitListExpr *ILE = new InitListExpr(SourceLocation(),
+ &InitExprs[0], InitExprs.size(),
+ SourceLocation());
+ CompoundLiteralExpr *SuperRep = new CompoundLiteralExpr(superType, ILE);
+ // struct objc_super *
+ Expr *Unop = new UnaryOperator(SuperRep, UnaryOperator::AddrOf,
+ Context->getPointerType(SuperRep->getType()),
+ SourceLocation());
+ MsgExprs.push_back(Unop);
+ } else {
+ recExpr = new CastExpr(Context->getObjcIdType(), recExpr, SourceLocation());
+ MsgExprs.push_back(recExpr);
+ }
}
// Create a call to sel_registerName("selName"), it will be the 2nd argument.
llvm::SmallVector<Expr*, 8> SelExprs;
@@ -1109,10 +1242,10 @@
returnType = Context->getObjcIdType();
}
// Get the type, we will need to reference it in a couple spots.
- QualType msgSendType = MsgSendFunctionDecl->getType();
+ QualType msgSendType = MsgSendFlavor->getType();
// Create a reference to the objc_msgSend() declaration.
- DeclRefExpr *DRE = new DeclRefExpr(MsgSendFunctionDecl, msgSendType, SourceLocation());
+ DeclRefExpr *DRE = new DeclRefExpr(MsgSendFlavor, msgSendType, SourceLocation());
// Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
// If we don't do this cast, we get the following bizarre warning/note:
More information about the cfe-commits
mailing list