diff options
| author | Mingming Liu <mingmingl@google.com> | 2025-09-10 15:25:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 15:25:31 -0700 |
| commit | 1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch) | |
| tree | 57f4b1f313c8cf74eed8819870f39c36ea263c68 /clang/test/Modules | |
| parent | 898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff) | |
| parent | b8cefcb601ddaa18482555c4ff363c01a270c2fe (diff) | |
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'clang/test/Modules')
19 files changed, 443 insertions, 29 deletions
diff --git a/clang/test/Modules/GH154840.cpp b/clang/test/Modules/GH154840.cpp new file mode 100644 index 000000000000..afeb39acb548 --- /dev/null +++ b/clang/test/Modules/GH154840.cpp @@ -0,0 +1,97 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// RUN: cd %t +// +// RUN: %clang_cc1 -fmodule-name=A -fno-cxx-modules -emit-module -fmodules -xc++ A.cppmap -o A.pcm +// RUN: %clang_cc1 -fmodule-name=B -fno-cxx-modules -emit-module -fmodules -xc++ B.cppmap -o B.pcm -fmodule-file=A.pcm +// RUN: %clang_cc1 -fmodule-name=C -fno-cxx-modules -emit-module -fmodules -xc++ C.cppmap -o C.pcm -fmodule-file=A.pcm +// RUN: %clang_cc1 -fmodule-name=D -fno-cxx-modules -emit-module -fmodules -xc++ D.cppmap -o D.pcm -fmodule-file=A.pcm +// RUN: %clang_cc1 -fmodule-name=E -fno-cxx-modules -emit-module -fmodules -xc++ E.cppmap -o E.pcm -fmodule-file=D.pcm -fmodule-file=B.pcm -fmodule-file=C.pcm +// RUN: %clang_cc1 -fno-cxx-modules -fmodules -fmodule-file=B.pcm -fmodule-file=E.pcm -emit-llvm -o /dev/null S.cpp + +//--- A.h +namespace std { + +template <class T> void zz(T); + +template <class> struct vec { + struct w {}; + struct xx {}; + + vec(vec &) { init(); } + constexpr vec &operator=(const vec &); + template <class U> constexpr void pb(U); + constexpr void init(); + + w s; +}; + +template <class T> constexpr void vec<T>::init() { + xx yy; + zz(yy); +} + +template <class T> constexpr vec<T> &vec<T>::operator=(const vec &) { + pb(s); + return *this; +} + +template <class T> template <class U> constexpr void vec<T>::pb(U) { init(); } +} // namespace std + +//--- A.cppmap +module "A" { + header "A.h" +} + +//--- X.h +#pragma clang module import A + +namespace project { + class thing : std::vec<thing> {}; +} // namespace project + +//--- B.h +#include "X.h" + +//--- B.cppmap +module "B" { + header "B.h" +} + +//--- C.h +#include "X.h" + +//--- C.cppmap +module "C" { + header "C.h" +} + +//--- D.h +#include "X.h" + +//--- D.cppmap +module "D" { + header "D.h" +} + +//--- Y.h +#include "X.h" +struct other { + other() : data(data) {} + std::vec<project::thing> data; +}; + +//--- E.h +#include "Y.h" + +//--- E.cppmap +module "E" { + header "E.h" +} + +//--- S.cpp +#pragma clang module import A +#pragma clang module import E +void func(std::vec<project::thing> *a, std::vec<project::thing> *b) { *a = *b; } diff --git a/clang/test/Modules/GH155028-1.cpp b/clang/test/Modules/GH155028-1.cpp new file mode 100644 index 000000000000..d60112b48c21 --- /dev/null +++ b/clang/test/Modules/GH155028-1.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++20 -verify %s +// expected-no-diagnostics + +#pragma clang module build M +module "M" { + module "A" {} + module "B" {} +} +#pragma clang module contents +#pragma clang module begin M.A +enum E1 {}; +#pragma clang module end +#pragma clang module begin M.B +enum E1 {}; +using T = __underlying_type(E1); +#pragma clang module end +#pragma clang module endbuild diff --git a/clang/test/Modules/Inputs/umbrella_header_order/module.modulemap b/clang/test/Modules/Inputs/umbrella_header_order/module.modulemap new file mode 100644 index 000000000000..5c64e3306882 --- /dev/null +++ b/clang/test/Modules/Inputs/umbrella_header_order/module.modulemap @@ -0,0 +1,3 @@ +module x { + umbrella "umbrella" +}
\ No newline at end of file diff --git a/clang/test/Modules/Inputs/umbrella_header_order/umbrella/A.h b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/A.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/A.h diff --git a/clang/test/Modules/Inputs/umbrella_header_order/umbrella/B.h b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/B.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/B.h diff --git a/clang/test/Modules/Inputs/umbrella_header_order/umbrella/C.h b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/C.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/C.h diff --git a/clang/test/Modules/Inputs/umbrella_header_order/umbrella/D.h b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/D.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/D.h diff --git a/clang/test/Modules/Inputs/umbrella_header_order/umbrella/E.h b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/E.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/E.h diff --git a/clang/test/Modules/Inputs/umbrella_header_order/umbrella/F.h b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/F.h new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/clang/test/Modules/Inputs/umbrella_header_order/umbrella/F.h diff --git a/clang/test/Modules/added-visible-decls.cppm b/clang/test/Modules/added-visible-decls.cppm new file mode 100644 index 000000000000..2f387db45290 --- /dev/null +++ b/clang/test/Modules/added-visible-decls.cppm @@ -0,0 +1,57 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm +// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/b.pcm -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface -o %t/c.pcm -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + +//--- a.h +template <typename T> +struct A { + static const T value0; + static const T value1; + + constexpr T get0() { + return value0; + } + + constexpr T get1() { + return value1; + } +}; + +template <typename T> +const T A<T>::value0 = T(43); +template <typename T> +const T A<T>::value1 = T(44); + +//--- a.cppm +module; +#include "a.h" +export module a; +export using ::A; + +//--- b.cppm +export module b; +export import a; + +export constexpr int bar() { + return A<int>().get0(); +} + +//--- c.cppm +export module c; +export import b; + +export constexpr int foo() { + return A<int>().get1() + A<int>().get0(); +} + +//--- d.cpp +// expected-no-diagnostics + +import c; + +static_assert(bar() + foo() == 130); + diff --git a/clang/test/Modules/coro-await-elidable.cppm b/clang/test/Modules/coro-await-elidable.cppm new file mode 100644 index 000000000000..2d635c6efa88 --- /dev/null +++ b/clang/test/Modules/coro-await-elidable.cppm @@ -0,0 +1,200 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 %t/task.cppm -I%t -emit-reduced-module-interface -o %t/task.pcm +// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/user.cpp -verify -fsyntax-only + +//--- coroutine.h + +namespace std { + +template <typename R, typename...> struct coroutine_traits { + using promise_type = typename R::promise_type; +}; + +template <typename Promise = void> struct coroutine_handle; + +template <> struct coroutine_handle<void> { + static coroutine_handle from_address(void *addr) noexcept { + coroutine_handle me; + me.ptr = addr; + return me; + } + void operator()() { resume(); } + void *address() const noexcept { return ptr; } + void resume() const { __builtin_coro_resume(ptr); } + void destroy() const { __builtin_coro_destroy(ptr); } + bool done() const { return __builtin_coro_done(ptr); } + coroutine_handle &operator=(decltype(nullptr)) { + ptr = nullptr; + return *this; + } + coroutine_handle(decltype(nullptr)) : ptr(nullptr) {} + coroutine_handle() : ptr(nullptr) {} +// void reset() { ptr = nullptr; } // add to P0057? + explicit operator bool() const { return ptr; } + +protected: + void *ptr; +}; + +template <typename Promise> struct coroutine_handle : coroutine_handle<> { + using coroutine_handle<>::operator=; + + static coroutine_handle from_address(void *addr) noexcept { + coroutine_handle me; + me.ptr = addr; + return me; + } + + Promise &promise() const { + return *reinterpret_cast<Promise *>( + __builtin_coro_promise(ptr, alignof(Promise), false)); + } + static coroutine_handle from_promise(Promise &promise) { + coroutine_handle p; + p.ptr = __builtin_coro_promise(&promise, alignof(Promise), true); + return p; + } +}; + +template <typename _PromiseT> +bool operator==(coroutine_handle<_PromiseT> const &_Left, + coroutine_handle<_PromiseT> const &_Right) noexcept { + return _Left.address() == _Right.address(); +} + +template <typename _PromiseT> +bool operator!=(coroutine_handle<_PromiseT> const &_Left, + coroutine_handle<_PromiseT> const &_Right) noexcept { + return !(_Left == _Right); +} + +struct noop_coroutine_promise {}; + +template <> +struct coroutine_handle<noop_coroutine_promise> { + operator coroutine_handle<>() const noexcept { + return coroutine_handle<>::from_address(address()); + } + + constexpr explicit operator bool() const noexcept { return true; } + constexpr bool done() const noexcept { return false; } + + constexpr void operator()() const noexcept {} + constexpr void resume() const noexcept {} + constexpr void destroy() const noexcept {} + + noop_coroutine_promise &promise() const noexcept { + return *static_cast<noop_coroutine_promise *>( + __builtin_coro_promise(this->__handle_, alignof(noop_coroutine_promise), false)); + } + + constexpr void *address() const noexcept { return __handle_; } + +private: + friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept; + + coroutine_handle() noexcept { + this->__handle_ = __builtin_coro_noop(); + } + + void *__handle_ = nullptr; +}; + +using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>; + +inline noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); } + +struct suspend_always { + bool await_ready() noexcept { return false; } + void await_suspend(coroutine_handle<>) noexcept {} + void await_resume() noexcept {} +}; +struct suspend_never { + bool await_ready() noexcept { return true; } + void await_suspend(coroutine_handle<>) noexcept {} + void await_resume() noexcept {} +}; + +} // namespace std + +//--- task.cppm +module; +#include "coroutine.h" +export module task; +export template <typename T> +struct [[clang::coro_await_elidable]] Task { + struct promise_type { + struct FinalAwaiter { + bool await_ready() const noexcept { return false; } + + template <typename P> + std::coroutine_handle<> await_suspend(std::coroutine_handle<P> coro) noexcept { + if (!coro) + return std::noop_coroutine(); + return coro.promise().continuation; + } + void await_resume() noexcept {} + }; + + Task get_return_object() noexcept { + return std::coroutine_handle<promise_type>::from_promise(*this); + } + + std::suspend_always initial_suspend() noexcept { return {}; } + FinalAwaiter final_suspend() noexcept { return {}; } + void unhandled_exception() noexcept {} + void return_value(T x) noexcept { + value = x; + } + + std::coroutine_handle<> continuation; + T value; + }; + + Task(std::coroutine_handle<promise_type> handle) : handle(handle) {} + ~Task() { + if (handle) + handle.destroy(); + } + + struct Awaiter { + Awaiter(Task *t) : task(t) {} + bool await_ready() const noexcept { return false; } + void await_suspend(std::coroutine_handle<void> continuation) noexcept {} + T await_resume() noexcept { + return task->handle.promise().value; + } + + Task *task; + }; + + auto operator co_await() { + return Awaiter{this}; + } + +private: + std::coroutine_handle<promise_type> handle; +}; + +inline Task<int> callee() { + co_return 1; +} + +export inline Task<int> elidable() { + co_return co_await callee(); +} + +namespace std { + export using std::coroutine_traits; + export using std::coroutine_handle; + export using std::suspend_always; +} + +//--- user.cpp +// expected-no-diagnostics +import task; +Task<int> test() { + co_return co_await elidable(); +} diff --git a/clang/test/Modules/crash-vfs-path-symlink-component.m b/clang/test/Modules/crash-vfs-path-symlink-component.m index fe6e4d6ff424..45a68659a825 100644 --- a/clang/test/Modules/crash-vfs-path-symlink-component.m +++ b/clang/test/Modules/crash-vfs-path-symlink-component.m @@ -1,4 +1,10 @@ -// REQUIRES: crash-recovery, shell +// Needs symlinks +// UNSUPPORTED: system-windows +// env -u is not supported on AIX. +// TODO(boomanaiden154): Remove this once we have switched over to lit's +// internal shell which does support env -u. +// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} +// REQUIRES: crash-recovery // FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it? // XFAIL: target={{.*-windows-gnu}} @@ -59,7 +65,7 @@ // %/t/i directory containing the symlink component. // RUN: rm -rf %/t/i -// RUN: unset FORCE_CLANG_DIAGNOSTICS_CRASH +// RUN: env -u FORCE_CLANG_DIAGNOSTICS_CRASH \ // RUN: %clang -E %s -I %/t/i -isysroot %/t/sysroot/ \ // RUN: -ivfsoverlay %t/crash-vfs-*.cache/vfs/vfs.yaml -fmodules \ // RUN: -fmodules-cache-path=%t/m/ 2>&1 \ diff --git a/clang/test/Modules/crash-vfs-path-traversal.m b/clang/test/Modules/crash-vfs-path-traversal.m index d6c9a0f2aeb8..8ab24755ed76 100644 --- a/clang/test/Modules/crash-vfs-path-traversal.m +++ b/clang/test/Modules/crash-vfs-path-traversal.m @@ -1,5 +1,11 @@ -// REQUIRES: crash-recovery, shell +// REQUIRES: crash-recovery // UNSUPPORTED: ms-sdk, target={{.*-(ps4|ps5)}} +// Some assertions in this test use Linux style (/) file paths. +// UNSUPPORTED: system-windows +// env -u is not supported on AIX. +// TODO(boomanaiden154): Remove this once we have switched over to lit's +// internal shell which does support env -u. +// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} // FIXME: Canonicalizing paths to remove relative traversal components // currenty fails a unittest on windows and is disable by default. @@ -57,7 +63,7 @@ // RUN: sed -e "s@usr/include@usr/include/../include@g" \ // RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml > %t/vfs.yaml // RUN: cp %t/vfs.yaml %t/crash-vfs-*.cache/vfs/vfs.yaml -// RUN: unset FORCE_CLANG_DIAGNOSTICS_CRASH +// RUN: env -u FORCE_CLANG_DIAGNOSTICS_CRASH \ // RUN: %clang -E %s -I %S/Inputs/crash-recovery -isysroot %/t/i/ \ // RUN: -ivfsoverlay %t/crash-vfs-*.cache/vfs/vfs.yaml -fmodules \ // RUN: -fmodules-cache-path=%t/m/ 2>&1 \ diff --git a/clang/test/Modules/crash-vfs-relative-overlay.m b/clang/test/Modules/crash-vfs-relative-overlay.m index 27f9c8d89066..048c65b90913 100644 --- a/clang/test/Modules/crash-vfs-relative-overlay.m +++ b/clang/test/Modules/crash-vfs-relative-overlay.m @@ -1,4 +1,9 @@ -// REQUIRES: crash-recovery, shell +// UNSUPPORTED: system-windows +// REQUIRES: crash-recovery +// env -u is not supported on AIX. +// TODO(boomanaiden154): Remove this once we have switched over to lit's +// internal shell which does support env -u. +// UNSUPPORTED: target={{.*}}-zos{{.*}}, target={{.*}}-aix{{.*}} // FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it? // XFAIL: target={{.*-windows-gnu}} @@ -52,7 +57,7 @@ // Test that reading the YAML file will yield the correct path after // the overlay dir is prefixed to access headers in .cache/vfs directory. -// RUN: unset FORCE_CLANG_DIAGNOSTICS_CRASH +// RUN: env -u FORCE_CLANG_DIAGNOSTICS_CRASH \ // RUN: %clang -E %s -I %S/Inputs/crash-recovery/usr/include -isysroot %/t/i/ \ // RUN: -ivfsoverlay %t/crash-vfs-*.cache/vfs/vfs.yaml -fmodules \ // RUN: -fmodules-cache-path=%t/m/ 2>&1 \ diff --git a/clang/test/Modules/implicit-opt-level.c b/clang/test/Modules/implicit-opt-level.c new file mode 100644 index 000000000000..f6f1f58d31d7 --- /dev/null +++ b/clang/test/Modules/implicit-opt-level.c @@ -0,0 +1,15 @@ +// This test checks that under implicit modules, different optimization levels +// get different context hashes. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +//--- module.modulemap +module M { header "M.h" } +//--- M.h +//--- tu.c +#include "M.h" + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -O0 -fsyntax-only %t/tu.c +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -O1 -fsyntax-only %t/tu.c +// RUN: find %t/cache -name "M-*.pcm" | count 2 diff --git a/clang/test/Modules/merge-records.cppm b/clang/test/Modules/merge-records.cppm index dee41bda210b..bf06d7c7cb89 100644 --- a/clang/test/Modules/merge-records.cppm +++ b/clang/test/Modules/merge-records.cppm @@ -31,27 +31,6 @@ union U { int c; }; -//--- another_records.h -struct A { - int a; - double b; - float c; -}; - -struct NoNameEntity { - struct { - int a; - unsigned b; - long c; - }; -}; - -union U { - int a; - double b; - short c; -}; - //--- A.cppm module; #include "records.h" diff --git a/clang/test/Modules/modules-cache-path-canonicalization-output.c b/clang/test/Modules/modules-cache-path-canonicalization-output.c new file mode 100644 index 000000000000..ad71b69e5299 --- /dev/null +++ b/clang/test/Modules/modules-cache-path-canonicalization-output.c @@ -0,0 +1,18 @@ +// This checks that implicitly-built modules produce identical PCM +// files regardless of the spelling of the same module cache path. + +// RUN: rm -rf %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fsyntax-only %t/tu.c \ +// RUN: -fmodules-cache-path=%t/cache -fdisable-module-hash +// RUN: mv %t/cache/M.pcm %t/M.pcm +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fsyntax-only %t/tu.c \ +// RUN: -fmodules-cache-path=%t/./cache -fdisable-module-hash +// RUN: diff %t/./cache/M.pcm %t/M.pcm + +//--- tu.c +#include "M.h" +//--- M.h +//--- module.modulemap +module M { header "M.h" } diff --git a/clang/test/Modules/safe_buffers_optout.cpp b/clang/test/Modules/safe_buffers_optout.cpp index 8c3d6a235d39..39020a48925e 100644 --- a/clang/test/Modules/safe_buffers_optout.cpp +++ b/clang/test/Modules/safe_buffers_optout.cpp @@ -96,7 +96,7 @@ int textual(int *p) { // `safe_buffers_test_base`. (So the module dependencies form a DAG.) // No expected warnings from base.h, test_sub1, or test_sub2 because they are -// in seperate modules, and the explicit commands that builds them have no +// in separate modules, and the explicit commands that builds them have no // `-Wunsafe-buffer-usage`. int foo(int * p) { @@ -122,7 +122,7 @@ int foo(int * p) { // `safe_buffers_test_base`. (So the module dependencies form a DAG.) // No expected warnings from base.h, test_sub1, or test_sub2 because they are -// in seperate modules, and the explicit commands that builds them have no +// in separate modules, and the explicit commands that builds them have no // `-Wunsafe-buffer-usage`. int foo(int * p) { diff --git a/clang/test/Modules/umbrella_dir_order.m b/clang/test/Modules/umbrella_dir_order.m new file mode 100644 index 000000000000..5faa1f940080 --- /dev/null +++ b/clang/test/Modules/umbrella_dir_order.m @@ -0,0 +1,11 @@ +// RUN: cd %S +// RUN: %clang_cc1 -fmodules -fno-implicit-modules -x objective-c -fmodule-name=x -emit-module Inputs/umbrella_header_order/module.modulemap -o %t/mod.pcm +// RUN: llvm-bcanalyzer --dump --disable-histogram %t/mod.pcm | FileCheck %s + +// CHECK: <INPUT_FILE abbrevid=4 op0=1 op1=36 op2=0 op3=0 op4=0 op5=1 op6=1 op7=16/> blob data = 'module.modulemap' +// CHECK: <INPUT_FILE abbrevid=4 op0=2 op1=0 op2=0 op3=0 op4=0 op5=0 op6=0 op7=12/> blob data = 'umbrella{{[/\\]}}A.h' +// CHECK: <INPUT_FILE abbrevid=4 op0=3 op1=0 op2=0 op3=0 op4=0 op5=0 op6=0 op7=12/> blob data = 'umbrella{{[/\\]}}B.h' +// CHECK: <INPUT_FILE abbrevid=4 op0=4 op1=0 op2=0 op3=0 op4=0 op5=0 op6=0 op7=12/> blob data = 'umbrella{{[/\\]}}C.h' +// CHECK: <INPUT_FILE abbrevid=4 op0=5 op1=0 op2=0 op3=0 op4=0 op5=0 op6=0 op7=12/> blob data = 'umbrella{{[/\\]}}D.h' +// CHECK: <INPUT_FILE abbrevid=4 op0=6 op1=0 op2=0 op3=0 op4=0 op5=0 op6=0 op7=12/> blob data = 'umbrella{{[/\\]}}E.h' +// CHECK: <INPUT_FILE abbrevid=4 op0=7 op1=0 op2=0 op3=0 op4=0 op5=0 op6=0 op7=12/> blob data = 'umbrella{{[/\\]}}F.h' |
