diff --git a/iwyu_output.cc b/iwyu_output.cc index 7d57886..cea2281 100644 --- a/iwyu_output.cc +++ b/iwyu_output.cc @@ -598,6 +598,10 @@ void IwyuFileInfo::ReportMacroUse(clang::SourceLocation use_loc, 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, const string& 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()); } -void IwyuFileInfo::ReportPragmaKeep(const clang::FileEntry* included_file) { +void IwyuFileInfo::ReportKnownDesiredFile(const FileEntry* included_file) { kept_includes_.insert(included_file); } @@ -1887,6 +1891,41 @@ size_t PrintableDiffs(const string& filename, } // 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 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() { // 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 diff --git a/iwyu_output.h b/iwyu_output.h index a8191f8..9fdbf2f 100644 --- a/iwyu_output.h +++ b/iwyu_output.h @@ -235,10 +235,14 @@ class IwyuFileInfo { const string& symbol); // 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, clang::SourceLocation dfn_loc, 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. void ReportForwardDeclareUse(clang::SourceLocation use_loc, const clang::NamedDecl* decl, @@ -256,15 +260,19 @@ class IwyuFileInfo { void ReportIncludeFileUse(const clang::FileEntry* included_file, const string& quoted_include); - // This is used when we see an "IWYU pragma: keep" comment - // on an include line. - void ReportPragmaKeep(const clang::FileEntry* included_file); + // This is used when we see a file we want to keep not due to symbol-use + // reasons. For example, it can be #included with an "IWYU pragma: keep" + // 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? const set& direct_includes_as_fileentries() const { 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 // and CalculateAndReportIwyuViolations. void ResolvePendingAnalysis(); @@ -345,9 +353,13 @@ class IwyuFileInfo { set direct_includes_as_fileentries_; set 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 kept_includes_; + // Holds files using macros defined in this file. + set macro_users_; + // What we will recommend the #includes to be. set desired_includes_; bool desired_includes_have_been_calculated_; diff --git a/iwyu_preprocessor.cc b/iwyu_preprocessor.cc index 71e0b01..7cb6815 100644 --- a/iwyu_preprocessor.cc +++ b/iwyu_preprocessor.cc @@ -11,6 +11,8 @@ #include // for size_t #include +#include +#include #include // for string, basic_string, etc #include // for pair, make_pair @@ -47,13 +49,6 @@ using std::string; 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 { @@ -393,7 +388,7 @@ void IwyuPreprocessorInfo::MaybeProtectInclude( if (IncludeLineHasText(includer_loc, "// IWYU pragma: keep") || IncludeLineHasText(includer_loc, "/* IWYU pragma: keep")) { protect_reason = "pragma_keep"; - FileInfoFor(includer)->ReportPragmaKeep(includee); + FileInfoFor(includer)->ReportKnownDesiredFile(includee); } else if (IncludeLineHasText(includer_loc, "// IWYU pragma: export") || IncludeLineHasText(includer_loc, "/* IWYU pragma: export") || @@ -640,13 +635,14 @@ void IwyuPreprocessorInfo::InclusionDirective( void IwyuPreprocessorInfo::FileChanged(SourceLocation loc, FileChangeReason reason, SrcMgr::CharacteristicKind file_type, - FileID exiting_from) { + FileID exiting_from_id) { switch (reason) { case EnterFile: FileChanged_EnterFile(loc); return; case ExitFile: - FileChanged_ExitToFile(loc, exiting_from); + FileChanged_ExitToFile( + loc, GlobalSourceManager()->getFileEntryForID(exiting_from_id)); return; case RenameFile: FileChanged_RenameFile(loc); @@ -737,12 +733,10 @@ void IwyuPreprocessorInfo::FileChanged_EnterFile( } // Called when done with an #included file and returning to the parent file. -void IwyuPreprocessorInfo::FileChanged_ExitToFile(SourceLocation include_loc, - FileID exiting_from_id) { +void IwyuPreprocessorInfo::FileChanged_ExitToFile( + SourceLocation include_loc, const FileEntry* exiting_from) { ERRSYM(GetFileEntry(include_loc)) << "[ Exiting to ] " << PrintableLoc(include_loc) << "\n"; - const FileEntry* exiting_from = GlobalSourceManager()->getFileEntryForID( - exiting_from_id); if (HasOpenBeginExports(exiting_from)) { Warn(begin_exports_location_stack_.top(), "begin_exports without an end_exports"); @@ -767,27 +761,29 @@ void IwyuPreprocessorInfo::FileChanged_SystemHeaderPragma(SourceLocation loc) { void IwyuPreprocessorInfo::ReportMacroUse(const string& name, SourceLocation usage_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. if (!dfn_location.isValid() || GetFilePath(dfn_location) == "") 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 - // that the symbol isn't defined. For instance: - // foo.h: #define FOO - // bar.h: #ifdef FOO ... #else ... #endif - // baz.cc: #include "foo.h" - // #include "bar.h" - // bang.cc: #include "bar.h" - // 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. - // 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. - GetFromFileInfoMap(used_in)->ReportMacroUse(usage_location, dfn_location, - name); + // TODO(csilvers): this isn't really a symbol use -- it may be ok + // that the symbol isn't defined. For instance: + // foo.h: #define FOO + // bar.h: #ifdef FOO ... #else ... #endif + // baz.cc: #include "foo.h" + // #include "bar.h" + // bang.cc: #include "bar.h" + // 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. + // 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. + GetFromFileInfoMap(used_in)->ReportMacroUse(usage_location, dfn_location, + 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_. @@ -934,6 +930,9 @@ void IwyuPreprocessorInfo::PopulateTransitiveIncludeMap() { // The public API. 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 // defined later in other files. In those cases, we can't // do an iwyu check until all header files have been read. @@ -945,6 +944,9 @@ void IwyuPreprocessorInfo::HandlePreprocessingDone() { } // Other post-processing steps. + for (auto& file_info_map_entry : iwyu_file_info_map_) { + file_info_map_entry.second.HandlePreprocessingDone(); + } MutableGlobalIncludePicker()->FinalizeAddedIncludes(); ProtectReexportIncludes(&iwyu_file_info_map_); PopulateIntendsToProvideMap(); diff --git a/iwyu_preprocessor.h b/iwyu_preprocessor.h index 89e5d91..a0aaa2e 100644 --- a/iwyu_preprocessor.h +++ b/iwyu_preprocessor.h @@ -208,7 +208,7 @@ class IwyuPreprocessorInfo : public clang::PPCallbacks, // FileChanged is actually a multi-plexer for 4 different callbacks. void FileChanged_EnterFile(clang::SourceLocation file_beginning); 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_SystemHeaderPragma(clang::SourceLocation loc); diff --git a/iwyu_verrs.h b/iwyu_verrs.h index 7455f0e..27e575a 100644 --- a/iwyu_verrs.h +++ b/iwyu_verrs.h @@ -40,6 +40,13 @@ bool ShouldPrintSymbolFromFile(const clang::FileEntry* file); if (!::include_what_you_use::ShouldPrint( \ 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 #endif // INCLUDE_WHAT_YOU_USE_IWYU_VERRS_H_ diff --git a/run_iwyu_tests.py b/run_iwyu_tests.py index 1b69e2b..a4501c4 100755 --- a/run_iwyu_tests.py +++ b/run_iwyu_tests.py @@ -98,6 +98,8 @@ class OneIwyuTest(unittest.TestCase): 'deleted_implicit.cc' : ['-std=c++11'], 'lambda_fwd_decl.cc': ['-std=c++11'], 'lateparsed_template.cc': ['-fdelayed-template-parsing'], + 'macro_defined_by_includer.cc': [ + '-std=c++11', '-DCOMMAND_LINE_TYPE=double'], 'ms_inline_asm.cc': ['-fms-extensions'], 'prefix_header_attribution.cc': [self.Include('prefix_header_attribution-d1.h')], 'prefix_header_includes_add.cc': prefix_headers, @@ -140,6 +142,7 @@ class OneIwyuTest(unittest.TestCase): 'iwyu_stricter_than_cpp.cc': ['.'], 'keep_mapping.cc': ['.'], 'lateparsed_template.cc': ['.'], + 'macro_defined_by_includer.cc': ['.'], 'macro_location.cc': ['.'], 'member_expr.cc': ['.'], 'multiple_include_paths.cc': ['.'], diff --git a/tests/cxx/macro_defined_by_includer-d1.h b/tests/cxx/macro_defined_by_includer-d1.h new file mode 100644 index 0000000..b6f1ba0 --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-d1.h @@ -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" diff --git a/tests/cxx/macro_defined_by_includer-d2.h b/tests/cxx/macro_defined_by_includer-d2.h new file mode 100644 index 0000000..ca8cb53 --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-d2.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" diff --git a/tests/cxx/macro_defined_by_includer-d3.h b/tests/cxx/macro_defined_by_includer-d3.h new file mode 100644 index 0000000..595c0cf --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-d3.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" diff --git a/tests/cxx/macro_defined_by_includer-d4.h b/tests/cxx/macro_defined_by_includer-d4.h new file mode 100644 index 0000000..5eab76a --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-d4.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" diff --git a/tests/cxx/macro_defined_by_includer-g1.h b/tests/cxx/macro_defined_by_includer-g1.h new file mode 100644 index 0000000..1e613cf --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-g1.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 diff --git a/tests/cxx/macro_defined_by_includer-g2.h b/tests/cxx/macro_defined_by_includer-g2.h new file mode 100644 index 0000000..b0d4c09 --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-g2.h @@ -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_ diff --git a/tests/cxx/macro_defined_by_includer-g3.h b/tests/cxx/macro_defined_by_includer-g3.h new file mode 100644 index 0000000..64eecbf --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-g3.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 diff --git a/tests/cxx/macro_defined_by_includer-g4.h b/tests/cxx/macro_defined_by_includer-g4.h new file mode 100644 index 0000000..b1e8b8d --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-g4.h @@ -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 diff --git a/tests/cxx/macro_defined_by_includer-g5.h b/tests/cxx/macro_defined_by_includer-g5.h new file mode 100644 index 0000000..742142f --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-g5.h @@ -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 diff --git a/tests/cxx/macro_defined_by_includer-i1.h b/tests/cxx/macro_defined_by_includer-i1.h new file mode 100644 index 0000000..d359441 --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-i1.h @@ -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" diff --git a/tests/cxx/macro_defined_by_includer-i2.h b/tests/cxx/macro_defined_by_includer-i2.h new file mode 100644 index 0000000..60b4a2b --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-i2.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" diff --git a/tests/cxx/macro_defined_by_includer-i3.h b/tests/cxx/macro_defined_by_includer-i3.h new file mode 100644 index 0000000..b7c9b41 --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-i3.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 diff --git a/tests/cxx/macro_defined_by_includer-xmacro.h b/tests/cxx/macro_defined_by_includer-xmacro.h new file mode 100644 index 0000000..e96a8b8 --- /dev/null +++ b/tests/cxx/macro_defined_by_includer-xmacro.h @@ -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) {} diff --git a/tests/cxx/macro_defined_by_includer.cc b/tests/cxx/macro_defined_by_includer.cc new file mode 100644 index 0000000..91ac4b9 --- /dev/null +++ b/tests/cxx/macro_defined_by_includer.cc @@ -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 defines LLONG_MIN and #include_next system +// which on Mac OS X uses LLONG_MIN. +// +// Test that we don't create a mapping between those 2 and don't try +// to mark system as private. +#include + + +/**** 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 // 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 */