summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Lex/PPLexerChange.cpp21
-rw-r--r--clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/Bar.h1
-rw-r--r--clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/FooPublic.h1
-rw-r--r--clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.modulemap5
-rw-r--r--clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.private.modulemap5
-rw-r--r--clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Baz.h1
-rw-r--r--clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Foo.h1
-rw-r--r--clang/test/Modules/incomplete-umbrella.m15
8 files changed, 46 insertions, 4 deletions
diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp
index 9f68f3bb89d..fcc49b38703 100644
--- a/clang/lib/Lex/PPLexerChange.cpp
+++ b/clang/lib/Lex/PPLexerChange.cpp
@@ -287,6 +287,14 @@ const char *Preprocessor::getCurLexerEndPos() {
return EndPos;
}
+static void collectAllSubModulesWithUmbrellaHeader(
+ const Module &Mod, SmallVectorImpl<const Module *> &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<const Module *, 4> AllMods;
+ collectAllSubModulesWithUmbrellaHeader(*Mod, AllMods);
+ for (auto *M : AllMods)
+ diagnoseMissingHeaderInUmbrellaDir(*M);
+ }
return true;
}
diff --git a/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/Bar.h b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/Bar.h
new file mode 100644
index 00000000000..fb5da09bac6
--- /dev/null
+++ b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/Bar.h
@@ -0,0 +1 @@
+#define BAR_PUBLIC 1
diff --git a/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/FooPublic.h b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/FooPublic.h
new file mode 100644
index 00000000000..cbbb44f42c7
--- /dev/null
+++ b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Headers/FooPublic.h
@@ -0,0 +1 @@
+// FooPublic.h
diff --git a/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.modulemap b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.modulemap
new file mode 100644
index 00000000000..af67e657405
--- /dev/null
+++ b/clang/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/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.private.modulemap b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/Modules/module.private.modulemap
new file mode 100644
index 00000000000..f6d9dfdcab3
--- /dev/null
+++ b/clang/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/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Baz.h b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Baz.h
new file mode 100644
index 00000000000..98064e08146
--- /dev/null
+++ b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Baz.h
@@ -0,0 +1 @@
+#define BAZ_PRIVATE 1
diff --git a/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Foo.h b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Foo.h
new file mode 100644
index 00000000000..9381133344b
--- /dev/null
+++ b/clang/test/Modules/Inputs/incomplete-umbrella/Foo.framework/PrivateHeaders/Foo.h
@@ -0,0 +1 @@
+// Foo.h
diff --git a/clang/test/Modules/incomplete-umbrella.m b/clang/test/Modules/incomplete-umbrella.m
new file mode 100644
index 00000000000..8760b815718
--- /dev/null
+++ b/clang/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 <Foo/Foo.h>
+#import <Foo/Bar.h>
+#import <Foo/Baz.h>
+@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;
+}
OpenPOWER on IntegriCloud