From eef63e0997e0f6d6436736ea919b851cfe34955a Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Wed, 2 Feb 2011 15:41:17 +0000 Subject: [PATCH] Frontend: Factor out header include dumping (-H) into its own preprocessor 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 --- .../clang/Frontend/DependencyOutputOptions.h | 2 + .../Frontend/PreprocessorOutputOptions.h | 2 - include/clang/Frontend/Utils.h | 4 + lib/Frontend/CMakeLists.txt | 1 + lib/Frontend/CompilerInstance.cpp | 4 + lib/Frontend/CompilerInvocation.cpp | 6 +- lib/Frontend/HeaderIncludeGen.cpp | 87 +++++++++++++++++++ lib/Frontend/PrintPreprocessedOutput.cpp | 40 +-------- 8 files changed, 105 insertions(+), 41 deletions(-) create mode 100644 lib/Frontend/HeaderIncludeGen.cpp diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h index 10327c022a..a812ded6c9 100644 --- a/include/clang/Frontend/DependencyOutputOptions.h +++ b/include/clang/Frontend/DependencyOutputOptions.h @@ -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; } }; diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h index 82517c51d1..1eda0d4027 100644 --- a/include/clang/Frontend/PreprocessorOutputOptions.h +++ b/include/clang/Frontend/PreprocessorOutputOptions.h @@ -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; diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index fe722db381..524db6e429 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -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); diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index c6ec7215c7..ceb9fcd361 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -24,6 +24,7 @@ add_clang_library(clangFrontend FrontendAction.cpp FrontendActions.cpp FrontendOptions.cpp + HeaderIncludeGen.cpp InitHeaderSearch.cpp InitPreprocessor.cpp LangStandards.cpp diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 9ff2e9d1be..dea698d593 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -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; } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 9ad41458b8..1869049cbc 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -220,6 +220,8 @@ static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts, std::vector &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 index 0000000000..f29e8f159d --- /dev/null +++ b/lib/Frontend/HeaderIncludeGen.cpp @@ -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 +*/ +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; + } +} + diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 7494bd3002..922d743adf 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -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 += ""; 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", -- 2.40.0