templates.cpp revision 793cd1c4cdfaafc52e2c2ad9dae959befe4bb166
1// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Winvalid-noreturn %s -verify
2
3template<typename T>
4void test_attributes() {
5  auto nrl = []() [[noreturn]] {}; // expected-error{{lambda declared 'noreturn' should not return}}
6}
7
8template void test_attributes<int>(); // expected-note{{in instantiation of function}}
9
10template<typename T>
11void call_with_zero() {
12  [](T *ptr) -> T& { return *ptr; }(0);
13}
14
15template void call_with_zero<int>();
16
17template<typename T>
18T captures(T x, T y) {
19  auto lambda = [=, &y] () -> T {
20    T i = x;
21    return i + y;
22  };
23
24  return lambda();
25}
26
27struct X {
28  X(const X&);
29};
30
31X operator+(X, X);
32X operator-(X, X);
33
34template int captures(int, int);
35template X captures(X, X);
36
37template<typename T>
38int infer_result(T x, T y) {
39  auto lambda = [=](bool b) { return x + y; };
40  return lambda(true); // expected-error{{no viable conversion from 'X' to 'int'}}
41}
42
43template int infer_result(int, int);
44template int infer_result(X, X); // expected-note{{in instantiation of function template specialization 'infer_result<X>' requested here}}
45
46// Make sure that lambda's operator() can be used from templates.
47template<typename F>
48void accept_lambda(F f) {
49  f(1);
50}
51
52template<typename T>
53void pass_lambda(T x) {
54  accept_lambda([&x](T y) { return x + y; });
55}
56
57template void pass_lambda(int);
58
59namespace std {
60  class type_info;
61}
62
63namespace p2 {
64  struct P {
65    virtual ~P();
66  };
67
68  template<typename T>
69  struct Boom {
70    Boom(const Boom&) {
71      T* x = 1; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \
72      // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}}
73    }
74    void tickle() const;
75  };
76
77  template<typename R, typename T>
78  void odr_used(R &r, Boom<T> boom) {
79    const std::type_info &ti
80      = typeid([=,&r] () -> R& { // expected-error{{lambda expression in an unevaluated operand}}
81          boom.tickle(); // expected-note{{in instantiation of member function}}
82          return r;
83        }());
84  }
85
86  template void odr_used(int&, Boom<int>); // expected-note{{in instantiation of function template specialization}}
87
88  template<typename R, typename T>
89  void odr_used2(R &r, Boom<T> boom) {
90    const std::type_info &ti
91      = typeid([=,&r] () -> R& {
92          boom.tickle(); // expected-note{{in instantiation of member function}}
93          return r;
94        }());
95  }
96
97  template void odr_used2(P&, Boom<float>);
98}
99
100namespace p5 {
101  struct NonConstCopy {
102    NonConstCopy(const NonConstCopy&) = delete;
103    NonConstCopy(NonConstCopy&);
104  };
105
106  template<typename T>
107  void double_capture(T &nc) {
108    [=] () mutable {
109      [=] () mutable {
110        T nc2(nc);
111      }();
112    }();
113  }
114
115  template void double_capture(NonConstCopy&);
116}
117