diff options
author | John McCall <rjmccall@apple.com> | 2009-11-04 02:18:39 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-11-04 02:18:39 +0000 |
commit | 54abf7d4fa3123b8324c09d2a4dfb789fd818403 (patch) | |
tree | e0a899f37d5b05f29b984352e1d9f09b610e12f5 /lib/Sema | |
parent | 05a2338f7ba1c8a0136e120502f80a38cf0e9fd3 (diff) |
Change our basic strategy for avoiding deprecation warnings when the decl use
appears in a deprecated context. In the new strategy, we emit the warnings
as usual unless we're currently parsing a declaration, where "declaration" is
restricted to mean a decl group or a few special cases in Objective C. If
we *are* parsing a declaration, we queue up the deprecation warnings until
the declaration has been completely parsed, and then emit them only if the
decl is not deprecated.
We also standardize the bookkeeping for deprecation so as to avoid special cases.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85998 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 16 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 59 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 30 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 34 |
7 files changed, 91 insertions, 65 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 64007f2323..8104dd39d0 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -350,7 +350,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CodeCompleter(0), CurContext(0), - PreDeclaratorDC(0), CurBlock(0), PackContext(0), + PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0), IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0), GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated), CompleteTranslationUnit(CompleteTranslationUnit), diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 53f0d7a192..bb59e1c9f4 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -272,6 +272,15 @@ public: llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions; std::vector<DeclarationName> TentativeDefinitionList; + /// \brief The collection of delayed deprecation warnings. + llvm::SmallVector<std::pair<SourceLocation,NamedDecl*>, 8> + DelayedDeprecationWarnings; + + /// \brief The depth of the current ParsingDeclaration stack. + /// If nonzero, we are currently parsing a declaration (and + /// hence should delay deprecation warnings). + unsigned ParsingDeclDepth; + /// WeakUndeclaredIdentifiers - Identifiers contained in /// #pragma weak before declared. rare. may alias another /// identifier, declared or undeclared @@ -1586,11 +1595,14 @@ public: /// whose result is unused, warn. void DiagnoseUnusedExprResult(const Stmt *S); + ParsingDeclStackState PushParsingDeclaration(); + void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D); + void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc); + //===--------------------------------------------------------------------===// // Expression Parsing Callbacks: SemaExpr.cpp. - bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, - bool IgnoreDeprecated = false); + bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc); bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, ObjCMethodDecl *Getter, SourceLocation Loc); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 82d467f966..d89cb5fc97 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -138,9 +138,11 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } assert(IIDecl && "Didn't find decl"); - + QualType T; if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { + DiagnoseUseOfDecl(IIDecl, NameLoc); + // C++ [temp.local]p2: // Within the scope of a class template specialization or // partial specialization, when the injected-class-name is @@ -160,6 +162,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, T = getQualifiedNameType(*SS, T); } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { + DiagnoseUseOfDecl(IIDecl, NameLoc); T = Context.getObjCInterfaceType(IDecl); } else return 0; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 3995e9b11e..a3f8eb5a0e 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1949,3 +1949,62 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { if (const AttributeList *Attrs = PD.getAttributes()) ProcessDeclAttributeList(S, D, Attrs); } + +/// PushParsingDeclaration - Enter a new "scope" of deprecation +/// warnings. +/// +/// The state token we use is the start index of this scope +/// on the warning stack. +Action::ParsingDeclStackState Sema::PushParsingDeclaration() { + ParsingDeclDepth++; + return (ParsingDeclStackState) DelayedDeprecationWarnings.size(); +} + +static bool isDeclDeprecated(Decl *D) { + do { + if (D->hasAttr<DeprecatedAttr>()) + return true; + } while ((D = cast_or_null<Decl>(D->getDeclContext()))); + return false; +} + +void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) { + assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack"); + ParsingDeclDepth--; + + if (DelayedDeprecationWarnings.empty()) + return; + + unsigned SavedIndex = (unsigned) S; + assert(SavedIndex <= DelayedDeprecationWarnings.size() && + "saved index is out of bounds"); + + if (Ctx && !isDeclDeprecated(Ctx.getAs<Decl>())) { + for (unsigned I = 0, E = DelayedDeprecationWarnings.size(); I != E; ++I) { + SourceLocation Loc = DelayedDeprecationWarnings[I].first; + NamedDecl *&ND = DelayedDeprecationWarnings[I].second; + if (ND) { + Diag(Loc, diag::warn_deprecated) << ND->getDeclName(); + + // Prevent this from triggering multiple times. + ND = 0; + } + } + } + + DelayedDeprecationWarnings.set_size(SavedIndex); +} + +void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) { + // Delay if we're currently parsing a declaration. + if (ParsingDeclDepth) { + DelayedDeprecationWarnings.push_back(std::make_pair(Loc, D)); + return; + } + + // Otherwise, don't warn if our current context is deprecated. + if (isDeclDeprecated(cast<Decl>(CurContext))) + return; + + Diag(Loc, diag::warn_deprecated) << D->getDeclName(); +} diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 46c6bf45ad..93f8d0dc37 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1748,6 +1748,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( if (AttrList) ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); + const ObjCMethodDecl *InterfaceMD = 0; + // For implementations (which can be very "coarse grain"), we add the // method now. This allows the AST to implement lookup methods that work // incrementally (without waiting until we parse the @end). It also allows @@ -1761,6 +1763,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( PrevMethod = ImpDecl->getClassMethod(Sel); ImpDecl->addClassMethod(ObjCMethod); } + InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel, + MethodType == tok::minus); if (AttrList) Diag(EndLoc, diag::warn_attribute_method_def); } else if (ObjCCategoryImplDecl *CatImpDecl = @@ -1781,6 +1785,12 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( << ObjCMethod->getDeclName(); Diag(PrevMethod->getLocation(), diag::note_previous_declaration); } + + // If the interface declared this method, and it was deprecated there, + // mark it deprecated here. + if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>()) + ObjCMethod->addAttr(::new (Context) DeprecatedAttr()); + return DeclPtrTy::make(ObjCMethod); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 4dd3c2dbef..f1014c6dfe 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -43,36 +43,10 @@ using namespace clang; /// \returns true if there was an error (this declaration cannot be /// referenced), false otherwise. /// -bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, - bool IgnoreDeprecated) { +bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { // See if the decl is deprecated. if (D->getAttr<DeprecatedAttr>()) { - // Implementing deprecated stuff requires referencing deprecated - // stuff. Don't warn if we are implementing a deprecated construct. - bool isSilenced = IgnoreDeprecated; - - if (NamedDecl *ND = getCurFunctionOrMethodDecl()) { - // If this reference happens *in* a deprecated function or method, don't - // warn. - isSilenced |= ND->getAttr<DeprecatedAttr>() != 0; - - // If this is an Objective-C method implementation, check to see if the - // method was deprecated on the declaration, not the definition. - if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND)) { - // The semantic decl context of a ObjCMethodDecl is the - // ObjCImplementationDecl. - if (ObjCImplementationDecl *Impl - = dyn_cast<ObjCImplementationDecl>(MD->getParent())) { - - MD = Impl->getClassInterface()->getMethod(MD->getSelector(), - MD->isInstanceMethod()); - isSilenced |= MD && MD->getAttr<DeprecatedAttr>(); - } - } - } - - if (!isSilenced) - Diag(Loc, diag::warn_deprecated) << D->getDeclName(); + EmitDeprecationWarning(D, Loc); } // See if the decl is unavailable diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 94b74fbcd1..0003b1b0c4 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -67,16 +67,6 @@ static bool isOmittedBlockReturnType(const Declarator &D) { return false; } -/// isDeclaratorDeprecated - Return true if the declarator is deprecated. -/// We do not want to warn about use of deprecated types (e.g. typedefs) when -/// defining a declaration that is itself deprecated. -static bool isDeclaratorDeprecated(const Declarator &D) { - for (const AttributeList *AL = D.getAttributes(); AL; AL = AL->getNext()) - if (AL->getKind() == AttributeList::AT_deprecated) - return true; - return false; -} - /// \brief Convert the specified declspec to the appropriate type /// object. /// \param D the declarator containing the declaration specifier. @@ -247,8 +237,7 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ } // If the type is deprecated or unavailable, diagnose it. - TheSema.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc(), - isDeclaratorDeprecated(TheDeclarator)); + TheSema.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc()); assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!"); @@ -303,27 +292,6 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ } } - // If this is a reference to an invalid typedef, propagate the invalidity. - if (TypedefType *TDT = dyn_cast<TypedefType>(Result)) { - if (TDT->getDecl()->isInvalidDecl()) - TheDeclarator.setInvalidType(true); - - // If the type is deprecated or unavailable, diagnose it. - TheSema.DiagnoseUseOfDecl(TDT->getDecl(), DS.getTypeSpecTypeLoc(), - isDeclaratorDeprecated(TheDeclarator)); - } else if (ObjCInterfaceType *OIT = dyn_cast<ObjCInterfaceType>(Result)) { - // If the type is deprecated or unavailable, diagnose it. - TheSema.DiagnoseUseOfDecl(OIT->getDecl(), DS.getTypeSpecTypeLoc(), - isDeclaratorDeprecated(TheDeclarator)); - } else if (ObjCObjectPointerType *DPT = - dyn_cast<ObjCObjectPointerType>(Result)) { - // If the type is deprecated or unavailable, diagnose it. - if (ObjCInterfaceDecl *D = DPT->getInterfaceDecl()) - TheSema.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc(), - isDeclaratorDeprecated(TheDeclarator)); - } - - // TypeQuals handled by caller. break; } |