xref: /llvm-project/clang/test/Modules/concept.cppm (revision da00c60dae0040185dc45039c4397f6e746548e9)
1e166755aSChuanqi Xu// RUN: rm -rf %t
2e166755aSChuanqi Xu// RUN: mkdir %t
3f4dd9775SChuanqi Xu// RUN: split-file %s %t
4f4dd9775SChuanqi Xu//
5f4dd9775SChuanqi Xu// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
6f6b0ae14SChuanqi Xu// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t -DDIFFERENT %t/B.cppm -verify
7f4dd9775SChuanqi Xu// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t -I%t %t/B.cppm -verify
8*8eea582dSChuanqi Xu//
9*8eea582dSChuanqi Xu// Testing the behavior of `-fskip-odr-check-in-gmf`
10*8eea582dSChuanqi Xu// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/A.cppm -emit-module-interface -o %t/A.pcm
11*8eea582dSChuanqi Xu// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf -fprebuilt-module-path=%t -I%t  \
12*8eea582dSChuanqi Xu// RUN:    -DDIFFERENT -DSKIP_ODR_CHECK_IN_GMF %t/B.cppm -verify
13*8eea582dSChuanqi Xu
14f4dd9775SChuanqi Xu//--- foo.h
15f4dd9775SChuanqi Xu#ifndef FOO_H
16f4dd9775SChuanqi Xu#define FOO_H
17f4dd9775SChuanqi Xu
18f4dd9775SChuanqi Xutemplate <class T>
19f4dd9775SChuanqi Xuconcept Range = requires(T &t) { t.begin(); };
20f4dd9775SChuanqi Xu
21f4dd9775SChuanqi Xutemplate<class _Tp>
22f4dd9775SChuanqi Xuconcept __integer_like = true;
23f4dd9775SChuanqi Xu
24f4dd9775SChuanqi Xutemplate <class _Tp>
25f4dd9775SChuanqi Xuconcept __member_size = requires(_Tp &&t) { t.size(); };
26f4dd9775SChuanqi Xu
27f6b0ae14SChuanqi Xutemplate <class First, class Second>
28f6b0ae14SChuanqi Xuconcept C = requires(First x, Second y) { x + y; };
29f6b0ae14SChuanqi Xu
30f4dd9775SChuanqi Xustruct A {
31f4dd9775SChuanqi Xupublic:
32f4dd9775SChuanqi Xu  template <Range T>
33f4dd9775SChuanqi Xu  using range_type = T;
34f4dd9775SChuanqi Xu};
35f4dd9775SChuanqi Xu
36f4dd9775SChuanqi Xustruct __fn {
37f4dd9775SChuanqi Xu  template <__member_size _Tp>
38f4dd9775SChuanqi Xu  constexpr __integer_like auto operator()(_Tp&& __t) const {
39f4dd9775SChuanqi Xu    return __t.size();
40f4dd9775SChuanqi Xu  }
41f6b0ae14SChuanqi Xu
42f6b0ae14SChuanqi Xu  template <__integer_like _Tp, C<_Tp> Sentinel>
43f6b0ae14SChuanqi Xu  constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
44f6b0ae14SChuanqi Xu    return __t;
45f6b0ae14SChuanqi Xu  }
46f6b0ae14SChuanqi Xu
47f6b0ae14SChuanqi Xu  template <template <class> class H, class S, C<H<S>> Sentinel>
48f6b0ae14SChuanqi Xu  constexpr H<S> operator()(H<S> &&__s, Sentinel &&last) const {
49f6b0ae14SChuanqi Xu    return __s;
50f6b0ae14SChuanqi Xu  }
51f6b0ae14SChuanqi Xu
52f6b0ae14SChuanqi Xu// Tests that we could find different concept definition indeed.
53f6b0ae14SChuanqi Xu#ifndef DIFFERENT
54f6b0ae14SChuanqi Xu  template <__integer_like _Tp, __integer_like _Up, C<_Tp> Sentinel>
55f6b0ae14SChuanqi Xu  constexpr _Tp operator()(_Tp &&__t, _Up _u, Sentinel &&last) const {
56f6b0ae14SChuanqi Xu    return __t;
57f6b0ae14SChuanqi Xu  }
58f6b0ae14SChuanqi Xu#else
59f6b0ae14SChuanqi Xu  template <__integer_like _Tp, __integer_like _Up, C<_Up> Sentinel>
60f6b0ae14SChuanqi Xu  constexpr _Tp operator()(_Tp &&__t, _Up _u, Sentinel &&last) const {
61f6b0ae14SChuanqi Xu    return __t;
62f6b0ae14SChuanqi Xu  }
63f6b0ae14SChuanqi Xu#endif
64f4dd9775SChuanqi Xu};
65f4dd9775SChuanqi Xu#endif
66f4dd9775SChuanqi Xu
67f4dd9775SChuanqi Xu//--- A.cppm
68f4dd9775SChuanqi Xumodule;
69f4dd9775SChuanqi Xu#include "foo.h"
70f4dd9775SChuanqi Xuexport module A;
71f4dd9775SChuanqi Xu
72f4dd9775SChuanqi Xu//--- B.cppm
73e166755aSChuanqi Xumodule;
74e166755aSChuanqi Xu#include "foo.h"
75e166755aSChuanqi Xuexport module B;
76e166755aSChuanqi Xuimport A;
77f4dd9775SChuanqi Xu
78*8eea582dSChuanqi Xu#ifdef SKIP_ODR_CHECK_IN_GMF
79*8eea582dSChuanqi Xu// expected-error@B.cppm:* {{call to object of type '__fn' is ambiguous}}
80*8eea582dSChuanqi Xu// expected-note@* 1+{{candidate function}}
81*8eea582dSChuanqi Xu#elif defined(DIFFERENT)
82*8eea582dSChuanqi Xu// expected-error@foo.h:41 {{'__fn::operator()' from module 'A.<global>' is not present in definition of '__fn' provided earlier}}
83*8eea582dSChuanqi Xu// expected-note@* 1+{{declaration of 'operator()' does not match}}
84*8eea582dSChuanqi Xu#else
85*8eea582dSChuanqi Xu// expected-no-diagnostics
86*8eea582dSChuanqi Xu#endif
87*8eea582dSChuanqi Xu
88f6b0ae14SChuanqi Xutemplate <class T>
89f6b0ae14SChuanqi Xustruct U {
90f6b0ae14SChuanqi Xu  auto operator+(U) { return 0; }
91f6b0ae14SChuanqi Xu};
92f6b0ae14SChuanqi Xu
93f4dd9775SChuanqi Xuvoid foo() {
94f4dd9775SChuanqi Xu    A a;
95f4dd9775SChuanqi Xu    struct S {
96f4dd9775SChuanqi Xu        int size() { return 0; }
97f4dd9775SChuanqi Xu        auto operator+(S s) { return 0; }
98f4dd9775SChuanqi Xu    };
99f4dd9775SChuanqi Xu    __fn{}(S());
100f6b0ae14SChuanqi Xu    __fn{}(S(), S());
101f6b0ae14SChuanqi Xu    __fn{}(S(), S(), S());
102f6b0ae14SChuanqi Xu
103f6b0ae14SChuanqi Xu    __fn{}(U<int>(), U<int>());
104f4dd9775SChuanqi Xu}
105