diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2012-09-21 20:46:37 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-09-21 20:46:37 +0000 |
commit | fd09088880f758c874edc8d3d22fa922baec0483 (patch) | |
tree | df4eac22e617887bdf6c4c5fb911df0c5362e436 /lib/Sema | |
parent | 022301b85823fc474965ce487fc9d61a156287e2 (diff) |
objective-C: when diagnosing deprecated/unavailable usage of
setter or getter backing a deprecated/unavailable property,
also not location of the property. // rdar://12324295
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164412 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/DelayedDiagnostic.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 53 |
4 files changed, 88 insertions, 9 deletions
diff --git a/lib/Sema/DelayedDiagnostic.cpp b/lib/Sema/DelayedDiagnostic.cpp index 876f9d7a95..3100432885 100644 --- a/lib/Sema/DelayedDiagnostic.cpp +++ b/lib/Sema/DelayedDiagnostic.cpp @@ -22,6 +22,7 @@ using namespace sema; DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, const NamedDecl *D, const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty, StringRef Msg) { DelayedDiagnostic DD; DD.Kind = Deprecation; @@ -29,6 +30,7 @@ DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, DD.Loc = Loc; DD.DeprecationData.Decl = D; DD.DeprecationData.UnknownObjCClass = UnknownObjCClass; + DD.DeprecationData.ObjCProperty = ObjCProperty; char *MessageData = 0; if (Msg.size()) { MessageData = new char [Msg.size()]; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index ae394d78b9..b09ec08651 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -4803,18 +4803,25 @@ static bool isDeclDeprecated(Decl *D) { static void DoEmitDeprecationWarning(Sema &S, const NamedDecl *D, StringRef Message, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCPropery) { DeclarationName Name = D->getDeclName(); if (!Message.empty()) { S.Diag(Loc, diag::warn_deprecated_message) << Name << Message; S.Diag(D->getLocation(), isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at : diag::note_previous_decl) << Name; + if (ObjCPropery) + S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) + << ObjCPropery->getDeclName() << 0; } else if (!UnknownObjCClass) { S.Diag(Loc, diag::warn_deprecated) << D->getDeclName(); S.Diag(D->getLocation(), isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at : diag::note_previous_decl) << Name; + if (ObjCPropery) + S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) + << ObjCPropery->getDeclName() << 0; } else { S.Diag(Loc, diag::warn_deprecated_fwdclass_message) << Name; S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); @@ -4829,16 +4836,19 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, DD.Triggered = true; DoEmitDeprecationWarning(*this, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc, - DD.getUnknownObjCClass()); + DD.getUnknownObjCClass(), + DD.getObjCProperty()); } void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty) { // Delay if we're currently parsing a declaration. if (DelayedDiagnostics.shouldDelayDiagnostics()) { DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, UnknownObjCClass, + ObjCProperty, Message)); return; } @@ -4846,5 +4856,5 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, // Otherwise, don't warn if our current context is deprecated. if (isDeclDeprecated(cast<Decl>(getCurLexicalContext()))) return; - DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass); + DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass, ObjCProperty); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 97591be98e..ff7e9101f1 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -87,6 +87,13 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC)) Result = TheEnumDecl->getAvailability(&Message); } + const ObjCPropertyDecl *ObjCPDecl = 0; + if (Result == AR_Deprecated || Result == AR_Unavailable) + if (ObjCPropertyDecl *ND = S.PropertyIfSetterOrGetter(D)) { + AvailabilityResult PDeclResult = ND->getAvailability(0); + if (PDeclResult == Result) + ObjCPDecl = ND; + } switch (Result) { case AR_Available: @@ -94,23 +101,30 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, break; case AR_Deprecated: - S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass); + S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass, ObjCPDecl); break; case AR_Unavailable: if (S.getCurContextAvailability() != AR_Unavailable) { if (Message.empty()) { - if (!UnknownObjCClass) + if (!UnknownObjCClass) { S.Diag(Loc, diag::err_unavailable) << D->getDeclName(); + if (ObjCPDecl) + S.Diag(ObjCPDecl->getLocation(), diag::note_property_attribute) + << ObjCPDecl->getDeclName() << 1; + } else S.Diag(Loc, diag::warn_unavailable_fwdclass_message) << D->getDeclName(); } - else + else S.Diag(Loc, diag::err_unavailable_message) << D->getDeclName() << Message; - S.Diag(D->getLocation(), diag::note_unavailable_here) - << isa<FunctionDecl>(D) << false; + S.Diag(D->getLocation(), diag::note_unavailable_here) + << isa<FunctionDecl>(D) << false; + if (ObjCPDecl) + S.Diag(ObjCPDecl->getLocation(), diag::note_property_attribute) + << ObjCPDecl->getDeclName() << 1; } break; } diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 0f6ae4c7c7..82b8094e76 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -22,6 +22,7 @@ #include "clang/Basic/SourceManager.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallString.h" +#include "clang/Lex/Preprocessor.h" using namespace clang; @@ -1560,6 +1561,58 @@ ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, return Prop; } } + else if (const ObjCCategoryDecl *CatDecl = + dyn_cast<ObjCCategoryDecl>(CDecl)) { + for (ObjCContainerDecl::prop_iterator P = CatDecl->prop_begin(), + E = CatDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = *P; + if (Prop->getIdentifier() == II) + return Prop; + } + } + return 0; +} + +/// PropertyIfSetterOrGetter - Looks up the property if named declaration +/// is a setter or getter method backing a property. +ObjCPropertyDecl *Sema::PropertyIfSetterOrGetter(NamedDecl *D) { + if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D)) { + Selector Sel = Method->getSelector(); + IdentifierInfo *Id = 0; + if (Sel.getNumArgs() == 0) + Id = Sel.getIdentifierInfoForSlot(0); + else if (Sel.getNumArgs() == 1) { + StringRef str = Sel.getNameForSlot(0); + if (str.startswith("set")) { + str = str.substr(3); + char front = str.front(); + front = islower(front) ? toupper(front) : tolower(front); + SmallString<100> PropertyName = str; + PropertyName[0] = front; + Id = &PP.getIdentifierTable().get(PropertyName); + } + } + if (Id) { + if (isa<ObjCInterfaceDecl>(Method->getDeclContext())) { + const ObjCInterfaceDecl *IDecl = Method->getClassInterface(); + while (IDecl) { + ObjCPropertyDecl *PDecl = + LookupPropertyDecl(cast<ObjCContainerDecl>(IDecl), Id); + if (PDecl) + return PDecl; + for (ObjCCategoryDecl *Category = IDecl->getCategoryList(); + Category; Category = Category->getNextClassCategory()) + if ((PDecl = + LookupPropertyDecl(cast<ObjCContainerDecl>(Category), Id))) + return PDecl; + IDecl = IDecl->getSuperClass(); + } + } else if (ObjCPropertyDecl *PDecl = + LookupPropertyDecl( + cast<ObjCContainerDecl>(Method->getDeclContext()), Id)) + return PDecl; + } + } return 0; } |