| // RUN: rm -rf %t |
| // RUN: mkdir -p %t |
| // RUN: split-file %s %t |
| // |
| // RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%t/module.modulemap %t/use.cpp -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s |
| // RUN: %clang_cc1 -DDEFINE_LOCALLY -std=c++20 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%t/module.modulemap %t/use.cpp -emit-llvm -o - -triple x86_64-linux-gnu | FileCheck %s |
| |
| //--- module.modulemap |
| module a { header "a.h" export * } |
| module b { header "b.h" export * } |
| module c { header "c.h" export * } |
| |
| //--- nonmodular.h |
| void not_constant(); |
| |
| template<typename T> struct A { |
| template<T M> static inline T N = [] { not_constant(); return M; } (); |
| }; |
| |
| template<typename T, T M> inline T N = [] { not_constant(); return M; } (); |
| |
| template<typename T, T M> inline auto L = [] {}; |
| |
| template<typename T> int Z; |
| |
| // These lambdas should not be merged, despite having the same context decl and |
| // mangling number (but different signatures). |
| inline auto MultipleLambdas = ((void)[](int*) { return 1; }, [] { return 2; }); |
| |
| //--- a.h |
| #include "nonmodular.h" |
| |
| //--- b.h |
| #include "a.h" |
| |
| int b1() { return A<int>::N<1>; } |
| int b2() { return N<int, 1>; } |
| |
| inline auto x1 = L<int, 1>; |
| inline auto x2 = L<int, 2>; |
| |
| inline constexpr int *P = &Z<decltype([] { static int n; return &n; }())>; |
| inline constexpr int *xP = P; |
| |
| static_assert(!__is_same(decltype(x1), decltype(x2))); |
| |
| //--- c.h |
| #include "a.h" |
| |
| int c1() { return A<int>::N<2>; } |
| int c2() { return N<int, 2>; } |
| |
| inline auto y2 = L<int, 2>; |
| inline auto y1 = L<int, 1>; |
| |
| inline constexpr int *P = &Z<decltype([] { static int n; return &n; }())>; |
| inline constexpr int *yP = P; |
| |
| //--- use.cpp |
| #ifdef DEFINE_LOCALLY |
| #include "nonmodular.h" |
| |
| inline constexpr int *P = &Z<decltype([] { static int n; return &n; }())>; |
| inline constexpr int *zP = P; |
| |
| auto z0 = L<int, 0>; |
| auto z2 = L<int, 2>; |
| auto z1 = L<int, 1>; |
| #endif |
| |
| #include "b.h" |
| #include "c.h" |
| |
| int b1v = b1(); |
| int b2v = b2(); |
| int c1v = c1(); |
| int c2v = c2(); |
| |
| // We should merge together matching lambdas. |
| static_assert(__is_same(decltype(x1), decltype(y1))); |
| static_assert(__is_same(decltype(x2), decltype(y2))); |
| static_assert(!__is_same(decltype(x1), decltype(x2))); |
| static_assert(!__is_same(decltype(y1), decltype(y2))); |
| static_assert(!__is_same(decltype(x1), decltype(y2))); |
| static_assert(!__is_same(decltype(x2), decltype(y1))); |
| static_assert(xP == yP); |
| #ifdef DEFINE_LOCALLY |
| static_assert(!__is_same(decltype(x1), decltype(z0))); |
| static_assert(!__is_same(decltype(x2), decltype(z0))); |
| static_assert(__is_same(decltype(x1), decltype(z1))); |
| static_assert(__is_same(decltype(x2), decltype(z2))); |
| static_assert(xP == zP); |
| #endif |
| |
| static_assert(MultipleLambdas() == 2); |
| |
| // We should not merge the instantiated lambdas from `b.h` and `c.h` together, |
| // even though they will both have anonymous declaration number #1 within |
| // A<int> and within the TU, respectively. |
| |
| // CHECK-LABEL: define {{.*}}global_var_init{{.*}} comdat($_Z1NIiLi1EE) { |
| // CHECK: load i8, ptr @_ZGV1NIiLi1EE, align 8 |
| // CHECK: call {{.*}} i32 @_ZNK1NIiLi1EEMUlvE_clEv( |
| // CHECK: store i32 {{.*}}, ptr @_Z1NIiLi1EE |
| |
| // CHECK-LABEL: define {{.*}}global_var_init{{.*}} comdat($_ZN1AIiE1NILi1EEE) { |
| // CHECK: load i8, ptr @_ZGVN1AIiE1NILi1EEE, align 8 |
| // CHECK: call {{.*}} i32 @_ZNK1AIiE1NILi1EEMUlvE_clEv( |
| // CHECK: store i32 {{.*}}, ptr @_ZN1AIiE1NILi1EEE |
| |
| // CHECK-LABEL: define {{.*}}global_var_init{{.*}} comdat($_Z1NIiLi2EE) { |
| // CHECK: load i8, ptr @_ZGV1NIiLi2EE, align 8 |
| // CHECK: call {{.*}} i32 @_ZNK1NIiLi2EEMUlvE_clEv( |
| // CHECK: store i32 {{.*}}, ptr @_Z1NIiLi2EE |
| |
| // CHECK-LABEL: define {{.*}}global_var_init{{.*}} comdat($_ZN1AIiE1NILi2EEE) { |
| // CHECK: load i8, ptr @_ZGVN1AIiE1NILi2EEE, align 8 |
| // CHECK: call {{.*}} i32 @_ZNK1AIiE1NILi2EEMUlvE_clEv( |
| // CHECK: store i32 {{.*}}, ptr @_ZN1AIiE1NILi2EEE |
| |