r301916 - Revert r301735 (and subsequent r301786).
Daniel Jasper via cfe-commits
cfe-commits at lists.llvm.org
Tue May 2 05:53:39 PDT 2017
I forgot the () in the lambda definition, this should be:
..
auto l = [this] { auto l = []() EXCLUSIVE_LOCKS_REQUIRED(mu_) {}; };
..
Doesn't change the fact that clang segfaults without this revert, though.
On Tue, May 2, 2017 at 2:38 PM, Daniel Jasper via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> Author: djasper
> Date: Tue May 2 07:38:27 2017
> New Revision: 301916
>
> URL: http://llvm.org/viewvc/llvm-project?rev=301916&view=rev
> Log:
> Revert r301735 (and subsequent r301786).
>
> It leads to clang crashing, e.g. on this short code fragment (added to
> test/SemaCXX/warn-thread-safety-parsing.cpp):
>
> class SomeClass {
> public:
> void foo() {
> auto l = [this] { auto l = [] EXCLUSIVE_LOCKS_REQUIRED(mu_) {}; };
> }
> Mutex mu_;
> };
>
> Modified:
> cfe/trunk/lib/Sema/SemaExprCXX.cpp
> cfe/trunk/test/SemaCXX/cxx1z-lambda-star-this.cpp
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/
> SemaExprCXX.cpp?rev=301916&r1=301915&r2=301916&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue May 2 07:38:27 2017
> @@ -901,35 +901,17 @@ static QualType adjustCVQualifiersForCXX
> // capturing lamdbda's call operator.
> //
>
> - // Since the FunctionScopeInfo stack is representative of the lexical
> - // nesting of the lambda expressions during initial parsing (and is the
> best
> - // place for querying information about captures about lambdas that are
> - // partially processed) and perhaps during instantiation of function
> templates
> - // that contain lambda expressions that need to be transformed BUT not
> - // necessarily during instantiation of a nested generic lambda's
> function call
> - // operator (which might even be instantiated at the end of the TU) -
> at which
> - // time the DeclContext tree is mature enough to query capture
> information
> - // reliably - we use a two pronged approach to walk through all the
> lexically
> - // enclosing lambda expressions:
> - //
> - // 1) Climb down the FunctionScopeInfo stack as long as each item
> represents
> - // a Lambda (i.e. LambdaScopeInfo) AND each LSI's 'closure-type' is
> lexically
> - // enclosed by the call-operator of the LSI below it on the stack
> (while
> - // tracking the enclosing DC for step 2 if needed). Note the topmost
> LSI on
> - // the stack represents the innermost lambda.
> - //
> - // 2) Iterate out through the DeclContext chain (if it represents a
> lambda's
> - // call operator, and therefore must be a generic lambda's call
> operator,
> - // which is the only time an inconsistency between the LSI and the
> - // DeclContext should occur) querying closure types regarding capture
> - // information.
> + // The issue is that we cannot rely entirely on the FunctionScopeInfo
> stack
> + // since ScopeInfos are pushed on during parsing and treetransforming.
> But
> + // since a generic lambda's call operator can be instantiated anywhere
> (even
> + // end of the TU) we need to be able to examine its enclosing lambdas
> and so
> + // we use the DeclContext to get a hold of the closure-class and query
> it for
> + // capture information. The reason we don't just resort to always
> using the
> + // DeclContext chain is that it is only mature for lambda expressions
> + // enclosing generic lambda's call operators that are being
> instantiated.
>
> -
> - // 1) Climb down the function scope info stack.
> for (int I = FunctionScopes.size();
> - I-- && isa<LambdaScopeInfo>(FunctionScopes[I]) &&
> - (!CurLSI || CurLSI->Lambda->getDeclContext() ==
> - cast<LambdaScopeInfo>(FunctionScopes[I])->
> CallOperator);
> + I-- && isa<LambdaScopeInfo>(FunctionScopes[I]);
> CurDC = getLambdaAwareParentOfDeclContext(CurDC)) {
> CurLSI = cast<LambdaScopeInfo>(FunctionScopes[I]);
>
> @@ -945,17 +927,11 @@ static QualType adjustCVQualifiersForCXX
> return ASTCtx.getPointerType(ClassType);
> }
> }
> -
> - // 2) We've run out of ScopeInfos but check if CurDC is a lambda (which
> can
> - // happen during instantiation of its nested generic lambda call
> operator)
> + // We've run out of ScopeInfos but check if CurDC is a lambda (which can
> + // happen during instantiation of generic lambdas)
> if (isLambdaCallOperator(CurDC)) {
> - assert(CurLSI && "While computing 'this' capture-type for a generic "
> - "lambda, we must have a corresponding
> LambdaScopeInfo");
> - assert(isGenericLambdaCallOperatorSpecialization(CurLSI->CallOperator)
> &&
> - "While computing 'this' capture-type for a generic lambda,
> when we "
> - "run out of enclosing LSI's, yet the enclosing DC is a "
> - "lambda-call-operator we must be (i.e. Current LSI) in a
> generic "
> - "lambda call oeprator");
> + assert(CurLSI);
> + assert(isGenericLambdaCallOperatorSpecialization(CurLSI->
> CallOperator));
> assert(CurDC == getLambdaAwareParentOfDeclCont
> ext(CurLSI->CallOperator));
>
> auto IsThisCaptured =
>
> Modified: cfe/trunk/test/SemaCXX/cxx1z-lambda-star-this.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/
> SemaCXX/cxx1z-lambda-star-this.cpp?rev=301916&r1=301915&
> r2=301916&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/cxx1z-lambda-star-this.cpp (original)
> +++ cfe/trunk/test/SemaCXX/cxx1z-lambda-star-this.cpp Tue May 2 07:38:27
> 2017
> @@ -1,293 +1,231 @@
> -// 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(); });
> - };
> - };
> - }
> -};
> -
> -} // namespace ns2
> -
> -} // namespace PR32831
> -
> +// 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; };
> + }
> +};
> +} // end 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}}
> + }
> + };
> +} // end 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}}
> +} // end 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
> +} // end 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*>);
> + };
> + };
> + };
> + }
> +
> +};
> +
> +} //end 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);
> +}
> +} // end 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();
> +}
> +} // end ns7
> +
> +} //end ns test_star_this
> +
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170502/3a105232/attachment-0001.html>
More information about the cfe-commits
mailing list