When variables are implicitly captured in lambdas, debug info generated for captured variables points to location where they are used first. This patch makes debug info to point to capture default location:
extern "C" int printf(const char *, ...); template<typename F> void invoke( const F& f ) { f(); } int main () { int apple = 0; int banana = 1; int cherry = 2; invoke( 13. [=]{ 14. printf("apple = %d\n",apple); 15. printf("banana = %d\n",banana); 16. printf("cherry = %d\n",cherry); } ); return 0; }
Clang is generating the following code for preparing the "invoke" parameter, which is the lambda:
%0 = getelementptr inbounds %class.anon, %class.anon* %ref.tmp, i32 0, i32 0, !dbg !40 %1 = load i32, i32* %apple, align 4, !dbg !41 store i32 %1, i32* %0, align 4, !dbg !40 %2 = getelementptr inbounds %class.anon, %class.anon* %ref.tmp, i32 0, i32 1, !dbg !40 %3 = load i32, i32* %banana, align 4, !dbg !42 store i32 %3, i32* %2, align 4, !dbg !40 %4 = getelementptr inbounds %class.anon, %class.anon* %ref.tmp, i32 0, i32 2, !dbg !40 %5 = load i32, i32* %cherry, align 4, !dbg !43 store i32 %5, i32* %4, align 4, !dbg !40 !39 = !DILocation(line: 10, column: 9, scope: !4) !40 = !DILocation(line: 13, column: 9, scope: !4) !41 = !DILocation(line: 14, column: 35, scope: !4) !42 = !DILocation(line: 15, column: 36, scope: !4) !43 = !DILocation(line: 16, column: 36, scope: !4)
Notice that both the GEP and the store are associated with line 13 (as expected), however the loads are associated with lines 14,15,16.
We expect these loads to be associated with line 13.
Notice that if the code was like this:
13. [apple, banana, cherry]{ 14. printf("apple = %d\n",apple); 15. printf("banana = %d\n",banana); 16. printf("cherry = %d\n",cherry); }
Then the loads would be associated with line 13.