diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2014-06-19 23:05:46 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2014-06-19 23:05:46 +0000 |
commit | 75f24133b0dac14fa24f1f41ee6a44d72932f8af (patch) | |
tree | 32ac5e9df6f9dc1ab0d979cf9984635711b513e6 | |
parent | d8a6309314eb4a6a97e04b04a6678ebc88920e83 (diff) | |
download | clang-75f24133b0dac14fa24f1f41ee6a44d72932f8af.tar.gz clang-75f24133b0dac14fa24f1f41ee6a44d72932f8af.tar.bz2 clang-75f24133b0dac14fa24f1f41ee6a44d72932f8af.tar.xz |
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
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 35 | ||||
-rw-r--r-- | test/SemaObjC/comptypes-legal.m | 17 |
3 files changed, 50 insertions, 4 deletions
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<ObjCObjectPointerType>(); + for (auto *srcProto : srcOPT->quals()) { + PDecl = srcProto; + break; + } + if (const ObjCInterfaceType *IFaceT = + DstType->getAs<ObjCObjectPointerType>()->getInterfaceType()) + IFace = IFaceT->getDecl(); + } + else if (DstType->isObjCQualifiedIdType()) { + const ObjCObjectPointerType *dstOPT = + DstType->getAs<ObjCObjectPointerType>(); + for (auto *dstProto : dstOPT->quals()) { + PDecl = dstProto; + break; + } + if (const ObjCInterfaceType *IFaceT = + SrcType->getAs<ObjCObjectPointerType>()->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 <NSCopying>)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<NSCopying>'}} + + id <NSCopying> id_ns = ns_forward; // expected-warning {{initializing 'id<NSCopying>' with an expression of incompatible type 'ForwarClass *'}} + + return id_ns; // expected-warning {{returning 'id<NSCopying>' from a function with incompatible result type 'ForwarClass *'}} +} |