forked from OSchip/llvm-project
modern objc translation of block literal expressions
declared at file scope. // rdar://11006566 llvm-svn: 153293
This commit is contained in:
parent
f351774f7b
commit
e005070ccf
|
@ -73,6 +73,7 @@ namespace {
|
|||
|
||||
TypeDecl *ProtocolTypeDecl;
|
||||
VarDecl *GlobalVarDecl;
|
||||
Expr *GlobalConstructionExp;
|
||||
unsigned RewriteFailedDiag;
|
||||
unsigned GlobalBlockRewriteFailedDiag;
|
||||
// ObjC string constant support.
|
||||
|
@ -612,6 +613,7 @@ void RewriteModernObjC::InitializeCommon(ASTContext &context) {
|
|||
CurFunctionDef = 0;
|
||||
CurFunctionDeclToDeclareForBlock = 0;
|
||||
GlobalVarDecl = 0;
|
||||
GlobalConstructionExp = 0;
|
||||
SuperStructDecl = 0;
|
||||
ProtocolTypeDecl = 0;
|
||||
ConstantStringDecl = 0;
|
||||
|
@ -3269,7 +3271,7 @@ std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
|
|||
QualType RT = AFT->getResultType();
|
||||
std::string StructRef = "struct " + Tag;
|
||||
std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
|
||||
funcName.str() + "_" + "block_func_" + utostr(i);
|
||||
funcName.str() + "_block_func_" + utostr(i);
|
||||
|
||||
BlockDecl *BD = CE->getBlockDecl();
|
||||
|
||||
|
@ -3632,7 +3634,27 @@ void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
|
|||
SC += "restrict ";
|
||||
InsertText(FunLocStart, SC);
|
||||
}
|
||||
if (GlobalConstructionExp) {
|
||||
// extra fancy dance for global literal expression.
|
||||
|
||||
// Always the latest block expression on the block stack.
|
||||
std::string Tag = "__";
|
||||
Tag += FunName;
|
||||
Tag += "_block_impl_";
|
||||
Tag += utostr(Blocks.size()-1);
|
||||
std::string globalBuf = "static ";
|
||||
globalBuf += Tag; globalBuf += " ";
|
||||
std::string SStr;
|
||||
|
||||
llvm::raw_string_ostream constructorExprBuf(SStr);
|
||||
GlobalConstructionExp->printPretty(constructorExprBuf, *Context, 0,
|
||||
PrintingPolicy(LangOpts));
|
||||
globalBuf += constructorExprBuf.str();
|
||||
globalBuf += ";\n";
|
||||
InsertText(FunLocStart, globalBuf);
|
||||
GlobalConstructionExp = 0;
|
||||
}
|
||||
|
||||
Blocks.clear();
|
||||
InnerDeclRefsCount.clear();
|
||||
InnerDeclRefs.clear();
|
||||
|
@ -4418,9 +4440,6 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
|
||||
const BlockDecl *block = Exp->getBlockDecl();
|
||||
|
||||
if (block->getDeclContext()->getRedeclContext()->isFileContext())
|
||||
Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
|
||||
|
||||
Blocks.push_back(Exp);
|
||||
|
||||
CollectBlockDeclRefInfo(Exp);
|
||||
|
@ -4465,9 +4484,16 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
else if (GlobalVarDecl)
|
||||
FuncName = std::string(GlobalVarDecl->getNameAsString());
|
||||
|
||||
bool GlobalBlockExpr =
|
||||
block->getDeclContext()->getRedeclContext()->isFileContext();
|
||||
|
||||
if (GlobalBlockExpr && !GlobalVarDecl) {
|
||||
Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
|
||||
GlobalBlockExpr = false;
|
||||
}
|
||||
|
||||
std::string BlockNumber = utostr(Blocks.size()-1);
|
||||
|
||||
std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
|
||||
std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
|
||||
|
||||
// Get a pointer to the function type so we can cast appropriately.
|
||||
|
@ -4478,6 +4504,14 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
Expr *NewRep;
|
||||
|
||||
// Simulate a contructor call...
|
||||
std::string Tag;
|
||||
|
||||
if (GlobalBlockExpr)
|
||||
Tag = "__global_";
|
||||
else
|
||||
Tag = "__";
|
||||
Tag += FuncName + "_block_impl_" + BlockNumber;
|
||||
|
||||
FD = SynthBlockInitFunctionDecl(Tag);
|
||||
DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue,
|
||||
SourceLocation());
|
||||
|
@ -4599,6 +4633,14 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
}
|
||||
NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
|
||||
FType, VK_LValue, SourceLocation());
|
||||
|
||||
if (GlobalBlockExpr) {
|
||||
assert (GlobalConstructionExp == 0 &&
|
||||
"SynthBlockInitExpr - GlobalConstructionExp must be null");
|
||||
GlobalConstructionExp = NewRep;
|
||||
NewRep = DRE;
|
||||
}
|
||||
|
||||
NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
|
||||
Context->getPointerType(NewRep->getType()),
|
||||
VK_RValue, OK_Ordinary, SourceLocation());
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
// RUN: %clang_cc1 -rewrite-objc %s -fblocks -o -
|
||||
// RUN: %clang_cc1 -E %s -o %t.mm
|
||||
// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %t.mm -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-fragile-abi %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: // 11006566
|
||||
|
||||
void I( void (^)(void));
|
||||
void (^noop)(void);
|
||||
|
@ -36,11 +41,6 @@ void test2() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void (^test3())(void) {
|
||||
return ^{};
|
||||
}
|
||||
|
||||
void test4() {
|
||||
void (^noop)(void) = ^{};
|
||||
void (*noop2)() = 0;
|
||||
|
@ -61,17 +61,11 @@ void test5() {
|
|||
|
||||
void *X;
|
||||
|
||||
void test_arguments() {
|
||||
int y;
|
||||
int (^c)(char);
|
||||
(1 ? c : 0)('x');
|
||||
(1 ? 0 : c)('x');
|
||||
|
||||
(1 ? c : c)('x');
|
||||
}
|
||||
|
||||
static int global_x = 10;
|
||||
void (^global_block)(void) = ^{ printf("global x is %d\n", global_x); }; // expected-warning {{rewriting block literal declared in global scope is not implemented}}
|
||||
void (^global_block)(void) = ^{ printf("global x is %d\n", global_x); };
|
||||
|
||||
// CHECK: static __global_block_block_impl_0 __global_global_block_block_impl_0((void *)__global_block_block_func_0, &__global_block_block_desc_0_DATA);
|
||||
// CHECK: void (*global_block)(void) = (void (*)())&__global_global_block_block_impl_0;
|
||||
|
||||
typedef void (^void_block_t)(void);
|
||||
|
Loading…
Reference in New Issue