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