r177378 - Add a clarifying note when a return statement is rejected because
John McCall
rjmccall at apple.com
Tue Mar 19 00:04:25 PDT 2013
Author: rjmccall
Date: Tue Mar 19 02:04:25 2013
New Revision: 177378
URL: http://llvm.org/viewvc/llvm-project?rev=177378&view=rev
Log:
Add a clarifying note when a return statement is rejected because
we expect a related result type.
rdar://12493140
Added:
cfe/trunk/test/SemaObjCXX/instancetype.mm
- copied, changed from r177370, cfe/trunk/test/SemaObjC/instancetype.m
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprObjC.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/test/CodeGenObjC/arc.m
cfe/trunk/test/SemaObjC/instancetype.m
cfe/trunk/test/SemaObjC/related-result-type-inference.m
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Mar 19 02:04:25 2013
@@ -6198,15 +6198,19 @@ def warn_related_result_type_compatibili
def warn_related_result_type_compatibility_protocol : Warning<
"protocol method is expected to return an instance of the implementing "
"class, but is declared to return %0">;
-def note_related_result_type_overridden_family : Note<
- "overridden method is part of the '%select{|alloc|copy|init|mutableCopy|"
- "new|autorelease|dealloc|finalize|release|retain|retainCount|self}0' method "
- "family">;
+def note_related_result_type_family : Note<
+ "%select{overridden|current}0 method is part of the '%select{|alloc|copy|init|"
+ "mutableCopy|new|autorelease|dealloc|finalize|release|retain|retainCount|"
+ "self}1' method family%select{| and is expected to return an instance of its "
+ "class type}0">;
def note_related_result_type_overridden : Note<
"overridden method returns an instance of its class type">;
def note_related_result_type_inferred : Note<
"%select{class|instance}0 method %1 is assumed to return an instance of "
"its receiver type (%2)">;
+def note_related_result_type_explicit : Note<
+ "%select{overridden|current}0 method is explicitly declared 'instancetype'"
+ "%select{| and is expected to return an instance of its class type}0">;
}
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Mar 19 02:04:25 2013
@@ -7026,6 +7026,11 @@ public:
/// with a related result type, emit a note describing what happened.
void EmitRelatedResultTypeNote(const Expr *E);
+ /// \brief Given that we had incompatible pointer types in a return
+ /// statement, check whether we're in a method with a related result
+ /// type, and if so, emit a note describing what happened.
+ void EmitRelatedResultTypeNoteForReturn(QualType destType);
+
/// CheckBooleanCondition - Diagnose problems involving the use of
/// the given expression as a boolean condition (e.g. in an if
/// statement). Also performs the standard function and array
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Mar 19 02:04:25 2013
@@ -151,7 +151,8 @@ void Sema::CheckObjCMethodOverride(ObjCM
if (ObjCMethodFamily Family = Overridden->getMethodFamily())
Diag(Overridden->getLocation(),
- diag::note_related_result_type_overridden_family)
+ diag::note_related_result_type_family)
+ << /*overridden method*/ 0
<< Family;
else
Diag(Overridden->getLocation(),
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Mar 19 02:04:25 2013
@@ -10039,6 +10039,9 @@ bool Sema::DiagnoseAssignmentResult(Assi
if (CheckInferredResultType)
EmitRelatedResultTypeNote(SrcExpr);
+
+ if (Action == AA_Returning && ConvTy == IncompatiblePointer)
+ EmitRelatedResultTypeNoteForReturn(DstType);
if (Complained)
*Complained = true;
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Mar 19 02:04:25 2013
@@ -1094,6 +1094,73 @@ QualType Sema::getMessageSendResultType(
return ReceiverType;
}
+/// Look for an ObjC method whose result type exactly matches the given type.
+static const ObjCMethodDecl *
+findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD,
+ QualType instancetype) {
+ if (MD->getResultType() == instancetype) return MD;
+
+ // For these purposes, a method in an @implementation overrides a
+ // declaration in the @interface.
+ if (const ObjCImplDecl *impl =
+ dyn_cast<ObjCImplDecl>(MD->getDeclContext())) {
+ const ObjCContainerDecl *iface;
+ if (const ObjCCategoryImplDecl *catImpl =
+ dyn_cast<ObjCCategoryImplDecl>(impl)) {
+ iface = catImpl->getCategoryDecl();
+ } else {
+ iface = impl->getClassInterface();
+ }
+
+ const ObjCMethodDecl *ifaceMD =
+ iface->getMethod(MD->getSelector(), MD->isInstanceMethod());
+ if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype);
+ }
+
+ SmallVector<const ObjCMethodDecl *, 4> overrides;
+ MD->getOverriddenMethods(overrides);
+ for (unsigned i = 0, e = overrides.size(); i != e; ++i) {
+ if (const ObjCMethodDecl *result =
+ findExplicitInstancetypeDeclarer(overrides[i], instancetype))
+ return result;
+ }
+
+ return 0;
+}
+
+void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) {
+ // Only complain if we're in an ObjC method and the required return
+ // type doesn't match the method's declared return type.
+ ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext);
+ if (!MD || !MD->hasRelatedResultType() ||
+ Context.hasSameUnqualifiedType(destType, MD->getResultType()))
+ return;
+
+ // Look for a method overridden by this method which explicitly uses
+ // 'instancetype'.
+ if (const ObjCMethodDecl *overridden =
+ findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) {
+ SourceLocation loc;
+ SourceRange range;
+ if (TypeSourceInfo *TSI = overridden->getResultTypeSourceInfo()) {
+ range = TSI->getTypeLoc().getSourceRange();
+ loc = range.getBegin();
+ }
+ if (loc.isInvalid())
+ loc = overridden->getLocation();
+ Diag(loc, diag::note_related_result_type_explicit)
+ << /*current method*/ 1 << range;
+ return;
+ }
+
+ // Otherwise, if we have an interesting method family, note that.
+ // This should always trigger if the above didn't.
+ if (ObjCMethodFamily family = MD->getMethodFamily())
+ Diag(MD->getLocation(), diag::note_related_result_type_family)
+ << /*current method*/ 1
+ << family;
+}
+
void Sema::EmitRelatedResultTypeNote(const Expr *E) {
E = E->IgnoreParenImpCasts();
const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E);
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Mar 19 02:04:25 2013
@@ -5590,6 +5590,26 @@ static bool DiagnoseUninitializedReferen
//===----------------------------------------------------------------------===//
// Diagnose initialization failures
//===----------------------------------------------------------------------===//
+
+/// Emit notes associated with an initialization that failed due to a
+/// "simple" conversion failure.
+static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity,
+ Expr *op) {
+ QualType destType = entity.getType();
+ if (destType.getNonReferenceType()->isObjCObjectPointerType() &&
+ op->getType()->isObjCObjectPointerType()) {
+
+ // Emit a possible note about the conversion failing because the
+ // operand is a message send with a related result type.
+ S.EmitRelatedResultTypeNote(op);
+
+ // Emit a possible note about a return failing because we're
+ // expecting a related result type.
+ if (entity.getKind() == InitializedEntity::EK_Result)
+ S.EmitRelatedResultTypeNoteForReturn(destType);
+ }
+}
+
bool InitializationSequence::Diagnose(Sema &S,
const InitializedEntity &Entity,
const InitializationKind &Kind,
@@ -5734,9 +5754,7 @@ bool InitializationSequence::Diagnose(Se
<< Args[0]->isLValue()
<< Args[0]->getType()
<< Args[0]->getSourceRange();
- if (DestType.getNonReferenceType()->isObjCObjectPointerType() &&
- Args[0]->getType()->isObjCObjectPointerType())
- S.EmitRelatedResultTypeNote(Args[0]);
+ emitBadConversionNotes(S, Entity, Args[0]);
break;
case FK_ConversionFailed: {
@@ -5749,9 +5767,7 @@ bool InitializationSequence::Diagnose(Se
<< Args[0]->getSourceRange();
S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
S.Diag(Kind.getLocation(), PDiag);
- if (DestType.getNonReferenceType()->isObjCObjectPointerType() &&
- Args[0]->getType()->isObjCObjectPointerType())
- S.EmitRelatedResultTypeNote(Args[0]);
+ emitBadConversionNotes(S, Entity, Args[0]);
break;
}
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Mar 19 02:04:25 2013
@@ -2536,20 +2536,7 @@ Sema::ActOnReturnStmt(SourceLocation Ret
if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) {
// we have a non-void function with an expression, continue checking
- if (!RelatedRetType.isNull()) {
- // If we have a related result type, perform an extra conversion here.
- // FIXME: The diagnostics here don't really describe what is happening.
- InitializedEntity Entity =
- InitializedEntity::InitializeTemporary(RelatedRetType);
-
- ExprResult Res = PerformCopyInitialization(Entity, SourceLocation(),
- RetValExp);
- if (Res.isInvalid()) {
- // FIXME: Cleanup temporaries here, anyway?
- return StmtError();
- }
- RetValExp = Res.takeAs<Expr>();
- }
+ QualType RetType = (RelatedRetType.isNull() ? FnRetType : RelatedRetType);
// C99 6.8.6.4p3(136): The return statement is not an assignment. The
// overlap restriction of subclause 6.5.16.1 does not apply to the case of
@@ -2559,18 +2546,33 @@ Sema::ActOnReturnStmt(SourceLocation Ret
// the C version of which boils down to CheckSingleAssignmentConstraints.
NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false);
InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc,
- FnRetType,
+ RetType,
NRVOCandidate != 0);
ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate,
- FnRetType, RetValExp);
+ RetType, RetValExp);
if (Res.isInvalid()) {
- // FIXME: Cleanup temporaries here, anyway?
+ // FIXME: Clean up temporaries here anyway?
return StmtError();
}
-
RetValExp = Res.takeAs<Expr>();
- if (RetValExp)
- CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
+
+ // If we have a related result type, we need to implicitly
+ // convert back to the formal result type. We can't pretend to
+ // initialize the result again --- we might end double-retaining
+ // --- so instead we initialize a notional temporary; this can
+ // lead to less-than-great diagnostics, but this stage is much
+ // less likely to fail than the previous stage.
+ if (!RelatedRetType.isNull()) {
+ Entity = InitializedEntity::InitializeTemporary(FnRetType);
+ Res = PerformCopyInitialization(Entity, ReturnLoc, RetValExp);
+ if (Res.isInvalid()) {
+ // FIXME: Clean up temporaries here anyway?
+ return StmtError();
+ }
+ RetValExp = Res.takeAs<Expr>();
+ }
+
+ CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc);
}
if (RetValExp) {
Modified: cfe/trunk/test/CodeGenObjC/arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/arc.m (original)
+++ cfe/trunk/test/CodeGenObjC/arc.m Tue Mar 19 02:04:25 2013
@@ -621,7 +621,9 @@ void test21(unsigned n) {
// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]]
// CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8*
-// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST27]]*
+// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST27]]* [[T3]] to i8*
// CHECK-NEXT: store i32 {{[0-9]+}}, i32* [[DEST]]
// CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8*
@@ -685,7 +687,9 @@ static id _test29_allocator = 0;
// Return statement.
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[CALL]]
// CHECK-NEXT: [[CALL:%.*]] = bitcast
-// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[CALL]]) [[NUW]]
+// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[CALL]]) [[NUW]]
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]*
+// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8*
// CHECK-NEXT: store i32 1, i32* [[CLEANUP]]
// Cleanup.
@@ -739,7 +743,9 @@ static id _test29_allocator = 0;
// Return statement.
// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8*
-// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]]
+// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[T1]]) [[NUW]]
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST29]]*
+// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST29]]* [[T1]] to i8*
// CHECK-NEXT: store i32 1, i32* [[CLEANUP]]
// Cleanup.
@@ -794,7 +800,9 @@ char *helper;
// Return.
// CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST30]]* [[T0]] to i8*
-// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[TEST30]]*
+// CHECK-NEXT: [[RET:%.*]] = bitcast [[TEST30]]* [[T1]] to i8*
// CHECK-NEXT: store i32 1
// Cleanup.
Modified: cfe/trunk/test/SemaObjC/instancetype.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/instancetype.m?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/instancetype.m (original)
+++ cfe/trunk/test/SemaObjC/instancetype.m Tue Mar 19 02:04:25 2013
@@ -5,9 +5,9 @@
#endif
@interface Root
-+ (instancetype)alloc;
++ (instancetype)alloc; // expected-note {{explicitly declared 'instancetype'}}
- (instancetype)init; // expected-note{{overridden method is part of the 'init' method family}}
-- (instancetype)self;
+- (instancetype)self; // expected-note {{explicitly declared 'instancetype'}}
- (Class)class;
@property (assign) Root *selfProp;
@@ -143,7 +143,7 @@ void test_instancetype_narrow_method_sea
@implementation Subclass4
+ (id)alloc {
- return self; // expected-warning{{incompatible pointer types casting 'Class' to type 'Subclass4 *'}}
+ return self; // expected-warning{{incompatible pointer types returning 'Class' from a function with result type 'Subclass4 *'}}
}
- (Subclass3 *)init { return 0; } // don't complain: we lost the related return type
@@ -164,14 +164,14 @@ void test_instancetype_inherited() {
// Check that related return types tighten up the semantics of
// Objective-C method implementations.
@implementation Subclass2
-- (instancetype)initSubclass2 {
+- (instancetype)initSubclass2 { // expected-note {{explicitly declared 'instancetype'}}
Subclass1 *sc1 = [[Subclass1 alloc] init];
- return sc1; // expected-warning{{incompatible pointer types casting 'Subclass1 *' to type 'Subclass2 *'}}
+ return sc1; // expected-warning{{incompatible pointer types returning 'Subclass1 *' from a function with result type 'Subclass2 *'}}
}
- (void)methodOnSubclass2 {}
- (id)self {
Subclass1 *sc1 = [[Subclass1 alloc] init];
- return sc1; // expected-warning{{incompatible pointer types casting 'Subclass1 *' to type 'Subclass2 *'}}
+ return sc1; // expected-warning{{incompatible pointer types returning 'Subclass1 *' from a function with result type 'Subclass2 *'}}
}
@end
@@ -188,3 +188,29 @@ void test_instancetype_inherited() {
@end
+// rdar://12493140
+ at protocol P4
+- (instancetype) foo; // expected-note {{current method is explicitly declared 'instancetype' and is expected to return an instance of its class type}}
+ at end
+ at interface A4 : Root <P4>
+- (instancetype) bar; // expected-note {{current method is explicitly declared 'instancetype' and is expected to return an instance of its class type}}
+- (instancetype) baz; // expected-note {{overridden method returns an instance of its class type}} expected-note {{previous definition is here}}
+ at end
+ at interface B4 : Root @end
+
+ at implementation A4 {
+ B4 *_b;
+}
+- (id) foo {
+ return _b; // expected-warning {{incompatible pointer types returning 'B4 *' from a function with result type 'A4 *'}}
+}
+- (id) bar {
+ return _b; // expected-warning {{incompatible pointer types returning 'B4 *' from a function with result type 'A4 *'}}
+}
+
+// This is really just to ensure that we don't crash.
+// FIXME: only one diagnostic, please
+- (float) baz { // expected-warning {{method is expected to return an instance of its class type 'A4', but is declared to return 'float'}} expected-warning {{conflicting return type in implementation}}
+ return 0;
+}
+ at end
Modified: cfe/trunk/test/SemaObjC/related-result-type-inference.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/related-result-type-inference.m?rev=177378&r1=177377&r2=177378&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/related-result-type-inference.m (original)
+++ cfe/trunk/test/SemaObjC/related-result-type-inference.m Tue Mar 19 02:04:25 2013
@@ -175,7 +175,7 @@ void test_inference() {
@implementation Fail
- (id<X>) initWithX
{
- return (id)self; // expected-warning {{returning 'Fail *' from a function with incompatible result type 'id<X>'}}
+ return (id)self; // expected-warning {{casting 'Fail *' to incompatible type 'id<X>'}}
}
@end
Copied: cfe/trunk/test/SemaObjCXX/instancetype.mm (from r177370, cfe/trunk/test/SemaObjC/instancetype.m)
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/instancetype.mm?p2=cfe/trunk/test/SemaObjCXX/instancetype.mm&p1=cfe/trunk/test/SemaObjC/instancetype.m&r1=177370&r2=177378&rev=177378&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/instancetype.m (original)
+++ cfe/trunk/test/SemaObjCXX/instancetype.mm Tue Mar 19 02:04:25 2013
@@ -7,7 +7,7 @@
@interface Root
+ (instancetype)alloc;
- (instancetype)init; // expected-note{{overridden method is part of the 'init' method family}}
-- (instancetype)self;
+- (instancetype)self; // expected-note {{explicitly declared 'instancetype'}}
- (Class)class;
@property (assign) Root *selfProp;
@@ -143,7 +143,7 @@ void test_instancetype_narrow_method_sea
@implementation Subclass4
+ (id)alloc {
- return self; // expected-warning{{incompatible pointer types casting 'Class' to type 'Subclass4 *'}}
+ return self; // FIXME: we accept this in ObjC++ but not ObjC?
}
- (Subclass3 *)init { return 0; } // don't complain: we lost the related return type
@@ -164,14 +164,14 @@ void test_instancetype_inherited() {
// Check that related return types tighten up the semantics of
// Objective-C method implementations.
@implementation Subclass2
-- (instancetype)initSubclass2 {
+- (instancetype)initSubclass2 { // expected-note {{explicitly declared 'instancetype'}}
Subclass1 *sc1 = [[Subclass1 alloc] init];
- return sc1; // expected-warning{{incompatible pointer types casting 'Subclass1 *' to type 'Subclass2 *'}}
+ return sc1; // expected-error{{cannot initialize return object of type 'Subclass2 *' with an lvalue of type 'Subclass1 *'}}
}
- (void)methodOnSubclass2 {}
- (id)self {
Subclass1 *sc1 = [[Subclass1 alloc] init];
- return sc1; // expected-warning{{incompatible pointer types casting 'Subclass1 *' to type 'Subclass2 *'}}
+ return sc1; // expected-error{{cannot initialize return object of type 'Subclass2 *' with an lvalue of type 'Subclass1 *'}}
}
@end
@@ -188,3 +188,29 @@ void test_instancetype_inherited() {
@end
+// rdar://12493140
+ at protocol P4
+- (instancetype) foo; // expected-note {{current method is explicitly declared 'instancetype' and is expected to return an instance of its class type}}
+ at end
+ at interface A4 : Root <P4>
+- (instancetype) bar; // expected-note {{current method is explicitly declared 'instancetype' and is expected to return an instance of its class type}}
+- (instancetype) baz; // expected-note {{overridden method returns an instance of its class type}} expected-note {{previous definition is here}}
+ at end
+ at interface B4 : Root @end
+
+ at implementation A4 {
+ B4 *_b;
+}
+- (id) foo {
+ return _b; // expected-error {{cannot initialize return object of type 'A4 *' with an lvalue of type 'B4 *'}}
+}
+- (id) bar {
+ return _b; // expected-error {{cannot initialize return object of type 'A4 *' with an lvalue of type 'B4 *'}}
+}
+
+// This is really just to ensure that we don't crash.
+// FIXME: only one diagnostic, please
+- (float) baz { // expected-warning {{method is expected to return an instance of its class type 'A4', but is declared to return 'float'}} expected-warning {{conflicting return type in implementation}}
+ return 0;
+}
+ at end
More information about the cfe-commits
mailing list