diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
| commit | 676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch) | |
| tree | 02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /test/Modules | |
| parent | c7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff) | |
Notes
Diffstat (limited to 'test/Modules')
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 |
