forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			301 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			301 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -emit-llvm-only %s
 | 
						|
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
 | 
						|
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
 | 
						|
// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
 | 
						|
 | 
						|
template <class, class>
 | 
						|
constexpr bool is_same = false;
 | 
						|
template <class T>
 | 
						|
constexpr bool is_same<T, T> = true;
 | 
						|
 | 
						|
namespace test_star_this {
 | 
						|
namespace ns1 {
 | 
						|
class A {
 | 
						|
  int x = 345;
 | 
						|
  auto foo() {
 | 
						|
    (void)[ *this, this ]{}; //expected-error{{'this' can appear only once}}
 | 
						|
    (void)[this] { ++x; };
 | 
						|
    (void)[*this] { ++x; }; //expected-error{{read-only variable}}
 | 
						|
    (void)[*this]() mutable { ++x; };
 | 
						|
    (void)[=] { return x; };
 | 
						|
    (void)[&, this ] { return x; };
 | 
						|
    (void)[ =, *this ] { return x; };
 | 
						|
    (void)[&, *this ] { return x; };
 | 
						|
  }
 | 
						|
};
 | 
						|
} // namespace ns1
 | 
						|
 | 
						|
namespace ns2 {
 | 
						|
class B {
 | 
						|
  B(const B &) = delete; //expected-note{{deleted here}}
 | 
						|
  int *x = (int *)456;
 | 
						|
  void foo() {
 | 
						|
    (void)[this] { return x; };
 | 
						|
    (void)[*this] { return x; }; //expected-error{{call to deleted}}
 | 
						|
  }
 | 
						|
};
 | 
						|
} // namespace ns2
 | 
						|
 | 
						|
namespace ns3 {
 | 
						|
class B {
 | 
						|
  B(const B &) = delete; //expected-note2{{deleted here}}
 | 
						|
 | 
						|
  int *x = (int *)456;
 | 
						|
 | 
						|
public:
 | 
						|
  template <class T = int>
 | 
						|
  void foo() {
 | 
						|
    (void)[this] { return x; };
 | 
						|
    (void)[*this] { return x; }; //expected-error2{{call to deleted}}
 | 
						|
  }
 | 
						|
 | 
						|
  B() = default;
 | 
						|
} b;
 | 
						|
B *c = (b.foo(), nullptr); //expected-note{{in instantiation}}
 | 
						|
} // namespace ns3
 | 
						|
 | 
						|
namespace ns4 {
 | 
						|
template <class U>
 | 
						|
class B {
 | 
						|
  B(const B &) = delete; //expected-note{{deleted here}}
 | 
						|
  double d = 3.14;
 | 
						|
 | 
						|
public:
 | 
						|
  template <class T = int>
 | 
						|
  auto foo() {
 | 
						|
    const auto &L = [*this](auto a) mutable { //expected-error{{call to deleted}}
 | 
						|
      d += a;
 | 
						|
      return [this](auto b) { return d += b; };
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  B() = default;
 | 
						|
};
 | 
						|
void main() {
 | 
						|
  B<int *> b;
 | 
						|
  b.foo(); //expected-note{{in instantiation}}
 | 
						|
} // end main
 | 
						|
} // namespace ns4
 | 
						|
 | 
						|
namespace ns5 {
 | 
						|
 | 
						|
struct X {
 | 
						|
  double d = 3.14;
 | 
						|
  X(const volatile X &);
 | 
						|
  void foo() {
 | 
						|
  }
 | 
						|
 | 
						|
  void foo() const { //expected-note{{const}}
 | 
						|
 | 
						|
    auto L = [*this]() mutable {
 | 
						|
      static_assert(is_same<decltype(this), X *>);
 | 
						|
      ++d;
 | 
						|
      auto M = [this] {
 | 
						|
        static_assert(is_same<decltype(this), X *>);
 | 
						|
        ++d;
 | 
						|
        auto N = [] {
 | 
						|
          static_assert(is_same<decltype(this), X *>);
 | 
						|
        };
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    auto L1 = [*this] {
 | 
						|
      static_assert(is_same<decltype(this), const X *>);
 | 
						|
      auto M = [this]() mutable {
 | 
						|
        static_assert(is_same<decltype(this), const X *>);
 | 
						|
        auto N = [] {
 | 
						|
          static_assert(is_same<decltype(this), const X *>);
 | 
						|
        };
 | 
						|
      };
 | 
						|
      auto M2 = [*this]() mutable {
 | 
						|
        static_assert(is_same<decltype(this), X *>);
 | 
						|
        auto N = [] {
 | 
						|
          static_assert(is_same<decltype(this), X *>);
 | 
						|
        };
 | 
						|
      };
 | 
						|
    };
 | 
						|
 | 
						|
    auto GL1 = [*this](auto a) {
 | 
						|
      static_assert(is_same<decltype(this), const X *>);
 | 
						|
      auto M = [this](auto b) mutable {
 | 
						|
        static_assert(is_same<decltype(this), const X *>);
 | 
						|
        auto N = [](auto c) {
 | 
						|
          static_assert(is_same<decltype(this), const X *>);
 | 
						|
        };
 | 
						|
        return N;
 | 
						|
      };
 | 
						|
 | 
						|
      auto M2 = [*this](auto a) mutable {
 | 
						|
        static_assert(is_same<decltype(this), X *>);
 | 
						|
        auto N = [](auto b) {
 | 
						|
          static_assert(is_same<decltype(this), X *>);
 | 
						|
        };
 | 
						|
        return N;
 | 
						|
      };
 | 
						|
      return [=](auto a) mutable { M(a)(a); M2(a)(a); };
 | 
						|
    };
 | 
						|
 | 
						|
    GL1("abc")
 | 
						|
    ("abc");
 | 
						|
 | 
						|
    auto L2 = [this]() mutable {
 | 
						|
      static_assert(is_same<decltype(this), const X *>);
 | 
						|
      ++d; //expected-error{{cannot assign}}
 | 
						|
    };
 | 
						|
    auto GL = [*this](auto a) mutable {
 | 
						|
      static_assert(is_same<decltype(this), X *>);
 | 
						|
      ++d;
 | 
						|
      auto M = [this](auto b) {
 | 
						|
        static_assert(is_same<decltype(this), X *>);
 | 
						|
        ++d;
 | 
						|
        auto N = [](auto c) {
 | 
						|
          static_assert(is_same<decltype(this), X *>);
 | 
						|
        };
 | 
						|
        N(3.14);
 | 
						|
      };
 | 
						|
      M("abc");
 | 
						|
    };
 | 
						|
    GL(3.14);
 | 
						|
  }
 | 
						|
  void foo() volatile const {
 | 
						|
    auto L = [this]() {
 | 
						|
      static_assert(is_same<decltype(this), const volatile X *>);
 | 
						|
      auto M = [*this]() mutable {
 | 
						|
        static_assert(is_same<decltype(this), X *>);
 | 
						|
        auto N = [this] {
 | 
						|
          static_assert(is_same<decltype(this), X *>);
 | 
						|
          auto M = [] {
 | 
						|
            static_assert(is_same<decltype(this), X *>);
 | 
						|
          };
 | 
						|
        };
 | 
						|
        auto N2 = [*this] {
 | 
						|
          static_assert(is_same<decltype(this), const X *>);
 | 
						|
        };
 | 
						|
      };
 | 
						|
      auto M2 = [*this]() {
 | 
						|
        static_assert(is_same<decltype(this), const X *>);
 | 
						|
        auto N = [this] {
 | 
						|
          static_assert(is_same<decltype(this), const X *>);
 | 
						|
        };
 | 
						|
      };
 | 
						|
    };
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
} // namespace ns5
 | 
						|
namespace ns6 {
 | 
						|
struct X {
 | 
						|
  double d;
 | 
						|
  auto foo() const {
 | 
						|
    auto L = [*this]() mutable {
 | 
						|
      auto M = [=](auto a) {
 | 
						|
        auto N = [this] {
 | 
						|
          ++d;
 | 
						|
          static_assert(is_same<decltype(this), X *>);
 | 
						|
          auto O = [*this] {
 | 
						|
            static_assert(is_same<decltype(this), const X *>);
 | 
						|
          };
 | 
						|
        };
 | 
						|
        N();
 | 
						|
        static_assert(is_same<decltype(this), X *>);
 | 
						|
      };
 | 
						|
      return M;
 | 
						|
    };
 | 
						|
    return L;
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
int main() {
 | 
						|
  auto L = X{}.foo();
 | 
						|
  auto M = L();
 | 
						|
  M(3.14);
 | 
						|
}
 | 
						|
} // namespace ns6
 | 
						|
namespace ns7 {
 | 
						|
 | 
						|
struct X {
 | 
						|
  double d;
 | 
						|
  X();
 | 
						|
  X(const X &);
 | 
						|
  X(X &) = delete;
 | 
						|
  auto foo() const {
 | 
						|
    //OK - the object used to initialize our capture is a const object and so prefers the non-deleted ctor.
 | 
						|
    const auto &&L = [*this]{};
 | 
						|
  }
 | 
						|
};
 | 
						|
int main() {
 | 
						|
  X x;
 | 
						|
  x.foo();
 | 
						|
}
 | 
						|
} // namespace ns7
 | 
						|
 | 
						|
} // namespace test_star_this
 | 
						|
 | 
						|
namespace PR32831 {
 | 
						|
// https://bugs.llvm.org/show_bug.cgi?id=32831
 | 
						|
namespace ns1 {
 | 
						|
template <typename Func>
 | 
						|
void fun_template(Func func) {
 | 
						|
  (void)[&]() {
 | 
						|
    func(0);
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
class A {
 | 
						|
  void member_foo() {
 | 
						|
    (void)[this] {
 | 
						|
      (void)[this] {
 | 
						|
        fun_template(
 | 
						|
            [this](auto X) {
 | 
						|
              auto L = [this](auto Y) { member_foo(); };
 | 
						|
              L(5);
 | 
						|
            });
 | 
						|
        fun_template(
 | 
						|
            [this](auto) { member_foo(); });
 | 
						|
      };
 | 
						|
    };
 | 
						|
  }
 | 
						|
};
 | 
						|
} // namespace ns1
 | 
						|
 | 
						|
namespace ns2 {
 | 
						|
 | 
						|
struct B {
 | 
						|
  int data = 0;
 | 
						|
  template <class F>
 | 
						|
  void mem2(F f) {
 | 
						|
    (void)[&](auto f) {
 | 
						|
      (void)[&] { f(this->data); };
 | 
						|
    }
 | 
						|
    (f);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class A {
 | 
						|
  void member_foo() {
 | 
						|
    (void)[this] {
 | 
						|
      (void)[this] {
 | 
						|
        B{}.mem2(
 | 
						|
            [this](auto X) {
 | 
						|
              auto L = [this](auto Y) { member_foo(); };
 | 
						|
              L(5);
 | 
						|
            });
 | 
						|
        B{}.mem2(
 | 
						|
            [this](auto) { member_foo(); });
 | 
						|
      };
 | 
						|
    };
 | 
						|
  }
 | 
						|
  int data = 0;
 | 
						|
  auto m2() {
 | 
						|
    return [this] { return [] () -> decltype(data){ return 0; }; };
 | 
						|
  }
 | 
						|
  auto m3() {
 | 
						|
    return [] { return [] () -> decltype(data){ return 0; }; };
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
} // namespace ns2
 | 
						|
 | 
						|
} // namespace PR32831
 | 
						|
 |