diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 9f68f3bb89d6..fcc49b387034 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -287,6 +287,14 @@ const char *Preprocessor::getCurLexerEndPos() { return EndPos; } +static void collectAllSubModulesWithUmbrellaHeader( + const Module &Mod, SmallVectorImpl &SubMods) { + if (Mod.getUmbrellaHeader()) + SubMods.push_back(&Mod); + for (auto *M : Mod.submodules()) + collectAllSubModulesWithUmbrellaHeader(*M, SubMods); +} + void Preprocessor::diagnoseMissingHeaderInUmbrellaDir(const Module &Mod) { assert(Mod.getUmbrellaHeader() && "Module must use umbrella header"); SourceLocation StartLoc = @@ -507,10 +515,15 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { } // If we are building a module that has an umbrella header, make sure that - // each of the headers within the directory covered by the umbrella header - // was actually included by the umbrella header. - if (Module *Mod = getCurrentModule()) - diagnoseMissingHeaderInUmbrellaDir(*Mod); + // each of the headers within the directory, including all submodules, is + // covered by the umbrella header was actually included by the umbrella + // header. + if (Module *Mod = getCurrentModule()) { + llvm::SmallVector AllMods; + collectAllSubModulesWithUmbrellaHeader(*Mod, AllMods); + for (auto *M : AllMods) + diagnoseMissingHeaderInUmbrellaDir(*M); + } return true; } diff --git a/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/Bar.h b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/Bar.h new file mode 100644 index 000000000000..fb5da09bac6c --- /dev/null +++ b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/Bar.h @@ -0,0 +1 @@ +#define BAR_PUBLIC 1 diff --git a/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/FooPublic.h b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/FooPublic.h new file mode 100644 index 000000000000..cbbb44f42c71 --- /dev/null +++ b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/FooPublic.h @@ -0,0 +1 @@ +// FooPublic.h diff --git a/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.modulemap b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.modulemap new file mode 100644 index 000000000000..af67e657405a --- /dev/null +++ b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +framework module Foo { + umbrella header "FooPublic.h" + requires objc + export * +} diff --git a/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.private.modulemap b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.private.modulemap new file mode 100644 index 000000000000..f6d9dfdcab33 --- /dev/null +++ b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.private.modulemap @@ -0,0 +1,5 @@ +explicit module Foo.Private { + umbrella header "Foo.h" + requires objc + export * +} diff --git a/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Baz.h b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Baz.h new file mode 100644 index 000000000000..98064e08146d --- /dev/null +++ b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Baz.h @@ -0,0 +1 @@ +#define BAZ_PRIVATE 1 diff --git a/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Foo.h b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Foo.h new file mode 100644 index 000000000000..9381133344b1 --- /dev/null +++ b/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Foo.h @@ -0,0 +1 @@ +// Foo.h diff --git a/test/Modules/incomplete-umbrella.m b/test/Modules/incomplete-umbrella.m new file mode 100644 index 000000000000..8760b815718b --- /dev/null +++ b/test/Modules/incomplete-umbrella.m @@ -0,0 +1,15 @@ +// RUN: rm -rf %t +// RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F%S/Inputs/incomplete-umbrella -fsyntax-only %s 2>&1 | FileCheck %s + +#import +#import +#import +@import Foo.Private; + +// CHECK: warning: umbrella header for module 'Foo' does not include header 'Bar.h' +// CHECK: warning: umbrella header for module 'Foo.Private' does not include header 'Baz.h' +int foo() { + int a = BAR_PUBLIC; + int b = BAZ_PRIVATE; + return 0; +}