def err_undeclared_use : Error<"use of undeclared %0">;
def warn_deprecated : Warning<"%0 is deprecated">,
InGroup<DeprecatedDeclarations>;
+def warn_property_method_deprecated :
+ Warning<"property access is using %0 method which is deprecated">,
+ InGroup<DeprecatedDeclarations>;
def warn_deprecated_message : Warning<"%0 is deprecated: %1">,
InGroup<DeprecatedDeclarations>;
def warn_deprecated_fwdclass_message : Warning<
"Implementing deprecated %select{method|class|category}0">,
InGroup<DeprecatedImplementations>, 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">,
const NamedDecl *D,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
- StringRef Msg);
+ StringRef Msg,
+ bool ObjCPropertyAccess);
static DelayedDiagnostic makeAccess(SourceLocation Loc,
const ObjCPropertyDecl *getObjCProperty() const {
return DeprecationData.ObjCProperty;
}
+
+ bool getObjCPropertyAccess() const {
+ return DeprecationData.ObjCPropertyAccess;
+ }
private:
const ObjCPropertyDecl *ObjCProperty;
const char *Message;
size_t MessageLen;
+ bool ObjCPropertyAccess;
};
struct FTD {
NamedDecl *D, StringRef Message,
SourceLocation Loc,
const ObjCInterfaceDecl *UnknownObjCClass,
- const ObjCPropertyDecl *ObjCProperty);
+ const ObjCPropertyDecl *ObjCProperty,
+ bool ObjCPropertyAccess);
void HandleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
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,
const NamedDecl *D,
const ObjCInterfaceDecl *UnknownObjCClass,
const ObjCPropertyDecl *ObjCProperty,
- StringRef Msg) {
+ StringRef Msg,
+ bool ObjCPropertyAccess) {
DelayedDiagnostic DD;
switch (AD) {
case Sema::AD_Deprecation:
DD.DeprecationData.Message = MessageData;
DD.DeprecationData.MessageLen = Msg.size();
+ DD.DeprecationData.ObjCPropertyAccess = ObjCPropertyAccess;
return DD;
}
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;
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;
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;
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;
}
}
DoEmitAvailabilityWarning(*this, K, Ctx, D, Message, Loc,
- UnknownObjCClass, ObjCProperty);
+ UnknownObjCClass, ObjCProperty, ObjCPropertyAccess);
}
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);
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;
}
/// referenced), false otherwise.
///
bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
- const ObjCInterfaceDecl *UnknownObjCClass) {
+ const ObjCInterfaceDecl *UnknownObjCClass,
+ bool ObjCPropertyAccess) {
if (getLangOpts().CPlusPlus && isa<FunctionDecl>(D)) {
// If there were any diagnostics suppressed by template argument deduction,
// emit them now.
DeduceReturnType(FD, Loc))
return true;
}
- DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass);
+ DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass, ObjCPropertyAccess);
DiagnoseUnusedOfDecl(*this, D, Loc);
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()) ||
// 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,
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}}
+}