[cfe-commits] r43316 - in /cfe/trunk: Driver/RewriteTest.cpp include/clang/AST/Expr.h
Steve Naroff
snaroff at apple.com
Wed Oct 24 15:48:43 PDT 2007
Author: snaroff
Date: Wed Oct 24 17:48:43 2007
New Revision: 43316
URL: http://llvm.org/viewvc/llvm-project?rev=43316&view=rev
Log:
More work on translating message expressions.
Still to do:
- Chris will fix a bug in the rewriting engine for nested stmts. For example, the following:
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
tranlates to:
NSAutoreleasePool * pool = objc_msgSend(objc_msgSend(objc_getClass("NSAutoreleasePool"), sel_getUid("alloc")), sel_getUid("init"))utoreleasePool"), sel_getUid("alloc")) init];
..which is correct, except there is garbage after sel_getUid("init"). This is because the rewriter isn't updating the extent of the containing message expression.
- Do the crazy cast thang.
Modified:
cfe/trunk/Driver/RewriteTest.cpp
cfe/trunk/include/clang/AST/Expr.h
Modified: cfe/trunk/Driver/RewriteTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteTest.cpp?rev=43316&r1=43315&r2=43316&view=diff
==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Wed Oct 24 17:48:43 2007
@@ -31,6 +31,7 @@
FunctionDecl *MsgSendFunctionDecl;
FunctionDecl *GetClassFunctionDecl;
+ FunctionDecl *SelGetUidFunctionDecl;
static const int OBJC_ABI_VERSION =7 ;
public:
@@ -40,6 +41,7 @@
MainFileID = mainFileID;
MsgSendFunctionDecl = 0;
GetClassFunctionDecl = 0;
+ SelGetUidFunctionDecl = 0;
Rewrite.setSourceMgr(Context->SourceMgr);
}
@@ -57,7 +59,8 @@
Stmt *RewriteFunctionBody(Stmt *S);
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
-
+ CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
+ Expr **args, unsigned nargs);
// Metadata emission.
void RewriteObjcClassMetaData(ObjcImplementationDecl *IDecl);
@@ -99,6 +102,8 @@
MsgSendFunctionDecl = FD;
else if (strcmp(FD->getName(), "objc_getClass") == 0)
GetClassFunctionDecl = FD;
+ else if (strcmp(FD->getName(), "sel_getUid") == 0)
+ SelGetUidFunctionDecl = FD;
}
// If we have a decl in the main file, see if we should rewrite it.
@@ -218,20 +223,20 @@
// as a comment.
std::string typedefString;
typedefString += "// ";
- typedefString.append(startBuf, semiPtr-startBuf+1);
- typedefString += "\n";
- for (int i = 0; i < numDecls; i++) {
- ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
- typedefString += "typedef struct ";
- typedefString += ForwardDecl->getName();
- typedefString += " ";
- typedefString += ForwardDecl->getName();
- typedefString += ";\n";
- }
-
- // Replace the @class with typedefs corresponding to the classes.
- Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
- typedefString.c_str(), typedefString.size());
+ typedefString.append(startBuf, semiPtr-startBuf+1);
+ typedefString += "\n";
+ for (int i = 0; i < numDecls; i++) {
+ ObjcInterfaceDecl *ForwardDecl = ForwardDecls[i];
+ typedefString += "typedef struct ";
+ typedefString += ForwardDecl->getName();
+ typedefString += " ";
+ typedefString += ForwardDecl->getName();
+ typedefString += ";\n";
+ }
+
+ // Replace the @class with typedefs corresponding to the classes.
+ Rewrite.ReplaceText(startLoc, semiPtr-startBuf+1,
+ typedefString.c_str(), typedefString.size());
}
//===----------------------------------------------------------------------===//
@@ -249,9 +254,25 @@
if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
return RewriteAtEncode(AtEncode);
- if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S))
+ if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
+ // Before we rewrite it, put the original message expression in a comment.
+ SourceLocation startLoc = MessExpr->getLocStart();
+ SourceLocation endLoc = MessExpr->getLocEnd();
+
+ const char *startBuf = SM->getCharacterData(startLoc);
+ const char *endBuf = SM->getCharacterData(endLoc);
+
+ std::string messString;
+ messString += "// ";
+ messString.append(startBuf, endBuf-startBuf+1);
+ messString += "\n";
+
+ // FIXME: Missing definition of Rewrite.InsertText(clang::SourceLocation, char const*, unsigned int).
+ // Rewrite.InsertText(startLoc, messString.c_str(), messString.size());
+ // Tried this, but it didn't work either...
+ // Rewrite.ReplaceText(startLoc, 0, messString.c_str(), messString.size());
return RewriteMessageExpr(MessExpr);
-
+ }
// Return this stmt unmodified.
return S;
}
@@ -266,35 +287,71 @@
return Replacement;
}
-Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
- assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
- //Exp->dumpPretty();
- //printf("\n");
-
- // Synthesize a call to objc_msgSend().
-
+CallExpr *RewriteTest::SynthesizeCallToFunctionDecl(
+ FunctionDecl *FD, Expr **args, unsigned nargs) {
// Get the type, we will need to reference it in a couple spots.
- QualType msgSendType = MsgSendFunctionDecl->getType();
+ QualType msgSendType = FD->getType();
// Create a reference to the objc_msgSend() declaration.
- DeclRefExpr *DRE = new DeclRefExpr(MsgSendFunctionDecl, msgSendType,
- SourceLocation());
+ DeclRefExpr *DRE = new DeclRefExpr(FD, msgSendType, SourceLocation());
// Now, we cast the reference to a pointer to the objc_msgSend type.
QualType pToFunc = Context->getPointerType(msgSendType);
ImplicitCastExpr *ICE = new ImplicitCastExpr(pToFunc, DRE);
const FunctionType *FT = msgSendType->getAsFunctionType();
- CallExpr *CE = new CallExpr(ICE, 0, 0, FT->getResultType(),
- SourceLocation());
- Rewrite.ReplaceStmt(Exp, CE);
- //Exp->dump();
- //CE->dump();
- // FIXME: Walk the operands of Exp, setting them to null before we delete Exp.
- // This will be needed when "CE" points to the operands of Exp.
+ return new CallExpr(ICE, args, nargs, FT->getResultType(), SourceLocation());
+}
+
+Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
+ assert(MsgSendFunctionDecl && "Can't find objc_msgSend() decl");
+ assert(SelGetUidFunctionDecl && "Can't find sel_getUid() decl");
+ assert(GetClassFunctionDecl && "Can't find objc_getClass() decl");
+
+ // Synthesize a call to objc_msgSend().
+ llvm::SmallVector<Expr*, 8> MsgExprs;
+ IdentifierInfo *clsName = Exp->getClassName();
+
+ // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
+ if (clsName) { // class message.
+ llvm::SmallVector<Expr*, 8> ClsExprs;
+ QualType argType = Context->getPointerType(Context->CharTy);
+ ClsExprs.push_back(new StringLiteral(clsName->getName(),
+ clsName->getLength(),
+ false, argType, SourceLocation(),
+ SourceLocation()));
+ CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
+ &ClsExprs[0], ClsExprs.size());
+ MsgExprs.push_back(Cls);
+ } else // instance message.
+ MsgExprs.push_back(Exp->getReceiver());
+
+ // Create a call to sel_getUid("selName"), it will be the 2nd argument.
+ llvm::SmallVector<Expr*, 8> SelExprs;
+ QualType argType = Context->getPointerType(Context->CharTy);
+ SelExprs.push_back(new StringLiteral(Exp->getSelector().getName().c_str(),
+ Exp->getSelector().getName().size(),
+ false, argType, SourceLocation(),
+ SourceLocation()));
+ CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
+ &SelExprs[0], SelExprs.size());
+ MsgExprs.push_back(SelExp);
+
+ // Now push any user supplied arguments.
+ for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
+ MsgExprs.push_back(Exp->getArg(i));
+ // We've transferred the ownership to MsgExprs. Null out the argument in
+ // the original expression, since we will delete it below.
+ Exp->setArg(i, 0);
+ }
+ CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
+ &MsgExprs[0], MsgExprs.size());
+ // Now do the actual rewrite.
+ Rewrite.ReplaceStmt(Exp, MessExp);
+
delete Exp;
- return CE;
+ return MessExp;
}
// RewriteObjcMethodsMetaData - Rewrite methods metadata for instance or
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=43316&r1=43315&r2=43316&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed Oct 24 17:48:43 2007
@@ -525,7 +525,11 @@
assert(Arg < NumArgs && "Arg access out of range!");
return SubExprs[Arg+ARGS_START];
}
-
+ /// setArg - Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < NumArgs && "Arg access out of range!");
+ SubExprs[Arg+ARGS_START] = ArgExpr;
+ }
/// getNumCommas - Return the number of commas that must have been present in
/// this function call.
unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; }
@@ -1202,7 +1206,11 @@
assert(Arg < SelName.getNumArgs() && "Arg access out of range!");
return SubExprs[Arg+ARGS_START];
}
-
+ /// setArg - Set the specified argument.
+ void setArg(unsigned Arg, Expr *ArgExpr) {
+ assert(Arg < SelName.getNumArgs() && "Arg access out of range!");
+ SubExprs[Arg+ARGS_START] = ArgExpr;
+ }
SourceRange getSourceRange() const { return SourceRange(LBracloc, RBracloc); }
static bool classof(const Stmt *T) {
More information about the cfe-commits
mailing list