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:
Steve Naroff 2008-10-02 17:12:56 +00:00
parent c3d16493ae
commit d40a39626c
3 changed files with 22 additions and 15 deletions

View File

@ -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,");

View File

@ -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;

View File

@ -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() {