From: Fariborz Jahanian Date: Mon, 16 Jun 2014 17:25:41 +0000 (+0000) Subject: Objective-C. Diagnose when property access is using declared X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=89ea9610b3061c4a897fedbe3bec319723e43066;p=platform%2Fupstream%2Fllvm.git Objective-C. Diagnose when property access is using declared property accessor methods which have become deprecated or available. // rdar://15951801 llvm-svn: 211039 --- diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c2fb552..aa02519 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3680,6 +3680,9 @@ def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to th def err_undeclared_use : Error<"use of undeclared %0">; def warn_deprecated : Warning<"%0 is deprecated">, InGroup; +def warn_property_method_deprecated : + Warning<"property access is using %0 method which is deprecated">, + InGroup; def warn_deprecated_message : Warning<"%0 is deprecated: %1">, InGroup; def warn_deprecated_fwdclass_message : Warning< @@ -3689,6 +3692,8 @@ def warn_deprecated_def : Warning< "Implementing deprecated %select{method|class|category}0">, InGroup, DefaultIgnore; def err_unavailable : Error<"%0 is unavailable">; +def err_property_method_unavailable : + Error<"property access is using %0 method which is unavailable">; def err_unavailable_message : Error<"%0 is unavailable: %1">; def warn_unavailable_fwdclass_message : Warning< "%0 may be unavailable because the receiver type is unknown">, diff --git a/clang/include/clang/Sema/DelayedDiagnostic.h b/clang/include/clang/Sema/DelayedDiagnostic.h index d33a723..85551f8 100644 --- a/clang/include/clang/Sema/DelayedDiagnostic.h +++ b/clang/include/clang/Sema/DelayedDiagnostic.h @@ -127,7 +127,8 @@ public: const NamedDecl *D, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, - StringRef Msg); + StringRef Msg, + bool ObjCPropertyAccess); static DelayedDiagnostic makeAccess(SourceLocation Loc, @@ -202,6 +203,10 @@ public: const ObjCPropertyDecl *getObjCProperty() const { return DeprecationData.ObjCProperty; } + + bool getObjCPropertyAccess() const { + return DeprecationData.ObjCPropertyAccess; + } private: @@ -211,6 +216,7 @@ private: const ObjCPropertyDecl *ObjCProperty; const char *Message; size_t MessageLen; + bool ObjCPropertyAccess; }; struct FTD { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 2f07877..4a21f36 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3211,7 +3211,8 @@ public: NamedDecl *D, StringRef Message, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty); + const ObjCPropertyDecl *ObjCProperty, + bool ObjCPropertyAccess); void HandleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); @@ -3223,7 +3224,8 @@ public: bool CanUseDecl(NamedDecl *D); bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass=nullptr); + const ObjCInterfaceDecl *UnknownObjCClass=nullptr, + bool ObjCPropertyAccess=false); void NoteDeletedFunction(FunctionDecl *FD); std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD); bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, diff --git a/clang/lib/Sema/DelayedDiagnostic.cpp b/clang/lib/Sema/DelayedDiagnostic.cpp index 13a428c..664a6b1 100644 --- a/clang/lib/Sema/DelayedDiagnostic.cpp +++ b/clang/lib/Sema/DelayedDiagnostic.cpp @@ -25,7 +25,8 @@ DelayedDiagnostic::makeAvailability(Sema::AvailabilityDiagnostic AD, const NamedDecl *D, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, - StringRef Msg) { + StringRef Msg, + bool ObjCPropertyAccess) { DelayedDiagnostic DD; switch (AD) { case Sema::AD_Deprecation: @@ -48,6 +49,7 @@ DelayedDiagnostic::makeAvailability(Sema::AvailabilityDiagnostic AD, DD.DeprecationData.Message = MessageData; DD.DeprecationData.MessageLen = Msg.size(); + DD.DeprecationData.ObjCPropertyAccess = ObjCPropertyAccess; return DD; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index bd9f650..5c868e9 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4850,7 +4850,8 @@ DoEmitAvailabilityWarning(Sema &S, StringRef Message, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty) { + const ObjCPropertyDecl *ObjCProperty, + bool ObjCPropertyAccess) { // Diagnostics for deprecated or unavailable. unsigned diag, diag_message, diag_fwdclass_message; @@ -4866,7 +4867,8 @@ DoEmitAvailabilityWarning(Sema &S, case DelayedDiagnostic::Deprecation: if (isDeclDeprecated(Ctx)) return; - diag = diag::warn_deprecated; + diag = !ObjCPropertyAccess ? diag::warn_deprecated + : diag::warn_property_method_deprecated; diag_message = diag::warn_deprecated_message; diag_fwdclass_message = diag::warn_deprecated_fwdclass_message; property_note_select = /* deprecated */ 0; @@ -4876,7 +4878,8 @@ DoEmitAvailabilityWarning(Sema &S, case DelayedDiagnostic::Unavailable: if (isDeclUnavailable(Ctx)) return; - diag = diag::err_unavailable; + diag = !ObjCPropertyAccess ? diag::err_unavailable + : diag::err_property_method_unavailable; diag_message = diag::err_unavailable_message; diag_fwdclass_message = diag::warn_unavailable_fwdclass_message; property_note_select = /* unavailable */ 1; @@ -4917,20 +4920,22 @@ void Sema::HandleDelayedAvailabilityCheck(DelayedDiagnostic &DD, DD.getDeprecationMessage(), DD.Loc, DD.getUnknownObjCClass(), - DD.getObjCProperty()); + DD.getObjCProperty(), false); } void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD, NamedDecl *D, StringRef Message, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty) { + const ObjCPropertyDecl *ObjCProperty, + bool ObjCPropertyAccess) { // Delay if we're currently parsing a declaration. if (DelayedDiagnostics.shouldDelayDiagnostics()) { DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(AD, Loc, D, UnknownObjCClass, ObjCProperty, - Message)); + Message, + ObjCPropertyAccess)); return; } @@ -4946,5 +4951,5 @@ void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD, } DoEmitAvailabilityWarning(*this, K, Ctx, D, Message, Loc, - UnknownObjCClass, ObjCProperty); + UnknownObjCClass, ObjCProperty, ObjCPropertyAccess); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4c329d9..0e1aade 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -83,7 +83,8 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass, + bool ObjCPropertyAccess) { // See if this declaration is unavailable or deprecated. std::string Message; AvailabilityResult Result = D->getAvailability(&Message); @@ -113,13 +114,15 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, case AR_Deprecated: if (S.getCurContextAvailability() != AR_Deprecated) S.EmitAvailabilityWarning(Sema::AD_Deprecation, - D, Message, Loc, UnknownObjCClass, ObjCPDecl); + D, Message, Loc, UnknownObjCClass, ObjCPDecl, + ObjCPropertyAccess); break; case AR_Unavailable: if (S.getCurContextAvailability() != AR_Unavailable) S.EmitAvailabilityWarning(Sema::AD_Unavailable, - D, Message, Loc, UnknownObjCClass, ObjCPDecl); + D, Message, Loc, UnknownObjCClass, ObjCPDecl, + ObjCPropertyAccess); break; } @@ -251,7 +254,8 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) { /// referenced), false otherwise. /// bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass, + bool ObjCPropertyAccess) { if (getLangOpts().CPlusPlus && isa(D)) { // If there were any diagnostics suppressed by template argument deduction, // emit them now. @@ -296,7 +300,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, DeduceReturnType(FD, Loc)) return true; } - DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass); + DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass, ObjCPropertyAccess); DiagnoseUnusedOfDecl(*this, D, Loc); diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index 3c9e83c..eaf170c 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -696,7 +696,8 @@ ExprResult ObjCPropertyOpBuilder::buildGet() { assert(InstanceReceiver); receiverType = InstanceReceiver->getType(); } - + if (!Getter->isImplicit()) + S.DiagnoseUseOfDecl(Getter, GenericLoc, nullptr, true); // Build a message-send. ExprResult msg; if ((Getter->isInstanceMethod() && !RefExpr->isClassReceiver()) || @@ -771,6 +772,8 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, // Build a message-send. ExprResult msg; + if (!Setter->isImplicit()) + S.DiagnoseUseOfDecl(Setter, GenericLoc, nullptr, true); if ((Setter->isInstanceMethod() && !RefExpr->isClassReceiver()) || RefExpr->isObjectReceiver()) { msg = S.BuildInstanceMessageImplicit(InstanceReceiver, receiverType, diff --git a/clang/test/SemaObjC/property-deprecated-warning.m b/clang/test/SemaObjC/property-deprecated-warning.m index c89edb9..4beb23a 100644 --- a/clang/test/SemaObjC/property-deprecated-warning.m +++ b/clang/test/SemaObjC/property-deprecated-warning.m @@ -78,3 +78,28 @@ id useDeprecatedProperty(ProtocolInCategory *obj, id

obj2, int flag) { return [obj ptarget]; // no-warning return [obj2 ptarget]; // expected-warning {{'ptarget' is deprecated: first deprecated in iOS 3.0}} } + +// rdar://15951801 +@interface Foo +{ + int _x; +} +@property(nonatomic,readonly) int x; +- (void)setX:(int)x __attribute__ ((deprecated)); // expected-note 2 {{'setX:' has been explicitly marked deprecated here}} +- (int)x __attribute__ ((unavailable)); // expected-note {{'x' has been explicitly marked unavailable here}} +@end + +@implementation Foo +- (void)setX:(int)x { + _x = x; +} +- (int)x { + return _x; +} +@end + +void testUserAccessorAttributes(Foo *foo) { + [foo setX:5678]; // expected-warning {{'setX:' is deprecated}} + foo.x = foo.x; // expected-error {{property access is using 'x' method which is unavailable}} \ + // expected-warning {{property access is using 'setX:' method which is deprecated}} +}