diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4945,6 +4945,11 @@ def sys_header_deps : Flag<["-"], "sys-header-deps">, HelpText<"Include system headers in dependency output">, MarshallingInfoFlag>; +def show_skipped_includes : Flag<["-"], "show-skipped-includes">, + HelpText<"Show skipped includes in -H output.">, + DocBrief<[{#include files may be "skipped" due to include guard optimization + or #pragma once. This flag makes -H show also such includes.}]>, + MarshallingInfoFlag>; def module_file_deps : Flag<["-"], "module-file-deps">, HelpText<"Include module files in dependency output">, MarshallingInfoFlag>; diff --git a/clang/include/clang/Frontend/DependencyOutputOptions.h b/clang/include/clang/Frontend/DependencyOutputOptions.h --- a/clang/include/clang/Frontend/DependencyOutputOptions.h +++ b/clang/include/clang/Frontend/DependencyOutputOptions.h @@ -39,6 +39,10 @@ /// problems. unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list unsigned IncludeModuleFiles : 1; ///< Include module file dependencies. + unsigned ShowSkippedHeaderIncludes : 1; ///< With ShowHeaderIncludes, show + /// also includes that were skipped + /// due to the "include guard + /// optimization" or #pragma once. /// Destination of cl.exe style /showIncludes info. ShowIncludesDestination ShowIncludesDest = ShowIncludesDestination::None; @@ -75,7 +79,8 @@ public: DependencyOutputOptions() : IncludeSystemHeaders(0), ShowHeaderIncludes(0), UsePhonyTargets(0), - AddMissingHeaderDeps(0), IncludeModuleFiles(0) {} + AddMissingHeaderDeps(0), IncludeModuleFiles(0), + ShowSkippedHeaderIncludes(0) {} }; } // end namespace clang diff --git a/clang/lib/Frontend/HeaderIncludeGen.cpp b/clang/lib/Frontend/HeaderIncludeGen.cpp --- a/clang/lib/Frontend/HeaderIncludeGen.cpp +++ b/clang/lib/Frontend/HeaderIncludeGen.cpp @@ -45,6 +45,9 @@ void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID) override; + + void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) override; }; } @@ -181,3 +184,16 @@ MSStyle); } } + +void HeaderIncludesCallback::FileSkipped(const FileEntryRef &SkippedFile, const + Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) { + if (!DepOpts.ShowSkippedHeaderIncludes) + return; + + if (!DepOpts.IncludeSystemHeaders && isSystem(FileType)) + return; + + PrintHeaderInfo(OutputFile, SkippedFile.getName(), ShowDepth, + CurrentIncludeDepth + 1, MSStyle); +} diff --git a/clang/test/Frontend/Inputs/test.h b/clang/test/Frontend/Inputs/test.h --- a/clang/test/Frontend/Inputs/test.h +++ b/clang/test/Frontend/Inputs/test.h @@ -1 +1,7 @@ +#ifndef TEST_H +#define TEST_H + #include "test2.h" +#include "test2.h" + +#endif diff --git a/clang/test/Frontend/Inputs/test2.h b/clang/test/Frontend/Inputs/test2.h --- a/clang/test/Frontend/Inputs/test2.h +++ b/clang/test/Frontend/Inputs/test2.h @@ -1 +1,6 @@ +#ifndef TEST2_H +#define TEST2_H + int x; + +#endif diff --git a/clang/test/Frontend/print-header-includes.c b/clang/test/Frontend/print-header-includes.c --- a/clang/test/Frontend/print-header-includes.c +++ b/clang/test/Frontend/print-header-includes.c @@ -6,6 +6,16 @@ // CHECK-NOT: . {{.*noline.h}} // CHECK: . {{.*test.h}} // CHECK: .. {{.*test2.h}} +// CHECK-NOT: .. {{.*test2.h}} + +// RUN: %clang_cc1 -I%S -isystem %S/Inputs/SystemHeaderPrefix \ +// RUN: -E -H -show-skipped-includes -o /dev/null %s 2> %t.stderr +// RUN: FileCheck --check-prefix=SKIPPED < %t.stderr %s + +// SKIPPED-NOT: . {{.*noline.h}} +// SKIPPED: . {{.*test.h}} +// SKIPPED: .. {{.*test2.h}} +// SKIPPED: .. {{.*test2.h}} // RUN: %clang_cc1 -I%S -include Inputs/test3.h -isystem %S/Inputs/SystemHeaderPrefix \ // RUN: -E -H -sys-header-deps -o /dev/null %s 2> %t.stderr