From d32967402813e489ab567c9d271804f12f1cfcaa Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 19 Jun 2014 23:05:46 +0000 Subject: [PATCH] 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 llvm-svn: 211324 --- .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaExpr.cpp | 35 ++++++++++++++++--- clang/test/SemaObjC/comptypes-legal.m | 17 +++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b3a732e9e4cb..e6c8b9a34bd0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 58a0c76769f2..2654c390ccf2 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/test/SemaObjC/comptypes-legal.m b/clang/test/SemaObjC/comptypes-legal.m index d83d559ee64c..05f18977cc4e 100644 --- a/clang/test/SemaObjC/comptypes-legal.m +++ b/clang/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 *'}} +}