summaryrefslogtreecommitdiff
path: root/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp')
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp149
1 files changed, 149 insertions, 0 deletions
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
new file mode 100644
index 0000000..49b9c66
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
@@ -0,0 +1,149 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Winvalid-noreturn %s -verify
+
+template<typename T>
+void test_attributes() {
+ auto nrl = []() [[noreturn]] {}; // expected-error{{lambda 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&);
+}
+
+namespace NonLocalLambdaInstantation {
+ template<typename T>
+ struct X {
+ static int value;
+ };
+
+ template<typename T>
+ int X<T>::value = []{ return T(); }(); // expected-error{{cannot initialize a variable of type 'int' with an rvalue of type 'int *'}}
+
+ template int X<int>::value;
+ template int X<float>::value;
+ template int X<int*>::value; // expected-note{{in instantiation of static data member }}
+
+ template<typename T>
+ void defaults(int x = []{ return T(); }()) { }; // expected-error{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}} \
+ // expected-note{{passing argument to parameter 'x' here}}
+
+ void call_defaults() {
+ defaults<int>();
+ defaults<float>();
+ defaults<int*>(); // expected-note{{in instantiation of default function argument expression for 'defaults<int *>' required here}}
+ }
+
+ template<typename T>
+ struct X2 {
+ int x = []{ return T(); }(); // expected-error{{cannot initialize a member subobject of type 'int' with an rvalue of type 'int *'}}
+ };
+
+ X2<int> x2i;
+ X2<float> x2f;
+ X2<int*> x2ip; // expected-note{{in instantiation of template class 'NonLocalLambdaInstantation::X2<int *>' requested here}}
+}