From 554bcb69c2d785a011a30e7db87a36a87fe7db10 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Wed, 15 Aug 2012 20:02:54 +0000
Subject: Vendor import of clang trunk r161861:
 http://llvm.org/svn/llvm-project/cfe/trunk@161861

---
 test/SemaCXX/lambda-expressions.cpp | 141 +++++++++++++++++++++++++++---------
 1 file changed, 107 insertions(+), 34 deletions(-)

(limited to 'test/SemaCXX/lambda-expressions.cpp')

diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp
index e91dee9..0fd6345 100644
--- a/test/SemaCXX/lambda-expressions.cpp
+++ b/test/SemaCXX/lambda-expressions.cpp
@@ -17,74 +17,71 @@ namespace ExplicitCapture {
       [this](){(void)Member;};
       [this]{[this]{};};
       []{[this]{};};// expected-error {{'this' cannot be implicitly captured in this context}}
-      []{Overload(3);}; 
-      []{Overload();}; // expected-error {{'this' cannot be implicitly captured in this context}} 
+      []{Overload(3);};
+      []{Overload();}; // expected-error {{'this' cannot be implicitly captured in this context}}
       []{(void)typeid(Overload());};
-      []{(void)typeid(Overload(.5f));};// expected-error {{'this' cannot be implicitly captured in this context}} 
+      []{(void)typeid(Overload(.5f));};// expected-error {{'this' cannot be implicitly captured in this context}}
     }
   };
 
   void f() {
-    [this] () {}; // expected-error {{'this' cannot be captured in this context}} 
+    [this] () {}; // expected-error {{'this' cannot be captured in this context}}
   }
 }
 
 namespace ReturnDeduction {
   void test() {
-    [](){ return 1; }; 
-    [](){ return 1; }; 
-    [](){ return ({return 1; 1;}); }; 
-    [](){ return ({return 'c'; 1;}); }; // expected-error {{must match previous return type}} \
-    // expected-warning{{omitted result type}}
-    []()->int{ return 'c'; return 1; }; 
+    [](){ return 1; };
+    [](){ return 1; };
+    [](){ return ({return 1; 1;}); };
+    [](){ return ({return 'c'; 1;}); }; // expected-error {{must match previous return type}}
+    []()->int{ return 'c'; return 1; };
     [](){ return 'c'; return 1; };  // expected-error {{must match previous return type}}
-    []() { return; return (void)0; }; 
-    [](){ return 1; return 1; }; // expected-warning{{omitted result type}}
+    []() { return; return (void)0; };
+    [](){ return 1; return 1; };
   }
 }
 
 namespace ImplicitCapture {
   void test() {
     int a = 0; // expected-note 5 {{declared}}
-    []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}}  
-    [&]() { return a; }; 
-    [=]() { return a; }; 
-    [=]() { int* b = &a; }; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}} 
+    []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}}
+    [&]() { return a; };
+    [=]() { return a; };
+    [=]() { int* b = &a; }; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}}
     [=]() { return [&]() { return a; }; };
-    []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} 
-    []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} 
-    []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}} 
-    [=]() { return [&a] { return a; }; }; // 
+    []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
+    []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
+    []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}}
+    [=]() { return [&a] { return a; }; }; //
 
     const int b = 2;
-    []() { return b; }; 
+    []() { return b; };
 
     union { // expected-note {{declared}}
       int c;
       float d;
     };
     d = 3;
-    [=]() { return c; }; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}} 
+    [=]() { return c; }; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}}
 
     __block int e; // expected-note 3 {{declared}}
-    [&]() { return e; }; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}} 
-    [&e]() { return e; }; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}} 
+    [&]() { return e; }; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}}
+    [&e]() { return e; }; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}}
 
     int f[10]; // expected-note {{declared}}
-    [&]() { return f[2]; };  
+    [&]() { return f[2]; };
     (void) ^{ return []() { return f[2]; }; }; // expected-error {{variable 'f' cannot be implicitly captured in a lambda with no capture-default specified}} \
     // expected-note{{lambda expression begins here}}
 
     struct G { G(); G(G&); int a; }; // expected-note 6 {{not viable}}
     G g;
-    [=]() { const G* gg = &g; return gg->a; }; // expected-warning{{omitted result type}}
-    [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'ImplicitCapture::G'}}  \
-    // expected-warning{{omitted result type}}
-    (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const ImplicitCapture::G'}}  \
-    // expected-warning{{omitted result type}}
+    [=]() { const G* gg = &g; return gg->a; };
+    [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'ImplicitCapture::G'}}
+    (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const ImplicitCapture::G'}}
 
     const int h = a; // expected-note {{declared}}
-    []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} 
+    []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
 
     // The exemption for variables which can appear in constant expressions
     // applies only to objects (and not to references).
@@ -120,16 +117,16 @@ namespace NullPtr {
 
     const int m = 0;
     [=] {
-      int &k = f(m); // a null pointer constant
+      int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
     } ();
 
     [=] () -> bool {
-      int &k = f(m); // a null pointer constant
+      int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
       return &m == 0;
     } ();
 
     [m] {
-      int &k = f(m); // a null pointer constant
+      int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
     } ();
   }
 }
@@ -148,3 +145,79 @@ namespace ModifyingCapture {
     };
   }
 }
+
+namespace VariadicPackExpansion {
+  template<typename T, typename U> using Fst = T;
+  template<typename...Ts> bool g(Fst<bool, Ts> ...bools);
+  template<typename...Ts> bool f(Ts &&...ts) {
+    return g<Ts...>([&ts] {
+      if (!ts)
+        return false;
+      --ts;
+      return true;
+    } () ...);
+  }
+  void h() {
+    int a = 5, b = 2, c = 3;
+    while (f(a, b, c)) {
+    }
+  }
+
+  struct sink {
+    template<typename...Ts> sink(Ts &&...) {}
+  };
+
+  template<typename...Ts> void local_class() {
+    sink {
+      [] (Ts t) {
+        struct S : Ts {
+          void f(Ts t) {
+            Ts &that = *this;
+            that = t;
+          }
+          Ts g() { return *this; };
+        };
+        S s;
+        s.f(t);
+        return s;
+      } (Ts()).g() ...
+    };
+  };
+  struct X {}; struct Y {};
+  template void local_class<X, Y>();
+
+  template<typename...Ts> void nested(Ts ...ts) {
+    f(
+      // Each expansion of this lambda implicitly captures all of 'ts', because
+      // the inner lambda also expands 'ts'.
+      [&] {
+        return ts + [&] { return f(ts...); } ();
+      } () ...
+    );
+  }
+  template void nested(int, int, int);
+
+  template<typename...Ts> void nested2(Ts ...ts) { // expected-note 2{{here}}
+    // Capture all 'ts', use only one.
+    f([&ts...] { return ts; } ()...);
+    // Capture each 'ts', use it.
+    f([&ts] { return ts; } ()...);
+    // Capture all 'ts', use all of them.
+    f([&ts...] { return (int)f(ts...); } ());
+    // Capture each 'ts', use all of them. Ill-formed. In more detail:
+    //
+    // We instantiate two lambdas here; the first captures ts$0, the second
+    // captures ts$1. Both of them reference both ts parameters, so both are
+    // ill-formed because ts can't be implicitly captured.
+    //
+    // FIXME: This diagnostic does not explain what's happening. We should
+    // specify which 'ts' we're referring to in its diagnostic name. We should
+    // also say which slice of the pack expansion is being performed in the
+    // instantiation backtrace.
+    f([&ts] { return (int)f(ts...); } ()...); // \
+    // expected-error 2{{'ts' cannot be implicitly captured}} \
+    // expected-note 2{{lambda expression begins here}}
+  }
+  template void nested2(int); // ok
+  template void nested2(int, int); // expected-note {{in instantiation of}}
+}
-- 
cgit v1.1