From: Fariborz Jahanian Date: Thu, 19 Jun 2014 23:05:46 +0000 (+0000) Subject: Objective-C qoi. When Objective-C pointer mismatches with X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=75f24133b0dac14fa24f1f41ee6a44d72932f8af;p=clang Objective-C qoi. When Objective-C pointer mismatches with a qualified-id type because pointer is object of a forward class declaration, include this info in a diagnostic note. // rdar://10751015 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211324 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b3a732e9e4..e6c8b9a34b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -5491,6 +5491,8 @@ def err_typecheck_missing_return_type_incompatible : Error< "return type must match previous return type}0,1 when %select{block " "literal|lambda expression}2 has unspecified explicit return type">; +def not_incomplete_class_and_qualified_id : Note< + "conformance of forward class %0 to protocol %1 can not be confirmed">; def warn_incompatible_qualified_id : Warning< "%select{%diff{assigning to $ from incompatible type $|" "assigning to type from incompatible type}0,1" diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 58a0c76769..2654c390cc 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10832,6 +10832,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, ConversionFixItGenerator ConvHints; bool MayHaveConvFixit = false; bool MayHaveFunctionDiff = false; + const ObjCInterfaceDecl *IFace = nullptr; + const ObjCProtocolDecl *PDecl = nullptr; switch (ConvTy) { case Compatible: @@ -10913,11 +10915,32 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, case IncompatibleBlockPointer: DiagKind = diag::err_typecheck_convert_incompatible_block_pointer; break; - case IncompatibleObjCQualifiedId: - // FIXME: Diagnose the problem in ObjCQualifiedIdTypesAreCompatible, since - // it can give a more specific diagnostic. + case IncompatibleObjCQualifiedId: { + if (SrcType->isObjCQualifiedIdType()) { + const ObjCObjectPointerType *srcOPT = + SrcType->getAs(); + for (auto *srcProto : srcOPT->quals()) { + PDecl = srcProto; + break; + } + if (const ObjCInterfaceType *IFaceT = + DstType->getAs()->getInterfaceType()) + IFace = IFaceT->getDecl(); + } + else if (DstType->isObjCQualifiedIdType()) { + const ObjCObjectPointerType *dstOPT = + DstType->getAs(); + for (auto *dstProto : dstOPT->quals()) { + PDecl = dstProto; + break; + } + if (const ObjCInterfaceType *IFaceT = + SrcType->getAs()->getInterfaceType()) + IFace = IFaceT->getDecl(); + } DiagKind = diag::warn_incompatible_qualified_id; break; + } case IncompatibleVectors: DiagKind = diag::warn_incompatible_vectors; break; @@ -10975,7 +10998,11 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, HandleFunctionTypeMismatch(FDiag, SecondType, FirstType); Diag(Loc, FDiag); - + if (DiagKind == diag::warn_incompatible_qualified_id && + PDecl && IFace && !IFace->hasDefinition()) + Diag(IFace->getLocation(), diag::not_incomplete_class_and_qualified_id) + << IFace->getName() << PDecl->getName(); + if (SecondType == Context.OverloadTy) NoteAllOverloadCandidates(OverloadExpr::find(SrcExpr).Expression, FirstType); diff --git a/test/SemaObjC/comptypes-legal.m b/test/SemaObjC/comptypes-legal.m index d83d559ee6..05f18977cc 100644 --- a/test/SemaObjC/comptypes-legal.m +++ b/test/SemaObjC/comptypes-legal.m @@ -35,3 +35,20 @@ void foo(void) // Since registerFunc: expects a Derived object as it's second argument, I don't know why this would be legal. [Derived registerFunc: ExternFunc]; // expected-warning{{incompatible pointer types sending 'NSObject *(NSObject *, NSObject *)' to parameter of type 'FuncSignature *'}} } + +// rdar://10751015 +@protocol NSCopying @end +@interface I +- (void) Meth : (id )aKey; // expected-note {{passing argument to parameter 'aKey' here}} +@end + +@class ForwarClass; // expected-note 3 {{conformance of forward class ForwarClass to protocol NSCopying can not be confirmed}} + +ForwarClass *Test10751015 (I* pi, ForwarClass *ns_forward) { + + [pi Meth : ns_forward ]; // expected-warning {{sending 'ForwarClass *' to parameter of incompatible type 'id'}} + + id id_ns = ns_forward; // expected-warning {{initializing 'id' with an expression of incompatible type 'ForwarClass *'}} + + return id_ns; // expected-warning {{returning 'id' from a function with incompatible result type 'ForwarClass *'}} +}