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
6*f6b0ae14SChuanqi 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
8e166755aSChuanqi Xu
9f4dd9775SChuanqi Xu//--- foo.h
10f4dd9775SChuanqi Xu#ifndef FOO_H
11f4dd9775SChuanqi Xu#define FOO_H
12f4dd9775SChuanqi Xu
13f4dd9775SChuanqi Xutemplate <class T>
14f4dd9775SChuanqi Xuconcept Range = requires(T &t) { t.begin(); };
15f4dd9775SChuanqi Xu
16f4dd9775SChuanqi Xutemplate<class _Tp>
17f4dd9775SChuanqi Xuconcept __integer_like = true;
18f4dd9775SChuanqi Xu
19f4dd9775SChuanqi Xutemplate <class _Tp>
20f4dd9775SChuanqi Xuconcept __member_size = requires(_Tp &&t) { t.size(); };
21f4dd9775SChuanqi Xu
22*f6b0ae14SChuanqi Xutemplate <class First, class Second>
23*f6b0ae14SChuanqi Xuconcept C = requires(First x, Second y) { x + y; };
24*f6b0ae14SChuanqi Xu
25f4dd9775SChuanqi Xustruct A {
26f4dd9775SChuanqi Xupublic:
27f4dd9775SChuanqi Xu  template <Range T>
28f4dd9775SChuanqi Xu  using range_type = T;
29f4dd9775SChuanqi Xu};
30f4dd9775SChuanqi Xu
31f4dd9775SChuanqi Xustruct __fn {
32f4dd9775SChuanqi Xu  template <__member_size _Tp>
33f4dd9775SChuanqi Xu  constexpr __integer_like auto operator()(_Tp&& __t) const {
34f4dd9775SChuanqi Xu    return __t.size();
35f4dd9775SChuanqi Xu  }
36*f6b0ae14SChuanqi Xu
37*f6b0ae14SChuanqi Xu  template <__integer_like _Tp, C<_Tp> Sentinel>
38*f6b0ae14SChuanqi Xu  constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
39*f6b0ae14SChuanqi Xu    return __t;
40*f6b0ae14SChuanqi Xu  }
41*f6b0ae14SChuanqi Xu
42*f6b0ae14SChuanqi Xu  template <template <class> class H, class S, C<H<S>> Sentinel>
43*f6b0ae14SChuanqi Xu  constexpr H<S> operator()(H<S> &&__s, Sentinel &&last) const {
44*f6b0ae14SChuanqi Xu    return __s;
45*f6b0ae14SChuanqi Xu  }
46*f6b0ae14SChuanqi Xu
47*f6b0ae14SChuanqi Xu// Tests that we could find different concept definition indeed.
48*f6b0ae14SChuanqi Xu#ifndef DIFFERENT
49*f6b0ae14SChuanqi Xu  template <__integer_like _Tp, __integer_like _Up, C<_Tp> Sentinel>
50*f6b0ae14SChuanqi Xu  constexpr _Tp operator()(_Tp &&__t, _Up _u, Sentinel &&last) const {
51*f6b0ae14SChuanqi Xu    return __t;
52*f6b0ae14SChuanqi Xu  }
53*f6b0ae14SChuanqi Xu#else
54*f6b0ae14SChuanqi Xu  template <__integer_like _Tp, __integer_like _Up, C<_Up> Sentinel>
55*f6b0ae14SChuanqi Xu  constexpr _Tp operator()(_Tp &&__t, _Up _u, Sentinel &&last) const {
56*f6b0ae14SChuanqi Xu    return __t;
57*f6b0ae14SChuanqi Xu  }
58*f6b0ae14SChuanqi Xu#endif
59f4dd9775SChuanqi Xu};
60f4dd9775SChuanqi Xu#endif
61f4dd9775SChuanqi Xu
62f4dd9775SChuanqi Xu//--- A.cppm
63f4dd9775SChuanqi Xumodule;
64f4dd9775SChuanqi Xu#include "foo.h"
65f4dd9775SChuanqi Xuexport module A;
66f4dd9775SChuanqi Xu
67f4dd9775SChuanqi Xu//--- B.cppm
68e166755aSChuanqi Xumodule;
69e166755aSChuanqi Xu#include "foo.h"
70e166755aSChuanqi Xuexport module B;
71e166755aSChuanqi Xuimport A;
72f4dd9775SChuanqi Xu
73*f6b0ae14SChuanqi Xu#ifdef DIFFERENT
74*f6b0ae14SChuanqi Xu// [email protected]:41 {{'__fn::operator()' from module 'A.<global>' is not present in definition of '__fn' provided earlier}}
75*f6b0ae14SChuanqi Xu// expected-note@* 1+{{declaration of 'operator()' does not match}}
76*f6b0ae14SChuanqi Xu#else
77*f6b0ae14SChuanqi Xu// expected-no-diagnostics
78*f6b0ae14SChuanqi Xu#endif
79*f6b0ae14SChuanqi Xu
80*f6b0ae14SChuanqi Xutemplate <class T>
81*f6b0ae14SChuanqi Xustruct U {
82*f6b0ae14SChuanqi Xu  auto operator+(U) { return 0; }
83*f6b0ae14SChuanqi Xu};
84*f6b0ae14SChuanqi Xu
85f4dd9775SChuanqi Xuvoid foo() {
86f4dd9775SChuanqi Xu    A a;
87f4dd9775SChuanqi Xu    struct S {
88f4dd9775SChuanqi Xu        int size() { return 0; }
89f4dd9775SChuanqi Xu        auto operator+(S s) { return 0; }
90f4dd9775SChuanqi Xu    };
91f4dd9775SChuanqi Xu    __fn{}(S());
92*f6b0ae14SChuanqi Xu    __fn{}(S(), S());
93*f6b0ae14SChuanqi Xu    __fn{}(S(), S(), S());
94*f6b0ae14SChuanqi Xu
95*f6b0ae14SChuanqi Xu    __fn{}(U<int>(), U<int>());
96f4dd9775SChuanqi Xu}
97