-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[DebugInfo] Correct the line attribution for IF branches #108300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// RUN: %clang_cc1 -debug-info-kind=limited -gno-column-info -triple=x86_64-pc-linux -emit-llvm %s -o - | FileCheck %s | ||
|
||
// The important thing is that the compare and the conditional branch have | ||
// locs with the same scope (the lexical block for the 'if'). By turning off | ||
// column info, they end up with the same !dbg record, which halves the number | ||
// of checks to verify the scope. | ||
|
||
int c = 2; | ||
|
||
int f() { | ||
#line 100 | ||
if (int a = 5; a > c) | ||
return 1; | ||
return 0; | ||
} | ||
// CHECK-LABEL: define {{.*}} @_Z1fv() | ||
// CHECK: = icmp {{.*}} !dbg [[F_CMP:![0-9]+]] | ||
// CHECK-NEXT: br i1 {{.*}} !dbg [[F_CMP]] | ||
|
||
int g() { | ||
#line 200 | ||
if (int a = f()) | ||
return 2; | ||
return 3; | ||
} | ||
// CHECK-LABEL: define {{.*}} @_Z1gv() | ||
// CHECK: = icmp {{.*}} !dbg [[G_CMP:![0-9]+]] | ||
// CHECK-NEXT: br i1 {{.*}} !dbg [[G_CMP]] | ||
|
||
int h() { | ||
#line 300 | ||
if (c > 3) | ||
return 4; | ||
return 5; | ||
} | ||
// CHECK-LABEL: define {{.*}} @_Z1hv() | ||
// CHECK: = icmp {{.*}} !dbg [[H_CMP:![0-9]+]] | ||
// CHECK-NEXT: br i1 {{.*}} !dbg [[H_CMP]] | ||
|
||
// CHECK-DAG: [[F_CMP]] = !DILocation(line: 100, scope: [[F_SCOPE:![0-9]+]] | ||
// CHECK-DAG: [[F_SCOPE]] = distinct !DILexicalBlock({{.*}} line: 100) | ||
// CHECK-DAG: [[G_CMP]] = !DILocation(line: 200, scope: [[G_SCOPE:![0-9]+]] | ||
// CHECK-DAG: [[G_SCOPE]] = distinct !DILexicalBlock({{.*}} line: 200) | ||
// CHECK-DAG: [[H_CMP]] = !DILocation(line: 300, scope: [[H_SCOPE:![0-9]+]] | ||
// CHECK-DAG: [[H_SCOPE]] = distinct !DILexicalBlock({{.*}} line: 300) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come this case ^ already works (so far as I can tell) without this patch, but the others don't? Because we introduce a scope for the variable declaration in a way that we don't in the (cond) case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes. That's because EmitIfStmt calls EmitStmt on the initialization statement, which calls EmitStopPoint, which creates a DILocation with the correct scope; this implicitly applies to the rest of the 'if' statement. For (int a = foo()) case, it just issues a declaration for the variable and then proceeds with a normal expression evaluation; the declaration doesn't call EmitStopPoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, yeah, that
EmitStopPoint
seems a bit unstable/unreliable - the scoped location handling is designed to be more robust to ensure locations don't "leak out" beyond where they're meant to apply...I think maybe
EmitStopPoint
should be removed/reconsidered, but that's perhaps beyond the scope (har har) of this issue - but thoughts in case anyone else feels like picking up and running with that.How's this location compare to other control structures (loops, etc) - do we (& GCC) use the condition as the location for the branch instructions, or would it be more suitable to use the start of
if
itself?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
& I guess this all only applies when the control structure doesn't have
{}
? (that being why the test doesn't have braces?)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed this where my test case led me. You're right it's worth looking at other control structures that have implied lexical blocks.
No, this applies in all cases.
The implied lexical block started by the
if
statement spans its then and else parts; whether those parts are simple or compound doesn't matter. Analogous to how a function definition has an implied lexical block at the opening paren of the parameter list; the function name is visible in the containing scope, the parameter names are not.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re. other statements:
while
does not appear to have a problem, howeverfor
does. Looking at the implementation, I would have expected it to crop up only when the firstfor
clause is empty, but in fact it happens regardless. It conjures up not one but two DILexicalBlocks, both pointing to thefor
keyword. I'd prefer to look into that more deeply as a separate task.