aboutsummaryrefslogtreecommitdiff
path: root/test/Modules
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
commit676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch)
tree02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /test/Modules
parentc7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff)
Notes
Diffstat (limited to 'test/Modules')
-rw-r--r--test/Modules/ExtDebugInfo.cpp4
-rw-r--r--test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing1.h1
-rw-r--r--test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing2.h1
-rw-r--r--test/Modules/Inputs/lsv-debuginfo/A/ADT.h45
-rw-r--r--test/Modules/Inputs/lsv-debuginfo/B/B.h14
-rw-r--r--test/Modules/Inputs/lsv-debuginfo/C/C.h13
-rw-r--r--test/Modules/Inputs/lsv-debuginfo/module.modulemap9
-rw-r--r--test/Modules/Inputs/no-module-map/a.h4
-rw-r--r--test/Modules/Inputs/no-module-map/b.h5
-rw-r--r--test/Modules/Inputs/odr_hash-Unresolved/class.h1
-rw-r--r--test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/h1.h1
-rw-r--r--test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/module.map5
-rw-r--r--test/Modules/Inputs/unavailable-local-visibility/a.h4
-rw-r--r--test/Modules/Inputs/unavailable-local-visibility/b.h13
-rw-r--r--test/Modules/Inputs/unavailable-local-visibility/module.modulemap9
-rw-r--r--test/Modules/Inputs/unavailable-local-visibility/x.h4
-rw-r--r--test/Modules/autolink.m4
-rw-r--r--test/Modules/crash-vfs-headermaps.m1
-rw-r--r--test/Modules/crash-vfs-include-pch.m1
-rw-r--r--test/Modules/crash-vfs-ivfsoverlay.m1
-rw-r--r--test/Modules/crash-vfs-path-emptydir-entries.m2
-rw-r--r--test/Modules/crash-vfs-path-symlink-component.m2
-rw-r--r--test/Modules/crash-vfs-path-symlink-topheader.m2
-rw-r--r--test/Modules/crash-vfs-path-traversal.m2
-rw-r--r--test/Modules/crash-vfs-relative-incdir.m1
-rw-r--r--test/Modules/crash-vfs-relative-overlay.m2
-rw-r--r--test/Modules/crash-vfs-run-reproducer.m1
-rw-r--r--test/Modules/crash-vfs-umbrella-frameworks.m2
-rw-r--r--test/Modules/cxx-templates.cpp2
-rw-r--r--test/Modules/double-quotes.m3
-rw-r--r--test/Modules/exception-spec.cpp36
-rw-r--r--test/Modules/friend-definition.cpp2
-rwxr-xr-xtest/Modules/lsv-debuginfo.cpp39
-rw-r--r--test/Modules/merge-deduced-return.cpp6
-rw-r--r--test/Modules/merge-lambdas.cpp5
-rw-r--r--test/Modules/merge-template-pattern-visibility-2.cpp34
-rw-r--r--test/Modules/merge-template-pattern-visibility-3.cpp34
-rw-r--r--test/Modules/mismatch-diagnostics.cpp22
-rw-r--r--test/Modules/module-debuginfo-prefix.m25
-rw-r--r--test/Modules/module_file_info.m3
-rw-r--r--test/Modules/no-module-map.cpp48
-rw-r--r--test/Modules/odr_hash-Friend.cpp10
-rw-r--r--test/Modules/odr_hash-blocks.cpp4
-rw-r--r--test/Modules/odr_hash-gnu.cpp130
-rw-r--r--test/Modules/odr_hash-vector.cpp128
-rw-r--r--test/Modules/odr_hash.cl80
-rw-r--r--test/Modules/odr_hash.cpp584
-rw-r--r--test/Modules/odr_hash.mm299
-rw-r--r--test/Modules/prune.m3
-rw-r--r--test/Modules/relative-dep-gen.cpp6
-rw-r--r--test/Modules/strict-decluse-headers.cpp17
-rw-r--r--test/Modules/subdirectory-module-maps-working-dir.m13
-rw-r--r--test/Modules/submodules-merge-defs.cpp2
-rw-r--r--test/Modules/target-platform-features.m79
-rw-r--r--test/Modules/templates.mm8
-rw-r--r--test/Modules/unavailable-local-visibility.test2
56 files changed, 1728 insertions, 50 deletions
diff --git a/test/Modules/ExtDebugInfo.cpp b/test/Modules/ExtDebugInfo.cpp
index c57f1f034eb2..592612b9a5db 100644
--- a/test/Modules/ExtDebugInfo.cpp
+++ b/test/Modules/ExtDebugInfo.cpp
@@ -83,11 +83,11 @@ void foo() {
// CHECK: ![[NS]] = !DINamespace(name: "DebugCXX", scope: ![[MOD:[0-9]+]])
// CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugCXX
-// This type is anchored in the module by an explicit template instantiation.
+// This type is not anchored in the module by an explicit template instantiation.
// CHECK: !DICompositeType(tag: DW_TAG_class_type,
// CHECK-SAME: name: "Template<long, DebugCXX::traits<long> >",
// CHECK-SAME: scope: ![[NS]],
-// CHECK-SAME: flags: DIFlagFwdDecl,
+// CHECK-SAME: elements:
// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE")
// This type is anchored in the module by an explicit template instantiation.
diff --git a/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing1.h b/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing1.h
new file mode 100644
index 000000000000..96212a03a113
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing1.h
@@ -0,0 +1 @@
+#include "Thing2.h"
diff --git a/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing2.h b/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing2.h
new file mode 100644
index 000000000000..7d1fe26edb09
--- /dev/null
+++ b/test/Modules/Inputs/double-quotes/NotAFramework/Headers/Headers/Thing2.h
@@ -0,0 +1 @@
+// Empty file!
diff --git a/test/Modules/Inputs/lsv-debuginfo/A/ADT.h b/test/Modules/Inputs/lsv-debuginfo/A/ADT.h
new file mode 100644
index 000000000000..f48d4f7820a8
--- /dev/null
+++ b/test/Modules/Inputs/lsv-debuginfo/A/ADT.h
@@ -0,0 +1,45 @@
+#ifndef ADT
+#define ADT
+
+#ifdef WITH_NAMESPACE
+namespace llvm {
+#endif
+template <unsigned Alignment, unsigned Size>
+struct AlignedCharArray {
+ alignas(Alignment) char buffer[Size];
+};
+
+template <typename T1>
+class AlignerImpl {
+ T1 t1;
+};
+
+template <typename T1>
+union SizerImpl {
+ char arr1[sizeof(T1)];
+};
+
+template <typename T1>
+struct AlignedCharArrayUnion
+ : AlignedCharArray<alignof(AlignerImpl<T1>), sizeof(SizerImpl<T1>)> {};
+
+template <typename T, unsigned N>
+struct SmallVectorStorage {
+ AlignedCharArrayUnion<T> InlineElts[N];
+};
+template <typename T, unsigned N>
+class SmallVector : SmallVectorStorage<T, N> {};
+
+template <typename T>
+struct OptionalStorage {
+ AlignedCharArrayUnion<T> storage;
+};
+template <typename T>
+class Optional {
+ OptionalStorage<T> Storage;
+};
+
+#ifdef WITH_NAMESPACE
+} // namespace llvm
+#endif
+#endif
diff --git a/test/Modules/Inputs/lsv-debuginfo/B/B.h b/test/Modules/Inputs/lsv-debuginfo/B/B.h
new file mode 100644
index 000000000000..c00bc3cddbf5
--- /dev/null
+++ b/test/Modules/Inputs/lsv-debuginfo/B/B.h
@@ -0,0 +1,14 @@
+#ifndef B_H
+#define B_H
+#include <A/ADT.h>
+#include <C/C.h>
+
+namespace llvm {
+struct S {
+ unsigned a, b, c, d;
+};
+class C {
+ Optional<S> S;
+};
+}
+#endif
diff --git a/test/Modules/Inputs/lsv-debuginfo/C/C.h b/test/Modules/Inputs/lsv-debuginfo/C/C.h
new file mode 100644
index 000000000000..52c6e4dbac94
--- /dev/null
+++ b/test/Modules/Inputs/lsv-debuginfo/C/C.h
@@ -0,0 +1,13 @@
+#ifndef C_H
+#define C_H
+#include <A/ADT.h>
+
+namespace llvm {
+class D {
+ struct Q {
+ unsigned a, b, c, d;
+ };
+ SmallVector<Q, 4> q;
+};
+} // namespace llvm
+#endif
diff --git a/test/Modules/Inputs/lsv-debuginfo/module.modulemap b/test/Modules/Inputs/lsv-debuginfo/module.modulemap
new file mode 100644
index 000000000000..5bb044908dc7
--- /dev/null
+++ b/test/Modules/Inputs/lsv-debuginfo/module.modulemap
@@ -0,0 +1,9 @@
+module A {
+ umbrella "A" module * { export * }
+}
+module B {
+ umbrella "B" module * { export * }
+}
+module C {
+ umbrella "C" module * { export * }
+}
diff --git a/test/Modules/Inputs/no-module-map/a.h b/test/Modules/Inputs/no-module-map/a.h
new file mode 100644
index 000000000000..546714f4ca3e
--- /dev/null
+++ b/test/Modules/Inputs/no-module-map/a.h
@@ -0,0 +1,4 @@
+#ifndef A_H
+#define A_H
+void a();
+#endif
diff --git a/test/Modules/Inputs/no-module-map/b.h b/test/Modules/Inputs/no-module-map/b.h
new file mode 100644
index 000000000000..d3fbc8b3ad59
--- /dev/null
+++ b/test/Modules/Inputs/no-module-map/b.h
@@ -0,0 +1,5 @@
+#ifndef B_H
+#define B_H
+#include "a.h"
+void b();
+#endif
diff --git a/test/Modules/Inputs/odr_hash-Unresolved/class.h b/test/Modules/Inputs/odr_hash-Unresolved/class.h
index fe3a7116f9bf..8a3c9f941f7e 100644
--- a/test/Modules/Inputs/odr_hash-Unresolved/class.h
+++ b/test/Modules/Inputs/odr_hash-Unresolved/class.h
@@ -6,6 +6,7 @@ class S {
void run() {
int x;
A::Check(&Field, 1);
+ A::Check(&Field, 1);
}
};
#endif
diff --git a/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/h1.h b/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/h1.h
new file mode 100644
index 000000000000..c362dd03f048
--- /dev/null
+++ b/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/h1.h
@@ -0,0 +1 @@
+int bar();
diff --git a/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/module.map b/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/module.map
new file mode 100644
index 000000000000..dc51f5d03aca
--- /dev/null
+++ b/test/Modules/Inputs/subdirectory-module-maps-working-dir/subdir_module/module.map
@@ -0,0 +1,5 @@
+module ModuleInSubdir {
+header "h1.h"
+ export *
+}
+
diff --git a/test/Modules/Inputs/unavailable-local-visibility/a.h b/test/Modules/Inputs/unavailable-local-visibility/a.h
new file mode 100644
index 000000000000..865bb65f4d28
--- /dev/null
+++ b/test/Modules/Inputs/unavailable-local-visibility/a.h
@@ -0,0 +1,4 @@
+#ifndef A_H
+#define A_H
+#include "x.h"
+#endif
diff --git a/test/Modules/Inputs/unavailable-local-visibility/b.h b/test/Modules/Inputs/unavailable-local-visibility/b.h
new file mode 100644
index 000000000000..71360e38b7b1
--- /dev/null
+++ b/test/Modules/Inputs/unavailable-local-visibility/b.h
@@ -0,0 +1,13 @@
+#ifndef B_H
+#define B_H
+#include "a.h"
+
+#ifndef A_H
+#error where is a?
+#endif
+
+#ifndef X_H
+#error where is x?
+#endif
+X f();
+#endif
diff --git a/test/Modules/Inputs/unavailable-local-visibility/module.modulemap b/test/Modules/Inputs/unavailable-local-visibility/module.modulemap
new file mode 100644
index 000000000000..8da3d3c1ab0e
--- /dev/null
+++ b/test/Modules/Inputs/unavailable-local-visibility/module.modulemap
@@ -0,0 +1,9 @@
+module M {
+ module a { header "a.h" export * }
+ module b { header "b.h" export * }
+ module doesnotexist { header "doesnotexist.h" }
+}
+module X {
+ header "x.h"
+ export *
+}
diff --git a/test/Modules/Inputs/unavailable-local-visibility/x.h b/test/Modules/Inputs/unavailable-local-visibility/x.h
new file mode 100644
index 000000000000..0498c5d2aabc
--- /dev/null
+++ b/test/Modules/Inputs/unavailable-local-visibility/x.h
@@ -0,0 +1,4 @@
+#ifndef X_H
+#define X_H
+struct X {};
+#endif
diff --git a/test/Modules/autolink.m b/test/Modules/autolink.m
index 6aee0e11b120..f15472692dd9 100644
--- a/test/Modules/autolink.m
+++ b/test/Modules/autolink.m
@@ -37,9 +37,9 @@ int use_autolink_sub3() {
// NOTE: "autolink_sub" is intentionally not linked.
// CHECK: !llvm.linker.options = !{![[AUTOLINK_PCH:[0-9]+]], ![[AUTOLINK_FRAMEWORK:[0-9]+]], ![[AUTOLINK:[0-9]+]], ![[DEPENDSONMODULE:[0-9]+]], ![[MODULE:[0-9]+]], ![[NOUMBRELLA:[0-9]+]]}
-// CHECK: ![[AUTOLINK_PCH]] = !{!"{{(\\01|-l|/DEFAULTLIB:)}}autolink_from_pch{{(\.lib)?}}"}
+// CHECK: ![[AUTOLINK_PCH]] = !{!"{{(\\01|-l|/DEFAULTLIB:|lib", !")}}autolink_from_pch{{(\.lib)?}}"}
// CHECK: ![[AUTOLINK_FRAMEWORK]] = !{!"-framework", !"autolink_framework"}
-// CHECK: ![[AUTOLINK]] = !{!"{{(\\01|-l|/DEFAULTLIB:)}}autolink{{(\.lib)?}}"}
+// CHECK: ![[AUTOLINK]] = !{!"{{(\\01|-l|/DEFAULTLIB:|lib", !")}}autolink{{(\.lib)?}}"}
// CHECK: ![[DEPENDSONMODULE]] = !{!"-framework", !"DependsOnModule"}
// CHECK: ![[MODULE]] = !{!"-framework", !"Module"}
// CHECK: ![[NOUMBRELLA]] = !{!"-framework", !"NoUmbrella"}
diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m
index 118537ba2a4f..f4c101cd0c6d 100644
--- a/test/Modules/crash-vfs-headermaps.m
+++ b/test/Modules/crash-vfs-headermaps.m
@@ -32,7 +32,6 @@
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/Foo.framework/Headers",
// CHECKYAML-NEXT: 'contents': [
diff --git a/test/Modules/crash-vfs-include-pch.m b/test/Modules/crash-vfs-include-pch.m
index 78a8e149a41b..f4ae00e3bb59 100644
--- a/test/Modules/crash-vfs-include-pch.m
+++ b/test/Modules/crash-vfs-include-pch.m
@@ -33,7 +33,6 @@ void g() { double x = DBL_MAX; }
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/out",
// CHECKYAML-NEXT: 'contents': [
diff --git a/test/Modules/crash-vfs-ivfsoverlay.m b/test/Modules/crash-vfs-ivfsoverlay.m
index 85aaeaef67a5..3cb0f1d0321d 100644
--- a/test/Modules/crash-vfs-ivfsoverlay.m
+++ b/test/Modules/crash-vfs-ivfsoverlay.m
@@ -36,7 +36,6 @@
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/example"
// CHECKYAML: 'contents': [
diff --git a/test/Modules/crash-vfs-path-emptydir-entries.m b/test/Modules/crash-vfs-path-emptydir-entries.m
index a50ea869f476..0c7286d248dc 100644
--- a/test/Modules/crash-vfs-path-emptydir-entries.m
+++ b/test/Modules/crash-vfs-path-emptydir-entries.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// Test clang can collect symbolic link headers used in modules.
// crash reproducer if there's a symbolic link header file used in a module.
diff --git a/test/Modules/crash-vfs-path-symlink-component.m b/test/Modules/crash-vfs-path-symlink-component.m
index 565a64fb5c23..b868625aa6a4 100644
--- a/test/Modules/crash-vfs-path-symlink-component.m
+++ b/test/Modules/crash-vfs-path-symlink-component.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// Test that clang is capable of collecting the right header files in the
// crash reproducer if there's a symbolic link component in the path.
diff --git a/test/Modules/crash-vfs-path-symlink-topheader.m b/test/Modules/crash-vfs-path-symlink-topheader.m
index fea1f01c02ae..6582243d62c9 100644
--- a/test/Modules/crash-vfs-path-symlink-topheader.m
+++ b/test/Modules/crash-vfs-path-symlink-topheader.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// Test clang can collect symbolic link headers used in modules.
// crash reproducer if there's a symbolic link header file used in a module.
diff --git a/test/Modules/crash-vfs-path-traversal.m b/test/Modules/crash-vfs-path-traversal.m
index cd12cadcf18e..b924d81d0467 100644
--- a/test/Modules/crash-vfs-path-traversal.m
+++ b/test/Modules/crash-vfs-path-traversal.m
@@ -3,7 +3,7 @@
// FIXME: Canonicalizing paths to remove relative traversal components
// currenty fails a unittest on windows and is disable by default.
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t
diff --git a/test/Modules/crash-vfs-relative-incdir.m b/test/Modules/crash-vfs-relative-incdir.m
index ed02de8d7e1e..d019c01e2f0f 100644
--- a/test/Modules/crash-vfs-relative-incdir.m
+++ b/test/Modules/crash-vfs-relative-incdir.m
@@ -36,7 +36,6 @@
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/Inputs/crash-recovery/usr/include",
// CHECKYAML-NEXT: 'contents': [
diff --git a/test/Modules/crash-vfs-relative-overlay.m b/test/Modules/crash-vfs-relative-overlay.m
index e55f4c8f272e..9eeed011fc78 100644
--- a/test/Modules/crash-vfs-relative-overlay.m
+++ b/test/Modules/crash-vfs-relative-overlay.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t
diff --git a/test/Modules/crash-vfs-run-reproducer.m b/test/Modules/crash-vfs-run-reproducer.m
index eba56c53f6fa..d15b52d40b97 100644
--- a/test/Modules/crash-vfs-run-reproducer.m
+++ b/test/Modules/crash-vfs-run-reproducer.m
@@ -36,7 +36,6 @@
// CHECKYAML: 'case-sensitive':
// CHECKYAML-NEXT: 'use-external-names': 'false',
// CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false'
// CHECKYAML: 'type': 'directory'
// CHECKYAML: 'name': "/[[PATH:.*]]/Inputs/crash-recovery/usr/include",
// CHECKYAML-NEXT: 'contents': [
diff --git a/test/Modules/crash-vfs-umbrella-frameworks.m b/test/Modules/crash-vfs-umbrella-frameworks.m
index a18acf576ea3..e311c608549a 100644
--- a/test/Modules/crash-vfs-umbrella-frameworks.m
+++ b/test/Modules/crash-vfs-umbrella-frameworks.m
@@ -1,7 +1,7 @@
// REQUIRES: crash-recovery, shell
// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it?
-// XFAIL: mingw32
+// XFAIL: windows-gnu
// RUN: rm -rf %t
// RUN: mkdir -p %t/i %t/m %t
diff --git a/test/Modules/cxx-templates.cpp b/test/Modules/cxx-templates.cpp
index 25f8a9992585..c085eb5f676c 100644
--- a/test/Modules/cxx-templates.cpp
+++ b/test/Modules/cxx-templates.cpp
@@ -199,6 +199,8 @@ namespace hidden_specializations {
cls<char*> uk4; // expected-error 1+{{partial specialization of 'cls<T *>' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}}
cls<void>::nested_cls_t<int> unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}}
+ // expected-error@cxx-templates-unimported.h:29 {{explicit specialization of 'nested_cls_t' must be imported}}
+ // expected-note@-2 {{in evaluation of exception specification}}
cls<void>::nested_cls_t<char> unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}}
// For enums, uses that would trigger instantiations of definitions are not
diff --git a/test/Modules/double-quotes.m b/test/Modules/double-quotes.m
index a21f12fa5e5a..8eec36574762 100644
--- a/test/Modules/double-quotes.m
+++ b/test/Modules/double-quotes.m
@@ -32,6 +32,9 @@
#import "A.h"
#import <Z/Z.h>
+// Make sure we correctly handle paths that resemble frameworks, but aren't.
+#import "NotAFramework/Headers/Headers/Thing1.h"
+
int bar() { return foo(); }
// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:1{{double-quoted include "A0.h" in framework header, expected angle-bracketed instead}}
diff --git a/test/Modules/exception-spec.cpp b/test/Modules/exception-spec.cpp
new file mode 100644
index 000000000000..083cd950f7c5
--- /dev/null
+++ b/test/Modules/exception-spec.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -x c++ -std=c++17 -fmodules -fmodules-local-submodule-visibility -fmodules-cache-path=%t %s -verify
+
+// expected-no-diagnostics
+
+#pragma clang module build PR38627
+module PR38627 {}
+#pragma clang module contents
+#pragma clang module begin PR38627
+namespace PR38627 {
+struct X {
+ virtual ~X() {}
+ struct C {
+ friend X::~X();
+ } c;
+};
+}
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module import PR38627
+
+namespace PR38627 {
+struct Y {
+ virtual ~Y() {}
+ struct C {
+ friend Y::~Y();
+ } c;
+};
+static_assert(noexcept(X().~X()));
+static_assert(noexcept(Y().~Y()));
+
+struct A { virtual ~A() = default; };
+struct B : public A, public X {
+ virtual ~B() override = default;
+};
+} // PR38627
diff --git a/test/Modules/friend-definition.cpp b/test/Modules/friend-definition.cpp
index 8588cbd9c6f4..32329d0e3e1c 100644
--- a/test/Modules/friend-definition.cpp
+++ b/test/Modules/friend-definition.cpp
@@ -7,6 +7,7 @@ module A {}
#pragma clang module begin A
template<typename T> struct A {
friend A operator+(const A&, const A&) { return {}; }
+ template<typename T2> friend void func_1(const A&, const T2 &) {}
};
#pragma clang module end
#pragma clang module endbuild
@@ -36,4 +37,5 @@ inline void g() { A<int> a; }
void h() {
A<int> a;
a + a;
+ func_1(a, 0);
}
diff --git a/test/Modules/lsv-debuginfo.cpp b/test/Modules/lsv-debuginfo.cpp
new file mode 100755
index 000000000000..30d3c2583fbd
--- /dev/null
+++ b/test/Modules/lsv-debuginfo.cpp
@@ -0,0 +1,39 @@
+// Test C++ -gmodules debug info in the PCMs with local submodule visibility.
+// REQUIRES: asserts
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 \
+// RUN: -fmodules-local-submodule-visibility %s \
+// RUN: -dwarf-ext-refs -fmodule-format=obj -debug-info-kind=standalone \
+// RUN: -dwarf-version=4 -fmodules -fimplicit-module-maps \
+// RUN: -fmodules-cache-path="%t" -o %t.ll -I%S/Inputs/lsv-debuginfo \
+// RUN: -mllvm -debug-only=pchcontainer &>%t-mod.ll
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++14 \
+// RUN: -fmodules-local-submodule-visibility %s \
+// RUN: -dwarf-ext-refs -fmodule-format=obj -debug-info-kind=standalone \
+// RUN: -dwarf-version=4 -fmodules -fimplicit-module-maps \
+// RUN: -fmodules-cache-path="%t" -o %t.ll -I%S/Inputs/lsv-debuginfo \
+// RUN: -DWITH_NAMESPACE \
+// RUN: -mllvm -debug-only=pchcontainer &>%t-mod.ll
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// ADT
+// CHECK: @__clang_ast =
+
+// B
+// CHECK: @__clang_ast =
+
+// This type isn't anchored anywhere, expect a full definition.
+// CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4, 16>",
+// CHECK-SAME: elements:
+
+// C
+// CHECK: @__clang_ast =
+
+// Here, too.
+// CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4, 16>",
+// CHECK-SAME: elements:
+
+#include <B/B.h>
diff --git a/test/Modules/merge-deduced-return.cpp b/test/Modules/merge-deduced-return.cpp
index 0a4de7b97554..71dc29b633b6 100644
--- a/test/Modules/merge-deduced-return.cpp
+++ b/test/Modules/merge-deduced-return.cpp
@@ -8,6 +8,8 @@ module A {}
#pragma clang module begin A
inline auto f() { struct X {}; return X(); }
inline auto a = f();
+auto g(int);
+template<typename T> auto h(T t) { return g(t); }
#pragma clang module end
#pragma clang module endbuild
@@ -17,12 +19,14 @@ module B {}
#pragma clang module begin B
inline auto f() { struct X {}; return X(); }
inline auto b = f();
+auto g(int) { return 0; }
#pragma clang module end
#pragma clang module endbuild
#ifdef LOCAL
inline auto f() { struct X {}; return X(); }
inline auto b = f();
+auto g(int) { return 0; }
#else
#pragma clang module import B
#endif
@@ -31,3 +35,5 @@ inline auto b = f();
using T = decltype(a);
using T = decltype(b);
+
+int test_g = h(0);
diff --git a/test/Modules/merge-lambdas.cpp b/test/Modules/merge-lambdas.cpp
index d14483aa3aa7..463a4c9b2fc6 100644
--- a/test/Modules/merge-lambdas.cpp
+++ b/test/Modules/merge-lambdas.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fmodules -verify %s
+// RUN: %clang_cc1 -fmodules -verify %s -emit-llvm-only
// expected-no-diagnostics
#pragma clang module build A
@@ -46,3 +46,6 @@ using U = decltype(y2);
using V = decltype(x3);
using V = decltype(y3);
+
+#pragma clang module import A
+void (*p)() = f<int>();
diff --git a/test/Modules/merge-template-pattern-visibility-2.cpp b/test/Modules/merge-template-pattern-visibility-2.cpp
new file mode 100644
index 000000000000..14577f146e94
--- /dev/null
+++ b/test/Modules/merge-template-pattern-visibility-2.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility %s -verify -Werror=undefined-inline
+
+#pragma clang module build A1
+module A1 { export * }
+#pragma clang module contents
+#pragma clang module begin A1
+template<typename T> class A {};
+template<typename T> inline bool f(const A<T>&) { return T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build A2
+module A2 { export * }
+#pragma clang module contents
+#pragma clang module begin A2
+#pragma clang module load A1
+template<typename T> class A {};
+template<typename T> inline bool f(const A<T>&) { return T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build A3
+module A3 { export * }
+#pragma clang module contents
+#pragma clang module begin A3
+template<typename T> class A {};
+template<typename T> inline bool f(const A<T>&) { return T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module load A3
+#pragma clang module import A2
+// expected-error@* {{cannot be used prior to}}
+bool y(A<int> o) { return f(o); } // expected-note {{instantiation of}}
diff --git a/test/Modules/merge-template-pattern-visibility-3.cpp b/test/Modules/merge-template-pattern-visibility-3.cpp
new file mode 100644
index 000000000000..9ac1b6699da3
--- /dev/null
+++ b/test/Modules/merge-template-pattern-visibility-3.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fmodules -emit-llvm-only %s -verify
+
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+template<typename T> void f(const T&) { T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+template<typename T> void f(const T&) { T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build C
+module C {}
+#pragma clang module contents
+#pragma clang module begin C
+#pragma clang module load B
+template<typename T> void f(const T&) { T::error; }
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module load A
+inline void f() {}
+void x() { f(); }
+
+#pragma clang module import C
+// expected-error@* {{cannot be used prior to}}
+void y(int n) { f(n); } // expected-note {{instantiation of}}
diff --git a/test/Modules/mismatch-diagnostics.cpp b/test/Modules/mismatch-diagnostics.cpp
new file mode 100644
index 000000000000..038e367e3973
--- /dev/null
+++ b/test/Modules/mismatch-diagnostics.cpp
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/prebuilt_modules
+//
+// RUN: %clang_cc1 -triple %itanium_abi_triple \
+// RUN: -fmodules-ts -fprebuilt-module-path=%t/prebuilt-modules \
+// RUN: -emit-module-interface -pthread -DBUILD_MODULE \
+// RUN: %s -o %t/prebuilt_modules/mismatching_module.pcm
+//
+// RUN: not %clang_cc1 -triple %itanium_abi_triple -fmodules-ts \
+// RUN: -fprebuilt-module-path=%t/prebuilt_modules -DCHECK_MISMATCH \
+// RUN: %s 2>&1 | FileCheck %s
+
+#ifdef BUILD_MODULE
+export module mismatching_module;
+#endif
+
+#ifdef CHECK_MISMATCH
+import mismatching_module;
+// CHECK: error: POSIX thread support was enabled in PCH file but is currently disabled
+// CHECK-NEXT: module file {{.*[/|\\\\]}}mismatching_module.pcm cannot be loaded due to a configuration mismatch with the current compilation
+#endif
+
diff --git a/test/Modules/module-debuginfo-prefix.m b/test/Modules/module-debuginfo-prefix.m
new file mode 100644
index 000000000000..da5d86abefd0
--- /dev/null
+++ b/test/Modules/module-debuginfo-prefix.m
@@ -0,0 +1,25 @@
+// REQUIRES: asserts
+
+// Modules:
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c -fmodules -fmodule-format=obj \
+// RUN: -fdebug-prefix-map=%S/Inputs=/OVERRIDE \
+// RUN: -fimplicit-module-maps -DMODULES -fmodules-cache-path=%t %s \
+// RUN: -I %S/Inputs -I %t -emit-llvm -o %t.ll \
+// RUN: -mllvm -debug-only=pchcontainer &>%t-mod.ll
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// PCH:
+// RUN: %clang_cc1 -x objective-c -emit-pch -fmodule-format=obj -I %S/Inputs \
+// RUN: -fdebug-prefix-map=%S/Inputs=/OVERRIDE \
+// RUN: -o %t.pch %S/Inputs/DebugObjC.h \
+// RUN: -mllvm -debug-only=pchcontainer &>%t-pch.ll
+// RUN: cat %t-pch.ll | FileCheck %s
+
+#ifdef MODULES
+@import DebugObjC;
+#endif
+
+// Dir should always be empty, but on Windows we can't recognize /var
+// as being an absolute path.
+// CHECK: !DIFile(filename: "/OVERRIDE/DebugObjC.h", directory: "{{()|(.*:.*)}}")
diff --git a/test/Modules/module_file_info.m b/test/Modules/module_file_info.m
index 05d401b9450a..0e3138935008 100644
--- a/test/Modules/module_file_info.m
+++ b/test/Modules/module_file_info.m
@@ -16,10 +16,11 @@
// CHECK: Module name: DependsOnModule
// CHECK: Module map file: {{.*}}DependsOnModule.framework{{[/\\]}}module.map
+// CHECK: Imports module 'Module': {{.*}}Module.pcm
// CHECK: Language options:
// CHECK: C99: Yes
-// CHECK: Objective-C 1: Yes
+// CHECK: Objective-C: Yes
// CHECK: modules extension to C: Yes
// CHECK: Module features:
// CHECK: myfeature
diff --git a/test/Modules/no-module-map.cpp b/test/Modules/no-module-map.cpp
new file mode 100644
index 000000000000..46ca38af7eed
--- /dev/null
+++ b/test/Modules/no-module-map.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -fmodules-ts -fmodule-name=ab -x c++-header %S/Inputs/no-module-map/a.h %S/Inputs/no-module-map/b.h -emit-header-module -o %t.pcm
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DA
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DB
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DA -DB
+
+// RUN: %clang_cc1 -E %t.pcm -o - | FileCheck %s
+// RUN: %clang_cc1 -frewrite-imports -E %t.pcm -o - | FileCheck %s
+// CHECK: # {{.*}}a.h
+// CHECK: # {{.*}}b.h
+
+#ifdef B
+// expected-no-diagnostics
+#endif
+
+#ifdef A
+#include "a.h"
+#endif
+
+#ifdef B
+#include "b.h"
+#endif
+
+#if defined(A) || defined(B)
+#ifndef A_H
+#error A_H should be defined
+#endif
+#else
+#ifdef A_H
+#error A_H should not be defined
+#endif
+// expected-error@+3 {{must be imported from}}
+// expected-note@* {{previous declaration}}
+#endif
+void use_a() { a(); }
+
+#if defined(B)
+#ifndef B_H
+#error B_H should be defined
+#endif
+#else
+#ifdef B_H
+#error B_H should not be defined
+#endif
+// expected-error@+3 {{must be imported from}}
+// expected-note@* {{previous declaration}}
+#endif
+void use_b() { b(); }
diff --git a/test/Modules/odr_hash-Friend.cpp b/test/Modules/odr_hash-Friend.cpp
index 8a2513e2f9cd..e55d9e8fd45a 100644
--- a/test/Modules/odr_hash-Friend.cpp
+++ b/test/Modules/odr_hash-Friend.cpp
@@ -9,7 +9,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST1 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST1
// RUN: %clang_cc1 \
// RUN: -I %S/Inputs/odr_hash-Friend \
@@ -17,7 +17,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST2 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST2
// RUN: %clang_cc1 \
// RUN: -I %S/Inputs/odr_hash-Friend \
@@ -25,7 +25,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST3
// RUN: %clang_cc1 \
// RUN: -I %S/Inputs/odr_hash-Friend \
@@ -33,7 +33,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST3
// RUN: %clang_cc1 \
// RUN: -I %S/Inputs/odr_hash-Friend \
@@ -41,7 +41,7 @@
// RUN: -fmodules \
// RUN: -fimplicit-module-maps \
// RUN: -fmodules-cache-path=%t/modules.cache \
-// RUN: -std=c++11 -x c++ %s -verify -DTEST3 -fcolor-diagnostics
+// RUN: -std=c++11 -x c++ %s -verify -DTEST3
#if defined(TEST1)
#include "Box.h"
diff --git a/test/Modules/odr_hash-blocks.cpp b/test/Modules/odr_hash-blocks.cpp
index 07dfa4ce2ac8..512c659f841e 100644
--- a/test/Modules/odr_hash-blocks.cpp
+++ b/test/Modules/odr_hash-blocks.cpp
@@ -41,7 +41,7 @@
#define ACCESS private:
#endif
-// TODO: S1, S2, and S3 should generate errors.
+// TODO: S1 and S2 should generate errors.
namespace Blocks {
#if defined(FIRST)
struct S1 {
@@ -77,6 +77,8 @@ struct S3 {
};
#else
S3 s3;
+// expected-error@first.h:* {{'Blocks::S3::run' from module 'FirstModule' is not present in definition of 'Blocks::S3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'run' does not match}}
#endif
#define DECLS \
diff --git a/test/Modules/odr_hash-gnu.cpp b/test/Modules/odr_hash-gnu.cpp
new file mode 100644
index 000000000000..7091bb559848
--- /dev/null
+++ b/test/Modules/odr_hash-gnu.cpp
@@ -0,0 +1,130 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=gnu++11 %t/Inputs/first.h
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=gnu++11 %t/Inputs/second.h
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=gnu++11
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+namespace Types {
+namespace TypeOfExpr {
+#if defined(FIRST)
+struct Invalid1 {
+ typeof(1 + 2) x;
+};
+double global;
+struct Invalid2 {
+ typeof(global) x;
+};
+struct Valid {
+ typeof(3) x;
+ typeof(x) y;
+ typeof(Valid*) self;
+};
+#elif defined(SECOND)
+struct Invalid1 {
+ typeof(3) x;
+};
+int global;
+struct Invalid2 {
+ typeof(global) x;
+};
+struct Valid {
+ typeof(3) x;
+ typeof(x) y;
+ typeof(Valid*) self;
+};
+#else
+Invalid1 i1;
+// expected-error@first.h:* {{'Types::TypeOfExpr::Invalid1' has different definitions in different modules; first difference is definition in module 'FirstModule' found field 'x' with type 'typeof (1 + 2)' (aka 'int')}}
+// expected-note@second.h:* {{but in 'SecondModule' found field 'x' with type 'typeof (3)' (aka 'int')}}
+Invalid2 i2;
+// expected-error@second.h:* {{'Types::TypeOfExpr::Invalid2::x' from module 'SecondModule' is not present in definition of 'Types::TypeOfExpr::Invalid2' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Valid v;
+#endif
+} // namespace TypeOfExpr
+
+namespace TypeOf {
+#if defined(FIRST)
+struct Invalid1 {
+ typeof(int) x;
+};
+struct Invalid2 {
+ typeof(int) x;
+};
+using T = int;
+struct Invalid3 {
+ typeof(T) x;
+};
+struct Valid {
+ typeof(int) x;
+ using T = typeof(double);
+ typeof(T) y;
+};
+#elif defined(SECOND)
+struct Invalid1 {
+ typeof(double) x;
+};
+using I = int;
+struct Invalid2 {
+ typeof(I) x;
+};
+using T = short;
+struct Invalid3 {
+ typeof(T) x;
+};
+struct Valid {
+ typeof(int) x;
+ using T = typeof(double);
+ typeof(T) y;
+};
+#else
+Invalid1 i1;
+// expected-error@second.h:* {{'Types::TypeOf::Invalid1::x' from module 'SecondModule' is not present in definition of 'Types::TypeOf::Invalid1' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Invalid2 i2;
+// expected-error@first.h:* {{'Types::TypeOf::Invalid2' has different definitions in different modules; first difference is definition in module 'FirstModule' found field 'x' with type 'typeof(int)' (aka 'int')}}
+// expected-note@second.h:* {{but in 'SecondModule' found field 'x' with type 'typeof(Types::TypeOf::I)' (aka 'int')}}
+Invalid3 i3;
+// expected-error@second.h:* {{'Types::TypeOf::Invalid3::x' from module 'SecondModule' is not present in definition of 'Types::TypeOf::Invalid3' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Valid v;
+#endif
+} // namespace TypeOf
+} // namespace Types
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
diff --git a/test/Modules/odr_hash-vector.cpp b/test/Modules/odr_hash-vector.cpp
new file mode 100644
index 000000000000..ee59cb617c1a
--- /dev/null
+++ b/test/Modules/odr_hash-vector.cpp
@@ -0,0 +1,128 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 %t/Inputs/first.h -fzvector
+// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 %t/Inputs/second.h -fzvector
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=c++11 -fzvector
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+namespace Types {
+namespace Vector {
+#if defined(FIRST)
+struct Invalid1 {
+ __attribute((vector_size(8))) int x;
+};
+struct Invalid2 {
+ __attribute((vector_size(8))) int x;
+};
+struct Invalid3 {
+ __attribute((vector_size(16))) int x;
+};
+struct Valid {
+ __attribute((vector_size(8))) int x1;
+ __attribute((vector_size(16))) int x2;
+ __attribute((vector_size(8))) unsigned x3;
+ __attribute((vector_size(16))) long x4;
+ vector unsigned x5;
+ vector int x6;
+};
+#elif defined(SECOND)
+struct Invalid1 {
+ __attribute((vector_size(16))) int x;
+};
+struct Invalid2 {
+ __attribute((vector_size(8))) unsigned x;
+};
+struct Invalid3 {
+ vector unsigned x;
+};
+struct Valid {
+ __attribute((vector_size(8))) int x1;
+ __attribute((vector_size(16))) int x2;
+ __attribute((vector_size(8))) unsigned x3;
+ __attribute((vector_size(16))) long x4;
+ vector unsigned x5;
+ vector int x6;
+};
+#else
+Invalid1 i1;
+// expected-error@second.h:* {{'Types::Vector::Invalid1::x' from module 'SecondModule' is not present in definition of 'Types::Vector::Invalid1' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Invalid2 i2;
+// expected-error@second.h:* {{'Types::Vector::Invalid2::x' from module 'SecondModule' is not present in definition of 'Types::Vector::Invalid2' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Invalid3 i3;
+// expected-error@second.h:* {{'Types::Vector::Invalid3::x' from module 'SecondModule' is not present in definition of 'Types::Vector::Invalid3' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+
+Valid v;
+#endif
+} // namespace Vector
+
+
+
+namespace ExtVector {
+} // namespace ExtVector
+#if defined(FIRST)
+struct Invalid {
+ using f = __attribute__((ext_vector_type(4))) float;
+};
+struct Valid {
+ using f = __attribute__((ext_vector_type(8))) float;
+};
+#elif defined(SECOND)
+struct Invalid {
+ using f = __attribute__((ext_vector_type(8))) float;
+};
+struct Valid {
+ using f = __attribute__((ext_vector_type(8))) float;
+};
+#else
+Invalid i;
+// expected-error@first.h:* {{'Types::Invalid::f' from module 'FirstModule' is not present in definition of 'Types::Invalid' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'f' does not match}}
+
+Valid v;
+#endif
+
+} // namespace Types
+
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
+
+#ifdef ACCESS
+#undef ACCESS
+#endif
diff --git a/test/Modules/odr_hash.cl b/test/Modules/odr_hash.cl
new file mode 100644
index 000000000000..d4af1cea6e26
--- /dev/null
+++ b/test/Modules/odr_hash.cl
@@ -0,0 +1,80 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x c++ %t/Inputs/first.h -cl-std=CL2.0
+// RUN: %clang_cc1 -fsyntax-only -x c++ %t/Inputs/second.h -cl-std=CL2.0
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -cl-std=CL2.0
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+
+#if defined(FIRST)
+void invalid1() {
+ typedef read_only pipe int x;
+}
+void invalid2() {
+ typedef read_only pipe int x;
+}
+void valid() {
+ typedef read_only pipe int x;
+ typedef write_only pipe int y;
+ typedef read_write pipe int z;
+}
+#elif defined(SECOND)
+void invalid1() {
+ typedef write_only pipe int x;
+}
+void invalid2() {
+ typedef read_only pipe float x;
+}
+void valid() {
+ typedef read_only pipe int x;
+ typedef write_only pipe int y;
+ typedef read_write pipe int z;
+}
+#else
+void run() {
+ invalid1();
+// expected-error@second.h:* {{'invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+ invalid2();
+// expected-error@second.h:* {{'invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+ valid();
+}
+#endif
+
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp
index 16ddfefa53c7..e4c5ba6f82a8 100644
--- a/test/Modules/odr_hash.cpp
+++ b/test/Modules/odr_hash.cpp
@@ -25,7 +25,9 @@
// RUN: echo "}" >> %t/Inputs/module.map
// Run test
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=c++1z
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -x c++ -std=c++1z \
+// RUN: -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \
+// RUN: -I%t/Inputs -verify %s
#if !defined(FIRST) && !defined(SECOND)
#include "first.h"
@@ -2244,22 +2246,6 @@ S2 s2;
#endif
#if defined(FIRST)
-struct T3 {};
-struct S3 {
- friend const T3;
-};
-#elif defined(SECOND)
-struct T3 {};
-struct S3 {
- friend T3;
-};
-#else
-S3 s3;
-// expected-error@second.h:* {{'Friend::S3' has different definitions in different modules; first difference is definition in module 'SecondModule' found friend 'Friend::T3'}}
-// expected-note@first.h:* {{but in 'FirstModule' found friend 'const Friend::T3'}}
-#endif
-
-#if defined(FIRST)
struct T4 {};
struct S4 {
friend T4;
@@ -2292,14 +2278,12 @@ S5 s5;
friend class FriendA; \
friend struct FriendB; \
friend FriendC; \
- friend const FriendD; \
friend void Function();
#if defined(FIRST) || defined(SECOND)
class FriendA {};
class FriendB {};
class FriendC {};
-class FriendD {};
#endif
#if defined(FIRST) || defined(SECOND)
@@ -3317,6 +3301,568 @@ Valid V;
#endif
} // namespace Enums
+namespace Types {
+namespace Complex {
+#if defined(FIRST)
+void invalid() {
+ _Complex float x;
+}
+void valid() {
+ _Complex float x;
+}
+#elif defined(SECOND)
+void invalid() {
+ _Complex double x;
+}
+void valid() {
+ _Complex float x;
+}
+#else
+auto function1 = invalid;
+// expected-error@second.h:* {{'Types::Complex::invalid' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = valid;
+#endif
+} // namespace Complex
+
+namespace Decltype {
+#if defined(FIRST)
+void invalid1() {
+ decltype(1 + 1) x;
+}
+int global;
+void invalid2() {
+ decltype(global) x;
+}
+void valid() {
+ decltype(1.5) x;
+ decltype(x) y;
+}
+#elif defined(SECOND)
+void invalid1() {
+ decltype(2) x;
+}
+float global;
+void invalid2() {
+ decltype(global) x;
+}
+void valid() {
+ decltype(1.5) x;
+ decltype(x) y;
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::Decltype::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::Decltype::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = valid;
+#endif
+} // namespace Decltype
+
+namespace Auto {
+#if defined(FIRST)
+void invalid1() {
+ decltype(auto) x = 1;
+}
+void invalid2() {
+ auto x = 1;
+}
+void invalid3() {
+ __auto_type x = 1;
+}
+void valid() {
+ decltype(auto) x = 1;
+ auto y = 1;
+ __auto_type z = 1;
+}
+#elif defined(SECOND)
+void invalid1() {
+ auto x = 1;
+}
+void invalid2() {
+ __auto_type x = 1;
+}
+void invalid3() {
+ decltype(auto) x = 1;
+}
+void valid() {
+ decltype(auto) x = 1;
+ auto y = 1;
+ __auto_type z = 1;
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::Auto::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid3;
+// expected-error@second.h:* {{'Types::Auto::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = invalid2;
+// expected-error@second.h:* {{'Types::Auto::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function4 = valid;
+#endif
+} // namespace Auto
+
+namespace DeducedTemplateSpecialization {
+#if defined(FIRST)
+template<typename T> struct A {};
+A() -> A<int>;
+template<typename T> struct B {};
+B() -> B<int>;
+
+void invalid1() {
+ A a{};
+}
+void invalid2() {
+ A a{};
+}
+void valid() {
+ B b{};
+}
+#elif defined(SECOND)
+template<typename T> struct A {};
+A() -> A<float>;
+template<typename T> struct B {};
+B() -> B<int>;
+
+void invalid1() {
+ A a{};
+}
+void invalid2() {
+ B a{};
+}
+void valid() {
+ B b{};
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::DeducedTemplateSpecialization::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::DeducedTemplateSpecialization::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = valid;
+#endif
+} // namespace DeducedTemplateSpecialization
+
+namespace DependentAddressSpace {
+#if defined(FIRST)
+template <int A1, int A2>
+void invalid1() {
+ using type = int __attribute__((address_space(A1)));
+}
+template <int A1>
+void invalid2() {
+ using type = float __attribute__((address_space(A1)));
+}
+template <int A1, int A2>
+void valid() {
+ using type1 = float __attribute__((address_space(A1)));
+ using type2 = int __attribute__((address_space(A2)));
+ using type3 = int __attribute__((address_space(A1 + A2)));
+}
+#elif defined(SECOND)
+template <int A1, int A2>
+void invalid1() {
+ using type = int __attribute__((address_space(A2)));
+}
+template <int A1>
+void invalid2() {
+ using type = int __attribute__((address_space(A1)));
+}
+template <int A1, int A2>
+void valid() {
+ using type1 = float __attribute__((address_space(A1)));
+ using type2 = int __attribute__((address_space(A2)));
+ using type3 = int __attribute__((address_space(A1 + A2)));
+}
+#else
+template <int A, int B>
+class S {
+ static auto function1 = invalid1<A, B>;
+ // expected-error@first.h:* {{'Types::DependentAddressSpace::invalid1' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto function2 = invalid2<B>;
+ // expected-error@first.h:* {{'Types::DependentAddressSpace::invalid2' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto function3 = valid<A, B>;
+};
+#endif
+} // namespace DependentAddressSpace
+
+namespace DependentSizedExtVector {
+#if defined(FIRST)
+template<int Size>
+void invalid1() {
+ typedef int __attribute__((ext_vector_type(Size))) type;
+}
+template<int Size>
+void invalid2() {
+ typedef int __attribute__((ext_vector_type(Size + 0))) type;
+}
+template<int Size>
+void valid() {
+ typedef int __attribute__((ext_vector_type(Size))) type;
+}
+#elif defined(SECOND)
+template<int Size>
+void invalid1() {
+ typedef float __attribute__((ext_vector_type(Size))) type;
+}
+template<int Size>
+void invalid2() {
+ typedef int __attribute__((ext_vector_type(Size + 1))) type;
+}
+template<int Size>
+void valid() {
+ typedef int __attribute__((ext_vector_type(Size))) type;
+}
+#else
+template <int Num>
+class S {
+ static auto Function1 = invalid1<Num>;
+ // expected-error@first.h:* {{'Types::DependentSizedExtVector::invalid1' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto Function2 = invalid2<Num>;
+ // expected-error@first.h:* {{'Types::DependentSizedExtVector::invalid2' has different definitions in different modules; definition in module 'FirstModule' first difference is function body}}
+ // expected-note@second.h:* {{but in 'SecondModule' found a different body}}
+ static auto Function3 = valid<Num>;
+};
+#endif
+} // namespace DependentSizedExtVector
+
+namespace InjectedClassName {
+#if defined(FIRST)
+struct Invalid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L3 *x;
+ };
+ };
+};
+struct Valid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L2 *x;
+ L3 *y;
+ };
+ };
+};
+#elif defined(SECOND)
+struct Invalid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L2 *x;
+ };
+ };
+};
+struct Valid {
+ template <int>
+ struct L2 {
+ template <int>
+ struct L3 {
+ L2 *x;
+ L3 *y;
+ };
+ };
+};
+#else
+Invalid::L2<1>::L3<1> invalid;
+// expected-error@second.h:* {{'Types::InjectedClassName::Invalid::L2::L3::x' from module 'SecondModule' is not present in definition of 'L3<>' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'x' does not match}}
+Valid::L2<1>::L3<1> valid;
+#endif
+} // namespace InjectedClassName
+
+namespace MemberPointer {
+#if defined(FIRST)
+struct A {};
+struct B {};
+
+void Invalid1() {
+ int A::*x;
+};
+void Invalid2() {
+ int A::*x;
+}
+void Invalid3() {
+ int (A::*x)(int);
+}
+void Valid() {
+ int A::*x;
+ float A::*y;
+ bool B::*z;
+ void (A::*fun1)();
+ int (A::*fun2)();
+ void (B::*fun3)(int);
+ void (B::*fun4)(bool*, int);
+}
+#elif defined(SECOND)
+struct A {};
+struct B {};
+
+void Invalid1() {
+ float A::*x;
+};
+void Invalid2() {
+ int B::*x;
+}
+void Invalid3() {
+ int (A::*x)(int, int);
+}
+void Valid() {
+ int A::*x;
+ float A::*y;
+ bool B::*z;
+ void (A::*fun1)();
+ int (A::*fun2)();
+ void (B::*fun3)(int);
+ void (B::*fun4)(bool*, int);
+}
+#else
+auto function1 = Invalid1;
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = Invalid2;
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = Invalid3;
+// expected-error@second.h:* {{'Types::MemberPointer::Invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function4 = Valid;
+#endif
+
+} // namespace MemberPointer
+
+namespace PackExpansion {
+#if defined(FIRST)
+struct Invalid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(A...);
+ void run(B...);
+ };
+ };
+};
+struct Valid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(A...);
+ void run(B...);
+ };
+ };
+};
+#elif defined(SECOND)
+struct Invalid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(B...);
+ void run(A...);
+ };
+ };
+};
+struct Valid {
+ template <class... A>
+ struct L2 {
+ template <class... B>
+ struct L3 {
+ void run(A...);
+ void run(B...);
+ };
+ };
+};
+#else
+Invalid::L2<int>::L3<short, bool> invalid;
+// expected-error@first.h:* {{'Types::PackExpansion::Invalid::L2::L3' has different definitions in different modules; first difference is definition in module 'FirstModule' found method 'run' with 1st parameter of type 'A...'}}
+// expected-note@second.h:* {{but in 'SecondModule' found method 'run' with 1st parameter of type 'B...'}}
+Valid::L2<int>::L3<short, bool> valid;
+#endif
+
+} // namespace PackExpansion
+
+namespace Paren {
+#if defined(FIRST)
+void invalid() {
+ int (*x);
+}
+void valid() {
+ int (*x);
+}
+#elif defined(SECOND)
+void invalid() {
+ float (*x);
+}
+void valid() {
+ int (*x);
+}
+#else
+auto function1 = invalid;
+// expected-error@second.h:* {{'Types::Paren::invalid' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = valid;
+#endif
+} // namespace Paren
+
+namespace SubstTemplateTypeParm {
+#if defined(FIRST)
+template <class> struct wrapper {};
+template <class, class, class> struct triple {};
+struct Valid {
+ template <class T,
+ template <class _T, class _U, class = wrapper<_T>> class A = triple>
+ struct L2 {
+ A<T, T> x;
+ };
+};
+#elif defined(SECOND)
+template <class> struct wrapper {};
+template <class, class, class> struct triple {};
+struct Valid {
+ template <class T,
+ template <class _T, class _U, class = wrapper<_T>> class A = triple>
+ struct L2 {
+ A<T, T> x;
+ };
+};
+#else
+template <class T,
+ template <class _T, class _U, class = wrapper<_T>> class A = triple>
+using V = Valid::L2<T, A>;
+#endif
+} // namespace SubstTemplateTypeParm
+
+namespace SubstTemplateTypeParmPack {
+} // namespace SubstTemplateTypeParmPack
+
+namespace UnaryTransform {
+#if defined(FIRST)
+enum class E1a : unsigned {};
+struct Invalid1 {
+ __underlying_type(E1a) x;
+};
+enum E2a : unsigned {};
+struct Invalid2 {
+ __underlying_type(E2a) x;
+};
+enum E3a {};
+struct Invalid3 {
+ __underlying_type(E3a) x;
+};
+enum E4a {};
+struct Invalid4 {
+ __underlying_type(E4a) x;
+};
+enum E1 {};
+struct Valid1 {
+ __underlying_type(E1) x;
+};
+enum E2 : unsigned {};
+struct Valid2 {
+ __underlying_type(E2) x;
+};
+enum class E3 {};
+struct Valid3 {
+ __underlying_type(E3) x;
+};
+#elif defined(SECOND)
+enum class E1b : signed {};
+struct Invalid1 {
+ __underlying_type(E1b) x;
+};
+enum class E2b : unsigned {};
+struct Invalid2 {
+ __underlying_type(E2b) x;
+};
+enum E3b : int {};
+struct Invalid3 {
+ __underlying_type(E3b) x;
+};
+enum E4b {};
+struct Invalid4 {
+ __underlying_type(E4b) x;
+};
+#else
+Invalid1 i1;
+// expected-error@first.h:* {{'Types::UnaryTransform::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::UnaryTransform::Invalid1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid2 i2;
+// expected-error@second.h:* {{'Types::UnaryTransform::Invalid2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E2b)' (aka 'unsigned int')}}
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E2a)' (aka 'unsigned int')}}
+Invalid3 i3;
+// expected-error@first.h:* {{'Types::UnaryTransform::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::UnaryTransform::Invalid3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid4 i4;
+// expected-error@second.h:* {{'Types::UnaryTransform::Invalid4' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E4b)' (aka 'unsigned int')}}
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type '__underlying_type(Types::UnaryTransform::E4a)' (aka 'unsigned int')}}
+Valid1 v1;
+Valid2 v2;
+Valid3 v3;
+#endif
+} // namespace UnaryTransform
+
+namespace UnresolvedUsing {
+#if defined(FIRST)
+template <class T> struct wrapper {};
+template <class T>
+struct Invalid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T1 x;
+};
+template <class T>
+struct Valid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T1 x;
+ T2 y;
+};
+#elif defined(SECOND)
+template <class T> struct wrapper {};
+template <class T>
+struct Invalid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T2 x;
+};
+template <class T>
+struct Valid {
+ using typename wrapper<T>::T1;
+ using typename wrapper<T>::T2;
+ T1 x;
+ T2 y;
+};
+#else
+template <class T> using I = Invalid<T>;
+// expected-error@first.h:* {{'Types::UnresolvedUsing::Invalid::x' from module 'FirstModule' is not present in definition of 'Invalid<T>' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+
+template <class T> using V = Valid<T>;
+#endif
+
+} // namespace UnresolvedUsing
+
+// Vector
+// void invalid1() {
+// __attribute((vector_size(8))) int *x1;
+//}
+
+} // namespace Types
+
// Collection of interesting cases below.
// Naive parsing of AST can lead to cycles in processing. Ensure
diff --git a/test/Modules/odr_hash.mm b/test/Modules/odr_hash.mm
new file mode 100644
index 000000000000..f04fb7eb5e8e
--- /dev/null
+++ b/test/Modules/odr_hash.mm
@@ -0,0 +1,299 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/Inputs
+
+// Build first header file
+// RUN: echo "#define FIRST" >> %t/Inputs/first.h
+// RUN: cat %s >> %t/Inputs/first.h
+
+// Build second header file
+// RUN: echo "#define SECOND" >> %t/Inputs/second.h
+// RUN: cat %s >> %t/Inputs/second.h
+
+// Test that each header can compile
+// RUN: %clang_cc1 -fsyntax-only -x objective-c++ %t/Inputs/first.h -fblocks -fobjc-arc
+// RUN: %clang_cc1 -fsyntax-only -x objective-c++ %t/Inputs/second.h -fblocks -fobjc-arc
+
+// Build module map file
+// RUN: echo "module FirstModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"first.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+// RUN: echo "module SecondModule {" >> %t/Inputs/module.map
+// RUN: echo " header \"second.h\"" >> %t/Inputs/module.map
+// RUN: echo "}" >> %t/Inputs/module.map
+
+// Run test
+// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c++ -I%t/Inputs -verify %s -fblocks -fobjc-arc
+
+#if !defined(FIRST) && !defined(SECOND)
+#include "first.h"
+#include "second.h"
+#endif
+
+#if defined(FIRST) || defined(SECOND)
+@protocol P1
+@end
+
+@protocol P2
+@end
+
+@interface I1
+@end
+
+@interface I2 : I1
+@end
+
+@interface Interface1 <T : I1 *> {
+@public
+ T<P1> x;
+}
+@end
+
+@interface Interface2 <T : I1 *>
+@end
+
+@interface Interface3 <T : I1 *>
+@end
+
+#endif
+
+#if defined(FIRST)
+struct S {
+ Interface1 *I;
+ decltype(I->x) x;
+ int y;
+};
+#elif defined(SECOND)
+struct S {
+ Interface1 *I;
+ decltype(I->x) x;
+ bool y;
+};
+#else
+S s;
+// expected-error@second.h:* {{'S::y' from module 'SecondModule' is not present in definition of 'S' in module 'FirstModule'}}
+// expected-note@first.h:* {{declaration of 'y' does not match}}
+#endif
+
+namespace Types {
+namespace Attributed {
+#if defined(FIRST)
+void invalid1() {
+ static double __attribute((objc_gc(strong))) *x;
+}
+void invalid2() {
+ static int __attribute((objc_gc(strong))) *x;
+}
+void valid() {
+ static int __attribute((objc_gc(strong))) *x;
+}
+#elif defined(SECOND)
+void invalid1() {
+ static int __attribute((objc_gc(strong))) *x;
+}
+void invalid2() {
+ static int __attribute((objc_gc(weak))) *x;
+}
+void valid() {
+ static int __attribute((objc_gc(strong))) *x;
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{Types::Attributed::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::Attributed::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = valid;
+#endif
+} // namespace Attributed
+
+namespace BlockPointer {
+#if defined(FIRST)
+void invalid1() {
+ void (^x)(int);
+}
+void invalid2() {
+ void (^x)(int);
+}
+void invalid3() {
+ void (^x)(int);
+}
+void invalid4() {
+ void (^x)(int);
+}
+void valid() {
+ void (^x1)(int);
+ int (^x2)(int);
+ void (^x3)(int, int);
+ void (^x4)(short);
+}
+#elif defined(SECOND)
+void invalid1() {
+ void (^x)();
+}
+void invalid2() {
+ void (^x)(int, int);
+}
+void invalid3() {
+ int (^x)(int);
+}
+void invalid4() {
+ void (^x)(float);
+}
+void valid() {
+ void (^x1)(int);
+ int (^x2)(int);
+ void (^x3)(int, int);
+ void (^x4)(short);
+}
+#else
+auto function1 = invalid1;
+// expected-error@second.h:* {{'Types::BlockPointer::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function2 = invalid2;
+// expected-error@second.h:* {{'Types::BlockPointer::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function3 = invalid3;
+// expected-error@second.h:* {{'Types::BlockPointer::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function4 = invalid4;
+// expected-error@second.h:* {{'Types::BlockPointer::invalid4' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
+// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
+auto function5 = valid;
+#endif
+} // namespace BlockPointer
+
+namespace ObjCObject {
+#if defined(FIRST)
+struct Invalid1 {
+ using T = Interface2<I1*>;
+};
+struct Invalid2 {
+ using T = Interface2<I1*>;
+};
+struct Invalid3 {
+ using T = Interface2<P1, P1>;
+};
+struct Invalid4 {
+ using T = Interface2<P1>;
+};
+struct Valid {
+ using T1 = Interface2<I1*>;
+ using T2 = Interface3<I1*>;
+ using T3 = Interface2<P1>;
+ using T4 = Interface3<P1, P2>;
+ using T5 = __kindof Interface2;
+};
+#elif defined(SECOND)
+struct Invalid1 {
+ using T = Interface3<I1*>;
+};
+struct Invalid2 {
+ using T = Interface2<I2*>;
+};
+struct Invalid3 {
+ using T = Interface2<P1>;
+};
+struct Invalid4 {
+ using T = Interface2<P2>;
+};
+struct Valid {
+ using T1 = Interface2<I1*>;
+ using T2 = Interface3<I1*>;
+ using T3 = Interface2<P1>;
+ using T4 = Interface3<P1, P2>;
+ using T5 = __kindof Interface2;
+};
+#else
+Invalid1 i1;
+// expected-error@first.h:* {{'Types::ObjCObject::Invalid1::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'T' does not match}}
+Invalid2 i2;
+// expected-error@first.h:* {{'Types::ObjCObject::Invalid2::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid2' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'T' does not match}}
+Invalid3 i3;
+// expected-error@second.h:* {{'Types::ObjCObject::Invalid3' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'T' with underlying type 'Interface2<P1>'}}
+// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'Interface2<P1,P1>'}}
+Invalid4 i4;
+// expected-error@first.h:* {{'Types::ObjCObject::Invalid4::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid4' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'T' does not match}}
+Valid v;
+#endif
+} // namespace VisitObjCObject
+} // namespace Types
+
+#if defined(FIRST)
+@interface Interface4 <T : I1 *> {
+@public
+ T<P1> x;
+}
+@end
+@interface Interface5 <T : I1 *> {
+@public
+ T<P1> x;
+}
+@end
+@interface Interface6 <T1 : I1 *, T2 : I2 *> {
+@public
+ T1 x;
+}
+@end
+#elif defined(SECOND)
+@interface Interface4 <T : I1 *> {
+@public
+ T<P2> x;
+}
+@end
+@interface Interface5 <T : I1 *> {
+@public
+ T<P1, P2> x;
+}
+@end
+@interface Interface6 <T1 : I1 *, T2 : I2 *> {
+@public
+ T2 x;
+}
+@end
+#endif
+
+namespace Types {
+namespace ObjCTypeParam {
+#if defined(FIRST) || defined(SECOND)
+struct Invalid1 {
+ Interface4 *I;
+ decltype(I->x) x;
+};
+struct Invalid2 {
+ Interface5 *I;
+ decltype(I->x) x;
+};
+struct Invalid3 {
+ Interface6 *I;
+ decltype(I->x) x;
+};
+#else
+Invalid1 i1;
+// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid1' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid2 i2;
+// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid2::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid2' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+Invalid3 i3;
+// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid3' in module 'SecondModule'}}
+// expected-note@second.h:* {{declaration of 'x' does not match}}
+#endif
+
+} // namespace ObjCTypeParam
+} // namespace Types
+
+// Keep macros contained to one file.
+#ifdef FIRST
+#undef FIRST
+#endif
+
+#ifdef SECOND
+#undef SECOND
+#endif
diff --git a/test/Modules/prune.m b/test/Modules/prune.m
index 97a2fd7d0dcc..7c462e20fcef 100644
--- a/test/Modules/prune.m
+++ b/test/Modules/prune.m
@@ -1,3 +1,6 @@
+// NetBSD: noatime mounts currently inhibit 'touch -a' updates
+// UNSUPPORTED: system-netbsd
+
// Test the automatic pruning of module cache entries.
#ifdef IMPORT_DEPENDS_ON_MODULE
@import DependsOnModule;
diff --git a/test/Modules/relative-dep-gen.cpp b/test/Modules/relative-dep-gen.cpp
index bfa9471859b8..e1db618c3622 100644
--- a/test/Modules/relative-dep-gen.cpp
+++ b/test/Modules/relative-dep-gen.cpp
@@ -30,9 +30,9 @@
#include "Inputs/relative-dep-gen-1.h"
// CHECK-BUILD: mod.pcm:
-// CHECK-BUILD: {{[ \t]}}Inputs/relative-dep-gen{{(-cwd)?}}.modulemap
-// CHECK-BUILD: {{[ \t]}}Inputs/relative-dep-gen-1.h
-// CHECK-BUILD: {{[ \t]}}Inputs/relative-dep-gen-2.h
+// CHECK-BUILD: {{[ \t]}}Inputs{{[/\\]}}relative-dep-gen{{(-cwd)?}}.modulemap
+// CHECK-BUILD: {{[ \t]}}Inputs{{[/\\]}}relative-dep-gen-1.h
+// CHECK-BUILD: {{[ \t]}}Inputs{{[/\\]}}relative-dep-gen-2.h
// CHECK-USE: use.o:
// CHECK-USE-DAG: {{[ \t]}}relative-dep-gen.cpp
// CHECK-EXPLICIT-DAG: mod.pcm
diff --git a/test/Modules/strict-decluse-headers.cpp b/test/Modules/strict-decluse-headers.cpp
new file mode 100644
index 000000000000..deeda2fe7f4d
--- /dev/null
+++ b/test/Modules/strict-decluse-headers.cpp
@@ -0,0 +1,17 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: touch %t/foo.h
+// RUN: echo '#include "foo.h"' > %t/bar.h
+// RUN: touch %t/baz.h
+// RUN: echo 'module X { header "bar.h" header "baz.h" }' > %t/map
+//
+// RUN: not %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%t/map -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/bar.h %t/baz.h 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%t/map -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/baz.h %t/bar.h 2>&1 | FileCheck %s
+//
+// Don't crash on this: (FIXME: we should produce an error that the specified module name is not known)
+// RUN: %clang_cc1 -fsyntax-only -fmodules -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/baz.h %t/bar.h
+//
+// Don't crash on this: (FIXME: we should produce an error that the specified file is not part of the specified module)
+// RUN: %clang_cc1 -fsyntax-only -fmodules -fmodule-map-file=%t/map -I%t -fmodules-strict-decluse -fmodule-name=X -x c++ %t/foo.h
+//
+// CHECK: module X does not depend on a module exporting 'foo.h'
diff --git a/test/Modules/subdirectory-module-maps-working-dir.m b/test/Modules/subdirectory-module-maps-working-dir.m
new file mode 100644
index 000000000000..c106dd453e04
--- /dev/null
+++ b/test/Modules/subdirectory-module-maps-working-dir.m
@@ -0,0 +1,13 @@
+// RUN: rm -rf %t
+// RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t \
+// RUN: -working-directory %S/Inputs \
+// RUN: -I subdirectory-module-maps-working-dir \
+// RUN: %s -Werror=implicit-function-declaration -Xclang -verify
+
+@import ModuleInSubdir;
+
+void foo() {
+ int x = bar();
+}
+
+// expected-no-diagnostics
diff --git a/test/Modules/submodules-merge-defs.cpp b/test/Modules/submodules-merge-defs.cpp
index 4ab822a022bd..795150208c95 100644
--- a/test/Modules/submodules-merge-defs.cpp
+++ b/test/Modules/submodules-merge-defs.cpp
@@ -65,7 +65,7 @@ using pre_i = I<>; // expected-error +{{must be imported}}
J<> pre_j; // expected-error {{declaration of 'J' must be imported}}
#ifdef IMPORT_USE_2
-// expected-error-re@-2 {{default argument of 'J' must be imported from one of {{.*}}stuff.use{{.*}}stuff.use-2}}
+// expected-error-re@-2 {{default argument of 'J' must be imported from one of {{.*}}stuff.use-2{{.*}}stuff.use}}
#elif EARLY_INDIRECT_INCLUDE
// expected-error@-4 {{default argument of 'J' must be imported from module 'merged-defs'}}
#else
diff --git a/test/Modules/target-platform-features.m b/test/Modules/target-platform-features.m
new file mode 100644
index 000000000000..875c83a2a545
--- /dev/null
+++ b/test/Modules/target-platform-features.m
@@ -0,0 +1,79 @@
+// Clear and create directories
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: mkdir %t/cache
+// RUN: mkdir %t/InputsA
+
+// RUN: echo "module RequiresMacOS {" >> %t/InputsA/module.map
+// RUN: echo " requires macos" >> %t/InputsA/module.map
+// RUN: echo "}" >> %t/InputsA/module.map
+// RUN: echo "module RequiresNotiOS {" >> %t/InputsA/module.map
+// RUN: echo " requires !ios" >> %t/InputsA/module.map
+// RUN: echo "}" >> %t/InputsA/module.map
+// RUN: echo "module RequiresMain {" >> %t/InputsA/module.map
+// RUN: echo " module SubRequiresNotiOS {" >> %t/InputsA/module.map
+// RUN: echo " requires !ios" >> %t/InputsA/module.map
+// RUN: echo " }" >> %t/InputsA/module.map
+// RUN: echo "}" >> %t/InputsA/module.map
+
+// RUN: %clang_cc1 -triple=x86_64-apple-macosx10.6 -DENABLE_DARWIN -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsA -verify %s
+// expected-no-diagnostics
+
+// RUN: not %clang_cc1 -triple=arm64-apple-ios -DENABLE_DARWIN -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsA %s 2> %t/notios
+// RUN: FileCheck %s -check-prefix=CHECK-IOS < %t/notios
+#ifdef ENABLE_DARWIN
+// CHECK-IOS: module 'RequiresMacOS' requires feature 'macos'
+@import RequiresMacOS;
+// CHECK-IOS: module 'RequiresNotiOS' is incompatible with feature 'ios'
+@import RequiresNotiOS;
+// We should never get errors for submodules that don't match
+// CHECK-IOS-NOT: module 'RequiresMain'
+@import RequiresMain;
+#endif
+
+// RUN: mkdir %t/InputsB
+// RUN: echo "module RequiresiOSSim {" >> %t/InputsB/module.map
+// RUN: echo " requires iossimulator" >> %t/InputsB/module.map
+// RUN: echo "}" >> %t/InputsB/module.map
+// RUN: %clang_cc1 -triple=x86_64-apple-iossimulator -DENABLE_IOSSIM -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsB %s -verify
+// RUN: %clang_cc1 -triple=x86_64-apple-ios-simulator -DENABLE_IOSSIM -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsB %s -verify
+
+#ifdef ENABLE_IOSSIM
+@import RequiresiOSSim;
+#endif
+
+// RUN: mkdir %t/InputsC
+// RUN: echo "module RequiresLinuxEABIA {" >> %t/InputsC/module.map
+// RUN: echo " requires linux, gnueabi" >> %t/InputsC/module.map
+// RUN: echo "}" >> %t/InputsC/module.map
+// RUN: echo "module RequiresLinuxEABIB {" >> %t/InputsC/module.map
+// RUN: echo " requires gnueabi" >> %t/InputsC/module.map
+// RUN: echo "}" >> %t/InputsC/module.map
+// RUN: echo "module RequiresLinuxEABIC {" >> %t/InputsC/module.map
+// RUN: echo " requires linux" >> %t/InputsC/module.map
+// RUN: echo "}" >> %t/InputsC/module.map
+// RUN: %clang_cc1 -triple=armv8r-none-linux-gnueabi -DENABLE_LINUXEABI -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsC %s -verify
+
+#ifdef ENABLE_LINUXEABI
+@import RequiresLinuxEABIA;
+@import RequiresLinuxEABIB;
+@import RequiresLinuxEABIC;
+#endif
+
+// RUN: mkdir %t/InputsD
+// RUN: echo "module RequiresWinMSVCA {" >> %t/InputsD/module.map
+// RUN: echo " requires windows" >> %t/InputsD/module.map
+// RUN: echo "}" >> %t/InputsD/module.map
+// RUN: echo "module RequiresWinMSVCB {" >> %t/InputsD/module.map
+// RUN: echo " requires windows, msvc" >> %t/InputsD/module.map
+// RUN: echo "}" >> %t/InputsD/module.map
+// RUN: echo "module RequiresWinMSVCC {" >> %t/InputsD/module.map
+// RUN: echo " requires msvc" >> %t/InputsD/module.map
+// RUN: echo "}" >> %t/InputsD/module.map
+// RUN: %clang_cc1 -triple=thumbv7-unknown-windows-msvc -DENABLE_WINMSVC -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c -I%t/InputsD %s -verify
+
+#ifdef ENABLE_WINMSVC
+@import RequiresWinMSVCA;
+@import RequiresWinMSVCB;
+@import RequiresWinMSVCC;
+#endif
diff --git a/test/Modules/templates.mm b/test/Modules/templates.mm
index 95e7a9caea55..6639775986d0 100644
--- a/test/Modules/templates.mm
+++ b/test/Modules/templates.mm
@@ -14,8 +14,8 @@ void testInlineRedeclEarly() {
// CHECK-DAG: @list_left = global %[[LIST:.*]] { %[[LISTNODE:.*]]* null, i32 8 }, align 8
// CHECK-DAG: @list_right = global %[[LIST]] { %[[LISTNODE]]* null, i32 12 }, align 8
-// CHECK-DAG: @_ZZ15testMixedStructvE1l = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 1 }, align 8
-// CHECK-DAG: @_ZZ15testMixedStructvE1r = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 2 }, align 8
+// CHECK-DAG: @__const._Z15testMixedStructv.l = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 1 }, align 8
+// CHECK-DAG: @__const._Z15testMixedStructv.r = {{.*}} constant %[[LIST]] { %{{.*}}* null, i32 2 }, align 8
// CHECK-DAG: @_ZN29WithUndefinedStaticDataMemberIA_iE9undefinedE = external global
void testTemplateClasses() {
@@ -77,10 +77,10 @@ unsigned testMixedStruct() {
// CHECK: %[[l:.*]] = alloca %[[ListInt:[^ ]*]], align 8
// CHECK: %[[r:.*]] = alloca %[[ListInt]], align 8
- // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @_ZZ15testMixedStructvE1l to i8*), i64 16,
+ // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @__const._Z15testMixedStructv.l to i8*), i64 16,
ListInt_left l{0, 1};
- // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @_ZZ15testMixedStructvE1r to i8*), i64 16,
+ // CHECK: call {{.*}}memcpy{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* align {{[0-9]+}} bitcast ({{.*}}* @__const._Z15testMixedStructv.r to i8*), i64 16,
ListInt_right r{0, 2};
// CHECK: call void @_Z10useListIntR4ListIiE(%[[ListInt]]* dereferenceable({{[0-9]+}}) %[[l]])
diff --git a/test/Modules/unavailable-local-visibility.test b/test/Modules/unavailable-local-visibility.test
new file mode 100644
index 000000000000..10b316a50ec0
--- /dev/null
+++ b/test/Modules/unavailable-local-visibility.test
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -fmodules -I%S/Inputs/unavailable-local-visibility -fmodule-name=X -emit-module -x c++-module-map %S/Inputs/unavailable-local-visibility/module.modulemap -o %t/x.pcm
+// RUN: %clang_cc1 -fmodules -I%S/Inputs/unavailable-local-visibility -fmodule-name=M -fmodule-map-file=%S/Inputs/unavailable-local-visibility/module.modulemap -fmodules-local-submodule-visibility -fmodule-file=%t/x.pcm -fsyntax-only -x c++-header %S/Inputs/unavailable-local-visibility/b.h