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.
public:
DependencyOutputOptions() {
IncludeSystemHeaders = 0;
+ ShowHeaderIncludes = 0;
UsePhonyTargets = 0;
}
};
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.
PreprocessorOutputOptions() {
ShowCPP = 1;
ShowComments = 0;
- ShowHeaderIncludes = 0;
ShowLineMarkers = 1;
ShowMacroComments = 0;
ShowMacros = 0;
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);
FrontendAction.cpp
FrontendActions.cpp
FrontendOptions.cpp
+ HeaderIncludeGen.cpp
InitHeaderSearch.cpp
InitPreprocessor.cpp
LangStandards.cpp
if (!DepOpts.OutputFile.empty())
AttachDependencyFileGen(*PP, DepOpts);
+ // Handle generating header include information, if requested.
+ if (DepOpts.ShowHeaderIncludes)
+ AttachHeaderIncludeGen(*PP);
+
return PP;
}
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()) {
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)
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,
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);
--- /dev/null
+//===--- 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;
+ }
+}
+
private:
unsigned CurLine;
- /// The current include nesting level, used by header include dumping (-H).
- unsigned CurrentIncludeDepth;
-
bool EmittedTokensOnThisLine;
bool EmittedMacroOnThisLine;
SrcMgr::CharacteristicKind FileType;
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;
// 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;
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) {
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",