Expr **args, unsigned nargs,
SourceLocation StartLoc=SourceLocation(),
SourceLocation EndLoc=SourceLocation());
+
+ Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
+ QualType msgSendType,
+ QualType returnType,
+ SmallVectorImpl<QualType> &ArgTypes,
+ SmallVectorImpl<Expr*> &MsgExprs,
+ ObjCMethodDecl *Method);
Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation StartLoc=SourceLocation(),
return Context->getTagDeclType(ConstantStringDecl);
}
+/// getFunctionSourceLocation - returns start location of a function
+/// definition. Complication arises when function has declared as
+/// extern "C" or extern "C" {...}
+static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
+ FunctionDecl *FD) {
+ if (FD->isExternC() && !FD->isMain()) {
+ const DeclContext *DC = FD->getDeclContext();
+ if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
+ // if it is extern "C" {...}, return function decl's own location.
+ if (!LSD->getRBraceLoc().isValid())
+ return LSD->getExternLoc();
+ }
+ if (FD->getStorageClassAsWritten() != SC_None)
+ R.RewriteBlockLiteralFunctionDecl(FD);
+ return FD->getTypeSpecStartLoc();
+}
+
+/// SynthMsgSendStretCallExpr - This routine translates message expression
+/// into a call to objc_msgSend_stret() entry point. Tricky part is that
+/// nil check on receiver must be performed before calling objc_msgSend_stret.
+/// MsgSendStretFlavor - function declaration objc_msgSend_stret(...)
+/// msgSendType - function type of objc_msgSend_stret(...)
+/// returnType - Result type of the method being synthesized.
+/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.
+/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,
+/// starting with receiver.
+/// Method - Method being rewritten.
+Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
+ QualType msgSendType,
+ QualType returnType,
+ SmallVectorImpl<QualType> &ArgTypes,
+ SmallVectorImpl<Expr*> &MsgExprs,
+ ObjCMethodDecl *Method) {
+ // Now do the "normal" pointer to function cast.
+ QualType castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
+ Method ? Method->isVariadic() : false);
+ castType = Context->getPointerType(castType);
+
+ // build type for containing the objc_msgSend_stret object.
+ static unsigned stretCount=0;
+ std::string name = "__Stret"; name += utostr(stretCount);
+ std::string str = "struct "; str += name;
+ str += " {\n\t";
+ str += name;
+ str += "(id receiver, SEL sel";
+ for (unsigned i = 2; i < ArgTypes.size(); i++) {
+ str += ", "; str += ArgTypes[i].getAsString(Context->getPrintingPolicy());
+ str += " arg"; str += utostr(i);
+ }
+ // could be vararg.
+ for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
+ str += ", "; str += MsgExprs[i]->getType().getAsString(Context->getPrintingPolicy());
+ str += " arg"; str += utostr(i);
+ }
+
+ str += ") {\n";
+ str += "\t if (receiver == 0)\n";
+ str += "\t memset((void*)&s, 0, sizeof(s));\n";
+ str += "\t else\n";
+ str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());
+ str += ")(void *)objc_msgSend_stret)(receiver, sel";
+ for (unsigned i = 2; i < ArgTypes.size(); i++) {
+ str += ", arg"; str += utostr(i);
+ }
+ // could be vararg.
+ for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
+ str += ", arg"; str += utostr(i);
+ }
+
+ str += ");\n";
+ str += "\t}\n";
+ str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());
+ str += " s;\n";
+ str += "};\n\n";
+ SourceLocation FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
+ InsertText(FunLocStart, str);
+ ++stretCount;
+
+ // AST for __Stretn(receiver, args).s;
+ IdentifierInfo *ID = &Context->Idents.get(name);
+ FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
+ SourceLocation(), ID, castType, 0, SC_Extern,
+ SC_None, false, false);
+ DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, castType, VK_RValue,
+ SourceLocation());
+ CallExpr *STCE = new (Context) CallExpr(*Context, DRE, &MsgExprs[0], MsgExprs.size(),
+ castType, VK_LValue, SourceLocation());
+
+ FieldDecl *FieldD = FieldDecl::Create(*Context, 0, SourceLocation(),
+ SourceLocation(),
+ &Context->Idents.get("s"),
+ returnType, 0,
+ /*BitWidth=*/0, /*Mutable=*/true,
+ ICIS_NoInit);
+ MemberExpr *ME = new (Context) MemberExpr(STCE, false, FieldD, SourceLocation(),
+ FieldD->getType(), VK_LValue,
+ OK_Ordinary);
+
+ return ME;
+}
+
Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation StartLoc,
SourceLocation EndLoc) {
// expression which dictate which one to envoke depending on size of
// method's return type.
- // Create a reference to the objc_msgSend_stret() declaration.
- DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor,
- false, msgSendType,
- VK_LValue, SourceLocation());
- // Need to cast objc_msgSend_stret to "void *" (see above comment).
- cast = NoTypeInfoCStyleCastExpr(Context,
- Context->getPointerType(Context->VoidTy),
- CK_BitCast, STDRE);
- // Now do the "normal" pointer to function cast.
- castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
- Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false);
- castType = Context->getPointerType(castType);
- cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
- cast);
-
- // Don't forget the parens to enforce the proper binding.
- PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
-
- FT = msgSendType->getAs<FunctionType>();
- CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
- MsgExprs.size(),
- FT->getResultType(), VK_RValue,
- SourceLocation());
+ Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
+ msgSendType, returnType,
+ ArgTypes, MsgExprs,
+ Exp->getMethodDecl());
// Build sizeof(returnType)
UnaryExprOrTypeTraitExpr *sizeofExpr =
return S;
}
-/// getFunctionSourceLocation - returns start location of a function
-/// definition. Complication arises when function has declared as
-/// extern "C" or extern "C" {...}
-static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
- FunctionDecl *FD) {
- if (FD->isExternC() && !FD->isMain()) {
- const DeclContext *DC = FD->getDeclContext();
- if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
- // if it is extern "C" {...}, return function decl's own location.
- if (!LSD->getRBraceLoc().isValid())
- return LSD->getExternLoc();
- }
- if (FD->getStorageClassAsWritten() != SC_None)
- R.RewriteBlockLiteralFunctionDecl(FD);
- return FD->getTypeSpecStartLoc();
-}
-
void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
StringRef FunName) {
bool RewriteSC = (GlobalVarDecl &&
Preamble += "#define __weak\n";
}
+ // needed for use of memset.
+ Preamble += "\n#include <string.h>\n";
+
// Declarations required for modern objective-c array and dictionary literals.
Preamble += "\n#include <stdarg.h>\n";
Preamble += "struct __NSContainer_literal {\n";