diff --git a/clang/include/clang/Sema/DelayedDiagnostic.h b/clang/include/clang/Sema/DelayedDiagnostic.h index dd2603dbc362..3320cd815a6b 100644 --- a/clang/include/clang/Sema/DelayedDiagnostic.h +++ b/clang/include/clang/Sema/DelayedDiagnostic.h @@ -122,8 +122,9 @@ public: void Destroy(); static DelayedDiagnostic makeDeprecation(SourceLocation Loc, - const NamedDecl *D, - StringRef Msg); + const NamedDecl *D, + const ObjCInterfaceDecl *UnknownObjCClass, + StringRef Msg); static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity) { @@ -187,12 +188,17 @@ public: assert(Kind == ForbiddenType && "not a forbidden-type diagnostic"); return QualType::getFromOpaquePtr(ForbiddenTypeData.OperandType); } + + const ObjCInterfaceDecl *getUnknownObjCClass() const { + return DeprecationData.UnknownObjCClass; + } private: union { /// Deprecation. struct { const NamedDecl *Decl; + const ObjCInterfaceDecl *UnknownObjCClass; const char *Message; size_t MessageLen; } DeprecationData; diff --git a/clang/lib/Sema/DelayedDiagnostic.cpp b/clang/lib/Sema/DelayedDiagnostic.cpp index d6c1ad13a854..876f9d7a9545 100644 --- a/clang/lib/Sema/DelayedDiagnostic.cpp +++ b/clang/lib/Sema/DelayedDiagnostic.cpp @@ -20,13 +20,15 @@ using namespace clang; using namespace sema; DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, - const NamedDecl *D, - StringRef Msg) { + const NamedDecl *D, + const ObjCInterfaceDecl *UnknownObjCClass, + StringRef Msg) { DelayedDiagnostic DD; DD.Kind = Deprecation; DD.Triggered = false; DD.Loc = Loc; DD.DeprecationData.Decl = D; + DD.DeprecationData.UnknownObjCClass = UnknownObjCClass; char *MessageData = 0; if (Msg.size()) { MessageData = new char [Msg.size()]; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 4f3b03f6e511..37edeff0ecd0 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4121,6 +4121,11 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, Diag(DD.Loc, diag::warn_deprecated_message) << DD.getDeprecationDecl()->getDeclName() << DD.getDeprecationMessage(); + else if (DD.getUnknownObjCClass()) { + Diag(DD.Loc, diag::warn_deprecated_fwdclass_message) + << DD.getDeprecationDecl()->getDeclName(); + Diag(DD.getUnknownObjCClass()->getLocation(), diag::note_forward_class); + } else Diag(DD.Loc, diag::warn_deprecated) << DD.getDeprecationDecl()->getDeclName(); @@ -4131,7 +4136,9 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, const ObjCInterfaceDecl *UnknownObjCClass) { // Delay if we're currently parsing a declaration. if (DelayedDiagnostics.shouldDelayDiagnostics()) { - DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, Message)); + DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, + UnknownObjCClass, + Message)); return; } diff --git a/clang/test/SemaObjC/warn-forward-class-attr-deprecated.m b/clang/test/SemaObjC/warn-forward-class-attr-deprecated.m new file mode 100644 index 000000000000..26e019627c47 --- /dev/null +++ b/clang/test/SemaObjC/warn-forward-class-attr-deprecated.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify +// rdar://10290322 + +@class ABGroupImportFilesScope; // expected-note {{forward declaration of class here}} + +@interface I1 +- (id) filenames __attribute__((deprecated)); +@end + +@interface I2 +- (id) Meth : (ABGroupImportFilesScope*) scope; +- (id) filenames __attribute__((deprecated)); +- (id)initWithAccount: (id)account filenames:(id)filenames; +@end + +@implementation I2 +- (id) Meth : (ABGroupImportFilesScope*) scope +{ + id p = [self initWithAccount : 0 filenames :[scope filenames]]; // expected-warning {{'filenames' maybe deprecated because receiver type is unknown}} + return 0; +} +- (id) filenames { return 0; } +- (id)initWithAccount: (id)account filenames:(id)filenames { return 0; } +@end