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.

llvm-svn: 85998
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index a47065c..e905553 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -338,7 +338,7 @@
 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 @@
   if (Tok.is(tok::semi)) {
     ConsumeToken();
     DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DS.complete(TheDecl);
     return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
 
@@ -357,11 +358,12 @@
 /// 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 @@
 
   llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
   DeclPtrTy FirstDecl = ParseDeclarationAfterDeclarator(D);
+  D.complete(FirstDecl);
   if (FirstDecl.get())
     DeclsInGroup.push_back(FirstDecl);
 
@@ -425,6 +428,7 @@
     ParseDeclarator(D);
 
     DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
+    D.complete(ThisDecl);
     if (ThisDecl.get())
       DeclsInGroup.push_back(ThisDecl);    
   }
@@ -1505,6 +1509,7 @@
   // 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 @@
     }
 
     // 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 @@
     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.
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index a8e1276..91f8686 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1099,7 +1099,7 @@
   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 @@
     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 @@
       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))
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index 65d71ae..b043dd9 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -698,6 +698,8 @@
                                               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 @@
       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 @@
     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:
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index a647720..045acd8 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -190,16 +190,18 @@
   }
 
   // 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 @@
 
     // Eat the semi colon after the declaration.
     ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
+    DS.complete(ThisDecl);
     return ThisDecl;
   }
 
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 6836c30..335a6cf 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -526,7 +526,7 @@
 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 @@
   if (Tok.is(tok::semi)) {
     ConsumeToken();
     DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DS.complete(TheDecl);
     return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
 
@@ -549,6 +550,8 @@
       return DeclGroupPtrTy();
     }
 
+    DS.abort();
+
     const char *PrevSpec = 0;
     unsigned DiagID;
     if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
@@ -568,6 +571,7 @@
   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 @@
 /// [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 @@
                                               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);