Since we ran into a couple of errors in Chromium when rolling past this, would you like to add a note about it in the release notes since it's possible that others will be affected too?
On Thu, Oct 17, 2019 at 5:24 PM James Y Knight via cfe-commits <cfe-commits@lists.llvm.org> wrote: > > Author: jyknight > Date: Thu Oct 17 08:27:04 2019 > New Revision: 375125 > > URL: http://llvm.org/viewvc/llvm-project?rev=375125&view=rev > Log: > [ObjC] Diagnose implicit type coercion from ObjC 'Class' to object > pointer types. > > For example, in Objective-C mode, the initialization of 'x' in: > ``` > @implementation MyType > + (void)someClassMethod { > MyType *x = self; > } > @end > ``` > is correctly diagnosed with an incompatible-pointer-types warning, but > in Objective-C++ mode, it is not diagnosed at all -- even though > incompatible pointer conversions generally become an error in C++. > > This patch fixes that oversight, allowing implicit conversions > involving Class only to/from unqualified-id, and between qualified and > unqualified Class, where the protocols are compatible. > > Note that this does change some behaviors in Objective-C, as well, as > shown by the modified tests. > > Of particular note is that assignment from from 'Class<MyProtocol>' to > 'id<MyProtocol>' now warns. (Despite appearances, those are not > compatible types. 'Class<MyProtocol>' is not expected to have instance > methods defined by 'MyProtocol', while 'id<MyProtocol>' is.) > > Differential Revision: https://reviews.llvm.org/D67983 > > Modified: > cfe/trunk/lib/AST/ASTContext.cpp > cfe/trunk/lib/Sema/SemaExpr.cpp > cfe/trunk/test/SemaObjC/comptypes-1.m > cfe/trunk/test/SemaObjCXX/class-method-self.mm > cfe/trunk/test/SemaObjCXX/comptypes-1.mm > cfe/trunk/test/SemaObjCXX/comptypes-7.mm > cfe/trunk/test/SemaObjCXX/instancetype.mm > > Modified: cfe/trunk/lib/AST/ASTContext.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=375125&r1=375124&r2=375125&view=diff > ============================================================================== > --- cfe/trunk/lib/AST/ASTContext.cpp (original) > +++ cfe/trunk/lib/AST/ASTContext.cpp Thu Oct 17 08:27:04 2019 > @@ -8025,14 +8025,15 @@ bool ASTContext::ObjCQualifiedClassTypes > bool ASTContext::ObjCQualifiedIdTypesAreCompatible( > const ObjCObjectPointerType *lhs, const ObjCObjectPointerType *rhs, > bool compare) { > - // Allow id<P..> and an 'id' or void* type in all cases. > - if (lhs->isVoidPointerType() || > - lhs->isObjCIdType() || lhs->isObjCClassType()) > - return true; > - else if (rhs->isVoidPointerType() || > - rhs->isObjCIdType() || rhs->isObjCClassType()) > + // Allow id<P..> and an 'id' in all cases. > + if (lhs->isObjCIdType() || rhs->isObjCIdType()) > return true; > > + // Don't allow id<P..> to convert to Class or Class<P..> in either > direction. > + if (lhs->isObjCClassType() || lhs->isObjCQualifiedClassType() || > + rhs->isObjCClassType() || rhs->isObjCQualifiedClassType()) > + return false; > + > if (lhs->isObjCQualifiedIdType()) { > if (rhs->qual_empty()) { > // If the RHS is a unqualified interface pointer "NSString*", > @@ -8142,9 +8143,8 @@ bool ASTContext::canAssignObjCInterfaces > const ObjCObjectType* LHS = LHSOPT->getObjectType(); > const ObjCObjectType* RHS = RHSOPT->getObjectType(); > > - // If either type represents the built-in 'id' or 'Class' types, return > true. > - if (LHS->isObjCUnqualifiedIdOrClass() || > - RHS->isObjCUnqualifiedIdOrClass()) > + // If either type represents the built-in 'id' type, return true. > + if (LHS->isObjCUnqualifiedId() || RHS->isObjCUnqualifiedId()) > return true; > > // Function object that propagates a successful result or handles > @@ -8162,14 +8162,22 @@ bool ASTContext::canAssignObjCInterfaces > > LHSOPT->stripObjCKindOfTypeAndQuals(*this)); > }; > > + // Casts from or to id<P> are allowed when the other side has compatible > + // protocols. > if (LHS->isObjCQualifiedId() || RHS->isObjCQualifiedId()) { > return finish(ObjCQualifiedIdTypesAreCompatible(LHSOPT, RHSOPT, false)); > } > > + // Verify protocol compatibility for casts from Class<P1> to Class<P2>. > if (LHS->isObjCQualifiedClass() && RHS->isObjCQualifiedClass()) { > return finish(ObjCQualifiedClassTypesAreCompatible(LHSOPT, RHSOPT)); > } > > + // Casts from Class to Class<Foo>, or vice-versa, are allowed. > + if (LHS->isObjCClass() && RHS->isObjCClass()) { > + return true; > + } > + > // If we have 2 user-defined types, fall into that path. > if (LHS->getInterface() && RHS->getInterface()) { > return finish(canAssignObjCInterfaces(LHS, RHS)); > > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=375125&r1=375124&r2=375125&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Oct 17 08:27:04 2019 > @@ -10068,8 +10068,8 @@ static bool convertPointersToCompositeTy > > QualType T = S.FindCompositePointerType(Loc, LHS, RHS); > if (T.isNull()) { > - if ((LHSType->isPointerType() || LHSType->isMemberPointerType()) && > - (RHSType->isPointerType() || RHSType->isMemberPointerType())) > + if ((LHSType->isAnyPointerType() || LHSType->isMemberPointerType()) && > + (RHSType->isAnyPointerType() || RHSType->isMemberPointerType())) > diagnoseDistinctPointerComparison(S, Loc, LHS, RHS, /*isError*/true); > else > S.InvalidOperands(Loc, LHS, RHS); > > Modified: cfe/trunk/test/SemaObjC/comptypes-1.m > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/comptypes-1.m?rev=375125&r1=375124&r2=375125&view=diff > ============================================================================== > --- cfe/trunk/test/SemaObjC/comptypes-1.m (original) > +++ cfe/trunk/test/SemaObjC/comptypes-1.m Thu Oct 17 08:27:04 2019 > @@ -49,7 +49,7 @@ int main() > obj_p = obj_c; // expected-warning {{assigning to 'id<MyProtocol>' from > incompatible type 'MyClass *'}} > obj_p = obj_cp; /* Ok */ > obj_p = obj_C; // expected-warning {{incompatible pointer types assigning > to 'id<MyProtocol>' from 'Class'}} > - obj_p = obj_CP; // FIXME -- should warn {{assigning to 'id<MyProtocol>' > from incompatible type 'Class<MyProtocol>'}} > + obj_p = obj_CP; // expected-warning {{assigning to 'id<MyProtocol>' from > incompatible type 'Class<MyProtocol>'}} > > /* Assigning to a 'MyOtherClass *' variable should always generate > a warning, unless done from an 'id' or an 'id<MyProtocol>' (since > @@ -92,8 +92,8 @@ int main() > if (obj_c == obj_cp) foo(); // expected-warning {{comparison of distinct > pointer types ('MyClass *' and 'MyOtherClass *')}} > if (obj_cp == obj_c) foo(); // expected-warning {{comparison of distinct > pointer types ('MyOtherClass *' and 'MyClass *')}} > > - if (obj_c == obj_C) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('MyClass *' and 'Class')}} > - if (obj_C == obj_c) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('Class' and 'MyClass *')}} > + if (obj_c == obj_C) foo(); // expected-warning {{comparison of distinct > pointer types ('MyClass *' and 'Class')}} > + if (obj_C == obj_c) foo(); // expected-warning {{comparison of distinct > pointer types ('Class' and 'MyClass *')}} > > if (obj_c == obj_CP) foo(); // expected-warning {{comparison of distinct > pointer types ('MyClass *' and 'Class<MyProtocol>')}} > if (obj_CP == obj_c) foo(); // expected-warning {{comparison of distinct > pointer types ('Class<MyProtocol>' and 'MyClass *')}} > @@ -103,15 +103,15 @@ int main() > if (obj_p == obj_cp) foo(); /* Ok */ > if (obj_cp == obj_p) foo(); /* Ok */ > > - if (obj_p == obj_C) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('id<MyProtocol>' and 'Class')}} > - if (obj_C == obj_p) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('Class' and 'id<MyProtocol>')}} > + if (obj_p == obj_C) foo(); // expected-warning {{comparison of distinct > pointer types ('id<MyProtocol>' and 'Class')}} > + if (obj_C == obj_p) foo(); // expected-warning {{comparison of distinct > pointer types ('Class' and 'id<MyProtocol>')}} > > - if (obj_p == obj_CP) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('id<MyProtocol>' and 'Class<MyProtocol>')}} > - if (obj_CP == obj_p) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('Class<MyProtocol>' and 'id<MyProtocol>')}} > + if (obj_p == obj_CP) foo(); // expected-warning {{comparison of distinct > pointer types ('id<MyProtocol>' and 'Class<MyProtocol>')}} > + if (obj_CP == obj_p) foo(); // expected-warning {{comparison of distinct > pointer types ('Class<MyProtocol>' and 'id<MyProtocol>')}} > > /* Comparisons between MyOtherClass * and Class types is a warning */ > - if (obj_cp == obj_C) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('MyOtherClass *' and 'Class')}} > - if (obj_C == obj_cp) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('Class' and 'MyOtherClass *')}} > + if (obj_cp == obj_C) foo(); // expected-warning {{comparison of distinct > pointer types ('MyOtherClass *' and 'Class')}} > + if (obj_C == obj_cp) foo(); // expected-warning {{comparison of distinct > pointer types ('Class' and 'MyOtherClass *')}} > > if (obj_cp == obj_CP) foo(); // expected-warning {{comparison of distinct > pointer types ('MyOtherClass *' and 'Class<MyProtocol>')}} > if (obj_CP == obj_cp) foo(); // expected-warning {{comparison of distinct > pointer types ('Class<MyProtocol>' and 'MyOtherClass *')}} > > Modified: cfe/trunk/test/SemaObjCXX/class-method-self.mm > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/class-method-self.mm?rev=375125&r1=375124&r2=375125&view=diff > ============================================================================== > --- cfe/trunk/test/SemaObjCXX/class-method-self.mm (original) > +++ cfe/trunk/test/SemaObjCXX/class-method-self.mm Thu Oct 17 08:27:04 2019 > @@ -1,8 +1,8 @@ > // RUN: %clang_cc1 -verify -Wno-objc-root-class %s > -// FIXME: expected-no-diagnostics > + > @interface XX > > -- (void)addObserver:(XX*)o; // FIXME -- should note 2{{passing argument to > parameter 'o' here}} > +- (void)addObserver:(XX*)o; // expected-note 2{{passing argument to > parameter 'o' here}} > > @end > > @@ -17,9 +17,9 @@ > static XX *obj; > > + (void)classMethod { > - [obj addObserver:self]; // FIXME -- should error {{cannot initialize a > parameter of type 'XX *' with an lvalue of type 'Class'}} > + [obj addObserver:self]; // expected-error {{cannot initialize a > parameter of type 'XX *' with an lvalue of type 'Class'}} > Class whatever; > - [obj addObserver:whatever]; // FIXME -- should error {{cannot initialize a > parameter of type 'XX *' with an lvalue of type 'Class'}} > + [obj addObserver:whatever]; // expected-error {{cannot initialize a > parameter of type 'XX *' with an lvalue of type 'Class'}} > } > @end > > > Modified: cfe/trunk/test/SemaObjCXX/comptypes-1.mm > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/comptypes-1.mm?rev=375125&r1=375124&r2=375125&view=diff > ============================================================================== > --- cfe/trunk/test/SemaObjCXX/comptypes-1.mm (original) > +++ cfe/trunk/test/SemaObjCXX/comptypes-1.mm Thu Oct 17 08:27:04 2019 > @@ -38,7 +38,7 @@ int main() > obj_c = obj; /* Ok */ > obj_c = obj_p; // expected-error {{assigning to 'MyClass *' from > incompatible type 'id<MyProtocol>'}} > obj_c = obj_cp; // expected-error {{assigning to 'MyClass *' from > incompatible type 'MyOtherClass *'}} > - obj_c = obj_C; // FIXME -- should error {{assigning to 'MyClass *' from > incompatible type 'Class'}} > + obj_c = obj_C; // expected-error {{assigning to 'MyClass *' from > incompatible type 'Class'}} > obj_c = obj_CP; // expected-error {{assigning to 'MyClass *' from > incompatible type 'Class<MyProtocol>'}} > > /* Assigning to an 'id<MyProtocol>' variable should generate a > @@ -48,8 +48,8 @@ int main() > obj_p = obj; /* Ok */ > obj_p = obj_c; // expected-error {{assigning to 'id<MyProtocol>' from > incompatible type 'MyClass *'}} > obj_p = obj_cp; /* Ok */ > - obj_p = obj_C; // FIXME -- should error {{assigning to 'id<MyProtocol>' > from incompatible type 'Class'}} > - obj_p = obj_CP; // FIXME -- should error {{assigning to 'id<MyProtocol>' > from incompatible type 'Class<MyProtocol>'}} > + obj_p = obj_C; // expected-error {{assigning to 'id<MyProtocol>' from > incompatible type 'Class'}} > + obj_p = obj_CP; // expected-error {{assigning to 'id<MyProtocol>' from > incompatible type 'Class<MyProtocol>'}} > > /* Assigning to a 'MyOtherClass *' variable should always generate > a warning, unless done from an 'id' or an 'id<MyProtocol>' (since > @@ -57,17 +57,17 @@ int main() > obj_cp = obj; /* Ok */ > obj_cp = obj_c; // expected-error {{assigning to 'MyOtherClass *' from > incompatible type 'MyClass *'}} > obj_cp = obj_p; /* Ok */ > - obj_cp = obj_C; // FIXME -- should error {{assigning to 'MyOtherClass *' > from incompatible type 'Class'}} > + obj_cp = obj_C; // expected-error {{assigning to 'MyOtherClass *' from > incompatible type 'Class'}} > obj_cp = obj_CP; // expected-error {{assigning to 'MyOtherClass *' from > incompatible type 'Class<MyProtocol>'}} > > obj_C = obj; // Ok > - obj_C = obj_p; // FIXME -- should error {{assigning to 'Class' from > incompatible type 'id<MyProtocol>'}} > - obj_C = obj_c; // FIXME -- should error {{assigning to 'Class' from > incompatible type 'MyClass *'}} > - obj_C = obj_cp; // FIXME -- should error {{assigning to 'Class' from > incompatible type 'MyOtherClass *'}} > + obj_C = obj_p; // expected-error {{assigning to 'Class' from > incompatible type 'id<MyProtocol>'}} > + obj_C = obj_c; // expected-error {{assigning to 'Class' from > incompatible type 'MyClass *'}} > + obj_C = obj_cp; // expected-error {{assigning to 'Class' from > incompatible type 'MyOtherClass *'}} > obj_C = obj_CP; // Ok > > obj_CP = obj; // Ok > - obj_CP = obj_p; // expected-warning {{incompatible pointer types > assigning to 'Class<MyProtocol>' from 'id<MyProtocol>'}} FIXME -- should > error {{assigning to 'Class<MyProtocol>' from incompatible type > 'id<MyProtocol>'}} > + obj_CP = obj_p; // expected-error {{assigning to 'Class<MyProtocol>' > from incompatible type 'id<MyProtocol>'}} > obj_CP = obj_c; // expected-error {{assigning to 'Class<MyProtocol>' > from incompatible type 'MyClass *}} > obj_CP = obj_cp; // expected-error {{assigning to 'Class<MyProtocol>' > from incompatible type 'MyOtherClass *'}} > obj_CP = obj_C; // Ok > @@ -92,8 +92,8 @@ int main() > if (obj_c == obj_cp) foo(); // expected-warning {{comparison of distinct > pointer types ('MyClass *' and 'MyOtherClass *')}} > if (obj_cp == obj_c) foo(); // expected-warning {{comparison of distinct > pointer types ('MyOtherClass *' and 'MyClass *')}} > > - if (obj_c == obj_C) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('MyClass *' and 'Class')}} > - if (obj_C == obj_c) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('Class' and 'MyClass *')}} > + if (obj_c == obj_C) foo(); // expected-warning {{comparison of distinct > pointer types ('MyClass *' and 'Class')}} > + if (obj_C == obj_c) foo(); // expected-warning {{comparison of distinct > pointer types ('Class' and 'MyClass *')}} > > if (obj_c == obj_CP) foo(); // expected-warning {{comparison of distinct > pointer types ('MyClass *' and 'Class<MyProtocol>')}} > if (obj_CP == obj_c) foo(); // expected-warning {{comparison of distinct > pointer types ('Class<MyProtocol>' and 'MyClass *')}} > @@ -103,15 +103,15 @@ int main() > if (obj_p == obj_cp) foo(); /* Ok */ > if (obj_cp == obj_p) foo(); /* Ok */ > > - if (obj_p == obj_C) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('id<MyProtocol>' and 'Class')}} > - if (obj_C == obj_p) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('Class' and 'id<MyProtocol>')}} > + if (obj_p == obj_C) foo(); // expected-warning {{comparison of distinct > pointer types ('id<MyProtocol>' and 'Class')}} > + if (obj_C == obj_p) foo(); // expected-warning {{comparison of distinct > pointer types ('Class' and 'id<MyProtocol>')}} > > - if (obj_p == obj_CP) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('id<MyProtocol>' and 'Class<MyProtocol>')}} > - if (obj_CP == obj_p) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('Class<MyProtocol>' and 'id<MyProtocol>')}} > + if (obj_p == obj_CP) foo(); // expected-warning {{comparison of distinct > pointer types ('id<MyProtocol>' and 'Class<MyProtocol>')}} > + if (obj_CP == obj_p) foo(); // expected-warning {{comparison of distinct > pointer types ('Class<MyProtocol>' and 'id<MyProtocol>')}} > > /* Comparisons between MyOtherClass * and Class types is a warning */ > - if (obj_cp == obj_C) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('MyOtherClass *' and 'Class')}} > - if (obj_C == obj_cp) foo(); // FIXME -- should warn {{comparison of > distinct pointer types ('Class' and 'MyOtherClass *')}} > + if (obj_cp == obj_C) foo(); // expected-warning {{comparison of distinct > pointer types ('MyOtherClass *' and 'Class')}} > + if (obj_C == obj_cp) foo(); // expected-warning {{comparison of distinct > pointer types ('Class' and 'MyOtherClass *')}} > > if (obj_cp == obj_CP) foo(); // expected-warning {{comparison of distinct > pointer types ('MyOtherClass *' and 'Class<MyProtocol>')}} > if (obj_CP == obj_cp) foo(); // expected-warning {{comparison of distinct > pointer types ('Class<MyProtocol>' and 'MyOtherClass *')}} > > Modified: cfe/trunk/test/SemaObjCXX/comptypes-7.mm > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/comptypes-7.mm?rev=375125&r1=375124&r2=375125&view=diff > ============================================================================== > --- cfe/trunk/test/SemaObjCXX/comptypes-7.mm (original) > +++ cfe/trunk/test/SemaObjCXX/comptypes-7.mm Thu Oct 17 08:27:04 2019 > @@ -47,23 +47,23 @@ int main() > > if (obj == i) foo() ; // expected-error {{comparison between pointer and > integer ('id' and 'int')}} > if (i == obj) foo() ; // expected-error {{comparison between pointer and > integer ('int' and 'id')}} > - if (obj == j) foo() ; // expected-error {{invalid operands to binary > expression ('id' and 'int *')}} > - if (j == obj) foo() ; // expected-error {{invalid operands to binary > expression ('int *' and 'id')}} > + if (obj == j) foo() ; // expected-error {{comparison of distinct pointer > types ('id' and 'int *')}} > + if (j == obj) foo() ; // expected-error {{comparison of distinct pointer > types ('int *' and 'id')}} > > if (obj_c == i) foo() ; // expected-error {{comparison between pointer and > integer ('MyClass *' and 'int')}} > if (i == obj_c) foo() ; // expected-error {{comparison between pointer and > integer ('int' and 'MyClass *')}} > - if (obj_c == j) foo() ; // expected-error {{invalid operands to binary > expression ('MyClass *' and 'int *')}} > - if (j == obj_c) foo() ; // expected-error {{invalid operands to binary > expression ('int *' and 'MyClass *')}} > + if (obj_c == j) foo() ; // expected-error {{comparison of distinct pointer > types ('MyClass *' and 'int *')}} > + if (j == obj_c) foo() ; // expected-error {{comparison of distinct pointer > types ('int *' and 'MyClass *')}} > > if (obj_p == i) foo() ; // expected-error {{comparison between pointer and > integer ('id<MyProtocol>' and 'int')}} > if (i == obj_p) foo() ; // expected-error {{comparison between pointer and > integer ('int' and 'id<MyProtocol>')}} > - if (obj_p == j) foo() ; // expected-error {{invalid operands to binary > expression ('id<MyProtocol>' and 'int *')}} > - if (j == obj_p) foo() ; // expected-error {{invalid operands to binary > expression ('int *' and 'id<MyProtocol>')}} > + if (obj_p == j) foo() ; // expected-error {{comparison of distinct pointer > types ('id<MyProtocol>' and 'int *')}} > + if (j == obj_p) foo() ; // expected-error {{comparison of distinct pointer > types ('int *' and 'id<MyProtocol>')}} > > if (obj_C == i) foo() ; // expected-error {{comparison between pointer and > integer ('Class' and 'int')}} > if (i == obj_C) foo() ; // expected-error {{comparison between pointer and > integer ('int' and 'Class')}} > - if (obj_C == j) foo() ; // expected-error {{invalid operands to binary > expression ('Class' and 'int *')}} > - if (j == obj_C) foo() ; // expected-error {{invalid operands to binary > expression ('int *' and 'Class')}} > + if (obj_C == j) foo() ; // expected-error {{comparison of distinct pointer > types ('Class' and 'int *')}} > + if (j == obj_C) foo() ; // expected-error {{comparison of distinct pointer > types ('int *' and 'Class')}} > > Class bar1 = nil; > Class <MyProtocol> bar = nil; > > Modified: cfe/trunk/test/SemaObjCXX/instancetype.mm > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/instancetype.mm?rev=375125&r1=375124&r2=375125&view=diff > ============================================================================== > --- cfe/trunk/test/SemaObjCXX/instancetype.mm (original) > +++ cfe/trunk/test/SemaObjCXX/instancetype.mm Thu Oct 17 08:27:04 2019 > @@ -5,7 +5,7 @@ > #endif > > @interface Root > -+ (instancetype)alloc; // FIXME -- should note {{explicitly declared > 'instancetype'}} > ++ (instancetype)alloc; // expected-note {{explicitly declared > 'instancetype'}} > - (instancetype)init; // expected-note{{overridden method is part of the > 'init' method family}} > - (instancetype)self; // expected-note {{explicitly declared 'instancetype'}} > - (Class)class; > @@ -143,7 +143,7 @@ void test_instancetype_narrow_method_sea > > @implementation Subclass4 > + (id)alloc { > - return self; // FIXME -- should error{{cannot initialize return object of > type 'Subclass4 *' with an lvalue of type 'Class'}} > + return self; // expected-error{{cannot initialize return object of type > 'Subclass4 *' with an lvalue of type 'Class'}} > } > > - (Subclass3 *)init { return 0; } // don't complain: we lost the related > return type > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits