]> granicus.if.org Git - clang/commitdiff
Change our basic strategy for avoiding deprecation warnings when the decl use
authorJohn McCall <rjmccall@apple.com>
Wed, 4 Nov 2009 02:18:39 +0000 (02:18 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 4 Nov 2009 02:18:39 +0000 (02:18 +0000)
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

15 files changed:
include/clang/Parse/Action.h
include/clang/Parse/Parser.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseObjc.cpp
lib/Parse/ParseTemplate.cpp
lib/Parse/Parser.cpp
lib/Sema/Sema.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaType.cpp
test/Sema/attr-deprecated.c

index 2989eb6adbdfd533fb8f633ed873557ecd5d3598..073365dcede366485980c4f688d15288c5254188 100644 (file)
@@ -161,6 +161,23 @@ public:
   // Declaration Tracking Callbacks.
   //===--------------------------------------------------------------------===//
 
+  typedef uintptr_t ParsingDeclStackState;
+
+  /// PushParsingDeclaration - Notes that the parser has begun
+  /// processing a declaration of some sort.  Guaranteed to be matched
+  /// by a call to PopParsingDeclaration with the value returned by
+  /// this method.
+  virtual ParsingDeclStackState PushParsingDeclaration() {
+    return ParsingDeclStackState();
+  }
+
+  /// PopParsingDeclaration - Notes that the parser has completed
+  /// processing a declaration of some sort.  The decl will be empty
+  /// if the declaration didn't correspond to a full declaration (or
+  /// if the actions module returned an empty decl for it).
+  virtual void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D) {
+  }
+
   /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it
   /// needs a decl group, it calls this to convert between the two
   /// representations.
index eb2ec53e6f01910b30a3304a95d037a762b98c2f..f34d469d9823424d0052473d5dc40a77a7050e53 100644 (file)
@@ -571,6 +571,99 @@ private:
     return *ClassStack.top();
   }
 
+  /// \brief RAII object used to inform the actions that we're
+  /// currently parsing a declaration.  This is active when parsing a
+  /// variable's initializer, but not when parsing the body of a
+  /// class or function definition.
+  class ParsingDeclRAIIObject {
+    Action &Actions;
+    Action::ParsingDeclStackState State;
+    bool Popped;
+    
+  public:
+    ParsingDeclRAIIObject(Parser &P) : Actions(P.Actions) {
+      push();
+    }
+
+    ~ParsingDeclRAIIObject() {
+      abort();
+    }
+
+    /// Resets the RAII object for a new declaration.
+    void reset() {
+      abort();
+      push();
+    }
+
+    /// Signals that the context was completed without an appropriate
+    /// declaration being parsed.
+    void abort() {
+      pop(DeclPtrTy());
+    }
+
+    void complete(DeclPtrTy D) {
+      assert(!Popped && "ParsingDeclaration has already been popped!");
+      pop(D);
+    }
+
+  private:
+    void push() {
+      State = Actions.PushParsingDeclaration();
+      Popped = false;
+    }
+
+    void pop(DeclPtrTy D) {
+      if (!Popped) {
+        Actions.PopParsingDeclaration(State, D);
+        Popped = true;
+      }
+    }
+  };
+
+  /// A class for parsing a DeclSpec.
+  class ParsingDeclSpec : public DeclSpec {
+    ParsingDeclRAIIObject ParsingRAII;
+
+  public:
+    ParsingDeclSpec(Parser &P) : ParsingRAII(P) {
+    }
+
+    void complete(DeclPtrTy D) {
+      ParsingRAII.complete(D);
+    }
+
+    void abort() {
+      ParsingRAII.abort();
+    }
+  };
+
+  /// A class for parsing a declarator.
+  class ParsingDeclarator : public Declarator {
+    ParsingDeclRAIIObject ParsingRAII;
+
+  public:
+    ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
+      : Declarator(DS, C), ParsingRAII(P) {
+    }
+
+    const ParsingDeclSpec &getDeclSpec() const {
+      return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
+    }
+
+    ParsingDeclSpec &getMutableDeclSpec() const {
+      return const_cast<ParsingDeclSpec&>(getDeclSpec());
+    }
+
+    void clear() {
+      Declarator::clear();
+      ParsingRAII.reset();
+    }
+
+    void complete(DeclPtrTy D) {
+      ParsingRAII.complete(D);
+    }
+  };
+
   /// \brief RAII object used to
   class ParsingClassDefinition {
     Parser &P;
@@ -664,7 +757,7 @@ private:
   DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(
             AccessSpecifier AS = AS_none);
 
-  DeclPtrTy ParseFunctionDefinition(Declarator &D,
+  DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D,
                  const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
   void ParseKNRParamDeclarations(Declarator &D);
   // EndLoc, if non-NULL, is filled with the location of the last token of
@@ -951,7 +1044,7 @@ private:
   DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd);
   DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
                                         SourceLocation &DeclEnd);
-  DeclGroupPtrTy ParseDeclGroup(DeclSpec &DS, unsigned Context,
+  DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context,
                                 bool AllowFunctionDefinitions,
                                 SourceLocation *DeclEnd = 0);
   DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D,
index a47065c2b54fa8ed77263dc1d3b926a46d9f4ae9..e905553fd818b1d7bd7228eb48e1e38096c37893 100644 (file)
@@ -338,7 +338,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
 Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
                                                       SourceLocation &DeclEnd) {
   // Parse the common declaration-specifiers piece.
-  DeclSpec DS;
+  ParsingDeclSpec DS(*this);
   ParseDeclarationSpecifiers(DS);
 
   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -346,6 +346,7 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
   if (Tok.is(tok::semi)) {
     ConsumeToken();
     DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DS.complete(TheDecl);
     return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
 
@@ -357,11 +358,12 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
 /// ParseDeclGroup - Having concluded that this is either a function
 /// definition or a group of object declarations, actually parse the
 /// result.
-Parser::DeclGroupPtrTy Parser::ParseDeclGroup(DeclSpec &DS, unsigned Context,
+Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
+                                              unsigned Context,
                                               bool AllowFunctionDefinitions,
                                               SourceLocation *DeclEnd) {
   // Parse the first declarator.
-  Declarator D(DS, static_cast<Declarator::TheContext>(Context));
+  ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context));
   ParseDeclarator(D);
 
   // Bail out if the first declarator didn't seem well-formed.
@@ -397,6 +399,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(DeclSpec &DS, unsigned Context,
 
   llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
   DeclPtrTy FirstDecl = ParseDeclarationAfterDeclarator(D);
+  D.complete(FirstDecl);
   if (FirstDecl.get())
     DeclsInGroup.push_back(FirstDecl);
 
@@ -425,6 +428,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(DeclSpec &DS, unsigned Context,
     ParseDeclarator(D);
 
     DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
+    D.complete(ThisDecl);
     if (ThisDecl.get())
       DeclsInGroup.push_back(ThisDecl);    
   }
@@ -1505,6 +1509,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
   // Read struct-declarators until we find the semicolon.
   bool FirstDeclarator = true;
   while (1) {
+    ParsingDeclRAIIObject PD(*this);
     FieldDeclarator DeclaratorInfo(DS);
 
     // Attributes are only allowed here on successive declarators.
@@ -1536,7 +1541,8 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
     }
 
     // We're done with this declarator;  invoke the callback.
-    (void) Fields.invoke(DeclaratorInfo);
+    DeclPtrTy D = Fields.invoke(DeclaratorInfo);
+    PD.complete(D);
 
     // If we don't have a comma, it is either the end of the list (a ';')
     // or an error, bail out.
@@ -2587,6 +2593,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
     SourceLocation DSStart = Tok.getLocation();
 
     // Parse the declaration-specifiers.
+    // Just use the ParsingDeclaration "scope" of the declarator.
     DeclSpec DS;
 
     // If the caller parsed attributes for the first argument, add them now.
index a8e127610c34ead595fcda8295fa05660796013e..91f86864f81fd9b86b31c50e1448331e5c8bcd5d 100644 (file)
@@ -1099,7 +1099,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
   SourceLocation DSStart = Tok.getLocation();
   // decl-specifier-seq:
   // Parse the common declaration-specifiers piece.
-  DeclSpec DS;
+  ParsingDeclSpec DS(*this);
   ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
 
   Action::MultiTemplateParamsArg TemplateParams(Actions,
@@ -1112,7 +1112,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
     return;
   }
 
-  Declarator DeclaratorInfo(DS, Declarator::MemberContext);
+  ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
 
   if (Tok.isNot(tok::colon)) {
     // Parse the first declarator.
@@ -1231,6 +1231,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
       HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
     }
 
+    DeclaratorInfo.complete(ThisDecl);
+
     // If we don't have a comma, it is either the end of the list (a ';')
     // or an error, bail out.
     if (Tok.isNot(tok::comma))
index 65d71ae481a94de45aee0a16d866d0d7ff6a97e7..b043dd99f304e7b706c1b3fbc6b91427b1ab61cf 100644 (file)
@@ -698,6 +698,8 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
                                               tok::TokenKind mType,
                                               DeclPtrTy IDecl,
                                           tok::ObjCKeywordKind MethodImplKind) {
+  ParsingDeclRAIIObject PD(*this);
+
   // Parse the return type if present.
   TypeTy *ReturnType = 0;
   ObjCDeclSpec DSRet;
@@ -724,10 +726,13 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
       MethodAttrs = ParseAttributes();
 
     Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
-    return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
+    DeclPtrTy Result
+         = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
                                           mType, IDecl, DSRet, ReturnType, Sel,
                                           0, CargNames, MethodAttrs,
                                           MethodImplKind);
+    PD.complete(Result);
+    return Result;
   }
 
   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
@@ -800,10 +805,13 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
     return DeclPtrTy();
   Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
                                                    &KeyIdents[0]);
-  return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
+  DeclPtrTy Result
+       = Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
                                         mType, IDecl, DSRet, ReturnType, Sel,
                                         &ArgInfos[0], CargNames, MethodAttrs,
                                         MethodImplKind, isVariadic);
+  PD.complete(Result);
+  return Result;
 }
 
 ///   objc-protocol-refs:
index a647720fb955e06011d2b0e3c92b779dfc958492..045acd86ad0f2d46cf93f92044f90b9880c96714 100644 (file)
@@ -190,16 +190,18 @@ Parser::ParseSingleDeclarationAfterTemplate(
   }
 
   // Parse the declaration specifiers.
-  DeclSpec DS;
+  ParsingDeclSpec DS(*this);
   ParseDeclarationSpecifiers(DS, TemplateInfo, AS);
 
   if (Tok.is(tok::semi)) {
     DeclEnd = ConsumeToken();
-    return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DS.complete(Decl);
+    return Decl;
   }
 
   // Parse the declarator.
-  Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
+  ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context);
   ParseDeclarator(DeclaratorInfo);
   // Error parsing the declarator?
   if (!DeclaratorInfo.hasName()) {
@@ -225,6 +227,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
 
     // Eat the semi colon after the declaration.
     ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
+    DS.complete(ThisDecl);
     return ThisDecl;
   }
 
index 6836c307d322b1a4e1cf30378d22b3960a22d7e4..335a6cf36254e60aa2b008bc2bfc9c844e9536bc 100644 (file)
@@ -526,7 +526,7 @@ bool Parser::isStartOfFunctionDefinition() {
 Parser::DeclGroupPtrTy
 Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
   // Parse the common declaration-specifiers piece.
-  DeclSpec DS;
+  ParsingDeclSpec DS(*this);
   ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);
 
   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
@@ -534,6 +534,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
   if (Tok.is(tok::semi)) {
     ConsumeToken();
     DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DS.complete(TheDecl);
     return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
 
@@ -549,6 +550,8 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
       return DeclGroupPtrTy();
     }
 
+    DS.abort();
+
     const char *PrevSpec = 0;
     unsigned DiagID;
     if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
@@ -568,6 +571,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
   if (Tok.is(tok::string_literal) && getLang().CPlusPlus &&
       DS.getStorageClassSpec() == DeclSpec::SCS_extern &&
       DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) {
+    DS.abort();
     DeclPtrTy TheDecl = ParseLinkage(Declarator::FileContext);
     return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
@@ -589,7 +593,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
 /// [C++] function-definition: [C++ 8.4]
 ///         decl-specifier-seq[opt] declarator function-try-block
 ///
-Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
+Parser::DeclPtrTy Parser::ParseFunctionDefinition(ParsingDeclarator &D,
                                      const ParsedTemplateInfo &TemplateInfo) {
   const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
   assert(FnTypeInfo.Kind == DeclaratorChunk::Function &&
@@ -641,6 +645,13 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
                                               D)
     : Actions.ActOnStartOfFunctionDef(CurScope, D);
 
+  // Break out of the ParsingDeclarator context before we parse the body.
+  D.complete(Res);
+  
+  // Break out of the ParsingDeclSpec context, too.  This const_cast is
+  // safe because we're always the sole owner.
+  D.getMutableDeclSpec().abort();
+
   if (Tok.is(tok::kw_try))
     return ParseFunctionTryBlock(Res);
 
index 64007f23237b9cc5d69c79981927eb1f8e986845..8104dd39d052836389e1399a82e8f4055a182622 100644 (file)
@@ -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),
index 53f0d7a192593a4d4a2871dfbe1417b03fc9a8ab..bb59e1c9f404eee974332b9b22f74607e07dfebf 100644 (file)
@@ -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);
index 82d467f9667a1815bee6f062dfa89a634834a284..d89cb5fc97f562fb5d2333406197426ba54fa30d 100644 (file)
@@ -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;
index 3995e9b11e9b627da51aaae7bf5580c73406793d..a3f8eb5a0e7710f0f33aa5bfbb0b61c3be42e056 100644 (file)
@@ -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();
+}
index 46c6bf45ad1a8703f80eee0259a87b7ff734909b..93f8d0dc37c14da14f1ccb734037e75d4b1dd9b0 100644 (file)
@@ -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);
 }
 
index 4dd3c2dbef4d0ea76e4e8a6ae32a05a44bbcf948..f1014c6dfecc43a1b884409aa8fc0e9d96ac8941 100644 (file)
@@ -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
index 94b74fbcd191cd2c307c1fc92ccc4c0047a3efdc..0003b1b0c4193bd7c734cba621c91df53bcb6d1c 100644 (file)
@@ -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;
   }
index 527f0106d46854367431ce0852b15db4dfd5189f..4b889fc8aa4f76e9bbe09e8ee5b63668bbf10020 100644 (file)
@@ -55,3 +55,48 @@ struct bar_dep *test3;   // expected-warning {{'bar_dep' is deprecated}}
 foo_dep *test4 __attribute__((deprecated));
 struct bar_dep *test5 __attribute__((deprecated));
 
+typedef foo_dep test6(struct bar_dep*); // expected-warning {{'foo_dep' is deprecated}} \
+                                        // expected-warning {{'bar_dep' is deprecated}}
+typedef foo_dep test7(struct bar_dep*) __attribute__((deprecated));
+
+int test8(char *p) {
+  p += sizeof(foo_dep); // expected-warning {{'foo_dep' is deprecated}}
+
+  foo_dep *ptr;         // expected-warning {{'foo_dep' is deprecated}}
+  ptr = (foo_dep*) p;   // expected-warning {{'foo_dep' is deprecated}}
+
+  int func(foo_dep *foo); // expected-warning {{'foo_dep' is deprecated}}
+  return func(ptr);
+}
+
+foo_dep *test9(void) __attribute__((deprecated));
+foo_dep *test9(void) {
+  void* myalloc(unsigned long);
+
+  foo_dep *ptr
+    = (foo_dep*)
+        myalloc(sizeof(foo_dep));
+  return ptr;
+}
+
+void test10(void) __attribute__((deprecated));
+void test10(void) {
+  if (sizeof(foo_dep) == sizeof(void*)) {
+  }
+  foo_dep *localfunc(void);
+  foo_dep localvar;
+}
+
+char test11[sizeof(foo_dep)] __attribute__((deprecated));
+char test12[sizeof(foo_dep)]; // expected-warning {{'foo_dep' is deprecated}}
+
+int test13(foo_dep *foo) __attribute__((deprecated));
+int test14(foo_dep *foo); // expected-warning {{'foo_dep' is deprecated}}
+
+unsigned long test15 = sizeof(foo_dep); // expected-warning {{'foo_dep' is deprecated}}
+unsigned long test16 __attribute__((deprecated))
+  = sizeof(foo_dep);
+
+foo_dep test17, // expected-warning {{'foo_dep' is deprecated}}
+        test18 __attribute__((deprecated)),
+        test19;