]> granicus.if.org Git - clang/commitdiff
Frontend: Factor out header include dumping (-H) into its own preprocessor
authorDaniel Dunbar <daniel@zuster.org>
Wed, 2 Feb 2011 15:41:17 +0000 (15:41 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Wed, 2 Feb 2011 15:41:17 +0000 (15:41 +0000)
callbacks class.
 - Aside from being generally cleaner, this also allows -H to work correctly in
   modes other than standard preprocessing (e.g., -c, -MM, etc.)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124723 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/DependencyOutputOptions.h
include/clang/Frontend/PreprocessorOutputOptions.h
include/clang/Frontend/Utils.h
lib/Frontend/CMakeLists.txt
lib/Frontend/CompilerInstance.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/HeaderIncludeGen.cpp [new file with mode: 0644]
lib/Frontend/PrintPreprocessedOutput.cpp

index 10327c022a308bdd6d4de3f80b82fb5a8f141cce..a812ded6c96be2d32274d4af460efa3799b2c041 100644 (file)
@@ -20,6 +20,7 @@ namespace clang {
 class DependencyOutputOptions {
 public:
   unsigned IncludeSystemHeaders : 1; ///< Include system header dependencies.
+  unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H).
   unsigned UsePhonyTargets : 1;      ///< Include phony targets for each
                                      /// dependency, which can avoid some 'make'
                                      /// problems.
@@ -34,6 +35,7 @@ public:
 public:
   DependencyOutputOptions() {
     IncludeSystemHeaders = 0;
+    ShowHeaderIncludes = 0;
     UsePhonyTargets = 0;
   }
 };
index 82517c51d1c1dac85e836d3e6352a2849fcc1cf5..1eda0d40275eaf7927061258b2ac735c9b152802 100644 (file)
@@ -18,7 +18,6 @@ class PreprocessorOutputOptions {
 public:
   unsigned ShowCPP : 1;            ///< Print normal preprocessed output.
   unsigned ShowComments : 1;       ///< Show comments.
-  unsigned ShowHeaderIncludes : 1; ///< Show header inclusions (-H).
   unsigned ShowLineMarkers : 1;    ///< Show #line markers.
   unsigned ShowMacroComments : 1;  ///< Show comments, even in macros.
   unsigned ShowMacros : 1;         ///< Print macro definitions.
@@ -27,7 +26,6 @@ public:
   PreprocessorOutputOptions() {
     ShowCPP = 1;
     ShowComments = 0;
-    ShowHeaderIncludes = 0;
     ShowLineMarkers = 1;
     ShowMacroComments = 0;
     ShowMacros = 0;
index fe722db381d0106b1379f3872fb45f7a7f90dc1f..524db6e429d5dc87078a0e5b952b3efd15b235f4 100644 (file)
@@ -73,6 +73,10 @@ bool CheckDiagnostics(Preprocessor &PP);
 void AttachDependencyFileGen(Preprocessor &PP,
                              const DependencyOutputOptions &Opts);
 
+/// AttachHeaderIncludeGen - Create a header include list generator, and attach
+/// it to the given preprocessor.
+void AttachHeaderIncludeGen(Preprocessor &PP);
+
 /// CacheTokens - Cache tokens for use with PCH. Note that this requires
 /// a seekable stream.
 void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS);
index c6ec7215c71cdf8bd8b3df5d34430d6812b1b02f..ceb9fcd36154530c0f8534e32caddc9cb98deb40 100644 (file)
@@ -24,6 +24,7 @@ add_clang_library(clangFrontend
   FrontendAction.cpp
   FrontendActions.cpp
   FrontendOptions.cpp
+  HeaderIncludeGen.cpp
   InitHeaderSearch.cpp
   InitPreprocessor.cpp
   LangStandards.cpp
index 9ff2e9d1bec648f3b49ef8ed458bb28d149d8477..dea698d5931bdf765d02bd24122d2d0e2bc0a0cf 100644 (file)
@@ -207,6 +207,10 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags,
   if (!DepOpts.OutputFile.empty())
     AttachDependencyFileGen(*PP, DepOpts);
 
+  // Handle generating header include information, if requested.
+  if (DepOpts.ShowHeaderIncludes)
+    AttachHeaderIncludeGen(*PP);
+
   return PP;
 }
 
index 9ad41458b8ce34a6a91ed7170a540926d5365c80..1869049cbc829a0726a93cee8575f49202aa4812 100644 (file)
@@ -220,6 +220,8 @@ static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
                                        std::vector<std::string> &Res) {
   if (Opts.IncludeSystemHeaders)
     Res.push_back("-sys-header-deps");
+  if (Opts.ShowHeaderIncludes)
+    Res.push_back("-H");
   if (Opts.UsePhonyTargets)
     Res.push_back("-MP");
   if (!Opts.OutputFile.empty()) {
@@ -732,8 +734,6 @@ static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
   else if (!Opts.ShowCPP && Opts.ShowMacros)
     Res.push_back("-dM");
 
-  if (Opts.ShowHeaderIncludes)
-    Res.push_back("-H");
   if (!Opts.ShowLineMarkers)
     Res.push_back("-P");
   if (Opts.ShowComments)
@@ -960,6 +960,7 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
   Opts.Targets = Args.getAllArgValues(OPT_MT);
   Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
   Opts.UsePhonyTargets = Args.hasArg(OPT_MP);
+  Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
 }
 
 static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
@@ -1581,7 +1582,6 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
   using namespace cc1options;
   Opts.ShowCPP = !Args.hasArg(OPT_dM);
   Opts.ShowComments = Args.hasArg(OPT_C);
-  Opts.ShowHeaderIncludes = Args.hasArg(OPT_H);
   Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
   Opts.ShowMacroComments = Args.hasArg(OPT_CC);
   Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
diff --git a/lib/Frontend/HeaderIncludeGen.cpp b/lib/Frontend/HeaderIncludeGen.cpp
new file mode 100644 (file)
index 0000000..f29e8f1
--- /dev/null
@@ -0,0 +1,87 @@
+//===--- HeaderIncludes.cpp - Generate Header Includes --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/Utils.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+/*
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Frontend/PreprocessorOutputOptions.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Pragma.h"
+#include "clang/Lex/TokenConcatenation.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdio>
+*/
+using namespace clang;
+
+namespace {
+class HeaderIncludesCallback : public PPCallbacks {
+  SourceManager &SM;
+  unsigned CurrentIncludeDepth;
+  bool HasProcessedPredefines;
+
+public:
+  HeaderIncludesCallback(const Preprocessor *PP)
+    : SM(PP->getSourceManager()), CurrentIncludeDepth(0),
+      HasProcessedPredefines(false) {}
+
+  virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
+                           SrcMgr::CharacteristicKind FileType);
+};
+}
+
+void clang::AttachHeaderIncludeGen(Preprocessor &PP) {
+  PP.addPPCallbacks(new HeaderIncludesCallback(&PP));
+}
+
+void HeaderIncludesCallback::FileChanged(SourceLocation Loc,
+                                         FileChangeReason Reason,
+                                       SrcMgr::CharacteristicKind NewFileType) {
+  // Unless we are exiting a #include, make sure to skip ahead to the line the
+  // #include directive was at.
+  PresumedLoc UserLoc = SM.getPresumedLoc(Loc);
+  if (UserLoc.isInvalid())
+    return;
+  
+  // Adjust the current include depth.
+  if (Reason == PPCallbacks::EnterFile) {
+    ++CurrentIncludeDepth;
+  } else {
+    if (CurrentIncludeDepth)
+      --CurrentIncludeDepth;
+
+    // We track when we are done with the predefines by watching for the first
+    // place where we drop back to a nesting depth of 0.
+    if (CurrentIncludeDepth == 0 && !HasProcessedPredefines)
+      HasProcessedPredefines = true;
+  }
+  
+  // Dump the header include information we are past the predefines buffer.
+  if (HasProcessedPredefines && Reason == PPCallbacks::EnterFile) {
+    // Write to a temporary string to avoid unnecessary flushing on errs().
+    llvm::SmallString<512> Filename(UserLoc.getFilename());
+    Lexer::Stringify(Filename);
+
+    llvm::SmallString<256> Msg;
+    for (unsigned i = 0; i != CurrentIncludeDepth; ++i)
+      Msg += '.';
+    Msg += ' ';
+    Msg += Filename;
+    Msg += '\n';
+
+    llvm::errs() << Msg;
+  }
+}
+
index 7494bd3002efe87c44e41f497974e1efa2658c9c..922d743adf4e96d4729e561a5c161ca238e3e7fd 100644 (file)
@@ -86,9 +86,6 @@ public:
 private:
   unsigned CurLine;
 
-  /// The current include nesting level, used by header include dumping (-H).
-  unsigned CurrentIncludeDepth;
-
   bool EmittedTokensOnThisLine;
   bool EmittedMacroOnThisLine;
   SrcMgr::CharacteristicKind FileType;
@@ -96,22 +93,19 @@ private:
   bool Initialized;
   bool DisableLineMarkers;
   bool DumpDefines;
-  bool DumpHeaderIncludes;
   bool UseLineDirective;
-  bool HasProcessedPredefines;
 public:
   PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os,
-                           bool lineMarkers, bool defines, bool headers)
+                           bool lineMarkers, bool defines)
      : PP(pp), SM(PP.getSourceManager()),
        ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers),
-       DumpDefines(defines), DumpHeaderIncludes(headers) {
-    CurLine = CurrentIncludeDepth = 0;
+       DumpDefines(defines) {
+    CurLine = 0;
     CurFilename += "<uninit>";
     EmittedTokensOnThisLine = false;
     EmittedMacroOnThisLine = false;
     FileType = SrcMgr::C_User;
     Initialized = false;
-    HasProcessedPredefines = false;
 
     // If we're in microsoft mode, use normal #line instead of line markers.
     UseLineDirective = PP.getLangOptions().Microsoft;
@@ -256,19 +250,6 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
     // directive and emits a bunch of spaces that aren't needed.  Emulate this
     // strange behavior.
   }
-
-  // Adjust the current include depth.
-  if (Reason == PPCallbacks::EnterFile) {
-    ++CurrentIncludeDepth;
-  } else {
-    if (CurrentIncludeDepth)
-      --CurrentIncludeDepth;
-
-    // We track when we are done with the predefines by watching for the first
-    // place where we drop back to a nesting depth of 0.
-    if (CurrentIncludeDepth == 0 && !HasProcessedPredefines)
-      HasProcessedPredefines = true;
-  }
   
   CurLine = NewLine;
 
@@ -277,19 +258,6 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
   Lexer::Stringify(CurFilename);
   FileType = NewFileType;
 
-  // Dump the header include information, if enabled and we are past the
-  // predefines buffer.
-  if (DumpHeaderIncludes && HasProcessedPredefines &&
-      Reason == PPCallbacks::EnterFile) {
-    // Write to a temporary string to avoid unnecessary flushing on errs().
-    llvm::SmallString<256> Msg;
-    llvm::raw_svector_ostream OS(Msg);
-    for (unsigned i = 0; i != CurrentIncludeDepth; ++i)
-      OS << '.';
-    OS << ' ' << CurFilename << '\n';
-    llvm::errs() << OS.str();
-  }
-
   if (DisableLineMarkers) return;
   
   if (!Initialized) {
@@ -581,7 +549,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS,
 
   PrintPPOutputPPCallbacks *Callbacks =
       new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers,
-                                   Opts.ShowMacros, Opts.ShowHeaderIncludes);
+                                   Opts.ShowMacros);
   PP.AddPragmaHandler(new UnknownPragmaHandler("#pragma", Callbacks));
   PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",Callbacks));
   PP.AddPragmaHandler("clang",