Handle internal headers guarded by macro and x-macros (fix issue #109).
I've made a few trade-offs in implementation which I'd like to explain more. First, code doesn't distinguish between guarded internal headers and headers with x-macros. They are handled the same way. But in tests both patterns are tested. It is done not to cover all code paths but to test include-what-you-use from user's perspective. Also I check if file defining macro is immediate includer. I decided not to check if it includes file using the macro transitively until we have such real-life use cases. Current implementation is strict in order to avoid unexpected results. For some cases I am reusing mechanism that keeps files included with the "IWYU pragma: keep" comment. The downside is that it keeps all lines including this file which might be not entirely correct for x-macros. Though x-macros are close to pure textual includes and we cannot reason about textual includes. I also didn't include a few test cases because I think they don't represent real-life use cases. These test cases are: * when associated header is included by non-associated header; * when file defining macro and file using macro are both included by the third file.
This commit is contained in:
parent
2f826a3323
commit
04f1c92537
|
@ -598,6 +598,10 @@ void IwyuFileInfo::ReportMacroUse(clang::SourceLocation use_loc,
|
||||||
LogSymbolUse("Marked full-info use of macro", symbol_uses_.back());
|
LogSymbolUse("Marked full-info use of macro", symbol_uses_.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IwyuFileInfo::ReportDefinedMacroUse(const clang::FileEntry* used_in) {
|
||||||
|
macro_users_.insert(used_in);
|
||||||
|
}
|
||||||
|
|
||||||
void IwyuFileInfo::ReportIncludeFileUse(const clang::FileEntry* included_file,
|
void IwyuFileInfo::ReportIncludeFileUse(const clang::FileEntry* included_file,
|
||||||
const string& quoted_include) {
|
const string& quoted_include) {
|
||||||
symbol_uses_.push_back(OneUse("", included_file, quoted_include,
|
symbol_uses_.push_back(OneUse("", included_file, quoted_include,
|
||||||
|
@ -605,7 +609,7 @@ void IwyuFileInfo::ReportIncludeFileUse(const clang::FileEntry* included_file,
|
||||||
LogSymbolUse("Marked use of include-file", symbol_uses_.back());
|
LogSymbolUse("Marked use of include-file", symbol_uses_.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IwyuFileInfo::ReportPragmaKeep(const clang::FileEntry* included_file) {
|
void IwyuFileInfo::ReportKnownDesiredFile(const FileEntry* included_file) {
|
||||||
kept_includes_.insert(included_file);
|
kept_includes_.insert(included_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1887,6 +1891,41 @@ size_t PrintableDiffs(const string& filename,
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
void IwyuFileInfo::HandlePreprocessingDone() {
|
||||||
|
// Check macros defined by includer. Requires file preprocessing to be
|
||||||
|
// finished to know all direct includes and all macro usages.
|
||||||
|
bool should_report_violations = ShouldReportIWYUViolationsFor(file_);
|
||||||
|
std::list<const FileEntry*> direct_macro_use_includees;
|
||||||
|
std::set_intersection(macro_users_.begin(), macro_users_.end(),
|
||||||
|
direct_includes_as_fileentries_.begin(),
|
||||||
|
direct_includes_as_fileentries_.end(),
|
||||||
|
std::inserter(direct_macro_use_includees,
|
||||||
|
direct_macro_use_includees.end()));
|
||||||
|
for (const FileEntry* macro_use_includee : direct_macro_use_includees) {
|
||||||
|
if (should_report_violations) {
|
||||||
|
ERRSYM(file_) << "Keep #include " << macro_use_includee->getName()
|
||||||
|
<< " in " << file_->getName()
|
||||||
|
<< " because used macro is defined by includer.\n";
|
||||||
|
ReportKnownDesiredFile(macro_use_includee);
|
||||||
|
} else {
|
||||||
|
string private_include =
|
||||||
|
ConvertToQuotedInclude(GetFilePath(macro_use_includee));
|
||||||
|
if (GlobalIncludePicker().IsPublic(macro_use_includee)) {
|
||||||
|
ERRSYM(file_) << "Skip marking " << quoted_file_
|
||||||
|
<< " as public header for " << private_include
|
||||||
|
<< " because latter is already marked as public,"
|
||||||
|
<< " though uses macro defined by includer.\n";
|
||||||
|
} else {
|
||||||
|
ERRSYM(file_) << "Mark " << quoted_file_
|
||||||
|
<< " as public header for " << private_include
|
||||||
|
<< " because used macro is defined by includer.\n";
|
||||||
|
MutableGlobalIncludePicker()->AddMapping(private_include, quoted_file_);
|
||||||
|
MutableGlobalIncludePicker()->MarkIncludeAsPrivate(private_include);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void IwyuFileInfo::ResolvePendingAnalysis() {
|
void IwyuFileInfo::ResolvePendingAnalysis() {
|
||||||
// Resolve using declarations: This handles the case where there's a using
|
// Resolve using declarations: This handles the case where there's a using
|
||||||
// declaration in the file but no code is actually using it. If that
|
// declaration in the file but no code is actually using it. If that
|
||||||
|
|
|
@ -235,10 +235,14 @@ class IwyuFileInfo {
|
||||||
const string& symbol);
|
const string& symbol);
|
||||||
// TODO(dsturtevant): Can we determine in_cxx_method_body? Do we care?
|
// TODO(dsturtevant): Can we determine in_cxx_method_body? Do we care?
|
||||||
|
|
||||||
|
// Called when using a macro in this file.
|
||||||
void ReportMacroUse(clang::SourceLocation use_loc,
|
void ReportMacroUse(clang::SourceLocation use_loc,
|
||||||
clang::SourceLocation dfn_loc,
|
clang::SourceLocation dfn_loc,
|
||||||
const string& symbol);
|
const string& symbol);
|
||||||
|
|
||||||
|
// Called when somebody uses a macro defined in this file.
|
||||||
|
void ReportDefinedMacroUse(const clang::FileEntry* used_in);
|
||||||
|
|
||||||
// We only allow forward-declaring of decls, not arbitrary symbols.
|
// We only allow forward-declaring of decls, not arbitrary symbols.
|
||||||
void ReportForwardDeclareUse(clang::SourceLocation use_loc,
|
void ReportForwardDeclareUse(clang::SourceLocation use_loc,
|
||||||
const clang::NamedDecl* decl,
|
const clang::NamedDecl* decl,
|
||||||
|
@ -256,15 +260,19 @@ class IwyuFileInfo {
|
||||||
void ReportIncludeFileUse(const clang::FileEntry* included_file,
|
void ReportIncludeFileUse(const clang::FileEntry* included_file,
|
||||||
const string& quoted_include);
|
const string& quoted_include);
|
||||||
|
|
||||||
// This is used when we see an "IWYU pragma: keep" comment
|
// This is used when we see a file we want to keep not due to symbol-use
|
||||||
// on an include line.
|
// reasons. For example, it can be #included with an "IWYU pragma: keep"
|
||||||
void ReportPragmaKeep(const clang::FileEntry* included_file);
|
// comment or it can be an x-macro.
|
||||||
|
void ReportKnownDesiredFile(const clang::FileEntry* included_file);
|
||||||
|
|
||||||
// This is used only in iwyu_preprocessor.cc. TODO(csilvers): revamp?
|
// This is used only in iwyu_preprocessor.cc. TODO(csilvers): revamp?
|
||||||
const set<const clang::FileEntry*>& direct_includes_as_fileentries() const {
|
const set<const clang::FileEntry*>& direct_includes_as_fileentries() const {
|
||||||
return direct_includes_as_fileentries_;
|
return direct_includes_as_fileentries_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called when all macros in the file are processed.
|
||||||
|
void HandlePreprocessingDone();
|
||||||
|
|
||||||
// Resolve and pending analysis that needs to occur between AST traversal
|
// Resolve and pending analysis that needs to occur between AST traversal
|
||||||
// and CalculateAndReportIwyuViolations.
|
// and CalculateAndReportIwyuViolations.
|
||||||
void ResolvePendingAnalysis();
|
void ResolvePendingAnalysis();
|
||||||
|
@ -345,9 +353,13 @@ class IwyuFileInfo {
|
||||||
set<const clang::FileEntry*> direct_includes_as_fileentries_;
|
set<const clang::FileEntry*> direct_includes_as_fileentries_;
|
||||||
set<const clang::NamedDecl*> direct_forward_declares_;
|
set<const clang::NamedDecl*> direct_forward_declares_;
|
||||||
|
|
||||||
// Holds any files included with the "IWYU pragma: keep" comment.
|
// Holds files forced to be kept. For example, files included with the
|
||||||
|
// "IWYU pragma: keep" comment and x-macros.
|
||||||
set<const clang::FileEntry*> kept_includes_;
|
set<const clang::FileEntry*> kept_includes_;
|
||||||
|
|
||||||
|
// Holds files using macros defined in this file.
|
||||||
|
set<const clang::FileEntry*> macro_users_;
|
||||||
|
|
||||||
// What we will recommend the #includes to be.
|
// What we will recommend the #includes to be.
|
||||||
set<string> desired_includes_;
|
set<string> desired_includes_;
|
||||||
bool desired_includes_have_been_calculated_;
|
bool desired_includes_have_been_calculated_;
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include <cstddef> // for size_t
|
#include <cstddef> // for size_t
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
#include <string> // for string, basic_string, etc
|
#include <string> // for string, basic_string, etc
|
||||||
#include <utility> // for pair, make_pair
|
#include <utility> // for pair, make_pair
|
||||||
|
|
||||||
|
@ -47,13 +49,6 @@ using std::string;
|
||||||
|
|
||||||
namespace SrcMgr = clang::SrcMgr;
|
namespace SrcMgr = clang::SrcMgr;
|
||||||
|
|
||||||
// Prints to errs() if the verbose level is at a high enough level to
|
|
||||||
// print symbols that occur in the given file. This is only valid
|
|
||||||
// when used inside a class, such as IwyuAstConsumer, that defines a
|
|
||||||
// method named ShouldPrintSymbolFromFile().
|
|
||||||
#define ERRSYM(file_entry) \
|
|
||||||
if (!ShouldPrintSymbolFromFile(file_entry)) ; else ::llvm::errs()
|
|
||||||
|
|
||||||
namespace include_what_you_use {
|
namespace include_what_you_use {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -393,7 +388,7 @@ void IwyuPreprocessorInfo::MaybeProtectInclude(
|
||||||
if (IncludeLineHasText(includer_loc, "// IWYU pragma: keep") ||
|
if (IncludeLineHasText(includer_loc, "// IWYU pragma: keep") ||
|
||||||
IncludeLineHasText(includer_loc, "/* IWYU pragma: keep")) {
|
IncludeLineHasText(includer_loc, "/* IWYU pragma: keep")) {
|
||||||
protect_reason = "pragma_keep";
|
protect_reason = "pragma_keep";
|
||||||
FileInfoFor(includer)->ReportPragmaKeep(includee);
|
FileInfoFor(includer)->ReportKnownDesiredFile(includee);
|
||||||
|
|
||||||
} else if (IncludeLineHasText(includer_loc, "// IWYU pragma: export") ||
|
} else if (IncludeLineHasText(includer_loc, "// IWYU pragma: export") ||
|
||||||
IncludeLineHasText(includer_loc, "/* IWYU pragma: export") ||
|
IncludeLineHasText(includer_loc, "/* IWYU pragma: export") ||
|
||||||
|
@ -640,13 +635,14 @@ void IwyuPreprocessorInfo::InclusionDirective(
|
||||||
void IwyuPreprocessorInfo::FileChanged(SourceLocation loc,
|
void IwyuPreprocessorInfo::FileChanged(SourceLocation loc,
|
||||||
FileChangeReason reason,
|
FileChangeReason reason,
|
||||||
SrcMgr::CharacteristicKind file_type,
|
SrcMgr::CharacteristicKind file_type,
|
||||||
FileID exiting_from) {
|
FileID exiting_from_id) {
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case EnterFile:
|
case EnterFile:
|
||||||
FileChanged_EnterFile(loc);
|
FileChanged_EnterFile(loc);
|
||||||
return;
|
return;
|
||||||
case ExitFile:
|
case ExitFile:
|
||||||
FileChanged_ExitToFile(loc, exiting_from);
|
FileChanged_ExitToFile(
|
||||||
|
loc, GlobalSourceManager()->getFileEntryForID(exiting_from_id));
|
||||||
return;
|
return;
|
||||||
case RenameFile:
|
case RenameFile:
|
||||||
FileChanged_RenameFile(loc);
|
FileChanged_RenameFile(loc);
|
||||||
|
@ -737,12 +733,10 @@ void IwyuPreprocessorInfo::FileChanged_EnterFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when done with an #included file and returning to the parent file.
|
// Called when done with an #included file and returning to the parent file.
|
||||||
void IwyuPreprocessorInfo::FileChanged_ExitToFile(SourceLocation include_loc,
|
void IwyuPreprocessorInfo::FileChanged_ExitToFile(
|
||||||
FileID exiting_from_id) {
|
SourceLocation include_loc, const FileEntry* exiting_from) {
|
||||||
ERRSYM(GetFileEntry(include_loc)) << "[ Exiting to ] "
|
ERRSYM(GetFileEntry(include_loc)) << "[ Exiting to ] "
|
||||||
<< PrintableLoc(include_loc) << "\n";
|
<< PrintableLoc(include_loc) << "\n";
|
||||||
const FileEntry* exiting_from = GlobalSourceManager()->getFileEntryForID(
|
|
||||||
exiting_from_id);
|
|
||||||
if (HasOpenBeginExports(exiting_from)) {
|
if (HasOpenBeginExports(exiting_from)) {
|
||||||
Warn(begin_exports_location_stack_.top(),
|
Warn(begin_exports_location_stack_.top(),
|
||||||
"begin_exports without an end_exports");
|
"begin_exports without an end_exports");
|
||||||
|
@ -767,27 +761,29 @@ void IwyuPreprocessorInfo::FileChanged_SystemHeaderPragma(SourceLocation loc) {
|
||||||
void IwyuPreprocessorInfo::ReportMacroUse(const string& name,
|
void IwyuPreprocessorInfo::ReportMacroUse(const string& name,
|
||||||
SourceLocation usage_location,
|
SourceLocation usage_location,
|
||||||
SourceLocation dfn_location) {
|
SourceLocation dfn_location) {
|
||||||
const FileEntry* used_in = GetFileEntry(usage_location);
|
|
||||||
|
|
||||||
if (!ShouldReportIWYUViolationsFor(used_in))
|
|
||||||
return; // ignore symbols used outside foo.{h,cc}
|
|
||||||
// Don't report macro uses that aren't actually in a file somewhere.
|
// Don't report macro uses that aren't actually in a file somewhere.
|
||||||
if (!dfn_location.isValid() || GetFilePath(dfn_location) == "<built-in>")
|
if (!dfn_location.isValid() || GetFilePath(dfn_location) == "<built-in>")
|
||||||
return;
|
return;
|
||||||
|
const FileEntry* used_in = GetFileEntry(usage_location);
|
||||||
|
if (ShouldReportIWYUViolationsFor(used_in)) {
|
||||||
|
// ignore symbols used outside foo.{h,cc}
|
||||||
|
|
||||||
// TODO(csilvers): this isn't really a symbol use -- it may be ok
|
// TODO(csilvers): this isn't really a symbol use -- it may be ok
|
||||||
// that the symbol isn't defined. For instance:
|
// that the symbol isn't defined. For instance:
|
||||||
// foo.h: #define FOO
|
// foo.h: #define FOO
|
||||||
// bar.h: #ifdef FOO ... #else ... #endif
|
// bar.h: #ifdef FOO ... #else ... #endif
|
||||||
// baz.cc: #include "foo.h"
|
// baz.cc: #include "foo.h"
|
||||||
// #include "bar.h"
|
// #include "bar.h"
|
||||||
// bang.cc: #include "bar.h"
|
// bang.cc: #include "bar.h"
|
||||||
// We don't want to say that bar.h 'uses' FOO, and thus needs to
|
// We don't want to say that bar.h 'uses' FOO, and thus needs to
|
||||||
// #include foo.h -- adding that #include could break bang.cc.
|
// #include foo.h -- adding that #include could break bang.cc.
|
||||||
// I think the solution is to have a 'soft' use -- don't remove it
|
// I think the solution is to have a 'soft' use -- don't remove it
|
||||||
// if it's there, but don't add it if it's not. Or something.
|
// if it's there, but don't add it if it's not. Or something.
|
||||||
GetFromFileInfoMap(used_in)->ReportMacroUse(usage_location, dfn_location,
|
GetFromFileInfoMap(used_in)->ReportMacroUse(usage_location, dfn_location,
|
||||||
name);
|
name);
|
||||||
|
}
|
||||||
|
const FileEntry* defined_in = GetFileEntry(dfn_location);
|
||||||
|
GetFromFileInfoMap(defined_in)->ReportDefinedMacroUse(used_in);
|
||||||
}
|
}
|
||||||
|
|
||||||
// As above, but get the definition location from macros_definition_loc_.
|
// As above, but get the definition location from macros_definition_loc_.
|
||||||
|
@ -934,6 +930,9 @@ void IwyuPreprocessorInfo::PopulateTransitiveIncludeMap() {
|
||||||
// The public API.
|
// The public API.
|
||||||
|
|
||||||
void IwyuPreprocessorInfo::HandlePreprocessingDone() {
|
void IwyuPreprocessorInfo::HandlePreprocessingDone() {
|
||||||
|
CHECK_(main_file_ && "Main file should be present");
|
||||||
|
FileChanged_ExitToFile(SourceLocation(), main_file_);
|
||||||
|
|
||||||
// In some cases, macros can refer to macros in files that are
|
// In some cases, macros can refer to macros in files that are
|
||||||
// defined later in other files. In those cases, we can't
|
// defined later in other files. In those cases, we can't
|
||||||
// do an iwyu check until all header files have been read.
|
// do an iwyu check until all header files have been read.
|
||||||
|
@ -945,6 +944,9 @@ void IwyuPreprocessorInfo::HandlePreprocessingDone() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other post-processing steps.
|
// Other post-processing steps.
|
||||||
|
for (auto& file_info_map_entry : iwyu_file_info_map_) {
|
||||||
|
file_info_map_entry.second.HandlePreprocessingDone();
|
||||||
|
}
|
||||||
MutableGlobalIncludePicker()->FinalizeAddedIncludes();
|
MutableGlobalIncludePicker()->FinalizeAddedIncludes();
|
||||||
ProtectReexportIncludes(&iwyu_file_info_map_);
|
ProtectReexportIncludes(&iwyu_file_info_map_);
|
||||||
PopulateIntendsToProvideMap();
|
PopulateIntendsToProvideMap();
|
||||||
|
|
|
@ -208,7 +208,7 @@ class IwyuPreprocessorInfo : public clang::PPCallbacks,
|
||||||
// FileChanged is actually a multi-plexer for 4 different callbacks.
|
// FileChanged is actually a multi-plexer for 4 different callbacks.
|
||||||
void FileChanged_EnterFile(clang::SourceLocation file_beginning);
|
void FileChanged_EnterFile(clang::SourceLocation file_beginning);
|
||||||
void FileChanged_ExitToFile(clang::SourceLocation include_loc,
|
void FileChanged_ExitToFile(clang::SourceLocation include_loc,
|
||||||
clang::FileID exiting_from);
|
const clang::FileEntry* exiting_from);
|
||||||
void FileChanged_RenameFile(clang::SourceLocation new_file);
|
void FileChanged_RenameFile(clang::SourceLocation new_file);
|
||||||
void FileChanged_SystemHeaderPragma(clang::SourceLocation loc);
|
void FileChanged_SystemHeaderPragma(clang::SourceLocation loc);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,13 @@ bool ShouldPrintSymbolFromFile(const clang::FileEntry* file);
|
||||||
if (!::include_what_you_use::ShouldPrint( \
|
if (!::include_what_you_use::ShouldPrint( \
|
||||||
verbose_level)) ; else ::llvm::errs()
|
verbose_level)) ; else ::llvm::errs()
|
||||||
|
|
||||||
|
// Prints to errs() if the verbose level is at a high enough level to
|
||||||
|
// print symbols that occur in the given file. This is only valid
|
||||||
|
// when used inside a class, such as IwyuAstConsumer, that defines a
|
||||||
|
// method named ShouldPrintSymbolFromFile().
|
||||||
|
#define ERRSYM(file_entry) \
|
||||||
|
if (!ShouldPrintSymbolFromFile(file_entry)) ; else ::llvm::errs()
|
||||||
|
|
||||||
} // namespace include_what_you_use
|
} // namespace include_what_you_use
|
||||||
|
|
||||||
#endif // INCLUDE_WHAT_YOU_USE_IWYU_VERRS_H_
|
#endif // INCLUDE_WHAT_YOU_USE_IWYU_VERRS_H_
|
||||||
|
|
|
@ -98,6 +98,8 @@ class OneIwyuTest(unittest.TestCase):
|
||||||
'deleted_implicit.cc' : ['-std=c++11'],
|
'deleted_implicit.cc' : ['-std=c++11'],
|
||||||
'lambda_fwd_decl.cc': ['-std=c++11'],
|
'lambda_fwd_decl.cc': ['-std=c++11'],
|
||||||
'lateparsed_template.cc': ['-fdelayed-template-parsing'],
|
'lateparsed_template.cc': ['-fdelayed-template-parsing'],
|
||||||
|
'macro_defined_by_includer.cc': [
|
||||||
|
'-std=c++11', '-DCOMMAND_LINE_TYPE=double'],
|
||||||
'ms_inline_asm.cc': ['-fms-extensions'],
|
'ms_inline_asm.cc': ['-fms-extensions'],
|
||||||
'prefix_header_attribution.cc': [self.Include('prefix_header_attribution-d1.h')],
|
'prefix_header_attribution.cc': [self.Include('prefix_header_attribution-d1.h')],
|
||||||
'prefix_header_includes_add.cc': prefix_headers,
|
'prefix_header_includes_add.cc': prefix_headers,
|
||||||
|
@ -140,6 +142,7 @@ class OneIwyuTest(unittest.TestCase):
|
||||||
'iwyu_stricter_than_cpp.cc': ['.'],
|
'iwyu_stricter_than_cpp.cc': ['.'],
|
||||||
'keep_mapping.cc': ['.'],
|
'keep_mapping.cc': ['.'],
|
||||||
'lateparsed_template.cc': ['.'],
|
'lateparsed_template.cc': ['.'],
|
||||||
|
'macro_defined_by_includer.cc': ['.'],
|
||||||
'macro_location.cc': ['.'],
|
'macro_location.cc': ['.'],
|
||||||
'member_expr.cc': ['.'],
|
'member_expr.cc': ['.'],
|
||||||
'multiple_include_paths.cc': ['.'],
|
'multiple_include_paths.cc': ['.'],
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
//===--- macro_defined_by_includer-d1.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Header file to provide extra level of inclusion indirection.
|
||||||
|
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-i1.h"
|
|
@ -0,0 +1,15 @@
|
||||||
|
//===--- macro_defined_by_includer-d2.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Tests case when file using macro is included from file defining macro but
|
||||||
|
// the macro user is first encountered as include in another file.
|
||||||
|
|
||||||
|
#define DIRECT_INCLUDE_GUARD_2
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-i2.h"
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-g2.h"
|
|
@ -0,0 +1,14 @@
|
||||||
|
//===--- macro_defined_by_includer-d3.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Tests nested guarded includes. Covers the case when "public" mapping for
|
||||||
|
// some private include can be in fact private.
|
||||||
|
|
||||||
|
#define DIRECT_INCLUDE_GUARD_3
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-g3.h"
|
|
@ -0,0 +1,12 @@
|
||||||
|
//===--- macro_defined_by_includer-d4.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Header file to provide extra level of inclusion indirection.
|
||||||
|
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-i3.h"
|
|
@ -0,0 +1,14 @@
|
||||||
|
//===--- macro_defined_by_includer-g1.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef DIRECT_INCLUDE_GUARD_1
|
||||||
|
#error Do not include directly
|
||||||
|
#else
|
||||||
|
class GuardedInclude1 {};
|
||||||
|
#endif
|
|
@ -0,0 +1,19 @@
|
||||||
|
//===--- macro_defined_by_includer-g2.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef INCLUDE_WHAT_YOU_USE_TESTS_CXX_MACRO_DEFINED_BY_INCLUDER_G2_H_
|
||||||
|
#define INCLUDE_WHAT_YOU_USE_TESTS_CXX_MACRO_DEFINED_BY_INCLUDER_G2_H_
|
||||||
|
|
||||||
|
#ifndef DIRECT_INCLUDE_GUARD_2
|
||||||
|
#error Do not include directly
|
||||||
|
#else
|
||||||
|
class GuardedInclude2 {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // INCLUDE_WHAT_YOU_USE_TESTS_CXX_MACRO_DEFINED_BY_INCLUDER_G2_H_
|
|
@ -0,0 +1,17 @@
|
||||||
|
//===--- macro_defined_by_includer-g3.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#define DIRECT_INCLUDE_GUARD_4
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-g4.h"
|
||||||
|
|
||||||
|
#ifndef DIRECT_INCLUDE_GUARD_3
|
||||||
|
#error Do not include directly
|
||||||
|
#else
|
||||||
|
class GuardedInclude3 {};
|
||||||
|
#endif
|
|
@ -0,0 +1,14 @@
|
||||||
|
//===--- macro_defined_by_includer-g4.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef DIRECT_INCLUDE_GUARD_4
|
||||||
|
#error Do not include directly
|
||||||
|
#else
|
||||||
|
class GuardedInclude4 {};
|
||||||
|
#endif
|
|
@ -0,0 +1,14 @@
|
||||||
|
//===--- macro_defined_by_includer-g5.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef DIRECT_INCLUDE_GUARD_5
|
||||||
|
#error Do not include directly
|
||||||
|
#else
|
||||||
|
class GuardedInclude5 {};
|
||||||
|
#endif
|
|
@ -0,0 +1,11 @@
|
||||||
|
//===--- macro_defined_by_includer-i1.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#define DIRECT_INCLUDE_GUARD_1
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-g1.h"
|
|
@ -0,0 +1,10 @@
|
||||||
|
//===--- macro_defined_by_includer-i2.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-g2.h"
|
|
@ -0,0 +1,14 @@
|
||||||
|
//===--- macro_defined_by_includer-i3.h - test input file for iwyu --------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Header file to test including file that uses x-macro.
|
||||||
|
|
||||||
|
#define TYPE char
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-xmacro.h"
|
||||||
|
#undef TYPE
|
|
@ -0,0 +1,12 @@
|
||||||
|
//===--- macro_defined_by_includer-xmacro.h - test input file for iwyu ----===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// File containing X-macro templates.
|
||||||
|
|
||||||
|
void f(TYPE const t) {}
|
|
@ -0,0 +1,89 @@
|
||||||
|
//===--- macro_defined_by_includer.cc - test input file for iwyu ----------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Tests a few macro patterns:
|
||||||
|
// * internal headers guarded by macro defined in designated header;
|
||||||
|
// * x-macros.
|
||||||
|
//
|
||||||
|
// Usually you include a file with a macro and use that macro. But in these
|
||||||
|
// macro patterns macro is defined by includer and includee doesn't know where
|
||||||
|
// the macro comes from.
|
||||||
|
|
||||||
|
|
||||||
|
// Test guarded includes.
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-d1.h"
|
||||||
|
// IWYU: GuardedInclude1 is...*macro_defined_by_includer-i1.h
|
||||||
|
GuardedInclude1 g1;
|
||||||
|
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-d2.h"
|
||||||
|
GuardedInclude2 g2;
|
||||||
|
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-d3.h"
|
||||||
|
GuardedInclude3 g3;
|
||||||
|
GuardedInclude4 g4;
|
||||||
|
|
||||||
|
#define DIRECT_INCLUDE_GUARD_5
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-g5.h"
|
||||||
|
GuardedInclude5 g5;
|
||||||
|
|
||||||
|
|
||||||
|
// Test x-macros.
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-d4.h"
|
||||||
|
|
||||||
|
#define TYPE int
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-xmacro.h"
|
||||||
|
#undef TYPE
|
||||||
|
|
||||||
|
// For x-macros we keep all includes even if its content isn't used.
|
||||||
|
#define TYPE double
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-xmacro.h"
|
||||||
|
#undef TYPE
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// IWYU: f is...*macro_defined_by_includer-i3.h
|
||||||
|
f(3);
|
||||||
|
// IWYU: f is...*macro_defined_by_includer-i3.h
|
||||||
|
f('a');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Test macro defined on command line. Make sure that detecting file defining
|
||||||
|
// macro works without actual file on disk.
|
||||||
|
COMMAND_LINE_TYPE x;
|
||||||
|
|
||||||
|
|
||||||
|
// Clang internal <limits.h> defines LLONG_MIN and #include_next system
|
||||||
|
// <limits.h> which on Mac OS X uses LLONG_MIN.
|
||||||
|
//
|
||||||
|
// Test that we don't create a mapping between those 2 <limits.h> and don't try
|
||||||
|
// to mark system <limits.h> as private.
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**** IWYU_SUMMARY
|
||||||
|
|
||||||
|
tests/cxx/macro_defined_by_includer.cc should add these lines:
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-i1.h"
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-i3.h"
|
||||||
|
|
||||||
|
tests/cxx/macro_defined_by_includer.cc should remove these lines:
|
||||||
|
- #include <limits.h> // lines XX-XX
|
||||||
|
- #include "tests/cxx/macro_defined_by_includer-d1.h" // lines XX-XX
|
||||||
|
- #include "tests/cxx/macro_defined_by_includer-d4.h" // lines XX-XX
|
||||||
|
|
||||||
|
The full include-list for tests/cxx/macro_defined_by_includer.cc:
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-d2.h" // for GuardedInclude2
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-d3.h" // for GuardedInclude3, GuardedInclude4
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-g5.h" // for GuardedInclude5
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-i1.h" // for GuardedInclude1
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-i3.h" // for f
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-xmacro.h" // lines XX-XX
|
||||||
|
#include "tests/cxx/macro_defined_by_includer-xmacro.h" // lines XX-XX
|
||||||
|
|
||||||
|
***** IWYU_SUMMARY */
|
Loading…
Reference in New Issue