r342194 - [Sema] Remove location from implicit capture init expr

Vedant Kumar via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 13 16:28:25 PDT 2018


Author: vedantk
Date: Thu Sep 13 16:28:25 2018
New Revision: 342194

URL: http://llvm.org/viewvc/llvm-project?rev=342194&view=rev
Log:
[Sema] Remove location from implicit capture init expr

A lambda's closure is initialized when the lambda is declared. For
implicit captures, the initialization code emitted from EmitLambdaExpr
references source locations *within the lambda body* in the function
containing the lambda. This results in a poor debugging experience: we
step to the line containing the lambda, then into lambda, out again,
over and over, until every capture's field is initialized.

To improve stepping behavior, assign the starting location of the lambda
to expressions which initialize an implicit capture within it.

rdar://39807527

Differential Revision: https://reviews.llvm.org/D50927

Added:
    cfe/trunk/test/CodeGenCXX/debug-info-lambda.cpp
Modified:
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
    cfe/trunk/test/SemaCXX/uninitialized.cpp
    cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=342194&r1=342193&r2=342194&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Thu Sep 13 16:28:25 2018
@@ -1392,13 +1392,14 @@ static void addBlockPointerConversion(Se
   Class->addDecl(Conversion);
 }
 
-static ExprResult performLambdaVarCaptureInitialization(Sema &S,
-                                                        const Capture &Capture,
-                                                        FieldDecl *Field) {
+static ExprResult performLambdaVarCaptureInitialization(
+    Sema &S, const Capture &Capture, FieldDecl *Field,
+    SourceLocation ImplicitCaptureLoc, bool IsImplicitCapture) {
   assert(Capture.isVariableCapture() && "not a variable capture");
 
   auto *Var = Capture.getVariable();
-  SourceLocation Loc = Capture.getLocation();
+  SourceLocation Loc =
+      IsImplicitCapture ? ImplicitCaptureLoc : Capture.getLocation();
 
   // C++11 [expr.prim.lambda]p21:
   //   When the lambda-expression is evaluated, the entities that
@@ -1607,8 +1608,8 @@ ExprResult Sema::BuildLambdaExpr(SourceL
                                        Var, From.getEllipsisLoc()));
       Expr *Init = From.getInitExpr();
       if (!Init) {
-        auto InitResult =
-            performLambdaVarCaptureInitialization(*this, From, *CurField);
+        auto InitResult = performLambdaVarCaptureInitialization(
+            *this, From, *CurField, CaptureDefaultLoc, IsImplicit);
         if (InitResult.isInvalid())
           return ExprError();
         Init = InitResult.get();

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp?rev=342194&r1=342193&r2=342194&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp Thu Sep 13 16:28:25 2018
@@ -15,8 +15,8 @@ public:
 
 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}} 
+  (void)[=] { // expected-error{{capture of variable 'ncr' as type 'NonCopyable' calls private copy constructor}}
+    ncr.foo();
   }();
 
   [nco] {}(); // expected-error{{no matching constructor for initialization of 'const NonConstCopy'}}

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp?rev=342194&r1=342193&r2=342194&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp Thu Sep 13 16:28:25 2018
@@ -88,8 +88,8 @@ namespace p2 {
   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}}
+      = typeid([=,&r] () -> R& { // expected-note{{in instantiation of member function 'p2::Boom<float>::Boom' requested here}}
+          boom.tickle();
           return r; 
         }()); 
   }

Added: cfe/trunk/test/CodeGenCXX/debug-info-lambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-lambda.cpp?rev=342194&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/debug-info-lambda.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/debug-info-lambda.cpp Thu Sep 13 16:28:25 2018
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm \
+// RUN:   -debug-info-kind=line-tables-only -dwarf-column-info -std=c++11 %s -o - | FileCheck %s
+
+// CHECK-LABEL: define{{.*}}lambda_in_func
+void lambda_in_func(int &ref) {
+  // CHECK: [[ref_slot:%.*]] = getelementptr inbounds %class.anon, %class.anon* {{.*}}, i32 0, i32 0, !dbg [[lambda_decl_loc:![0-9]+]]
+  // CHECK-NEXT: %1 = load i32*, i32** %ref.addr, align 8, !dbg [[capture_init_loc:![0-9]+]]
+  // CHECK-NEXT: store i32* %1, i32** %0, align 8, !dbg [[lambda_decl_loc]]
+  // CHECK-NEXT: call void {{.*}}, !dbg [[lambda_call_loc:![0-9]+]]
+
+  auto helper = [       // CHECK: [[lambda_decl_loc]] = !DILocation(line: [[@LINE]], column: 17
+                 &]() { // CHECK: [[capture_init_loc]] = !DILocation(line: [[@LINE]], column: 18
+    ++ref;
+  };
+  helper();             // CHECK: [[lambda_call_loc]] = !DILocation(line: [[@LINE]]
+}

Modified: cfe/trunk/test/SemaCXX/uninitialized.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/uninitialized.cpp?rev=342194&r1=342193&r2=342194&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/uninitialized.cpp (original)
+++ cfe/trunk/test/SemaCXX/uninitialized.cpp Thu Sep 13 16:28:25 2018
@@ -884,8 +884,10 @@ namespace lambdas {
     int x;
   };
   A a0([] { return a0.x; }); // ok
-  void f() { 
-    A a1([=] { return a1.x; }); // expected-warning{{variable 'a1' is uninitialized when used within its own initialization}}
+  void f() {
+    A a1([=] { // expected-warning{{variable 'a1' is uninitialized when used within its own initialization}}
+      return a1.x;
+    });
     A a2([&] { return a2.x; }); // ok
   }
 }

Modified: cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp?rev=342194&r1=342193&r2=342194&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp (original)
+++ cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/DeclRefExpr.cpp Thu Sep 13 16:28:25 2018
@@ -75,11 +75,11 @@ TEST(RecursiveASTVisitor, VisitsUseOfImp
 TEST(RecursiveASTVisitor, VisitsImplicitLambdaCaptureInit) {
   DeclRefExprVisitor Visitor;
   Visitor.setShouldVisitImplicitCode(true);
-  // We're expecting the "i" in the lambda to be visited twice:
-  // - Once for the DeclRefExpr in the lambda capture initialization (whose
-  //   source code location is set to the first use of the variable).
-  // - Once for the DeclRefExpr for the use of "i" inside the lambda.
-  Visitor.ExpectMatch("i", 1, 24, /*Times=*/2);
+  // We're expecting "i" to be visited twice: once for the initialization expr
+  // for the captured variable "i" outside of the lambda body, and again for
+  // the use of "i" inside the lambda.
+  Visitor.ExpectMatch("i", 1, 20, /*Times=*/1);
+  Visitor.ExpectMatch("i", 1, 24, /*Times=*/1);
   EXPECT_TRUE(Visitor.runOver(
     "void f() { int i; [=]{ i; }; }",
     DeclRefExprVisitor::Lang_CXX11));




More information about the cfe-commits mailing list