
Close https://github.com/llvm/llvm-project/issues/71034 See https://discourse.llvm.org/t/rfc-c-20-modules-introduce-thin-bmi-and-decls-hash/74755 This patch introduces reduced BMI, which doesn't contain the definitions of functions and variables if its definitions won't contribute to the ABI. Testing is a big part of the patch. We want to make sure the reduced BMI contains the same behavior with the existing and relatively stable fatBMI. This is pretty helpful for further reduction. The user interfaces part it left to following patches to ease the reviewing.
105 lines
2.6 KiB
C++
105 lines
2.6 KiB
C++
// RUN: rm -rf %t
|
|
// RUN: mkdir %t
|
|
// RUN: split-file %s %t
|
|
//
|
|
// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
|
|
// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t -DDIFFERENT %t/B.cppm -verify
|
|
// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/B.cppm -verify
|
|
//
|
|
// Testing the behavior of `-fskip-odr-check-in-gmf`
|
|
// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/A.cppm -emit-module-interface -o %t/A.pcm
|
|
// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf -fprebuilt-module-path=%t -I%t \
|
|
// RUN: -DDIFFERENT -DSKIP_ODR_CHECK_IN_GMF %t/B.cppm -verify
|
|
|
|
//--- foo.h
|
|
#ifndef FOO_H
|
|
#define FOO_H
|
|
|
|
template <class T>
|
|
concept Range = requires(T &t) { t.begin(); };
|
|
|
|
template<class _Tp>
|
|
concept __integer_like = true;
|
|
|
|
template <class _Tp>
|
|
concept __member_size = requires(_Tp &&t) { t.size(); };
|
|
|
|
template <class First, class Second>
|
|
concept C = requires(First x, Second y) { x + y; };
|
|
|
|
struct A {
|
|
public:
|
|
template <Range T>
|
|
using range_type = T;
|
|
};
|
|
|
|
struct __fn {
|
|
template <__member_size _Tp>
|
|
constexpr __integer_like auto operator()(_Tp&& __t) const {
|
|
return __t.size();
|
|
}
|
|
|
|
template <__integer_like _Tp, C<_Tp> Sentinel>
|
|
constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
|
|
return __t;
|
|
}
|
|
|
|
template <template <class> class H, class S, C<H<S>> Sentinel>
|
|
constexpr H<S> operator()(H<S> &&__s, Sentinel &&last) const {
|
|
return __s;
|
|
}
|
|
|
|
// Tests that we could find different concept definition indeed.
|
|
#ifndef DIFFERENT
|
|
template <__integer_like _Tp, __integer_like _Up, C<_Tp> Sentinel>
|
|
constexpr _Tp operator()(_Tp &&__t, _Up _u, Sentinel &&last) const {
|
|
return __t;
|
|
}
|
|
#else
|
|
template <__integer_like _Tp, __integer_like _Up, C<_Up> Sentinel>
|
|
constexpr _Tp operator()(_Tp &&__t, _Up _u, Sentinel &&last) const {
|
|
return __t;
|
|
}
|
|
#endif
|
|
};
|
|
#endif
|
|
|
|
//--- A.cppm
|
|
module;
|
|
#include "foo.h"
|
|
export module A;
|
|
|
|
//--- B.cppm
|
|
module;
|
|
#include "foo.h"
|
|
export module B;
|
|
import A;
|
|
|
|
#ifdef SKIP_ODR_CHECK_IN_GMF
|
|
// expected-error@B.cppm:* {{call to object of type '__fn' is ambiguous}}
|
|
// expected-note@* 1+{{candidate function}}
|
|
#elif defined(DIFFERENT)
|
|
// expected-error@foo.h:41 {{'__fn::operator()' from module 'A.<global>' is not present in definition of '__fn' provided earlier}}
|
|
// expected-note@* 1+{{declaration of 'operator()' does not match}}
|
|
#else
|
|
// expected-no-diagnostics
|
|
#endif
|
|
|
|
template <class T>
|
|
struct U {
|
|
auto operator+(U) { return 0; }
|
|
};
|
|
|
|
void foo() {
|
|
A a;
|
|
struct S {
|
|
int size() { return 0; }
|
|
auto operator+(S s) { return 0; }
|
|
};
|
|
__fn{}(S());
|
|
__fn{}(S(), S());
|
|
__fn{}(S(), S(), S());
|
|
|
|
__fn{}(U<int>(), U<int>());
|
|
}
|