forked from OSchip/llvm-project
Changed Sema::CheckForConstantInitializer to allow global block literals.
This commit also includes some name changes in the blocks rewriter (no functionality change). llvm-svn: 56955
This commit is contained in:
parent
c3d16493ae
commit
d40a39626c
|
@ -186,18 +186,18 @@ void RewriteBlocks::Initialize(ASTContext &context) {
|
||||||
Rewrite.setSourceMgr(Context->getSourceManager());
|
Rewrite.setSourceMgr(Context->getSourceManager());
|
||||||
|
|
||||||
const char *s = "#pragma once\n"
|
const char *s = "#pragma once\n"
|
||||||
"#ifndef CLOSURE_IMPL\n"
|
"#ifndef BLOCK_IMPL\n"
|
||||||
"struct __closure_impl {\n"
|
"struct __block_impl {\n"
|
||||||
" long Reserved;\n"
|
" void *isa;\n"
|
||||||
" int Flags;\n"
|
" int Flags;\n"
|
||||||
" int Size;\n"
|
" int Size;\n"
|
||||||
" void *Invoke;\n"
|
" void *FuncPtr;\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"enum {\n"
|
"enum {\n"
|
||||||
" HAS_NONPOD = (1<<25),\n"
|
" BLOCK_HAS_COPY_DISPOSE = (1<<25),\n"
|
||||||
" HAS_BYREF = (1<<26)\n"
|
" BLOCK_IS_GLOBAL = (1<<28)\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"#define CLOSURE_IMPL\n"
|
"#define BLOCK_IMPL\n"
|
||||||
"#endif\n";
|
"#endif\n";
|
||||||
if (IsHeader) {
|
if (IsHeader) {
|
||||||
// insert the whole string when rewriting a header file
|
// insert the whole string when rewriting a header file
|
||||||
|
@ -243,7 +243,7 @@ void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) {
|
||||||
const char *endBuf = SM->getCharacterData(LocEnd);
|
const char *endBuf = SM->getCharacterData(LocEnd);
|
||||||
|
|
||||||
const char *methodPtr = startBuf;
|
const char *methodPtr = startBuf;
|
||||||
std::string Tag = "struct __closure_impl *";
|
std::string Tag = "struct __block_impl *";
|
||||||
|
|
||||||
while (*methodPtr++ && (methodPtr != endBuf)) {
|
while (*methodPtr++ && (methodPtr != endBuf)) {
|
||||||
switch (*methodPtr) {
|
switch (*methodPtr) {
|
||||||
|
@ -405,7 +405,7 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
|
||||||
// };
|
// };
|
||||||
//
|
//
|
||||||
if (isBlockPointerType((*I)->getType()))
|
if (isBlockPointerType((*I)->getType()))
|
||||||
S += "struct __closure_impl *";
|
S += "struct __block_impl *";
|
||||||
else
|
else
|
||||||
(*I)->getType().getAsStringInternal(Name);
|
(*I)->getType().getAsStringInternal(Name);
|
||||||
S += Name + " = __cself->" + (*I)->getName() + "; // bound by copy\n";
|
S += Name + " = __cself->" + (*I)->getName() + "; // bound by copy\n";
|
||||||
|
@ -471,7 +471,7 @@ std::string RewriteBlocks::SynthesizeBlockFunc(BlockExpr *CE, int i,
|
||||||
|
|
||||||
std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE,
|
std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE,
|
||||||
std::string Tag) {
|
std::string Tag) {
|
||||||
std::string S = Tag + " {\n struct __closure_impl impl;\n";
|
std::string S = Tag + " {\n struct __block_impl impl;\n";
|
||||||
|
|
||||||
GetBlockDeclRefExprs(CE);
|
GetBlockDeclRefExprs(CE);
|
||||||
if (BlockDeclRefs.size()) {
|
if (BlockDeclRefs.size()) {
|
||||||
|
@ -500,7 +500,7 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE,
|
||||||
// };
|
// };
|
||||||
//
|
//
|
||||||
if (isBlockPointerType((*I)->getType()))
|
if (isBlockPointerType((*I)->getType()))
|
||||||
S += "struct __closure_impl *";
|
S += "struct __block_impl *";
|
||||||
else
|
else
|
||||||
(*I)->getType().getAsStringInternal(Name);
|
(*I)->getType().getAsStringInternal(Name);
|
||||||
S += Name + ";\n";
|
S += Name + ";\n";
|
||||||
|
@ -511,7 +511,7 @@ std::string RewriteBlocks::SynthesizeBlockImpl(BlockExpr *CE,
|
||||||
S += " ";
|
S += " ";
|
||||||
std::string Name = (*I)->getName();
|
std::string Name = (*I)->getName();
|
||||||
if (isBlockPointerType((*I)->getType()))
|
if (isBlockPointerType((*I)->getType()))
|
||||||
S += "struct __closure_impl *";
|
S += "struct __block_impl *";
|
||||||
else
|
else
|
||||||
Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
|
Context->getPointerType((*I)->getType()).getAsStringInternal(Name);
|
||||||
S += Name + "; // by ref\n";
|
S += Name + "; // by ref\n";
|
||||||
|
@ -702,7 +702,7 @@ std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) {
|
||||||
|
|
||||||
// Synthesize the cast.
|
// Synthesize the cast.
|
||||||
BlockCall += "(" + Exp->getType().getAsString() + "(*)";
|
BlockCall += "(" + Exp->getType().getAsString() + "(*)";
|
||||||
BlockCall += "(struct __closure_impl *";
|
BlockCall += "(struct __block_impl *";
|
||||||
if (FTP) {
|
if (FTP) {
|
||||||
for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
|
for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(),
|
||||||
E = FTP->arg_type_end(); I && (I != E); ++I)
|
E = FTP->arg_type_end(); I && (I != E); ++I)
|
||||||
|
@ -755,7 +755,7 @@ void RewriteBlocks::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
|
||||||
const char *topLevelCommaCursor = 0;
|
const char *topLevelCommaCursor = 0;
|
||||||
const char *argPtr = startArgList;
|
const char *argPtr = startArgList;
|
||||||
bool scannedBlockDecl = false;
|
bool scannedBlockDecl = false;
|
||||||
std::string Tag = "struct __closure_impl *";
|
std::string Tag = "struct __block_impl *";
|
||||||
|
|
||||||
while (*argPtr++ && parenCount) {
|
while (*argPtr++ && parenCount) {
|
||||||
switch (*argPtr) {
|
switch (*argPtr) {
|
||||||
|
@ -925,7 +925,7 @@ void RewriteBlocks::RewriteBlockExpr(BlockExpr *Exp) {
|
||||||
|
|
||||||
// Rewrite the closure block with a compound literal. The first cast is
|
// Rewrite the closure block with a compound literal. The first cast is
|
||||||
// to prevent warnings from the C compiler.
|
// to prevent warnings from the C compiler.
|
||||||
std::string Init = "(struct __closure_impl *)&(" + Tag + "){{0,";
|
std::string Init = "(struct __block_impl *)&(" + Tag + "){{0,";
|
||||||
|
|
||||||
// Initialize the Flags, Size, and Invoke fields.
|
// Initialize the Flags, Size, and Invoke fields.
|
||||||
Init += (haveByRefDecls ? "HAS_BYREF," : "0,");
|
Init += (haveByRefDecls ? "HAS_BYREF," : "0,");
|
||||||
|
|
|
@ -1286,6 +1286,10 @@ bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) {
|
||||||
if (Init->getType()->isFunctionType())
|
if (Init->getType()->isFunctionType())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Allow block exprs at top level.
|
||||||
|
if (Init->getType()->isBlockPointerType())
|
||||||
|
return false;
|
||||||
|
|
||||||
Diag(Init->getExprLoc(), diag::err_init_element_not_constant,
|
Diag(Init->getExprLoc(), diag::err_init_element_not_constant,
|
||||||
Init->getSourceRange());
|
Init->getSourceRange());
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -78,6 +78,9 @@ void test_arguments() {
|
||||||
(1 ? c : c)('x');
|
(1 ? c : c)('x');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int global_x = 10;
|
||||||
|
void (^global_block)(void) = ^{ printf("global x is %d\n", global_x); };
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Old syntax. FIXME: convert/test.
|
// Old syntax. FIXME: convert/test.
|
||||||
void test_byref() {
|
void test_byref() {
|
||||||
|
|
Loading…
Reference in New Issue