summaryrefslogtreecommitdiff
path: root/clang/test/CXX/expr/expr.prim
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/expr/expr.prim')
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp38
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp101
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp20
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp78
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm88
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp50
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp40
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp16
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp77
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp16
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp75
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp12
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp40
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp45
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp28
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp42
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp12
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp9
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp58
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp6
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp51
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm8
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp64
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp22
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp56
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp29
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp149
27 files changed, 1230 insertions, 0 deletions
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp
new file mode 100644
index 0000000..249c976
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p12-0x.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+struct S {
+ int *j = &nonexistent; // expected-error {{use of undeclared identifier 'nonexistent'}}
+ int *m = &n; // ok
+
+ int n = f(); // ok
+ int f();
+};
+
+int i = sizeof(S::m); // ok
+int j = sizeof(S::m + 42); // ok
+
+
+struct T {
+ int n;
+ static void f() {
+ int a[n]; // expected-error {{invalid use of member 'n' in static member function}}
+ int b[sizeof n]; // ok
+ }
+};
+
+// Make sure the rule for unevaluated operands works correctly with typeid.
+namespace std {
+ class type_info;
+}
+class Poly { virtual ~Poly(); };
+const std::type_info& k = typeid(S::m);
+const std::type_info& m = typeid(*(Poly*)S::m); // expected-error {{invalid use of non-static data member}}
+const std::type_info& n = typeid(*(Poly*)(0*sizeof S::m));
+
+namespace PR11956 {
+ struct X { char a; };
+ struct Y { int f() { return sizeof(X::a); } }; // ok
+
+ struct A { enum E {} E; };
+ struct B { int f() { return sizeof(A::E); } }; // ok
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
new file mode 100644
index 0000000..030c90c
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
@@ -0,0 +1,101 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+struct A {
+ int &f(int*);
+ float &f(int*) const noexcept;
+
+ int *ptr;
+ auto g1() noexcept(noexcept(f(ptr))) -> decltype(f(this->ptr));
+ auto g2() const noexcept(noexcept(f((*this).ptr))) -> decltype(f(ptr));
+};
+
+void testA(A &a) {
+ int &ir = a.g1();
+ float &fr = a.g2();
+ static_assert(!noexcept(a.g1()), "exception-specification failure");
+ static_assert(noexcept(a.g2()), "exception-specification failure");
+}
+
+struct B {
+ char g();
+ template<class T> auto f(T t) -> decltype(t + g())
+ { return t + g(); }
+};
+
+template auto B::f(int t) -> decltype(t + g());
+
+template<typename T>
+struct C {
+ int &f(T*);
+ float &f(T*) const noexcept;
+
+ T* ptr;
+ auto g1() noexcept(noexcept(f(ptr))) -> decltype(f((*this).ptr));
+ auto g2() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(ptr));
+};
+
+void test_C(C<int> ci) {
+ int *p = 0;
+ int &ir = ci.g1();
+ float &fr = ci.g2();
+ static_assert(!noexcept(ci.g1()), "exception-specification failure");
+ static_assert(noexcept(ci.g2()), "exception-specification failure");
+}
+
+namespace PR10036 {
+ template <class I>
+ void
+ iter_swap(I x, I y) noexcept;
+
+ template <class T>
+ class A
+ {
+ T t_;
+ public:
+ void swap(A& a) noexcept(noexcept(iter_swap(&t_, &a.t_)));
+ };
+
+ void test() {
+ A<int> i, j;
+ i.swap(j);
+ }
+}
+
+namespace Static {
+ struct X1 {
+ int m;
+ static auto f() -> decltype(m); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+ static auto g() -> decltype(this->m); // expected-error{{'this' cannot be used in a static member function declaration}}
+
+ static int h();
+
+ static int i() noexcept(noexcept(m + 2)); // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+ };
+
+ auto X1::h() -> decltype(m) { return 0; } // expected-error{{'this' cannot be implicitly used in a static member function declaration}}
+
+ template<typename T>
+ struct X2 {
+ int m;
+
+ T f(T*);
+ static T f(int);
+
+ auto g(T x) -> decltype(f(x)) { return 0; }
+ };
+
+ void test_X2() {
+ X2<int>().g(0);
+ }
+}
+
+namespace PR12564 {
+ struct Base {
+ void bar(Base&) {} // unexpected-note {{here}}
+ };
+
+ struct Derived : Base {
+ // FIXME: This should be accepted.
+ void foo(Derived& d) noexcept(noexcept(d.bar(d))) {} // unexpected-error {{cannot bind to a value of unrelated type}}
+ };
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp
new file mode 100644
index 0000000..4e57b74
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p4-0x.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+struct S {
+ S *p = this; // ok
+ decltype(this) q; // expected-error {{invalid use of 'this' outside of a non-static member function}}
+
+ int arr[sizeof(this)]; // expected-error {{invalid use of 'this' outside of a non-static member function}}
+ int sz = sizeof(this); // ok
+};
+
+namespace CaptureThis {
+ struct X {
+ int n = 10;
+ int m = [&]{return n + 1; }();
+ int o = [&]{return this->m + 1; }();
+ int p = [&]{return [&](int x) { return this->m + x;}(o); }();
+ };
+
+ X x;
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp
new file mode 100644
index 0000000..5b3a004
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.general/p8-0x.cpp
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+struct global {
+};
+
+namespace PR10127 {
+ struct outer {
+ struct middle {
+ struct inner {
+ int func();
+ int i;
+ };
+ struct inner2 {
+ };
+ struct inner3 {
+ };
+ int mfunc();
+ };
+ typedef int td_int;
+ };
+
+ struct str {
+ operator decltype(outer::middle::inner()) ();
+ operator decltype(outer::middle())::inner2 ();
+ operator decltype(outer())::middle::inner3 ();
+ str(int (decltype(outer::middle::inner())::*n)(),
+ int (decltype(outer::middle())::inner::*o)(),
+ int (decltype(outer())::middle::inner::*p)());
+ };
+
+ decltype(outer::middle::inner()) a;
+ void scope() {
+ a.decltype(outer::middle())::mfunc(); // expected-error{{'PR10127::outer::middle::mfunc' is not a member of class 'decltype(outer::middle::inner())'}}
+ a.decltype(outer::middle::inner())::func();
+ a.decltype(outer::middle())::inner::func();
+ a.decltype(outer())::middle::inner::func();
+
+ a.decltype(outer())::middle::inner::~inner();
+
+ decltype(outer())::middle::inner().func();
+ }
+ decltype(outer::middle())::inner b;
+ decltype(outer())::middle::inner c;
+ decltype(outer())::fail d; // expected-error{{no type named 'fail' in 'PR10127::outer'}}
+ decltype(outer())::fail::inner e; // expected-error{{no member named 'fail' in 'PR10127::outer'}}
+ decltype()::fail f; // expected-error{{expected expression}}
+ decltype()::middle::fail g; // expected-error{{expected expression}}
+
+ decltype(int()) h;
+ decltype(int())::PR10127::outer i; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}}
+ decltype(int())::global j; // expected-error{{'decltype(int())' (aka 'int') is not a class, namespace, or scoped enumeration}}
+
+ outer::middle k = decltype(outer())::middle();
+ outer::middle::inner l = decltype(outer())::middle::inner();
+
+ template<typename T>
+ struct templ {
+ typename decltype(T())::middle::inner x; // expected-error{{type 'decltype(int())' (aka 'int') cannot be used prior to '::' because it has no members}}
+ };
+
+ template class templ<int>; // expected-note{{in instantiation of template class 'PR10127::templ<int>' requested here}}
+ template class templ<outer>;
+
+ enum class foo {
+ bar,
+ baz
+ };
+
+ foo m = decltype(foo::bar)::baz;
+
+ enum E {
+ };
+ struct bar {
+ enum E : decltype(outer())::td_int(4);
+ enum F : decltype(outer())::td_int;
+ enum G : decltype; // expected-error{{expected '(' after 'decltype'}}
+ };
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
new file mode 100644
index 0000000..0c3fdb2
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
@@ -0,0 +1,88 @@
+// RUN: %clang_cc1 -std=c++11 -fblocks %s -verify
+
+void block_capture_errors() {
+ __block int var; // expected-note 2{{'var' declared here}}
+ (void)[var] { }; // expected-error{{__block variable 'var' cannot be captured in a lambda}}
+
+ (void)[=] { var = 17; }; // expected-error{{__block variable 'var' cannot be captured in a lambda}}
+}
+
+void conversion_to_block(int captured) {
+ int (^b1)(int) = [=](int x) { return x + captured; };
+
+ const auto lambda = [=](int x) { return x + captured; };
+ int (^b2)(int) = lambda;
+}
+
+template<typename T>
+class ConstCopyConstructorBoom {
+public:
+ ConstCopyConstructorBoom(ConstCopyConstructorBoom&);
+
+ ConstCopyConstructorBoom(const ConstCopyConstructorBoom&) {
+ T *ptr = 1; // expected-error{{cannot initialize a variable of type 'float *' with an rvalue of type 'int'}}
+ }
+
+ void foo() const;
+};
+
+void conversion_to_block_init(ConstCopyConstructorBoom<int> boom,
+ ConstCopyConstructorBoom<float> boom2) {
+ const auto& lambda1([=] { boom.foo(); }); // okay
+
+ const auto& lambda2([=] { boom2.foo(); }); // expected-note{{in instantiation of member function}}
+ void (^block)(void) = lambda2;
+}
+
+
+void nesting() {
+ int array[7]; // expected-note 2{{'array' declared here}}
+ [=] () mutable {
+ [&] {
+ ^ {
+ int i = array[2];
+ i += array[3];
+ }();
+ }();
+ }();
+
+ [&] {
+ [=] () mutable {
+ ^ {
+ int i = array[2]; // expected-error{{cannot refer to declaration with an array type inside block}}
+ i += array[3]; // expected-error{{cannot refer to declaration with an array type inside block}}
+ }();
+ }();
+ }();
+}
+
+namespace overloading {
+ void bool_conversion() {
+ if ([](){}) {
+ }
+
+ bool b = []{};
+ b = (bool)[]{};
+ }
+
+ void conversions() {
+ int (*fp)(int) = [](int x) { return x + 1; };
+ fp = [](int x) { return x + 1; };
+
+ typedef int (*func_ptr)(int);
+ fp = (func_ptr)[](int x) { return x + 1; };
+
+ int (^bp)(int) = [](int x) { return x + 1; };
+ bp = [](int x) { return x + 1; };
+
+ typedef int (^block_ptr)(int);
+ bp = (block_ptr)[](int x) { return x + 1; };
+ }
+
+ int &accept_lambda_conv(int (*fp)(int));
+ float &accept_lambda_conv(int (^bp)(int));
+
+ void call_with_lambda() {
+ int &ir = accept_lambda_conv([](int x) { return x + 1; });
+ }
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
new file mode 100644
index 0000000..5dac886
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/default-arguments.cpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -Wno-lambda-extensions -verify
+
+void defargs() {
+ auto l1 = [](int i, int j = 17, int k = 18) { return i + j + k; };
+ int i1 = l1(1);
+ int i2 = l1(1, 2);
+ int i3 = l1(1, 2, 3);
+}
+
+
+void defargs_errors() {
+ auto l1 = [](int i,
+ int j = 17,
+ int k) { }; // expected-error{{missing default argument on parameter 'k'}}
+
+ auto l2 = [](int i, int j = i) {}; // expected-error{{default argument references parameter 'i'}}
+
+ int foo;
+ auto l3 = [](int i = foo) {}; // expected-error{{default argument references local variable 'foo' of enclosing function}}
+}
+
+struct NonPOD {
+ NonPOD();
+ NonPOD(const NonPOD&);
+ ~NonPOD();
+};
+
+struct NoDefaultCtor {
+ NoDefaultCtor(const NoDefaultCtor&); // expected-note{{candidate constructor}}
+ ~NoDefaultCtor();
+};
+
+template<typename T>
+void defargs_in_template_unused(T t) {
+ auto l1 = [](const T& value = T()) { };
+ l1(t);
+}
+
+template void defargs_in_template_unused(NonPOD);
+template void defargs_in_template_unused(NoDefaultCtor);
+
+template<typename T>
+void defargs_in_template_used() {
+ auto l1 = [](const T& value = T()) { }; // expected-error{{no matching constructor for initialization of 'NoDefaultCtor'}}
+ l1(); // expected-note{{in instantiation of default function argument expression for 'operator()<NoDefaultCtor>' required here}}
+}
+
+template void defargs_in_template_used<NonPOD>();
+template void defargs_in_template_used<NoDefaultCtor>(); // expected-note{{in instantiation of function template specialization}}
+
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp
new file mode 100644
index 0000000..245e270
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p10.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify
+
+int GlobalVar; // expected-note {{declared here}}
+
+namespace N {
+ int AmbiguousVar; // expected-note {{candidate}}
+}
+int AmbiguousVar; // expected-note {{candidate}}
+using namespace N;
+
+class X0 {
+ int Member;
+
+ static void Overload(int);
+ void Overload();
+ virtual X0& Overload(float);
+
+ void explicit_capture() {
+ int variable; // expected-note {{declared here}}
+ (void)[&Overload] () {}; // expected-error {{does not name a variable}}
+ (void)[&GlobalVar] () {}; // expected-error {{does not have automatic storage duration}}
+ (void)[&AmbiguousVar] () {}; // expected-error {{reference to 'AmbiguousVar' is ambiguous}}
+ (void)[&Variable] () {}; // expected-error {{use of undeclared identifier 'Variable'; did you mean 'variable'}}
+ }
+};
+
+void test_reaching_scope() {
+ int local; // expected-note{{declared here}}
+ static int local_static; // expected-note{{'local_static' declared here}}
+ (void)[=]() {
+ struct InnerLocal {
+ void member() {
+ (void)[local, // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}}
+ local_static]() { // expected-error{{'local_static' cannot be captured because it does not have automatic storage duration}}
+ return 0;
+ };
+ }
+ };
+ };
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp
new file mode 100644
index 0000000..d265dd7
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify
+
+void test_reaching_scope() {
+ int local; // expected-note{{declared here}}
+ static int local_static;
+ (void)[=]() {
+ struct InnerLocal {
+ void member() {
+ (void)[=]() {
+ return local + // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}}
+ local_static;
+ };
+ }
+ };
+ };
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
new file mode 100644
index 0000000..4a2a4f3
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p12.cpp
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
+
+void odr_used() {
+ int i = 17;
+ [i]{}();
+}
+
+struct ReachingThis {
+ static void static_foo() {
+ (void)[this](){}; // expected-error{{'this' cannot be captured in this context}}
+
+ struct Local {
+ int i;
+
+ void bar() {
+ (void)[this](){};
+ (void)[&](){i = 7; };
+ }
+ };
+ }
+
+ void foo() {
+ (void)[this](){};
+
+ struct Local {
+ int i;
+
+ static void static_bar() {
+ (void)[this](){}; // expected-error{{'this' cannot be captured in this context}}
+ (void)[&](){i = 7; }; // expected-error{{invalid use of member 'i' in static member function}}
+ }
+ };
+ }
+};
+
+void immediately_enclosing(int i) { // expected-note{{'i' declared here}}
+ [i]() {
+ [i] {}();
+ }();
+
+ [=]() {
+ [i] {}();
+ }();
+
+ []() { // expected-note{{lambda expression begins here}}
+ [i] {}(); // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}}
+ }();
+}
+
+void f1(int i) { // expected-note{{declared here}}
+ int const N = 20;
+ auto m1 = [=]{
+ int const M = 30;
+ auto m2 = [i]{
+ int x[N][M];
+ x[0][0] = i;
+ };
+ (void)N;
+ (void)M;
+ (void)m2;
+ };
+ struct s1 {
+ int f;
+ void work(int n) { // expected-note{{declared here}}
+ int m = n*n;
+ int j = 40; // expected-note{{declared here}}
+ auto m3 = [this,m] { // expected-note 3{{lambda expression begins here}}
+ auto m4 = [&,j] { // expected-error{{variable 'j' cannot be implicitly captured in a lambda with no capture-default specified}}
+ int x = n; // expected-error{{variable 'n' cannot be implicitly captured in a lambda with no capture-default specified}}
+ x += m;
+ x += i; // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}}
+ x += f;
+ };
+ };
+ }
+ };
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp
new file mode 100644
index 0000000..8bb707e
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p13.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
+
+void f2() {
+ int i = 1;
+ void g1(int = ([i]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}}
+ void g2(int = ([i]{ return 0; })()); // expected-error{{lambda expression in default argument cannot capture any entity}}
+ void g3(int = ([=]{ return i; })()); // expected-error{{lambda expression in default argument cannot capture any entity}}
+ void g4(int = ([=]{ return 0; })());
+ void g5(int = ([]{ return sizeof i; })());
+}
+
+namespace lambda_in_default_args {
+ int f(int = [] () -> int { int n; return ++n; } ());
+ template<typename T> T g(T = [] () -> T { T n; return ++n; } ());
+ int k = f() + g<int>();
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
new file mode 100644
index 0000000..678fa4b
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
@@ -0,0 +1,75 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+template<typename T> void capture(const T&);
+
+class NonCopyable {
+ NonCopyable(const NonCopyable&); // expected-note 2 {{implicitly declared private here}}
+public:
+ void foo() const;
+};
+
+class NonConstCopy {
+public:
+ NonConstCopy(NonConstCopy&); // expected-note{{would lose const}}
+};
+
+void capture_by_copy(NonCopyable nc, NonCopyable &ncr, const NonConstCopy nco) {
+ (void)[nc] { }; // expected-error{{capture of variable 'nc' as type 'NonCopyable' calls private copy constructor}}
+ (void)[=] {
+ ncr.foo(); // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}}
+ }();
+
+ [nco] {}(); // expected-error{{no matching constructor for initialization of 'const NonConstCopy'}}
+}
+
+struct NonTrivial {
+ NonTrivial();
+ NonTrivial(const NonTrivial &);
+ ~NonTrivial();
+};
+
+struct CopyCtorDefault {
+ CopyCtorDefault();
+ CopyCtorDefault(const CopyCtorDefault&, NonTrivial nt = NonTrivial());
+
+ void foo() const;
+};
+
+void capture_with_default_args(CopyCtorDefault cct) {
+ (void)[=] () -> void { cct.foo(); };
+}
+
+struct ExpectedArrayLayout {
+ CopyCtorDefault array[3];
+};
+
+void capture_array() {
+ CopyCtorDefault array[3];
+ auto x = [=]() -> void {
+ capture(array[0]);
+ };
+ static_assert(sizeof(x) == sizeof(ExpectedArrayLayout), "layout mismatch");
+}
+
+// Check for the expected non-static data members.
+
+struct ExpectedLayout {
+ char a;
+ short b;
+};
+
+void test_layout(char a, short b) {
+ auto x = [=] () -> void {
+ capture(a);
+ capture(b);
+ };
+ static_assert(sizeof(x) == sizeof(ExpectedLayout), "Layout mismatch!");
+}
+
+struct ExpectedThisLayout {
+ ExpectedThisLayout* a;
+ void f() {
+ auto x = [this]() -> void {};
+ static_assert(sizeof(x) == sizeof(ExpectedThisLayout), "Layout mismatch!");
+ }
+};
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp
new file mode 100644
index 0000000..c4deba9
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+class NonCopyable {
+ NonCopyable(const NonCopyable&);
+};
+
+void capture_by_ref(NonCopyable nc, NonCopyable &ncr) {
+ int array[3];
+ (void)[&nc] () -> void {};
+ (void)[&ncr] () -> void {};
+ (void)[&array] () -> void {};
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
new file mode 100644
index 0000000..0cf01ad
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
+
+
+struct X {
+ X(const X&) = delete; // expected-note 2{{explicitly marked deleted}}
+ X(X&);
+};
+
+void test_capture(X x) {
+ [x] { }(); // okay: non-const copy ctor
+
+ [x] {
+ [x] { // expected-error{{call to deleted constructor of 'X'}}
+ }();
+ }();
+
+ [x] {
+ [&x] {
+ [x] { // expected-error{{call to deleted constructor of 'const X'}}
+ }();
+ }();
+ }();
+
+ int a;
+ [=]{
+ [&] {
+ int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
+ int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
+ }();
+ }();
+
+ [=]{
+ [&a] {
+ [&] {
+ int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
+ int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
+ }();
+ }();
+ }();
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
new file mode 100644
index 0000000..930a4b3
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
+
+template<typename T, typename U>
+struct is_same {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+ static const bool value = true;
+};
+
+void f3() {
+ float x, &r = x;
+ int i;
+ int &ir = i;
+ const int &irc = i;
+
+ [=,&irc,&ir] {
+ static_assert(is_same<decltype(((r))), float const&>::value,
+ "should be const float&");
+ static_assert(is_same<decltype(x), float>::value, "should be float");
+ static_assert(is_same<decltype((x)), const float&>::value,
+ "should be const float&");
+ static_assert(is_same<decltype(r), float&>::value, "should be float&");
+ static_assert(is_same<decltype(ir), int&>::value, "should be int&");
+ static_assert(is_same<decltype((ir)), int&>::value, "should be int&");
+ static_assert(is_same<decltype(irc), const int&>::value,
+ "should be const int&");
+ static_assert(is_same<decltype((irc)), const int&>::value,
+ "should be const int&");
+ }();
+
+ [=] {
+ [=] () mutable {
+ static_assert(is_same<decltype(x), float>::value, "should be float");
+ static_assert(is_same<decltype((x)), float&>::value,
+ "should be float&");
+ }();
+ }();
+
+ [&i] {
+ static_assert(is_same<decltype((i)), int&>::value, "should be int&");
+ }();
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp
new file mode 100644
index 0000000..6fe3b25
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
+
+struct MoveOnly {
+ MoveOnly(MoveOnly&&);
+ MoveOnly(const MoveOnly&);
+};
+
+template<typename T> T &&move(T&);
+void test_special_member_functions(MoveOnly mo, int i) {
+ auto lambda1 = [i]() { }; // expected-note 2 {{lambda expression begins here}}
+
+ // Default constructor
+ decltype(lambda1) lambda2; // expected-error{{call to implicitly-deleted default constructor of 'decltype(lambda1)' (aka '<lambda}}
+
+ // Copy assignment operator
+ lambda1 = lambda1; // expected-error{{overload resolution selected implicitly-deleted copy assignment operator}}
+
+ // Move assignment operator
+ lambda1 = move(lambda1);
+
+ // Copy constructor
+ decltype(lambda1) lambda3 = lambda1;
+ decltype(lambda1) lambda4(lambda1);
+
+ // Move constructor
+ decltype(lambda1) lambda5 = move(lambda1);
+ decltype(lambda1) lambda6(move(lambda1));
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp
new file mode 100644
index 0000000..c6ed308
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+// prvalue
+void prvalue() {
+ auto&& x = []()->void { };
+ auto& y = []()->void { }; // expected-error{{cannot bind to a temporary of type}}
+}
+
+namespace std {
+ class type_info;
+}
+
+struct P {
+ virtual ~P();
+};
+
+void unevaluated_operand(P &p, int i) {
+ int i2 = sizeof([]()->void{}()); // expected-error{{lambda expression in an unevaluated operand}}
+ const std::type_info &ti1 = typeid([&]() -> P& { return p; }());
+ const std::type_info &ti2 = typeid([&]() -> int { return i; }()); // expected-error{{lambda expression in an unevaluated operand}}
+}
+
+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'}} \
+ // expected-error{{cannot initialize a variable of type 'double *' with an rvalue of type 'int'}}
+ }
+ void tickle() const;
+};
+
+void odr_used(P &p, Boom<int> boom_int, Boom<float> boom_float,
+ Boom<double> boom_double) {
+ const std::type_info &ti1
+ = typeid([=,&p]() -> P& { boom_int.tickle(); return p; }()); // expected-note{{in instantiation of member function 'Boom<int>::Boom' requested here}}
+ const std::type_info &ti2
+ = typeid([=]() -> int { boom_float.tickle(); return 0; }()); // expected-error{{lambda expression in an unevaluated operand}} \
+ // expected-note{{in instantiation of member function 'Boom<float>::Boom' requested here}}
+
+ auto foo = [=]() -> int { boom_double.tickle(); return 0; }; // expected-note{{in instantiation of member function 'Boom<double>::Boom' requested here}}
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp
new file mode 100644
index 0000000..4487cfc
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p20.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
+
+template<typename T>
+void destroy(T* ptr) {
+ ptr->~T();
+ (*ptr).~T();
+}
+
+void destructor() {
+ auto lambda = []{};
+ destroy(&lambda);
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp
new file mode 100644
index 0000000..7139058
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p21.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+struct DirectInitOnly {
+ explicit DirectInitOnly(DirectInitOnly&);
+};
+
+void direct_init_capture(DirectInitOnly &dio) {
+ [dio] {}();
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
new file mode 100644
index 0000000..174db25
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+void print();
+
+template<typename T, typename... Ts>
+void print(T first, Ts... rest) {
+ (void)first;
+ print(rest...);
+}
+
+template<typename... Ts>
+void unsupported(Ts ...values) {
+ auto unsup = [values] {}; // expected-error{{unexpanded function parameter pack capture is unsupported}}
+}
+
+template<typename... Ts>
+void implicit_capture(Ts ...values) {
+ auto implicit = [&] { print(values...); };
+ implicit();
+}
+
+template<typename... Ts>
+void do_print(Ts... values) {
+ auto bycopy = [values...]() { print(values...); };
+ bycopy();
+ auto byref = [&values...]() { print(values...); };
+ byref();
+
+ auto bycopy2 = [=]() { print(values...); };
+ bycopy2();
+ auto byref2 = [&]() { print(values...); };
+ byref2();
+}
+
+template void do_print(int, float, double);
+
+template<typename T, int... Values>
+void bogus_expansions(T x) {
+ auto l1 = [x...] {}; // expected-error{{pack expansion does not contain any unexpanded parameter packs}}
+ auto l2 = [Values...] {}; // expected-error{{'Values' in capture list does not name a variable}}
+}
+
+void g(int*, float*, double*);
+
+template<class... Args>
+void std_example(Args... args) {
+ auto lm = [&, args...] { return g(args...); };
+};
+
+template void std_example(int*, float*, double*);
+
+template<typename ...Args>
+void variadic_lambda(Args... args) {
+ auto lambda = [](Args... inner_args) { return g(inner_args...); };
+ lambda(args...);
+}
+
+template void variadic_lambda(int*, float*, double*);
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp
new file mode 100644
index 0000000..562f92a
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+void test_nonaggregate(int i) {
+ auto lambda = [i]() -> void {}; // expected-note 3{{candidate constructor}}
+ decltype(lambda) foo = { 1 }; // expected-error{{no matching constructor}}
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
new file mode 100644
index 0000000..d816e17
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+void missing_lambda_declarator() {
+ [](){}();
+}
+
+template<typename T> T get();
+
+void infer_void_return_type(int i) {
+ if (i > 17)
+ return []() { }();
+
+ if (i > 11)
+ return []() { return; }();
+
+ return [](int x) {
+ switch (x) {
+ case 0: return get<void>();
+ case 1: return;
+ case 2: return { 1, 2.0 }; // expected-error{{cannot deduce lambda return type from initializer list}}
+ }
+ }(7);
+}
+
+struct X { };
+
+X infer_X_return_type(X x) {
+ return [&x](int y) { // expected-warning{{omitted result type}}
+ if (y > 0)
+ return X();
+ else
+ return x;
+ }(5);
+}
+
+X infer_X_return_type_fail(X x) {
+ return [x](int y) { // expected-warning{{omitted result type}}
+ if (y > 0)
+ return X();
+ else
+ return x; // expected-error{{return type 'const X' must match previous return type 'X' when lambda expression has unspecified explicit return type}}
+ }(5);
+}
+
+struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}}
+void test_result_type(int N) {
+ auto l1 = [] () -> Incomplete { }; // expected-error{{incomplete result type 'Incomplete' in lambda expression}}
+
+ typedef int vla[N];
+ auto l2 = [] () -> vla { }; // expected-error{{function cannot return array type 'vla' (aka 'int [N]')}}
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm
new file mode 100644
index 0000000..0126e23
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.mm
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+@interface A
+@end
+
+void test_result_type() {
+ auto l1 = [] () -> A { }; // expected-error{{non-pointer Objective-C class type 'A' in lambda expression result}}
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp
new file mode 100644
index 0000000..68460f0
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p5.cpp
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -std=c++11 %s -Winvalid-noreturn -verify
+
+// An attribute-specifier-seq in a lambda-declarator appertains to the
+// type of the corresponding function call operator.
+void test_attributes() {
+ auto nrl = [](int x) -> int { if (x > 0) return x; }; // expected-warning{{control may reach end of non-void lambda}}
+
+ auto nrl2 = []() [[noreturn]] { return; }; // expected-error{{lambda declared 'noreturn' should not return}}
+}
+
+template<typename T>
+struct bogus_override_if_virtual : public T {
+ bogus_override_if_virtual() : T(*(T*)0) { }
+ int operator()() const;
+};
+
+void test_quals() {
+ // This function call operator is declared const (9.3.1) if and only
+ // if the lambda- expression's parameter-declaration-clause is not
+ // followed by mutable.
+ auto l = [=](){}; // expected-note{{method is not marked volatile}}
+ const decltype(l) lc = l;
+ l();
+ lc();
+
+ auto ml = [=]() mutable{}; // expected-note{{method is not marked const}} \
+ // expected-note{{method is not marked volatile}}
+ const decltype(ml) mlc = ml;
+ ml();
+ mlc(); // expected-error{{no matching function for call to object of type}}
+
+ // It is neither virtual nor declared volatile.
+ volatile decltype(l) lv = l;
+ volatile decltype(ml) mlv = ml;
+ lv(); // expected-error{{no matching function for call to object of type}}
+ mlv(); // expected-error{{no matching function for call to object of type}}
+
+ bogus_override_if_virtual<decltype(l)> bogus;
+}
+
+// Default arguments (8.3.6) shall not be specified in the
+// parameter-declaration-clause of a lambda- declarator.
+// Note: Removed by core issue 974.
+int test_default_args() {
+ return [](int i = 5, // expected-warning{{C++11 forbids default arguments for lambda expressions}}
+ int j = 17) { return i+j;}(5, 6);
+}
+
+// Any exception-specification specified on a lambda-expression
+// applies to the corresponding function call operator.
+void test_exception_spec() {
+ auto tl1 = []() throw(int) {};
+ auto tl2 = []() {};
+ static_assert(!noexcept(tl1()), "lambda can throw");
+ static_assert(!noexcept(tl2()), "lambda can throw");
+
+ auto ntl1 = []() throw() {};
+ auto ntl2 = []() noexcept(true) {};
+ auto ntl3 = []() noexcept {};
+ static_assert(noexcept(ntl1()), "lambda cannot throw");
+ static_assert(noexcept(ntl2()), "lambda cannot throw");
+ static_assert(noexcept(ntl3()), "lambda cannot throw");
+}
+
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp
new file mode 100644
index 0000000..8b43cef
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p6.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+void test_conversion() {
+ int (*fp1)(int) = [](int x) { return x + 1; };
+ void (*fp2)(int) = [](int x) { };
+
+ const auto lambda = [](int x) { };
+ void (*fp3)(int) = lambda;
+
+ volatile const auto lambda2 = [](int x) { }; // expected-note{{but method is not marked volatile}}
+ void (*fp4)(int) = lambda2; // expected-error{{no viable conversion}}
+}
+
+void test_no_conversion() {
+ int (*fp1)(int) = [=](int x) { return x + 1; }; // expected-error{{no viable conversion}}
+ void (*fp2)(int) = [&](int x) { }; // expected-error{{no viable conversion}}
+}
+
+void test_wonky() {
+ const auto l = [](int x) mutable -> int { return + 1; };
+ l(17); // okay: uses conversion function
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp
new file mode 100644
index 0000000..9dbe2e1
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p7.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+
+// Check that analysis-based warnings work in lambda bodies.
+void analysis_based_warnings() {
+ (void)[]() -> int { }; // expected-warning{{control reaches end of non-void lambda}}
+}
+
+// Check that we get the right types of captured variables (the
+// semantic-analysis part of p7).
+int &check_const_int(int&);
+float &check_const_int(const int&);
+
+void test_capture_constness(int i, const int ic) {
+ (void)[i,ic] ()->void {
+ float &fr1 = check_const_int(i);
+ float &fr2 = check_const_int(ic);
+ };
+
+ (void)[=] ()->void {
+ float &fr1 = check_const_int(i);
+ float &fr2 = check_const_int(ic);
+ };
+
+ (void)[i,ic] () mutable ->void {
+ int &ir = check_const_int(i);
+ float &fr = check_const_int(ic);
+ };
+
+ (void)[=] () mutable ->void {
+ int &ir = check_const_int(i);
+ float &fr = check_const_int(ic);
+ };
+
+ (void)[&i,&ic] ()->void {
+ int &ir = check_const_int(i);
+ float &fr = check_const_int(ic);
+ };
+
+ (void)[&] ()->void {
+ int &ir = check_const_int(i);
+ float &fr = check_const_int(ic);
+ };
+}
+
+
+struct S1 {
+ int x, y;
+ S1 &operator=(int*);
+ int operator()(int);
+ void f() {
+ [&]()->int {
+ S1 &s1 = operator=(&this->x);
+ return operator()(this->x + y);
+ }();
+ }
+};
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
new file mode 100644
index 0000000..d1384f1
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify
+
+class X0 {
+ void explicit_capture() {
+ int foo;
+
+ (void)[foo, foo] () {}; // expected-error {{'foo' can appear only once}}
+ (void)[this, this] () {}; // expected-error {{'this' can appear only once}}
+ (void)[=, foo] () {}; // expected-error {{'&' must precede a capture when}}
+ (void)[=, &foo] () {};
+ (void)[=, this] () {}; // expected-error {{'this' cannot be explicitly captured}}
+ (void)[&, foo] () {};
+ (void)[&, &foo] () {}; // expected-error {{'&' cannot precede a capture when}}
+ (void)[&, this] () {};
+ }
+};
+
+struct S2 {
+ void f(int i);
+ void g(int i);
+};
+
+void S2::f(int i) {
+ (void)[&, i]{ };
+ (void)[&, &i]{ }; // expected-error{{'&' cannot precede a capture when the capture default is '&'}}
+ (void)[=, this]{ }; // expected-error{{'this' cannot be explicitly captured}}
+ (void)[=]{ this->g(i); };
+ (void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}}
+}
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}}
+}