Block C++ code gen. Adds support for block reference argument

types. Executable test will be added to LLVM test suite.
(radar 8041962).

llvm-svn: 105347
This commit is contained in:
Fariborz Jahanian 2010-06-02 21:35:17 +00:00
parent 6a7f9f5c8f
commit d1b378e08d
2 changed files with 43 additions and 4 deletions

View File

@ -296,8 +296,11 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
QualType Ty = E->getType();
if (BDRE && BDRE->isByRef()) {
Types[i+BlockFields] = llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
} else
Types[i+BlockFields] =
llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
} else if (BDRE && BDRE->getDecl()->getType()->isReferenceType()) {
Types[i+BlockFields] = llvm::PointerType::get(ConvertType(Ty), 0);
} else
Types[i+BlockFields] = ConvertType(Ty);
}
@ -359,8 +362,13 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
continue;
} else {
E = new (getContext()) DeclRefExpr(const_cast<ValueDecl*>(VD),
VD->getType(),
SourceLocation());
VD->getType().getNonReferenceType(),
SourceLocation());
if (VD->getType()->isReferenceType())
E = new (getContext())
UnaryOperator(const_cast<Expr*>(E), UnaryOperator::AddrOf,
getContext().getPointerType(E->getType()),
SourceLocation());
}
}
@ -629,6 +637,8 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const ValueDecl *VD,
Ty = llvm::PointerType::get(Ty, 0);
V = Builder.CreateBitCast(V, Ty);
if (VD->getType()->isReferenceType())
V = Builder.CreateLoad(V, "tmp");
}
return V;
}

View File

@ -0,0 +1,29 @@
// RUN: %clang_cc1 -fblocks %s -emit-llvm -o %t
// rdar: // 8041962
extern "C" int printf(const char*, ...);
struct ST {
int filler;
int referrer;
};
void OUTER_BLOCK(void (^fixer)(ST& ref)) {
ST ref = {2, 100};
fixer(ref);
}
void INNER_BLOCK(int (^largeDo) ()) {
printf("%d\n", largeDo());
}
void scan() {
OUTER_BLOCK(^(ST &ref) {
INNER_BLOCK(^() { return ref.referrer + ref.filler; });
});
}
int main() {
scan();
}