aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
blob: baa29ea944301579098f94979a2f2b911fc79460 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Winvalid-noreturn %s -verify

template<typename T>
void test_attributes() {
  auto nrl = []() [[noreturn]] {}; // expected-warning{{function declared 'noreturn' should not return}}
}

template void test_attributes<int>(); // expected-note{{in instantiation of function}}

template<typename T>
void call_with_zero() {
  [](T *ptr) -> T& { return *ptr; }(0);
}

template void call_with_zero<int>();

template<typename T>
T captures(T x, T y) {
  auto lambda = [=, &y] () -> T {
    T i = x;
    return i + y;
  };

  return lambda();
}

struct X {
  X(const X&);
};

X operator+(X, X);
X operator-(X, X);

template int captures(int, int);
template X captures(X, X);

template<typename T>
int infer_result(T x, T y) {
  auto lambda = [=](bool b) { return x + y; };
  return lambda(true); // expected-error{{no viable conversion from 'X' to 'int'}}
}

template int infer_result(int, int);
template int infer_result(X, X); // expected-note{{in instantiation of function template specialization 'infer_result<X>' requested here}}

// Make sure that lambda's operator() can be used from templates.
template<typename F>
void accept_lambda(F f) {
  f(1);
}

template<typename T>
void pass_lambda(T x) {
  accept_lambda([&x](T y) { return x + y; });
}

template void pass_lambda(int);

namespace std {
  class type_info;
}

namespace p2 {
  struct P {
    virtual ~P();
  };

  template<typename T>
  struct Boom {
    Boom(const Boom&) { 
      T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \
      // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}}
    }
    void tickle() const;
  };
  
  template<typename R, typename T>
  void odr_used(R &r, Boom<T> boom) {
    const std::type_info &ti
      = typeid([=,&r] () -> R& { // expected-error{{lambda expression in an unevaluated operand}}
          boom.tickle(); // expected-note{{in instantiation of member function}}
          return r; 
        }()); 
  }

  template void odr_used(int&, Boom<int>); // expected-note{{in instantiation of function template specialization}}

  template<typename R, typename T>
  void odr_used2(R &r, Boom<T> boom) {
    const std::type_info &ti
      = typeid([=,&r] () -> R& {
          boom.tickle(); // expected-note{{in instantiation of member function}}
          return r; 
        }()); 
  }

  template void odr_used2(P&, Boom<float>);
}

namespace p5 {
  struct NonConstCopy {
    NonConstCopy(const NonConstCopy&) = delete;
    NonConstCopy(NonConstCopy&);
  };

  template<typename T>
  void double_capture(T &nc) {
    [=] () mutable {
      [=] () mutable {
        T nc2(nc);
      }();
    }();
  }

  template void double_capture(NonConstCopy&);
}