From 58ea48dc1dd970f131207e00ae7ece159d1a08ed Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 20 May 2013 13:49:41 +0000 Subject: [PATCH] Add -Wincomplete-module, which detects when a header is included from a module but isn't itself part of a module. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182263 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 1 + include/clang/Basic/DiagnosticLexKinds.td | 5 +++- lib/Lex/PPLexerChange.cpp | 30 +++++++++++++++++++- test/Modules/Inputs/incomplete_mod.h | 1 + test/Modules/Inputs/incomplete_mod_missing.h | 2 ++ test/Modules/Inputs/module.map | 4 +++ test/Modules/incomplete-module.m | 5 ++++ 7 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 test/Modules/Inputs/incomplete_mod.h create mode 100644 test/Modules/Inputs/incomplete_mod_missing.h create mode 100644 test/Modules/incomplete-module.m diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 605e6cc7d9..e56cfda056 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -149,6 +149,7 @@ def IncompatiblePointerTypes : DiagGroup<"incompatible-pointer-types", [IncompatiblePointerTypesDiscardsQualifiers]>; def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">; +def IncompleteModule : DiagGroup<"incomplete-module", [IncompleteUmbrella]>; def InvalidNoreturn : DiagGroup<"invalid-noreturn">; def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">; def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 2c16000d33..6d4008c5e7 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -579,7 +579,10 @@ def warn_auto_module_import : Warning< "import of module '%1'">, InGroup, DefaultIgnore; def warn_uncovered_module_header : Warning< "umbrella header for module '%0' does not include header '%1'">, - InGroup; + InGroup, DefaultIgnore; +def warn_forgotten_module_header : Warning< + "header '%0' is included in module '%1' but not listed in module map">, + InGroup, DefaultIgnore; def err_expected_id_building_module : Error< "expected a module name in '__building_module' expression">; diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index a22d67a6ed..deec5a8766 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -401,8 +401,36 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { } } } + + // Check whether there are any headers that were included, but not + // mentioned at all in the module map. Such headers + SourceLocation StartLoc + = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); + if (getDiagnostics().getDiagnosticLevel(diag::warn_forgotten_module_header, + StartLoc) + != DiagnosticsEngine::Ignored) { + ModuleMap &ModMap = getHeaderSearchInfo().getModuleMap(); + for (unsigned I = 0, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { + // We only care about file entries. + const SrcMgr::SLocEntry &Entry = SourceMgr.getLocalSLocEntry(I); + if (!Entry.isFile()) + continue; + + // Dig out the actual file. + const FileEntry *File = Entry.getFile().getContentCache()->OrigEntry; + if (!File) + continue; + + // If it's not part of a module and not unknown, complain. + if (!ModMap.findModuleForHeader(File) && + !ModMap.isHeaderInUnavailableModule(File)) { + Diag(StartLoc, diag::warn_forgotten_module_header) + << File->getName() << Mod->getFullModuleName(); + } + } + } } - + return true; } diff --git a/test/Modules/Inputs/incomplete_mod.h b/test/Modules/Inputs/incomplete_mod.h new file mode 100644 index 0000000000..f08be72441 --- /dev/null +++ b/test/Modules/Inputs/incomplete_mod.h @@ -0,0 +1 @@ +#include "incomplete_mod_missing.h" diff --git a/test/Modules/Inputs/incomplete_mod_missing.h b/test/Modules/Inputs/incomplete_mod_missing.h new file mode 100644 index 0000000000..ffc85d5e73 --- /dev/null +++ b/test/Modules/Inputs/incomplete_mod_missing.h @@ -0,0 +1,2 @@ +extern int *missing; + diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index d20521f9c7..249700a494 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -209,3 +209,7 @@ module linkage_merge { } } + +module incomplete_mod { + header "incomplete_mod.h" +} diff --git a/test/Modules/incomplete-module.m b/test/Modules/incomplete-module.m new file mode 100644 index 0000000000..8edaea983c --- /dev/null +++ b/test/Modules/incomplete-module.m @@ -0,0 +1,5 @@ +@import incomplete_mod; + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules-cache-path=%t -Wincomplete-module -fmodules -I %S/Inputs %s 2>&1 | FileCheck %s +// CHECK: {{warning: header '.*incomplete_mod_missing.h' is included in module 'incomplete_mod' but not listed in module map}} -- 2.40.0