summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2014-06-19 23:05:46 +0000
committerFariborz Jahanian <fjahanian@apple.com>2014-06-19 23:05:46 +0000
commit75f24133b0dac14fa24f1f41ee6a44d72932f8af (patch)
tree32ac5e9df6f9dc1ab0d979cf9984635711b513e6
parentd8a6309314eb4a6a97e04b04a6678ebc88920e83 (diff)
downloadclang-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.td2
-rw-r--r--lib/Sema/SemaExpr.cpp35
-rw-r--r--test/SemaObjC/comptypes-legal.m17
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 *'}}
+}