forked from OSchip/llvm-project
objective-c modern translator: Translation into objc_msgSend_stret
entry point which requires nil check before calling objc_msgSend_stret. // rdar://11359268 - wip. llvm-svn: 159445
This commit is contained in:
parent
025d518e3e
commit
4a031bdc8f
|
@ -368,6 +368,13 @@ namespace {
|
|||
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(),
|
||||
SourceLocation EndLoc=SourceLocation());
|
||||
|
@ -3055,6 +3062,107 @@ QualType RewriteModernObjC::getConstantStringStructType() {
|
|||
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) {
|
||||
|
@ -3443,29 +3551,10 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|||
// 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 =
|
||||
|
@ -4152,23 +4241,6 @@ std::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag,
|
|||
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 &&
|
||||
|
@ -5885,6 +5957,9 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
|
|||
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";
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
|
||||
// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
|
||||
// rdar://11359268
|
||||
|
||||
extern "C" void *sel_registerName(const char *);
|
||||
|
||||
union U {
|
||||
double d1;
|
||||
char filler[32];
|
||||
};
|
||||
|
||||
struct S {
|
||||
char filler[128];
|
||||
};
|
||||
|
||||
@interface I
|
||||
- (struct S) Meth : (int) arg1 : (id) arg2;
|
||||
- (struct S) Meth1;
|
||||
- (union U) Meth2 : (double)d;
|
||||
- (struct S) VAMeth : (int)anchor, ...;
|
||||
@end
|
||||
|
||||
I* PI();
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct S foo () {
|
||||
struct S s = [PI() Meth : 1 : (id)0];
|
||||
|
||||
U u = [PI() Meth2 : 3.14];
|
||||
|
||||
S s1 = [PI() VAMeth : 12, 13.4, 1000, "hello"];
|
||||
|
||||
S s2 = [PI() VAMeth : 12];
|
||||
|
||||
S s3 = [PI() VAMeth : 0, "hello", "there"];
|
||||
|
||||
return [PI() Meth1];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,9 +2,10 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
|
||||
// rdar://11203853
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void *sel_registerName(const char *);
|
||||
|
||||
typedef unsigned int size_t;
|
||||
@protocol P @end
|
||||
|
||||
@interface NSMutableArray
|
||||
|
|
Loading…
Reference in New Issue