зеркало из https://github.com/microsoft/clang.git
Qualified 'id' should implement all of static class type's
protocols, including those added to class, super class and categories; otherewise issue a warning. This fixes pr8453. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117678 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
f4dd962e68
Коммит
0483dceea0
|
@ -2039,7 +2039,6 @@
|
|||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
|
||||
compatibilityVersion = "Xcode 2.4";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
English,
|
||||
|
|
|
@ -4404,33 +4404,17 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
|
|||
|
||||
if (const ObjCObjectPointerType *lhsOPT =
|
||||
lhs->getAsObjCInterfacePointerType()) {
|
||||
if (lhsOPT->qual_empty()) {
|
||||
bool match = false;
|
||||
if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) {
|
||||
for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(),
|
||||
E = rhsQID->qual_end(); I != E; ++I) {
|
||||
// when comparing an id<P> on rhs with a static type on lhs,
|
||||
// static class must implement all of id's protocols directly or
|
||||
// indirectly through its super class.
|
||||
if (lhsID->ClassImplementsProtocol(*I, true)) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Both the right and left sides have qualifiers.
|
||||
// If both the right and left sides have qualifiers.
|
||||
for (ObjCObjectPointerType::qual_iterator I = lhsOPT->qual_begin(),
|
||||
E = lhsOPT->qual_end(); I != E; ++I) {
|
||||
ObjCProtocolDecl *lhsProto = *I;
|
||||
bool match = false;
|
||||
|
||||
// when comparing an id<P> on lhs with a static type on rhs,
|
||||
// when comparing an id<P> on rhs with a static type on lhs,
|
||||
// see if static class implements all of id's protocols, directly or
|
||||
// through its super class and categories.
|
||||
// First, lhs protocols in the qualifier list must be found, direct
|
||||
// or indirect in rhs's qualifier list or it is a mismatch.
|
||||
for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(),
|
||||
E = rhsQID->qual_end(); J != E; ++J) {
|
||||
ObjCProtocolDecl *rhsProto = *J;
|
||||
|
@ -4443,6 +4427,35 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs,
|
|||
if (!match)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Static class's protocols, or its super class or category protocols
|
||||
// must be found, direct or indirect in rhs's qualifier list or it is a mismatch.
|
||||
if (ObjCInterfaceDecl *lhsID = lhsOPT->getInterfaceDecl()) {
|
||||
llvm::SmallPtrSet<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
|
||||
CollectInheritedProtocols(lhsID, LHSInheritedProtocols);
|
||||
// This is rather dubious but matches gcc's behavior. If lhs has
|
||||
// no type qualifier and its class has no static protocol(s) assume
|
||||
// assume that it is mismatch.
|
||||
if (LHSInheritedProtocols.empty() && lhsOPT->qual_empty())
|
||||
return false;
|
||||
for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I =
|
||||
LHSInheritedProtocols.begin(),
|
||||
E = LHSInheritedProtocols.end(); I != E; ++I) {
|
||||
bool match = false;
|
||||
ObjCProtocolDecl *lhsProto = (*I);
|
||||
for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(),
|
||||
E = rhsQID->qual_end(); J != E; ++J) {
|
||||
ObjCProtocolDecl *rhsProto = *J;
|
||||
if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) ||
|
||||
(compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
//rdar: //8591619
|
||||
// pr8453
|
||||
|
||||
@protocol NSCopying @end
|
||||
@protocol NSPROTO @end
|
||||
@protocol NSPROTO1 @end
|
||||
@protocol NSPROTO2 @end
|
||||
|
||||
@interface NSObject <NSCopying, NSPROTO, NSPROTO1> {
|
||||
Class isa;
|
||||
}
|
||||
@end
|
||||
|
||||
void gorf(NSObject <NSCopying> *); // expected-note {{passing argument to parameter here}}
|
||||
|
||||
NSObject <NSCopying> *foo(id <NSCopying> bar, id id_obj)
|
||||
{
|
||||
NSObject <NSCopying> *Init = bar; // expected-warning {{initializing 'NSObject<NSCopying> *' with an expression of incompatible type 'id<NSCopying>'}}
|
||||
NSObject *Init1 = bar; // expected-warning {{initializing 'NSObject *' with an expression of incompatible type 'id<NSCopying>'}}
|
||||
|
||||
NSObject <NSCopying> *I = id_obj;
|
||||
NSObject *I1 = id_obj;
|
||||
gorf(bar); // expected-warning {{passing 'id<NSCopying>' to parameter of incompatible type 'NSObject<NSCopying> *'}}
|
||||
|
||||
gorf(id_obj);
|
||||
|
||||
return bar; // expected-warning {{returning 'id<NSCopying>' from a function with incompatible result type 'NSObject<NSCopying> *'}}
|
||||
}
|
||||
|
||||
void test(id <NSCopying, NSPROTO, NSPROTO2> bar)
|
||||
{
|
||||
NSObject <NSCopying> *Init = bar; // expected-warning {{initializing 'NSObject<NSCopying> *' with an expression of incompatible type 'id<NSCopying,NSPROTO,NSPROTO2>'}}
|
||||
}
|
Загрузка…
Ссылка в новой задаче