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
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 3995e9b..a3f8eb5 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1949,3 +1949,62 @@
   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();
+}