зеркало из https://github.com/microsoft/clang-1.git
Patch to rewrite block pointers as arguments to
methods. (Radar 7987817). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104608 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
af7bea5fb4
Коммит
1f90622e9d
|
@ -276,6 +276,7 @@ namespace {
|
|||
bool isSuperReceiver(Expr *recExpr);
|
||||
QualType getSuperStructType();
|
||||
QualType getConstantStringStructType();
|
||||
QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
|
||||
bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
|
||||
|
||||
// Expression Rewriting.
|
||||
|
@ -2945,6 +2946,11 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
|
|||
QualType type = ICE->getType()->isObjCQualifiedIdType()
|
||||
? Context->getObjCIdType()
|
||||
: ICE->getType();
|
||||
// Make sure we convert "type (^)(...)" to "type (*)(...)".
|
||||
if (isTopLevelBlockPointerType(type)) {
|
||||
const BlockPointerType *BPT = type->getAs<BlockPointerType>();
|
||||
type = Context->getPointerType(BPT->getPointeeType());
|
||||
}
|
||||
userExpr = NoTypeInfoCStyleCastExpr(Context, type, CastExpr::CK_Unknown,
|
||||
userExpr);
|
||||
}
|
||||
|
@ -4113,7 +4119,14 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
|
|||
E = BD->param_end(); AI != E; ++AI) {
|
||||
if (AI != BD->param_begin()) S += ", ";
|
||||
ParamStr = (*AI)->getNameAsString();
|
||||
(*AI)->getType().getAsStringInternal(ParamStr, Context->PrintingPolicy);
|
||||
QualType QT = (*AI)->getType();
|
||||
if (isTopLevelBlockPointerType(QT)) {
|
||||
const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
|
||||
Context->getPointerType(BPT->getPointeeType()).
|
||||
getAsStringInternal(ParamStr, Context->PrintingPolicy);
|
||||
}
|
||||
else
|
||||
QT.getAsStringInternal(ParamStr, Context->PrintingPolicy);
|
||||
S += ParamStr;
|
||||
}
|
||||
if (FT->isVariadic()) {
|
||||
|
@ -4534,6 +4547,47 @@ void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
|
|||
return;
|
||||
}
|
||||
|
||||
/// convertFunctionTypeOfBlocks - This routine converts a function type
|
||||
/// whose result type may be a block pointer or whose argument type(s)
|
||||
/// might be block pointers to an equivalent funtion type replacing
|
||||
/// all block pointers to function pointers.
|
||||
QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
|
||||
const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
|
||||
// FTP will be null for closures that don't take arguments.
|
||||
// Generate a funky cast.
|
||||
llvm::SmallVector<QualType, 8> ArgTypes;
|
||||
bool HasBlockType = false;
|
||||
QualType Res = FT->getResultType();
|
||||
if (isTopLevelBlockPointerType(Res)) {
|
||||
const BlockPointerType *BPT = Res->getAs<BlockPointerType>();
|
||||
Res = Context->getPointerType(BPT->getPointeeType());
|
||||
HasBlockType = true;
|
||||
}
|
||||
|
||||
if (FTP) {
|
||||
for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(),
|
||||
E = FTP->arg_type_end(); I && (I != E); ++I) {
|
||||
QualType t = *I;
|
||||
// Make sure we convert "t (^)(...)" to "t (*)(...)".
|
||||
if (isTopLevelBlockPointerType(t)) {
|
||||
const BlockPointerType *BPT = t->getAs<BlockPointerType>();
|
||||
t = Context->getPointerType(BPT->getPointeeType());
|
||||
HasBlockType = true;
|
||||
}
|
||||
ArgTypes.push_back(t);
|
||||
}
|
||||
}
|
||||
QualType FuncType;
|
||||
// FIXME. Does this work if block takes no argument but has a return type
|
||||
// which is of block type?
|
||||
if (HasBlockType)
|
||||
FuncType = Context->getFunctionType(Res,
|
||||
&ArgTypes[0], ArgTypes.size(), false/*no variadic*/, 0,
|
||||
false, false, 0, 0, FunctionType::ExtInfo());
|
||||
else FuncType = QualType(FT, 0);
|
||||
return FuncType;
|
||||
}
|
||||
|
||||
Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
|
||||
// Navigate to relevant type information.
|
||||
const BlockPointerType *CPT = 0;
|
||||
|
@ -5176,7 +5230,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
|||
std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
|
||||
|
||||
// Get a pointer to the function type so we can cast appropriately.
|
||||
QualType FType = Context->getPointerType(QualType(Exp->getFunctionType(),0));
|
||||
QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
|
||||
QualType FType = Context->getPointerType(BFT);
|
||||
|
||||
FunctionDecl *FD;
|
||||
Expr *NewRep;
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// RUN: %clang_cc1 -x objective-c -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
|
||||
// RUN: %clang_cc1 -Wno-address-of-temporary -Did="void *" -D"SEL=void*" -D"__declspec(X)=" -emit-llvm -o %t %t-rw.cpp
|
||||
// radar 7987817
|
||||
|
||||
void *sel_registerName(const char *);
|
||||
|
||||
@interface Test {
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation Test
|
||||
|
||||
- (void)enumerateProvidersWithBlock:(void (^)(void))block {
|
||||
block();
|
||||
}
|
||||
|
||||
- (void)providerEnumerator {
|
||||
^(void (^providerBlock)(void)) {
|
||||
[self enumerateProvidersWithBlock:providerBlock];
|
||||
};
|
||||
}
|
||||
|
||||
- (void)testNilBlock {
|
||||
[self enumerateProvidersWithBlock:0];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
Загрузка…
Ссылка в новой задаче