1// RUN: rm -rf %t 2// RUN: mkdir -p %t 3// RUN: split-file %s %t 4// 5// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm 6// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-module-interface -o %t/b.pcm 7// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-module-interface \ 8// RUN: -fprebuilt-module-path=%t -o %t/c.pcm 9// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t \ 10// RUN: -fsyntax-only -verify 11 12// Test again with reduced BMI. 13// RUN: rm -rf %t 14// RUN: mkdir -p %t 15// RUN: split-file %s %t 16// 17// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o %t/a.pcm 18// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/b.pcm 19// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface \ 20// RUN: -fprebuilt-module-path=%t -o %t/c.pcm 21// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t \ 22// RUN: -fsyntax-only -verify 23 24//--- foo.h 25#ifndef FOO_H 26#define FOO_H 27 28template<class _Tp> 29concept __has_member_value_type = requires { typename _Tp::value_type; }; 30 31template<class _Tp> 32concept __has_member_element_type = requires { typename _Tp::element_type; }; 33 34template <class _Tp> 35inline constexpr bool is_object_v = __is_object(_Tp); 36 37template<class> struct __cond_value_type {}; 38 39template<class _Tp> 40requires is_object_v<_Tp> 41struct __cond_value_type<_Tp> { using value_type = bool; }; 42 43template<class> struct indirectly_readable_traits { 44 static constexpr int value = false; 45}; 46#endif 47 48//--- foo.member_value_type.h 49#include "foo.h" 50template<__has_member_value_type _Tp> 51struct indirectly_readable_traits<_Tp> : __cond_value_type<typename _Tp::value_type> { 52 static constexpr int value = false; 53}; 54 55//--- foo.memeber_element_type.h 56#include "foo.h" 57template<__has_member_element_type _Tp> 58struct indirectly_readable_traits<_Tp> : __cond_value_type<typename _Tp::element_type> { 59 static constexpr int value = false; 60}; 61 62template<__has_member_value_type _Tp> 63 requires __has_member_element_type<_Tp> 64struct indirectly_readable_traits<_Tp> { 65 static constexpr int value = true; 66}; 67 68//--- foo.a.h 69#include "foo.h" 70#include "foo.member_value_type.h" 71#include "foo.memeber_element_type.h" 72template <typename T> 73using AType = indirectly_readable_traits<T>; 74 75//--- a.cppm 76module; 77#include "foo.a.h" 78export module a; 79 80export using ::AType; 81 82//--- b.cppm 83module; 84#include "foo.h" 85#include "foo.memeber_element_type.h" 86export module b; 87 88//--- c.cppm 89export module c; 90 91export import a; 92export import b; 93 94//--- use.cpp 95// expected-no-diagnostics 96import c; 97 98template <typename T> 99class U { 100public: 101 using value_type = T; 102 using element_type = T; 103}; 104 105template <typename T> 106class V { 107public: 108}; 109 110static_assert(!AType<V<int*>>::value); 111static_assert(AType<U<int**>>::value); 112