Skip to content

Commit 4a031bd

Browse files
author
Fariborz Jahanian
committed
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
1 parent 025d518 commit 4a031bd

File tree

3 files changed

+159
-41
lines changed

3 files changed

+159
-41
lines changed

clang/lib/Rewrite/RewriteModernObjC.cpp

Lines changed: 115 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,13 @@ namespace {
367367
Expr **args, unsigned nargs,
368368
SourceLocation StartLoc=SourceLocation(),
369369
SourceLocation EndLoc=SourceLocation());
370+
371+
Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
372+
QualType msgSendType,
373+
QualType returnType,
374+
SmallVectorImpl<QualType> &ArgTypes,
375+
SmallVectorImpl<Expr*> &MsgExprs,
376+
ObjCMethodDecl *Method);
370377

371378
Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
372379
SourceLocation StartLoc=SourceLocation(),
@@ -3055,6 +3062,107 @@ QualType RewriteModernObjC::getConstantStringStructType() {
30553062
return Context->getTagDeclType(ConstantStringDecl);
30563063
}
30573064

3065+
/// getFunctionSourceLocation - returns start location of a function
3066+
/// definition. Complication arises when function has declared as
3067+
/// extern "C" or extern "C" {...}
3068+
static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
3069+
FunctionDecl *FD) {
3070+
if (FD->isExternC() && !FD->isMain()) {
3071+
const DeclContext *DC = FD->getDeclContext();
3072+
if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
3073+
// if it is extern "C" {...}, return function decl's own location.
3074+
if (!LSD->getRBraceLoc().isValid())
3075+
return LSD->getExternLoc();
3076+
}
3077+
if (FD->getStorageClassAsWritten() != SC_None)
3078+
R.RewriteBlockLiteralFunctionDecl(FD);
3079+
return FD->getTypeSpecStartLoc();
3080+
}
3081+
3082+
/// SynthMsgSendStretCallExpr - This routine translates message expression
3083+
/// into a call to objc_msgSend_stret() entry point. Tricky part is that
3084+
/// nil check on receiver must be performed before calling objc_msgSend_stret.
3085+
/// MsgSendStretFlavor - function declaration objc_msgSend_stret(...)
3086+
/// msgSendType - function type of objc_msgSend_stret(...)
3087+
/// returnType - Result type of the method being synthesized.
3088+
/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.
3089+
/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,
3090+
/// starting with receiver.
3091+
/// Method - Method being rewritten.
3092+
Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
3093+
QualType msgSendType,
3094+
QualType returnType,
3095+
SmallVectorImpl<QualType> &ArgTypes,
3096+
SmallVectorImpl<Expr*> &MsgExprs,
3097+
ObjCMethodDecl *Method) {
3098+
// Now do the "normal" pointer to function cast.
3099+
QualType castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
3100+
Method ? Method->isVariadic() : false);
3101+
castType = Context->getPointerType(castType);
3102+
3103+
// build type for containing the objc_msgSend_stret object.
3104+
static unsigned stretCount=0;
3105+
std::string name = "__Stret"; name += utostr(stretCount);
3106+
std::string str = "struct "; str += name;
3107+
str += " {\n\t";
3108+
str += name;
3109+
str += "(id receiver, SEL sel";
3110+
for (unsigned i = 2; i < ArgTypes.size(); i++) {
3111+
str += ", "; str += ArgTypes[i].getAsString(Context->getPrintingPolicy());
3112+
str += " arg"; str += utostr(i);
3113+
}
3114+
// could be vararg.
3115+
for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
3116+
str += ", "; str += MsgExprs[i]->getType().getAsString(Context->getPrintingPolicy());
3117+
str += " arg"; str += utostr(i);
3118+
}
3119+
3120+
str += ") {\n";
3121+
str += "\t if (receiver == 0)\n";
3122+
str += "\t memset((void*)&s, 0, sizeof(s));\n";
3123+
str += "\t else\n";
3124+
str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());
3125+
str += ")(void *)objc_msgSend_stret)(receiver, sel";
3126+
for (unsigned i = 2; i < ArgTypes.size(); i++) {
3127+
str += ", arg"; str += utostr(i);
3128+
}
3129+
// could be vararg.
3130+
for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
3131+
str += ", arg"; str += utostr(i);
3132+
}
3133+
3134+
str += ");\n";
3135+
str += "\t}\n";
3136+
str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());
3137+
str += " s;\n";
3138+
str += "};\n\n";
3139+
SourceLocation FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
3140+
InsertText(FunLocStart, str);
3141+
++stretCount;
3142+
3143+
// AST for __Stretn(receiver, args).s;
3144+
IdentifierInfo *ID = &Context->Idents.get(name);
3145+
FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
3146+
SourceLocation(), ID, castType, 0, SC_Extern,
3147+
SC_None, false, false);
3148+
DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, castType, VK_RValue,
3149+
SourceLocation());
3150+
CallExpr *STCE = new (Context) CallExpr(*Context, DRE, &MsgExprs[0], MsgExprs.size(),
3151+
castType, VK_LValue, SourceLocation());
3152+
3153+
FieldDecl *FieldD = FieldDecl::Create(*Context, 0, SourceLocation(),
3154+
SourceLocation(),
3155+
&Context->Idents.get("s"),
3156+
returnType, 0,
3157+
/*BitWidth=*/0, /*Mutable=*/true,
3158+
ICIS_NoInit);
3159+
MemberExpr *ME = new (Context) MemberExpr(STCE, false, FieldD, SourceLocation(),
3160+
FieldD->getType(), VK_LValue,
3161+
OK_Ordinary);
3162+
3163+
return ME;
3164+
}
3165+
30583166
Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
30593167
SourceLocation StartLoc,
30603168
SourceLocation EndLoc) {
@@ -3443,29 +3551,10 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
34433551
// expression which dictate which one to envoke depending on size of
34443552
// method's return type.
34453553

3446-
// Create a reference to the objc_msgSend_stret() declaration.
3447-
DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor,
3448-
false, msgSendType,
3449-
VK_LValue, SourceLocation());
3450-
// Need to cast objc_msgSend_stret to "void *" (see above comment).
3451-
cast = NoTypeInfoCStyleCastExpr(Context,
3452-
Context->getPointerType(Context->VoidTy),
3453-
CK_BitCast, STDRE);
3454-
// Now do the "normal" pointer to function cast.
3455-
castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(),
3456-
Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false);
3457-
castType = Context->getPointerType(castType);
3458-
cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
3459-
cast);
3460-
3461-
// Don't forget the parens to enforce the proper binding.
3462-
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
3463-
3464-
FT = msgSendType->getAs<FunctionType>();
3465-
CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
3466-
MsgExprs.size(),
3467-
FT->getResultType(), VK_RValue,
3468-
SourceLocation());
3554+
Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
3555+
msgSendType, returnType,
3556+
ArgTypes, MsgExprs,
3557+
Exp->getMethodDecl());
34693558

34703559
// Build sizeof(returnType)
34713560
UnaryExprOrTypeTraitExpr *sizeofExpr =
@@ -4152,23 +4241,6 @@ std::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag,
41524241
return S;
41534242
}
41544243

4155-
/// getFunctionSourceLocation - returns start location of a function
4156-
/// definition. Complication arises when function has declared as
4157-
/// extern "C" or extern "C" {...}
4158-
static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
4159-
FunctionDecl *FD) {
4160-
if (FD->isExternC() && !FD->isMain()) {
4161-
const DeclContext *DC = FD->getDeclContext();
4162-
if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
4163-
// if it is extern "C" {...}, return function decl's own location.
4164-
if (!LSD->getRBraceLoc().isValid())
4165-
return LSD->getExternLoc();
4166-
}
4167-
if (FD->getStorageClassAsWritten() != SC_None)
4168-
R.RewriteBlockLiteralFunctionDecl(FD);
4169-
return FD->getTypeSpecStartLoc();
4170-
}
4171-
41724244
void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
41734245
StringRef FunName) {
41744246
bool RewriteSC = (GlobalVarDecl &&
@@ -5885,6 +5957,9 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
58855957
Preamble += "#define __weak\n";
58865958
}
58875959

5960+
// needed for use of memset.
5961+
Preamble += "\n#include <string.h>\n";
5962+
58885963
// Declarations required for modern objective-c array and dictionary literals.
58895964
Preamble += "\n#include <stdarg.h>\n";
58905965
Preamble += "struct __NSContainer_literal {\n";
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
2+
// 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
3+
// rdar://11359268
4+
5+
extern "C" void *sel_registerName(const char *);
6+
7+
union U {
8+
double d1;
9+
char filler[32];
10+
};
11+
12+
struct S {
13+
char filler[128];
14+
};
15+
16+
@interface I
17+
- (struct S) Meth : (int) arg1 : (id) arg2;
18+
- (struct S) Meth1;
19+
- (union U) Meth2 : (double)d;
20+
- (struct S) VAMeth : (int)anchor, ...;
21+
@end
22+
23+
I* PI();
24+
25+
extern "C" {
26+
27+
struct S foo () {
28+
struct S s = [PI() Meth : 1 : (id)0];
29+
30+
U u = [PI() Meth2 : 3.14];
31+
32+
S s1 = [PI() VAMeth : 12, 13.4, 1000, "hello"];
33+
34+
S s2 = [PI() VAMeth : 12];
35+
36+
S s3 = [PI() VAMeth : 0, "hello", "there"];
37+
38+
return [PI() Meth1];
39+
}
40+
41+
}
42+

clang/test/Rewriter/objc-modern-container-subscript.mm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
// 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
33
// rdar://11203853
44

5+
#include <string.h>
6+
57
void *sel_registerName(const char *);
68

7-
typedef unsigned int size_t;
89
@protocol P @end
910

1011
@interface NSMutableArray

0 commit comments

Comments
 (0)