Frontend: Add basic -H support.
- I didn't implement the GCC "multiple include guard" detection parts, because
it doesn't seem useful or obvious.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111983 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 9a22c21..bdb918b 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -556,3 +556,5 @@
HelpText<"Print macro definitions in -E mode instead of normal output">;
def dD : Flag<"-dD">,
HelpText<"Print macro definitions in -E mode in addition to normal output">;
+def H : Flag<"-H">,
+ HelpText<"Show header includes and nesting depth">;
diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h
index a712a3d..82517c5 100644
--- a/include/clang/Frontend/PreprocessorOutputOptions.h
+++ b/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -16,19 +16,21 @@
/// output (e.g., -E).
class PreprocessorOutputOptions {
public:
- unsigned ShowCPP : 1; ///< Print normal preprocessed output.
- unsigned ShowMacros : 1; ///< Print macro definitions.
- unsigned ShowLineMarkers : 1; ///< Show #line markers.
- unsigned ShowComments : 1; ///< Show comments.
- unsigned ShowMacroComments : 1; ///< Show comments, even in macros.
+ 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.
public:
PreprocessorOutputOptions() {
ShowCPP = 1;
- ShowMacros = 0;
- ShowLineMarkers = 1;
ShowComments = 0;
+ ShowHeaderIncludes = 0;
+ ShowLineMarkers = 1;
ShowMacroComments = 0;
+ ShowMacros = 0;
}
};
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 4f839e9..9e7a061 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -962,6 +962,7 @@
}
Args.AddAllArgs(CmdArgs, options::OPT_v);
+ Args.AddLastArg(CmdArgs, options::OPT_H);
Args.AddLastArg(CmdArgs, options::OPT_P);
Args.AddLastArg(CmdArgs, options::OPT_print_ivar_layout);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 86ce315..68e2d84 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -689,6 +689,8 @@
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)
@@ -1456,10 +1458,11 @@
ArgList &Args) {
using namespace cc1options;
Opts.ShowCPP = !Args.hasArg(OPT_dM);
- Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
- Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
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);
}
static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index e68fd58..cfaf8a2 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -85,6 +85,10 @@
llvm::raw_ostream &OS;
private:
unsigned CurLine;
+
+ /// The current include nesting level, used by header include dumping (-H).
+ unsigned CurrentIncludeDepth;
+
bool EmittedTokensOnThisLine;
bool EmittedMacroOnThisLine;
SrcMgr::CharacteristicKind FileType;
@@ -92,19 +96,22 @@
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 lineMarkers, bool defines, bool headers)
: PP(pp), SM(PP.getSourceManager()),
ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers),
- DumpDefines(defines) {
- CurLine = 0;
+ DumpDefines(defines), DumpHeaderIncludes(headers) {
+ CurLine = CurrentIncludeDepth = 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;
@@ -219,7 +226,7 @@
PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc);
unsigned NewLine = UserLoc.getLine();
-
+
if (Reason == PPCallbacks::EnterFile) {
SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc();
if (IncludeLoc.isValid())
@@ -231,16 +238,41 @@
// 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;
- if (DisableLineMarkers) return;
-
CurFilename.clear();
CurFilename += UserLoc.getFilename();
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) {
+ 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) {
WriteLineInfo(CurLine);
Initialized = true;
@@ -529,7 +561,7 @@
PrintPPOutputPPCallbacks *Callbacks =
new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers,
- Opts.ShowMacros);
+ Opts.ShowMacros, Opts.ShowHeaderIncludes);
PP.AddPragmaHandler(new UnknownPragmaHandler("#pragma", Callbacks));
PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",
Callbacks));
diff --git a/test/Frontend/Inputs/lit.local.cfg b/test/Frontend/Inputs/lit.local.cfg
new file mode 100644
index 0000000..e6f55ee
--- /dev/null
+++ b/test/Frontend/Inputs/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = []
diff --git a/test/Frontend/Inputs/test.h b/test/Frontend/Inputs/test.h
new file mode 100644
index 0000000..98cc459
--- /dev/null
+++ b/test/Frontend/Inputs/test.h
@@ -0,0 +1 @@
+#include "test2.h"
diff --git a/test/Frontend/Inputs/test2.h b/test/Frontend/Inputs/test2.h
new file mode 100644
index 0000000..6d1a0d4
--- /dev/null
+++ b/test/Frontend/Inputs/test2.h
@@ -0,0 +1 @@
+int x;
diff --git a/test/Frontend/Inputs/test3.h b/test/Frontend/Inputs/test3.h
new file mode 100644
index 0000000..92ff4b8
--- /dev/null
+++ b/test/Frontend/Inputs/test3.h
@@ -0,0 +1 @@
+int y;
diff --git a/test/Frontend/print-header-includes.c b/test/Frontend/print-header-includes.c
new file mode 100644
index 0000000..7773d20
--- /dev/null
+++ b/test/Frontend/print-header-includes.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -include Inputs/test3.h -E -H -o %t.out %s 2> %t.err
+// RUN: FileCheck < %t.err %s
+
+// CHECK-NOT: test3.h
+// CHECK: . {{.*test.h}}
+// CHECK: .. {{.*test2.h}}
+
+#include "Inputs/test.h"