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:
parent
3438889dec
commit
97676979a7
|
@ -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;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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}}
|
Loading…
Reference in New Issue