From: Ben Langmuir Date: Mon, 5 May 2014 21:44:13 +0000 (+0000) Subject: Add -Wnon-modular-include* options X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=57973be024e1b0cb252ae43ddc05d4ce4203b1f1;p=clang Add -Wnon-modular-include* options Warn on non-modular includes in various contexts. -Wnon-modular-include -Wnon-modular-include-in-module -Wnon-modular-include-in-framework-module Where each group is a subgroup of those above it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208004 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index b1665f5373..a2cc7406ab 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -186,6 +186,12 @@ def IncompatiblePointerTypes [IncompatiblePointerTypesDiscardsQualifiers]>; def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">; def IncompleteModule : DiagGroup<"incomplete-module", [IncompleteUmbrella]>; +def NonModularIncludeInFrameworkModule + : DiagGroup<"non-modular-include-in-framework-module">; +def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module", + [NonModularIncludeInFrameworkModule]>; +def NonModularInclude : DiagGroup<"non-modular-include", + [NonModularIncludeInModule]>; 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 aef3c585a9..abd386fc36 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -620,6 +620,14 @@ def error_use_of_private_header_outside_module : Error< "use of private header from outside its module: '%0'">; def error_undeclared_use_of_module : Error< "module %0 does not depend on a module exporting '%1'">; +def warn_non_modular_include_in_framework_module : Warning< + "include of non-modular header inside framework module '%0'">, + InGroup, DefaultIgnore; +def warn_non_modular_include_in_module : Warning< + "include of non-modular header inside module '%0'">, + InGroup, DefaultIgnore; +def warn_non_modular_include : Warning< + "include of non-modular header">, InGroup, DefaultIgnore; def warn_header_guard : Warning< "%0 is used as a header guard here, followed by #define of a different macro">, diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index dbd9fd1c0c..74c83b26ea 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -195,6 +195,13 @@ private: KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File, SmallVectorImpl &IntermediateDirs); + /// \brief A convenience method to determine if \p File is (possibly nested) + /// in an umbrella directory. + bool isHeaderInUmbrellaDirs(const FileEntry *File) { + SmallVector IntermediateDirs; + return static_cast(findHeaderInUmbrellaDirs(File, IntermediateDirs)); + } + public: /// \brief Construct a new module map. /// diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 39c1121011..f89d91d056 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -230,56 +230,57 @@ static bool violatesPrivateInclude(Module *RequestingModule, RequestedModule->getTopLevelModule() != RequestingModule; } +static Module *getTopLevelOrNull(Module *M) { + return M ? M->getTopLevelModule() : nullptr; +} + void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, SourceLocation FilenameLoc, StringRef Filename, const FileEntry *File) { // No errors for indirect modules. This may be a bit of a problem for modules // with no source files. - if (RequestingModule != SourceModule) + if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) return; if (RequestingModule) resolveUses(RequestingModule, /*Complain=*/false); - HeadersMap::iterator Known = findKnownHeader(File); - if (Known == Headers.end()) { - if (LangOpts.ModulesStrictDeclUse) - Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module) - << RequestingModule->getFullModuleName() << Filename; - return; - } - + bool Excluded = false; Module *Private = NULL; Module *NotUsed = NULL; - for (SmallVectorImpl::iterator I = Known->second.begin(), - E = Known->second.end(); - I != E; ++I) { - // Excluded headers don't really belong to a module. - if (I->getRole() == ModuleMap::ExcludedHeader) - continue; - // If 'File' is part of 'RequestingModule' we can definitely include it. - if (I->getModule() == RequestingModule) - return; + HeadersMap::iterator Known = findKnownHeader(File); + if (Known != Headers.end()) { + for (const KnownHeader &Header : Known->second) { + // Excluded headers don't really belong to a module. + if (Header.getRole() == ModuleMap::ExcludedHeader) { + Excluded = true; + continue; + } - // Remember private headers for later printing of a diagnostic. - if (violatesPrivateInclude(RequestingModule, File, I->getRole(), - I->getModule())) { - Private = I->getModule(); - continue; - } + // If 'File' is part of 'RequestingModule' we can definitely include it. + if (Header.getModule() == RequestingModule) + return; - // If uses need to be specified explicitly, we are only allowed to return - // modules that are explicitly used by the requesting module. - if (RequestingModule && LangOpts.ModulesDeclUse && - !directlyUses(RequestingModule, I->getModule())) { - NotUsed = I->getModule(); - continue; - } + // Remember private headers for later printing of a diagnostic. + if (violatesPrivateInclude(RequestingModule, File, Header.getRole(), + Header.getModule())) { + Private = Header.getModule(); + continue; + } - // We have found a module that we can happily use. - return; + // If uses need to be specified explicitly, we are only allowed to return + // modules that are explicitly used by the requesting module. + if (RequestingModule && LangOpts.ModulesDeclUse && + !directlyUses(RequestingModule, Header.getModule())) { + NotUsed = Header.getModule(); + continue; + } + + // We have found a module that we can happily use. + return; + } } // We have found a header, but it is private. @@ -296,7 +297,22 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, return; } - // Headers for which we have not found a module are fine to include. + if (Excluded || isHeaderInUmbrellaDirs(File)) + return; + + // At this point, only non-modular includes remain. + + if (LangOpts.ModulesStrictDeclUse) { + Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module) + << RequestingModule->getFullModuleName() << Filename; + } else if (RequestingModule) { + diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? + diag::warn_non_modular_include_in_framework_module : + diag::warn_non_modular_include_in_module; + Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName(); + } else { + Diags.Report(FilenameLoc, diag::warn_non_modular_include); + } } ModuleMap::KnownHeader diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 57dc49536a..b1675bc043 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -611,22 +611,32 @@ const FileEntry *Preprocessor::LookupFile( // to one of the headers on the #include stack. Walk the list of the current // headers on the #include stack and pass them to HeaderInfo. if (IsFileLexer()) { - if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) + if ((CurFileEnt = SourceMgr.getFileEntryForID(CurPPLexer->getFileID()))) { if ((FE = HeaderInfo.LookupSubframeworkHeader(Filename, CurFileEnt, SearchPath, RelativePath, - SuggestedModule))) + SuggestedModule))) { + if (SuggestedModule && !LangOpts.AsmPreprocessor) + HeaderInfo.getModuleMap().diagnoseHeaderInclusion( + getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE); return FE; + } + } } for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) { IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1]; if (IsFileLexer(ISEntry)) { if ((CurFileEnt = - SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) + SourceMgr.getFileEntryForID(ISEntry.ThePPLexer->getFileID()))) { if ((FE = HeaderInfo.LookupSubframeworkHeader( Filename, CurFileEnt, SearchPath, RelativePath, - SuggestedModule))) + SuggestedModule))) { + if (SuggestedModule && !LangOpts.AsmPreprocessor) + HeaderInfo.getModuleMap().diagnoseHeaderInclusion( + getModuleForLocation(FilenameLoc), FilenameLoc, Filename, FE); return FE; + } + } } } diff --git a/test/Modules/Inputs/require-modular-includes/A.framework/Headers/A.h b/test/Modules/Inputs/require-modular-includes/A.framework/Headers/A.h new file mode 100644 index 0000000000..fad91bdbfd --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/A.framework/Headers/A.h @@ -0,0 +1 @@ +#include "B/B.h" diff --git a/test/Modules/Inputs/require-modular-includes/AnotherModule.h b/test/Modules/Inputs/require-modular-includes/AnotherModule.h new file mode 100644 index 0000000000..96913aa22a --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/AnotherModule.h @@ -0,0 +1 @@ +// AnotherModule.h diff --git a/test/Modules/Inputs/require-modular-includes/AnotherModuleExcluded.h b/test/Modules/Inputs/require-modular-includes/AnotherModuleExcluded.h new file mode 100644 index 0000000000..b539dd9ba9 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/AnotherModuleExcluded.h @@ -0,0 +1 @@ +// AnotherModuleExcluded.h diff --git a/test/Modules/Inputs/require-modular-includes/B.framework/Headers/B.h b/test/Modules/Inputs/require-modular-includes/B.framework/Headers/B.h new file mode 100644 index 0000000000..77d6ff1e5f --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/B.framework/Headers/B.h @@ -0,0 +1 @@ +#include "C.h" diff --git a/test/Modules/Inputs/require-modular-includes/C.h b/test/Modules/Inputs/require-modular-includes/C.h new file mode 100644 index 0000000000..a0121d46b4 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/C.h @@ -0,0 +1 @@ +// C.h diff --git a/test/Modules/Inputs/require-modular-includes/ExcludedFromAnotherModule.framework/Headers/ExcludedFromAnotherModule.h b/test/Modules/Inputs/require-modular-includes/ExcludedFromAnotherModule.framework/Headers/ExcludedFromAnotherModule.h new file mode 100644 index 0000000000..0c0ce7bb56 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/ExcludedFromAnotherModule.framework/Headers/ExcludedFromAnotherModule.h @@ -0,0 +1 @@ +#include "AnotherModuleExcluded.h" diff --git a/test/Modules/Inputs/require-modular-includes/FromAnotherModule.framework/Headers/FromAnotherModule.h b/test/Modules/Inputs/require-modular-includes/FromAnotherModule.framework/Headers/FromAnotherModule.h new file mode 100644 index 0000000000..1fe5c08ace --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromAnotherModule.framework/Headers/FromAnotherModule.h @@ -0,0 +1 @@ +#include "AnotherModule.h" diff --git a/test/Modules/Inputs/require-modular-includes/FromImportedModuleFail.framework/Headers/FromImportedModuleFail.h b/test/Modules/Inputs/require-modular-includes/FromImportedModuleFail.framework/Headers/FromImportedModuleFail.h new file mode 100644 index 0000000000..a80bcc6945 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromImportedModuleFail.framework/Headers/FromImportedModuleFail.h @@ -0,0 +1,2 @@ +// FromImportedModuleFail.h +#include "NotInModule.h" diff --git a/test/Modules/Inputs/require-modular-includes/FromImportedModuleOK.framework/Headers/FromImportedModuleOK.h b/test/Modules/Inputs/require-modular-includes/FromImportedModuleOK.framework/Headers/FromImportedModuleOK.h new file mode 100644 index 0000000000..3b2056c454 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromImportedModuleOK.framework/Headers/FromImportedModuleOK.h @@ -0,0 +1 @@ +#include "FromImportedModuleOK2.h" diff --git a/test/Modules/Inputs/require-modular-includes/FromImportedModuleOK.framework/Headers/FromImportedModuleOK2.h b/test/Modules/Inputs/require-modular-includes/FromImportedModuleOK.framework/Headers/FromImportedModuleOK2.h new file mode 100644 index 0000000000..775fd6e4d8 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromImportedModuleOK.framework/Headers/FromImportedModuleOK2.h @@ -0,0 +1 @@ +// FromImportedModuleOK2.h diff --git a/test/Modules/Inputs/require-modular-includes/FromImportedModuleOK.framework/Modules/module.modulemap b/test/Modules/Inputs/require-modular-includes/FromImportedModuleOK.framework/Modules/module.modulemap new file mode 100644 index 0000000000..26381110d2 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromImportedModuleOK.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +framework module FromImportedModuleOK { + header "FromImportedModuleOK.h" + header "FromImportedModuleOK2.h" +} diff --git a/test/Modules/Inputs/require-modular-includes/FromImportedSubModule.framework/Headers/Header.h b/test/Modules/Inputs/require-modular-includes/FromImportedSubModule.framework/Headers/Header.h new file mode 100644 index 0000000000..613cd9d681 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromImportedSubModule.framework/Headers/Header.h @@ -0,0 +1,2 @@ +// Header.h +#include "NotInModule.h" diff --git a/test/Modules/Inputs/require-modular-includes/FromImportedSubModule.framework/Modules/module.modulemap b/test/Modules/Inputs/require-modular-includes/FromImportedSubModule.framework/Modules/module.modulemap new file mode 100644 index 0000000000..c07efec72b --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromImportedSubModule.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module FromImportedSubModule { + module Sub { + header "Header.h" + } +} diff --git a/test/Modules/Inputs/require-modular-includes/FromNonModularSubframework.framework/Frameworks/Subframework.framework/Headers/Subframework.h b/test/Modules/Inputs/require-modular-includes/FromNonModularSubframework.framework/Frameworks/Subframework.framework/Headers/Subframework.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/Modules/Inputs/require-modular-includes/FromNonModularSubframework.framework/Headers/FromNonModularSubframework.h b/test/Modules/Inputs/require-modular-includes/FromNonModularSubframework.framework/Headers/FromNonModularSubframework.h new file mode 100644 index 0000000000..4680be4a37 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromNonModularSubframework.framework/Headers/FromNonModularSubframework.h @@ -0,0 +1 @@ +#include "Subframework/Subframework.h" diff --git a/test/Modules/Inputs/require-modular-includes/FromNonModularSubframework.framework/Modules/module.modulemap b/test/Modules/Inputs/require-modular-includes/FromNonModularSubframework.framework/Modules/module.modulemap new file mode 100644 index 0000000000..c308ea429b --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromNonModularSubframework.framework/Modules/module.modulemap @@ -0,0 +1,3 @@ +framework module FromNonModularSubframework { + header "FromNonModularSubframework.h" +} diff --git a/test/Modules/Inputs/require-modular-includes/FromSubframework.framework/Frameworks/Subframework.framework/Headers/Subframework.h b/test/Modules/Inputs/require-modular-includes/FromSubframework.framework/Frameworks/Subframework.framework/Headers/Subframework.h new file mode 100644 index 0000000000..c08fac0b55 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromSubframework.framework/Frameworks/Subframework.framework/Headers/Subframework.h @@ -0,0 +1 @@ +// Subframework.h diff --git a/test/Modules/Inputs/require-modular-includes/FromSubframework.framework/Headers/FromSubframework.h b/test/Modules/Inputs/require-modular-includes/FromSubframework.framework/Headers/FromSubframework.h new file mode 100644 index 0000000000..4680be4a37 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromSubframework.framework/Headers/FromSubframework.h @@ -0,0 +1 @@ +#include "Subframework/Subframework.h" diff --git a/test/Modules/Inputs/require-modular-includes/FromSubframework.framework/Modules/module.modulemap b/test/Modules/Inputs/require-modular-includes/FromSubframework.framework/Modules/module.modulemap new file mode 100644 index 0000000000..250f05ace0 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromSubframework.framework/Modules/module.modulemap @@ -0,0 +1,7 @@ +framework module FromSubframework { + umbrella header "FromSubframework.h" + + framework module Subframework { + umbrella header "Subframework.h" + } +} diff --git a/test/Modules/Inputs/require-modular-includes/FromUmbrella.framework/Headers/FromUmbrella.h b/test/Modules/Inputs/require-modular-includes/FromUmbrella.framework/Headers/FromUmbrella.h new file mode 100644 index 0000000000..f6f891f53f --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/FromUmbrella.framework/Headers/FromUmbrella.h @@ -0,0 +1,2 @@ +#include "umbrella/foo.h" +#include "umbrella/bar/bar.h" diff --git a/test/Modules/Inputs/require-modular-includes/IncludeExcluded.framework/Headers/Excluded.h b/test/Modules/Inputs/require-modular-includes/IncludeExcluded.framework/Headers/Excluded.h new file mode 100644 index 0000000000..f330e6c0ec --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/IncludeExcluded.framework/Headers/Excluded.h @@ -0,0 +1 @@ +// Excluded.h diff --git a/test/Modules/Inputs/require-modular-includes/IncludeExcluded.framework/Headers/IncludeExcluded.h b/test/Modules/Inputs/require-modular-includes/IncludeExcluded.framework/Headers/IncludeExcluded.h new file mode 100644 index 0000000000..f2ffdc327e --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/IncludeExcluded.framework/Headers/IncludeExcluded.h @@ -0,0 +1 @@ +#include "Excluded.h" diff --git a/test/Modules/Inputs/require-modular-includes/IncludeExcluded.framework/Modules/module.modulemap b/test/Modules/Inputs/require-modular-includes/IncludeExcluded.framework/Modules/module.modulemap new file mode 100644 index 0000000000..a1753539bd --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/IncludeExcluded.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +framework module IncludeExcluded { + header "IncludeExcluded.h" + exclude header "Excluded.h" +} diff --git a/test/Modules/Inputs/require-modular-includes/NotFramework.h b/test/Modules/Inputs/require-modular-includes/NotFramework.h new file mode 100644 index 0000000000..3afd8fc64a --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/NotFramework.h @@ -0,0 +1,2 @@ +// NotFramework.h +#import "NotInModule.h" diff --git a/test/Modules/Inputs/require-modular-includes/NotInModule.h b/test/Modules/Inputs/require-modular-includes/NotInModule.h new file mode 100644 index 0000000000..c2a626cab9 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/NotInModule.h @@ -0,0 +1 @@ +// NotInModule.h diff --git a/test/Modules/Inputs/require-modular-includes/module.modulemap b/test/Modules/Inputs/require-modular-includes/module.modulemap new file mode 100644 index 0000000000..0ac4d5b703 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/module.modulemap @@ -0,0 +1,12 @@ +module AnotherModule { + header "AnotherModule.h" + exclude header "AnotherModuleExcluded.h" +} +module Umbrella { + umbrella "umbrella" +} +module NotFramework { + header "NotFramework.h" +} + +framework module * { } diff --git a/test/Modules/Inputs/require-modular-includes/umbrella/bar/bar.h b/test/Modules/Inputs/require-modular-includes/umbrella/bar/bar.h new file mode 100644 index 0000000000..410aba2639 --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/umbrella/bar/bar.h @@ -0,0 +1 @@ +// bar.h diff --git a/test/Modules/Inputs/require-modular-includes/umbrella/foo.h b/test/Modules/Inputs/require-modular-includes/umbrella/foo.h new file mode 100644 index 0000000000..249664863b --- /dev/null +++ b/test/Modules/Inputs/require-modular-includes/umbrella/foo.h @@ -0,0 +1 @@ +// foo.h diff --git a/test/Modules/require-modular-includes.m b/test/Modules/require-modular-includes.m new file mode 100644 index 0000000000..55674319ff --- /dev/null +++ b/test/Modules/require-modular-includes.m @@ -0,0 +1,95 @@ +// RUN: rm -rf %t +// REQUIRES: shell + +// Including a header from the imported module +// RUN: echo '@import FromImportedModuleOK;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -Werror -fsyntax-only -x objective-c - + +// Including a non-modular header +// RUN: echo '@import FromImportedModuleFail;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -I %S/Inputs/require-modular-includes \ +// RUN: -fsyntax-only -x objective-c - 2>&1 | FileCheck %s + +// Including a header from a subframework +// RUN: echo '@import FromSubframework;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -Werror -fsyntax-only -x objective-c - + +// Including a header from a subframework (fail) +// RUN: echo '@import FromNonModularSubframework;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -I %S/Inputs/require-modular-includes \ +// RUN: -fsyntax-only -x objective-c - 2>&1 | FileCheck %s + +// Including a non-modular header from a submodule +// RUN: echo '@import FromImportedSubModule;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -I %S/Inputs/require-modular-includes \ +// RUN: -fsyntax-only -x objective-c - 2>&1 | FileCheck %s + +// Including a non-modular header (directly) with -fmodule-name set +// RUN: echo '#include "NotInModule.h"' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -I %S/Inputs/require-modular-includes \ +// RUN: -Werror -fmodule-name=A -fsyntax-only -x objective-c - + +// Including a non-modular header (directly) with -Wnon-modular-include +// RUN: echo '#include "NotInModule.h"' | \ +// RUN: %clang_cc1 -Wnon-modular-include -fmodules \ +// RUN: -fmodules-cache-path=%t -I %S/Inputs/require-modular-includes \ +// RUN: -fmodule-name=A -fsyntax-only -x objective-c - 2>&1 | FileCheck %s + +// Including an excluded header +// RUN: echo '@import IncludeExcluded;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -Werror -fsyntax-only -x objective-c - + +// Including a header from another module +// RUN: echo '@import FromAnotherModule;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -I %S/Inputs/require-modular-includes \ +// RUN: -Werror -fsyntax-only -x objective-c - + +// Including an excluded header from another module +// RUN: echo '@import ExcludedFromAnotherModule;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -I %S/Inputs/require-modular-includes \ +// RUN: -Werror -fsyntax-only -x objective-c - + +// Including a header from an umbrella directory +// RUN: echo '@import FromUmbrella;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -I %S/Inputs/require-modular-includes \ +// RUN: -Werror -fsyntax-only -x objective-c - + +// A includes B includes non-modular C +// RUN: echo '@import A;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -F %S/Inputs/require-modular-includes \ +// RUN: -I %S/Inputs/require-modular-includes \ +// RUN: -fsyntax-only -x objective-c - 2>&1 | FileCheck %s + +// Non-framework module (pass) +// RUN: echo '@import NotFramework;' | \ +// RUN: %clang_cc1 -Wnon-modular-include-in-framework-module -fmodules \ +// RUN: -fmodules-cache-path=%t -I %S/Inputs/require-modular-includes \ +// RUN: -Werror -fsyntax-only -x objective-c - + +// Non-framework module (fail) +// RUN: echo '@import NotFramework;' | \ +// RUN: not %clang_cc1 -Werror=non-modular-include -fmodules \ +// RUN: -fmodules-cache-path=%t -I %S/Inputs/require-modular-includes \ +// RUN: -fsyntax-only -x objective-c - 2>&1 | FileCheck %s + +// CHECK: include of non-modular header