diff options
author | Ted Kremenek <kremenek@apple.com> | 2013-12-18 23:30:06 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2013-12-18 23:30:06 +0000 |
commit | b79ee57080fa37ecd2ea0378e466530e844c7f3c (patch) | |
tree | fbd8c11e3f563fa500c0c19fcbe2cd18e906791c /clang/lib | |
parent | e7106c9e0ba0cddc7305f7b9eeecf93fc15b6a73 (diff) | |
download | bcm5719-llvm-b79ee57080fa37ecd2ea0378e466530e844c7f3c.tar.gz bcm5719-llvm-b79ee57080fa37ecd2ea0378e466530e844c7f3c.zip |
Implemented delayed processing of 'unavailable' checking, just like with 'deprecated'.
Fixes <rdar://problem/15584219> and <rdar://problem/12241361>.
This change looks large, but all it does is reuse and consolidate
the delayed diagnostic logic for deprecation warnings with unavailability
warnings. By doing so, it showed various inconsistencies between the
diagnostics, which were close, but not consistent. It also revealed
some missing "note:"'s in the deprecated diagnostics that were showing
up in the unavailable diagnostics, etc.
This change also changes the wording of the core deprecation diagnostics.
Instead of saying "function has been explicitly marked deprecated"
we now saw "'X' has been been explicitly marked deprecated". It
turns out providing a bit more context is useful, and often we
got the actual term wrong or it was not very precise
(e.g., "function" instead of "destructor"). By just saying the name
of the thing that is deprecated/deleted/unavailable we define
this issue away. This diagnostic can likely be further wordsmithed
to be shorter.
llvm-svn: 197627
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/DelayedDiagnostic.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 153 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 34 |
3 files changed, 129 insertions, 71 deletions
diff --git a/clang/lib/Sema/DelayedDiagnostic.cpp b/clang/lib/Sema/DelayedDiagnostic.cpp index 31004328855..533b7ef3e87 100644 --- a/clang/lib/Sema/DelayedDiagnostic.cpp +++ b/clang/lib/Sema/DelayedDiagnostic.cpp @@ -19,13 +19,22 @@ using namespace clang; using namespace sema; -DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, +DelayedDiagnostic +DelayedDiagnostic::makeAvailability(Sema::AvailabilityDiagnostic AD, + SourceLocation Loc, const NamedDecl *D, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, StringRef Msg) { DelayedDiagnostic DD; - DD.Kind = Deprecation; + switch (AD) { + case Sema::AD_Deprecation: + DD.Kind = Deprecation; + break; + case Sema::AD_Unavailable: + DD.Kind = Unavailable; + break; + } DD.Triggered = false; DD.Loc = Loc; DD.DeprecationData.Decl = D; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 5e9bd2cf49b..b44506c0a3f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4477,9 +4477,11 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { switch (diag.Kind) { case DelayedDiagnostic::Deprecation: - // Don't bother giving deprecation diagnostics if the decl is invalid. + case DelayedDiagnostic::Unavailable: + // Don't bother giving deprecation/unavailable diagnostics if + // the decl is invalid. if (!decl->isInvalidDecl()) - HandleDelayedDeprecationCheck(diag, decl); + HandleDelayedAvailabilityCheck(diag, decl); break; case DelayedDiagnostic::Access: @@ -4514,61 +4516,124 @@ static bool isDeclDeprecated(Decl *D) { return false; } +static bool isDeclUnavailable(Decl *D) { + do { + if (D->isUnavailable()) + return true; + // A category implicitly has the availability of the interface. + if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) + return CatD->getClassInterface()->isUnavailable(); + } while ((D = cast_or_null<Decl>(D->getDeclContext()))); + return false; +} + static void -DoEmitDeprecationWarning(Sema &S, const NamedDecl *D, StringRef Message, - SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCPropery) { +DoEmitAvailabilityWarning(Sema &S, + DelayedDiagnostic::DDKind K, + Decl *Ctx, + const NamedDecl *D, + StringRef Message, + SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty) { + + // Diagnostics for deprecated or unavailable. + unsigned diag, diag_message, diag_fwdclass_message; + + // Matches 'diag::note_property_attribute' options. + unsigned property_note_select; + + // Matches diag::note_availability_specified_here. + unsigned available_here_select_kind; + + // Don't warn if our current context is deprecated or unavailable. + switch (K) { + case DelayedDiagnostic::Deprecation: + if (isDeclDeprecated(Ctx)) + return; + diag = diag::warn_deprecated; + diag_message = diag::warn_deprecated_message; + diag_fwdclass_message = diag::warn_deprecated_fwdclass_message; + property_note_select = /* deprecated */ 0; + available_here_select_kind = /* deprecated */ 2; + break; + + case DelayedDiagnostic::Unavailable: + if (isDeclUnavailable(Ctx)) + return; + diag = diag::err_unavailable; + diag_message = diag::err_unavailable_message; + diag_fwdclass_message = diag::warn_unavailable_fwdclass_message; + property_note_select = /* unavailable */ 1; + available_here_select_kind = /* unavailable */ 0; + break; + + default: + llvm_unreachable("Neither a deprecation or unavailable kind"); + } + 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; + S.Diag(Loc, diag_message) << Name << Message; +// S.Diag(D->getLocation(), diag::note_availability_specified_here) +// << D << available_here_select_kind; + if (ObjCProperty) + S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute) + << ObjCProperty->getDeclName() << property_note_select; } 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; + S.Diag(Loc, diag) << Name; +// S.Diag(D->getLocation(), diag::note_availability_specified_here) +// << D << available_here_select_kind; + if (ObjCProperty) + S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute) + << ObjCProperty->getDeclName() << property_note_select; } else { - S.Diag(Loc, diag::warn_deprecated_fwdclass_message) << Name; + S.Diag(Loc, diag_fwdclass_message) << Name; S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); } -} - -void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, - Decl *Ctx) { - if (isDeclDeprecated(Ctx)) - return; - DD.Triggered = true; - DoEmitDeprecationWarning(*this, DD.getDeprecationDecl(), - DD.getDeprecationMessage(), DD.Loc, - DD.getUnknownObjCClass(), - DD.getObjCProperty()); + S.Diag(D->getLocation(), diag::note_availability_specified_here) + << D << available_here_select_kind; } -void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, - SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty) { +void Sema::HandleDelayedAvailabilityCheck(DelayedDiagnostic &DD, + Decl *Ctx) { + DD.Triggered = true; + DoEmitAvailabilityWarning(*this, + (DelayedDiagnostic::DDKind) DD.Kind, + Ctx, + DD.getDeprecationDecl(), + DD.getDeprecationMessage(), + DD.Loc, + DD.getUnknownObjCClass(), + DD.getObjCProperty()); +} + +void Sema::EmitAvailabilityWarning(AvailabilityDiagnostic AD, + NamedDecl *D, StringRef Message, + SourceLocation Loc, + 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)); + DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(AD, Loc, D, + UnknownObjCClass, + ObjCProperty, + Message)); return; } - // Otherwise, don't warn if our current context is deprecated. - if (isDeclDeprecated(cast<Decl>(getCurLexicalContext()))) - return; - DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass, ObjCProperty); + Decl *Ctx = cast<Decl>(getCurLexicalContext()); + DelayedDiagnostic::DDKind K; + switch (AD) { + case AD_Deprecation: + K = DelayedDiagnostic::Deprecation; + break; + case AD_Unavailable: + K = DelayedDiagnostic::Unavailable; + break; + } + + DoEmitAvailabilityWarning(*this, K, Ctx, D, Message, Loc, + UnknownObjCClass, ObjCProperty); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index a1de4046e0f..3bc221fb7ee 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -112,32 +112,16 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, case AR_Deprecated: if (S.getCurContextAvailability() != AR_Deprecated) - S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass, ObjCPDecl); + S.EmitAvailabilityWarning(Sema::AD_Deprecation, + D, Message, Loc, UnknownObjCClass, ObjCPDecl); break; - + case AR_Unavailable: - if (S.getCurContextAvailability() != AR_Unavailable) { - if (Message.empty()) { - 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 - S.Diag(Loc, diag::err_unavailable_message) - << D->getDeclName() << Message; - 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; - } + if (S.getCurContextAvailability() != AR_Unavailable) + S.EmitAvailabilityWarning(Sema::AD_Unavailable, + D, Message, Loc, UnknownObjCClass, ObjCPDecl); break; + } return Result; } @@ -177,8 +161,8 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) { } } - Diag(Decl->getLocation(), diag::note_unavailable_here) - << 1 << true; + Diag(Decl->getLocation(), diag::note_availability_specified_here) + << Decl << true; } /// \brief Determine whether a FunctionDecl was ever declared with an |