195 lines · cpp
1// RUN: rm -rf %t2// RUN: mkdir %t3// RUN: split-file %s %t4//5// RUN: cd %t6//7// RUN: %clang_cc1 -fmodules -fno-implicit-modules -fmodule-name=c \8// RUN: -fmodule-map-file=c.cppmap -xc++ c.cppmap -emit-module -o c.pcm9// RUN: %clang_cc1 -fmodules -fno-implicit-modules -fmodule-name=a \10// RUN: -fmodule-map-file=a.cppmap -fmodule-map-file=c.cppmap -xc++ a.cppmap \11// RUN: -emit-module -o a.pcm12// RUN: %clang_cc1 -fmodules -fno-implicit-modules -fmodule-name=b \13// RUN: -fmodule-map-file=b.cppmap -fmodule-map-file=c.cppmap -xc++ b.cppmap \14// RUN: -emit-module -o b.pcm15// RUN: %clang_cc1 -fmodules -fno-implicit-modules -fmodule-name=test \16// RUN: -fmodule-map-file=test.cppmap -fmodule-map-file=a.cppmap \17// RUN: -fmodule-map-file=b.cppmap -fmodule-file=a.pcm -fmodule-file=b.pcm -xc++ \18// RUN: test.cc -emit-llvm -o - | FileCheck test.cc19 20//--- a.cppmap21module "a" {22 export *23 module "a.h" {24 export *25 header "a.h"26 }27 use "c"28}29 30//--- b.cppmap31module "b" {32 export *33 module "b.h" {34 export *35 header "b.h"36 }37 use "c"38}39 40//--- c.cppmap41module "c" {42 export *43 module "c1.h" {44 export *45 textual header "c1.h"46 }47 module "c2.h" {48 export *49 textual header "c2.h"50 }51 module "c3.h" {52 export *53 textual header "c3.h"54 }55}56 57//--- test.cppmap58module "test" {59 export *60 use "a"61 use "b"62}63 64//--- a.h65#ifndef A_H_66#define A_H_67 68#include "c1.h"69 70namespace q {71template <typename T,72 typename std::enable_if<::p::P<T>::value>::type>73class X {};74} // namespace q75 76#include "c3.h"77 78#endif // A_H_79 80//--- b.h81#ifndef B_H_82#define B_H_83 84#include "c2.h"85 86#endif // B_H_87 88//--- c1.h89#ifndef C1_H_90#define C1_H_91 92namespace std {93template <class _Tp, _Tp __v>94struct integral_constant {95 static constexpr const _Tp value = __v;96 typedef _Tp value_type;97 typedef integral_constant type;98 constexpr operator value_type() const noexcept { return value; }99 constexpr value_type operator()() const noexcept { return value; }100};101 102template <class _Tp, _Tp __v>103constexpr const _Tp integral_constant<_Tp, __v>::value;104 105typedef integral_constant<bool, true> true_type;106typedef integral_constant<bool, false> false_type;107 108template <bool, class _Tp = void>109struct enable_if {};110template <class _Tp>111struct enable_if<true, _Tp> {112 typedef _Tp type;113};114} // namespace std115 116namespace p {117template <typename T>118struct P : ::std::false_type {};119}120 121#endif // C1_H_122 123//--- c2.h124#ifndef C2_H_125#define C2_H_126 127#include "c3.h"128 129enum E {};130namespace p {131template <>132struct P<E> : std::true_type {};133} // namespace proto2134 135inline void f(::util::EnumErrorSpace<E>) {}136 137#endif // C2_H_138 139//--- c3.h140#ifndef C3_H_141#define C3_H_142 143#include "c1.h"144 145namespace util {146 147template <typename T>148class ErrorSpaceImpl;149 150class ErrorSpace {151 protected:152 template <bool* addr>153 struct OdrUse {154 constexpr OdrUse() : b(*addr) {}155 bool& b;156 };157 template <typename T>158 struct Registerer {159 static bool register_token;160 static constexpr OdrUse<®ister_token> kRegisterTokenUse{};161 };162 163 private:164 template <typename T>165 static const ErrorSpace* GetBase() {166 return 0;167 }168 169 static bool Register(const ErrorSpace* (*space)()) { return true; }170};171 172template <typename T>173bool ErrorSpace::Registerer<T>::register_token =174 Register(&ErrorSpace::GetBase<T>);175 176template <typename T>177class ErrorSpaceImpl : public ErrorSpace {178 private:179 static constexpr Registerer<ErrorSpaceImpl> kRegisterer{};180};181 182template <typename T, typename = typename std::enable_if<p::P<T>::value>::type>183class EnumErrorSpace : public ErrorSpaceImpl<EnumErrorSpace<T>> {};184 185} // namespace util186#endif // C3_H_187 188//--- test.cc189#include "a.h"190#include "b.h"191 192int main(int, char**) {}193 194// CHECK-NOT: error195