From f31a13cc41eac5279fd4e0fd01c3a593ba21d338 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Tue, 18 Jul 2017 20:32:07 +0000 Subject: [PATCH] [Sema] NFC: Move all availability checking code to SemaDeclAttr.cpp Previously, this was awkwardly split up between SemaExpr.cpp. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@308356 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 20 ++----- lib/Sema/SemaDeclAttr.cpp | 109 +++++++++++++++++++++++++++++++++----- lib/Sema/SemaExpr.cpp | 79 +-------------------------- 3 files changed, 102 insertions(+), 106 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 1fa3f831d9..5a70854570 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3881,13 +3881,10 @@ public: void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); - void EmitAvailabilityWarning(AvailabilityResult AR, - const NamedDecl *ReferringDecl, - const NamedDecl *OffendingDecl, - StringRef Message, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty, - bool ObjCPropertyAccess); + void DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass, + bool ObjCPropertyAccess, + bool AvoidPartialAvailabilityChecks = false); bool makeUnavailableInSystemHeader(SourceLocation loc, UnavailableAttr::ImplicitReason reason); @@ -10426,15 +10423,6 @@ public: return OriginalLexicalContext ? OriginalLexicalContext : CurContext; } - /// The diagnostic we should emit for \c D, and the declaration that - /// originated it, or \c AR_Available. - /// - /// \param D The declaration to check. - /// \param Message If non-null, this will be populated with the message from - /// the availability attribute that is selected. - std::pair - ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message); - const DeclContext *getCurObjCLexicalContext() const { const DeclContext *DC = getCurLexicalContext(); // A category implicitly has the attribute of the interface. diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index a4149f55de..2a310bf41c 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -6853,6 +6853,50 @@ static const AvailabilityAttr *getAttrForPlatform(ASTContext &Context, return nullptr; } +/// The diagnostic we should emit for \c D, and the declaration that +/// originated it, or \c AR_Available. +/// +/// \param D The declaration to check. +/// \param Message If non-null, this will be populated with the message from +/// the availability attribute that is selected. +static std::pair +ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message) { + AvailabilityResult Result = D->getAvailability(Message); + + // For typedefs, if the typedef declaration appears available look + // to the underlying type to see if it is more restrictive. + while (const TypedefNameDecl *TD = dyn_cast(D)) { + if (Result == AR_Available) { + if (const TagType *TT = TD->getUnderlyingType()->getAs()) { + D = TT->getDecl(); + Result = D->getAvailability(Message); + continue; + } + } + break; + } + + // Forward class declarations get their attributes from their definition. + if (const ObjCInterfaceDecl *IDecl = dyn_cast(D)) { + if (IDecl->getDefinition()) { + D = IDecl->getDefinition(); + Result = D->getAvailability(Message); + } + } + + if (const auto *ECD = dyn_cast(D)) + if (Result == AR_Available) { + const DeclContext *DC = ECD->getDeclContext(); + if (const auto *TheEnumDecl = dyn_cast(DC)) { + Result = TheEnumDecl->getAvailability(Message); + D = TheEnumDecl; + } + } + + return {Result, D}; +} + + /// \brief whether we should emit a diagnostic for \c K and \c DeclVersion in /// the context of \c Ctx. For example, we should emit an unavailable diagnostic /// in a deprecated context, but not the other way around. @@ -7220,24 +7264,24 @@ void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) { curPool->steal(pool); } -void Sema::EmitAvailabilityWarning(AvailabilityResult AR, - const NamedDecl *ReferringDecl, - const NamedDecl *OffendingDecl, - StringRef Message, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty, - bool ObjCPropertyAccess) { +static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR, + const NamedDecl *ReferringDecl, + const NamedDecl *OffendingDecl, + StringRef Message, SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty, + bool ObjCPropertyAccess) { // Delay if we're currently parsing a declaration. - if (DelayedDiagnostics.shouldDelayDiagnostics()) { - DelayedDiagnostics.add( + if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { + S.DelayedDiagnostics.add( DelayedDiagnostic::makeAvailability( AR, Loc, ReferringDecl, OffendingDecl, UnknownObjCClass, ObjCProperty, Message, ObjCPropertyAccess)); return; } - Decl *Ctx = cast(getCurLexicalContext()); - DoEmitAvailabilityWarning(*this, AR, Ctx, ReferringDecl, OffendingDecl, + Decl *Ctx = cast(S.getCurLexicalContext()); + DoEmitAvailabilityWarning(S, AR, Ctx, ReferringDecl, OffendingDecl, Message, Loc, UnknownObjCClass, ObjCProperty, ObjCPropertyAccess); } @@ -7394,7 +7438,7 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability( AvailabilityResult Result; const NamedDecl *OffendingDecl; std::tie(Result, OffendingDecl) = - SemaRef.ShouldDiagnoseAvailabilityOfDecl(D, nullptr); + ShouldDiagnoseAvailabilityOfDecl(D, nullptr); if (Result != AR_Available) { // All other diagnostic kinds have already been handled in // DiagnoseAvailabilityOfDecl. @@ -7572,3 +7616,44 @@ void Sema::DiagnoseUnguardedAvailabilityViolations(Decl *D) { DiagnoseUnguardedAvailability(*this, D).IssueDiagnostics(Body); } + +void Sema::DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass, + bool ObjCPropertyAccess, + bool AvoidPartialAvailabilityChecks) { + std::string Message; + AvailabilityResult Result; + const NamedDecl* OffendingDecl; + // See if this declaration is unavailable, deprecated, or partial. + std::tie(Result, OffendingDecl) = ShouldDiagnoseAvailabilityOfDecl(D, &Message); + if (Result == AR_Available) + return; + + if (Result == AR_NotYetIntroduced) { + if (AvoidPartialAvailabilityChecks) + return; + + // We need to know the @available context in the current function to + // diagnose this use, let DiagnoseUnguardedAvailabilityViolations do that + // when we're done parsing the current function. + if (getCurFunctionOrMethodDecl()) { + getEnclosingFunction()->HasPotentialAvailabilityViolations = true; + return; + } else if (getCurBlock() || getCurLambda()) { + getCurFunction()->HasPotentialAvailabilityViolations = true; + return; + } + } + + const ObjCPropertyDecl *ObjCPDecl = nullptr; + if (const ObjCMethodDecl *MD = dyn_cast(D)) { + if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) { + AvailabilityResult PDeclResult = PD->getAvailability(nullptr); + if (PDeclResult == Result) + ObjCPDecl = PD; + } + } + + EmitAvailabilityWarning(*this, Result, D, OffendingDecl, Message, Loc, + UnknownObjCClass, ObjCPDecl, ObjCPropertyAccess); +} diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8016bf9988..ead80b6158 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -87,82 +87,6 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { } } -std::pair -Sema::ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, - std::string *Message) { - AvailabilityResult Result = D->getAvailability(Message); - - // For typedefs, if the typedef declaration appears available look - // to the underlying type to see if it is more restrictive. - while (const TypedefNameDecl *TD = dyn_cast(D)) { - if (Result == AR_Available) { - if (const TagType *TT = TD->getUnderlyingType()->getAs()) { - D = TT->getDecl(); - Result = D->getAvailability(Message); - continue; - } - } - break; - } - - // Forward class declarations get their attributes from their definition. - if (const ObjCInterfaceDecl *IDecl = dyn_cast(D)) { - if (IDecl->getDefinition()) { - D = IDecl->getDefinition(); - Result = D->getAvailability(Message); - } - } - - if (const auto *ECD = dyn_cast(D)) - if (Result == AR_Available) { - const DeclContext *DC = ECD->getDeclContext(); - if (const auto *TheEnumDecl = dyn_cast(DC)) { - Result = TheEnumDecl->getAvailability(Message); - D = TheEnumDecl; - } - } - - return {Result, D}; -} - -static void -DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass, - bool ObjCPropertyAccess, - bool AvoidPartialAvailabilityChecks = false) { - std::string Message; - AvailabilityResult Result; - const NamedDecl* OffendingDecl; - // See if this declaration is unavailable, deprecated, or partial. - std::tie(Result, OffendingDecl) = S.ShouldDiagnoseAvailabilityOfDecl(D, &Message); - if (Result == AR_Available) - return; - - if (Result == AR_NotYetIntroduced) { - if (AvoidPartialAvailabilityChecks) - return; - if (S.getCurFunctionOrMethodDecl()) { - S.getEnclosingFunction()->HasPotentialAvailabilityViolations = true; - return; - } else if (S.getCurBlock() || S.getCurLambda()) { - S.getCurFunction()->HasPotentialAvailabilityViolations = true; - return; - } - } - - const ObjCPropertyDecl *ObjCPDecl = nullptr; - if (const ObjCMethodDecl *MD = dyn_cast(D)) { - if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) { - AvailabilityResult PDeclResult = PD->getAvailability(nullptr); - if (PDeclResult == Result) - ObjCPDecl = PD; - } - } - - S.EmitAvailabilityWarning(Result, D, OffendingDecl, Message, Loc, - UnknownObjCClass, ObjCPDecl, ObjCPropertyAccess); -} - /// \brief Emit a note explaining that this function is deleted. void Sema::NoteDeletedFunction(FunctionDecl *Decl) { assert(Decl->isDeleted()); @@ -363,8 +287,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, return true; } - DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass, - ObjCPropertyAccess, + DiagnoseAvailabilityOfDecl(D, Loc, UnknownObjCClass, ObjCPropertyAccess, AvoidPartialAvailabilityChecks); DiagnoseUnusedOfDecl(*this, D, Loc); -- 2.40.0