Modify behavior of -ast-dump-lookups: if -ast-dump is not also provided, dump
anyway. If -ast-dump *is* also provided, then dump the AST declarations as well
as the lookup results. This is invaluable for cross-correlating the lookup
information with the declarations actually found.

llvm-svn: 215393
diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index ac3c652..5d6e18a 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -220,7 +220,7 @@
     void dumpName(const NamedDecl *D);
     bool hasNodes(const DeclContext *DC);
     void dumpDeclContext(const DeclContext *DC);
-    void dumpLookups(const DeclContext *DC);
+    void dumpLookups(const DeclContext *DC, bool DumpDecls);
     void dumpAttr(const Attr *A);
 
     // C++ Utilities
@@ -569,7 +569,7 @@
   }
 }
 
-void ASTDumper::dumpLookups(const DeclContext *DC) {
+void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
   IndentScope Indent(*this);
 
   OS << "StoredDeclsMap ";
@@ -602,9 +602,26 @@
          RI != RE; ++RI) {
       if (RI + 1 == RE)
         lastChild();
-      dumpDeclRef(*RI);
+
+      IndentScope LookupIndent(*this);
+      dumpBareDeclRef(*RI);
+
       if ((*RI)->isHidden())
         OS << " hidden";
+
+      // If requested, dump the redecl chain for this lookup.
+      if (DumpDecls) {
+        // Dump earliest decl first.
+        std::function<void(Decl*)> DumpPrev = [&](Decl *D) {
+          if (Decl *Prev = D->getPreviousDecl()) {
+            DumpPrev(Prev);
+            dumpDecl(Prev);
+          }
+        };
+        DumpPrev(*RI);
+        lastChild();
+        dumpDecl(*RI);
+      }
     }
   }
 
@@ -2169,13 +2186,14 @@
   dumpLookups(llvm::errs());
 }
 
-LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS) const {
+LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
+                                               bool DumpDecls) const {
   const DeclContext *DC = this;
   while (!DC->isTranslationUnit())
     DC = DC->getParent();
   ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
   ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager());
-  P.dumpLookups(this);
+  P.dumpLookups(this, DumpDecls);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Frontend/ASTConsumers.cpp b/clang/lib/Frontend/ASTConsumers.cpp
index d836ed4..f53c614 100644
--- a/clang/lib/Frontend/ASTConsumers.cpp
+++ b/clang/lib/Frontend/ASTConsumers.cpp
@@ -57,7 +57,8 @@
         bool ShowColors = Out.has_colors();
         if (ShowColors)
           Out.changeColor(raw_ostream::BLUE);
-        Out << (Dump ? "Dumping " : "Printing ") << getName(D) << ":\n";
+        Out << ((Dump || DumpLookups) ? "Dumping " : "Printing ") << getName(D)
+            << ":\n";
         if (ShowColors)
           Out.resetColor();
         print(D);
@@ -79,9 +80,13 @@
     }
     void print(Decl *D) {
       if (DumpLookups) {
-        if (DeclContext *DC = dyn_cast<DeclContext>(D))
-          DC->dumpLookups(Out);
-        else
+        if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
+          if (DC == DC->getPrimaryContext())
+            DC->dumpLookups(Out, Dump);
+          else
+            Out << "Lookup map is in primary DeclContext "
+                << DC->getPrimaryContext() << "\n";
+        } else
           Out << "Not a DeclContext\n";
       } else if (Dump)
         D->dump(Out);
@@ -124,8 +129,10 @@
 }
 
 std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString,
+                                                    bool DumpDecls,
                                                     bool DumpLookups) {
-  return llvm::make_unique<ASTPrinter>(nullptr, /*Dump=*/true, FilterString,
+  assert((DumpDecls || DumpLookups) && "nothing to dump");
+  return llvm::make_unique<ASTPrinter>(nullptr, DumpDecls, FilterString,
                                        DumpLookups);
 }
 
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 7b864bf..070b00c 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -718,6 +718,7 @@
     case OPT_ast_list:
       Opts.ProgramAction = frontend::ASTDeclList; break;
     case OPT_ast_dump:
+    case OPT_ast_dump_lookups:
       Opts.ProgramAction = frontend::ASTDump; break;
     case OPT_ast_print:
       Opts.ProgramAction = frontend::ASTPrint; break;
@@ -825,6 +826,7 @@
   Opts.FixOnlyWarnings = Args.hasArg(OPT_fix_only_warnings);
   Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile);
   Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp);
+  Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump);
   Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter);
   Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups);
   Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index);
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index e5830d6..f3be243 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -55,6 +55,7 @@
 std::unique_ptr<ASTConsumer>
 ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
   return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter,
+                         CI.getFrontendOpts().ASTDumpDecls,
                          CI.getFrontendOpts().ASTDumpLookups);
 }