objc arc: Diagnose block pointer type mismatch when

some arguments types are ns_consumed and some otherwise
matching types are not. This is objc side of
// rdar://10187884

llvm-svn: 140729
This commit is contained in:
Fariborz Jahanian 2011-09-28 21:52:05 +00:00
parent 3438889dec
commit 97676979a7
4 changed files with 53 additions and 16 deletions

View File

@ -1510,6 +1510,10 @@ public:
bool Unqualified = false); bool Unqualified = false);
QualType mergeObjCGCQualifiers(QualType, QualType); QualType mergeObjCGCQualifiers(QualType, QualType);
bool FunctionTypesMatchOnNSConsumedAttrs(
const FunctionProtoType *FromFunctionType,
const FunctionProtoType *ToFunctionType);
void ResetObjCLayout(const ObjCContainerDecl *CD) { void ResetObjCLayout(const ObjCContainerDecl *CD) {
ObjCLayouts[CD] = 0; ObjCLayouts[CD] = 0;

View File

@ -5570,6 +5570,10 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (lproto->getTypeQuals() != rproto->getTypeQuals()) if (lproto->getTypeQuals() != rproto->getTypeQuals())
return QualType(); return QualType();
if (LangOpts.ObjCAutoRefCount &&
!FunctionTypesMatchOnNSConsumedAttrs(rproto, lproto))
return QualType();
// Check argument compatibility // Check argument compatibility
SmallVector<QualType, 10> types; SmallVector<QualType, 10> types;
for (unsigned i = 0; i < lproto_nargs; i++) { for (unsigned i = 0; i < lproto_nargs; i++) {
@ -5594,6 +5598,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
if (getCanonicalType(argtype) != getCanonicalType(rargtype)) if (getCanonicalType(argtype) != getCanonicalType(rargtype))
allRTypes = false; allRTypes = false;
} }
if (allLTypes) return lhs; if (allLTypes) return lhs;
if (allRTypes) return rhs; if (allRTypes) return rhs;
@ -5892,6 +5897,26 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
return QualType(); return QualType();
} }
bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs(
const FunctionProtoType *FromFunctionType,
const FunctionProtoType *ToFunctionType) {
if (FromFunctionType->hasAnyConsumedArgs() !=
ToFunctionType->hasAnyConsumedArgs())
return false;
FunctionProtoType::ExtProtoInfo FromEPI =
FromFunctionType->getExtProtoInfo();
FunctionProtoType::ExtProtoInfo ToEPI =
ToFunctionType->getExtProtoInfo();
if (FromEPI.ConsumedArguments && ToEPI.ConsumedArguments)
for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
ArgIdx != NumArgs; ++ArgIdx) {
if (FromEPI.ConsumedArguments[ArgIdx] !=
ToEPI.ConsumedArguments[ArgIdx])
return false;
}
return true;
}
/// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and /// mergeObjCGCQualifiers - This routine merges ObjC's GC attribute of 'LHS' and
/// 'RHS' attributes and returns the merged version; including for function /// 'RHS' attributes and returns the merged version; including for function
/// return types. /// return types.

View File

@ -2074,22 +2074,10 @@ bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType,
// Argument types are too different. Abort. // Argument types are too different. Abort.
return false; return false;
} }
if (LangOpts.ObjCAutoRefCount) { if (LangOpts.ObjCAutoRefCount &&
if (FromFunctionType->hasAnyConsumedArgs() != !Context.FunctionTypesMatchOnNSConsumedAttrs(FromFunctionType,
ToFunctionType->hasAnyConsumedArgs()) ToFunctionType))
return false; return false;
FunctionProtoType::ExtProtoInfo FromEPI =
FromFunctionType->getExtProtoInfo();
FunctionProtoType::ExtProtoInfo ToEPI =
ToFunctionType->getExtProtoInfo();
if (FromEPI.ConsumedArguments && ToEPI.ConsumedArguments)
for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs();
ArgIdx != NumArgs; ++ArgIdx) {
if (FromEPI.ConsumedArguments[ArgIdx] !=
ToEPI.ConsumedArguments[ArgIdx])
return false;
}
}
ConvertedType = ToType; ConvertedType = ToType;
return true; return true;

View File

@ -0,0 +1,20 @@
// RUN: %clang_cc1 -fobjc-nonfragile-abi -fsyntax-only -fobjc-arc -verify -fblocks -triple x86_64-apple-darwin10.0.0 %s
// rdar://10187884
typedef void (^blk)(id arg1, __attribute((ns_consumed)) id arg2);
typedef void (^blk1)(__attribute((ns_consumed))id arg1, __attribute((ns_consumed)) id arg2);
blk a = ^void (__attribute((ns_consumed)) id arg1, __attribute((ns_consumed)) id arg2){}; // expected-error {{incompatible block pointer types initializing}}
blk b = ^void (id arg1, __attribute((ns_consumed)) id arg2){};
blk c = ^void (__attribute((ns_consumed)) id arg1, __attribute((ns_consumed)) id arg2){}; // expected-error {{incompatible block pointer types initializing}}
blk d = ^void (id arg1, id arg2) {}; // expected-error {{incompatible block pointer types initializing}}
blk1 a1 = ^void (__attribute((ns_consumed)) id arg1, id arg2){}; // expected-error {{incompatible block pointer types initializing}}
blk1 b2 = ^void (id arg1, __attribute((ns_consumed)) id arg2){}; // expected-error {{incompatible block pointer types initializing}}
blk1 c3 = ^void (__attribute((ns_consumed)) id arg1, __attribute((ns_consumed)) id arg2){};
blk1 d4 = ^void (id arg1, id arg2) {}; // expected-error {{incompatible block pointer types initializing}}