This fixes a bug in clang where, when clang sees a switch with a fallthrough to a default like this:
static void funcA(void) {}
static void funcB(void) {}
int main(int argc, char **argv) {
switch (argc) { case 0: funcA(); break; case 10: default: funcB(); break; }
}
It does not add a proper debug location for that switch case, such as case 10: above.
The IR output looks like this:
Function Attrs: noinline nounwind optnone ssp uwtable
define i32 @main(i32 %0, i8** %1) #0 !dbg !9 {
%3 = alloca i32, align 4 %4 = alloca i32, align 4 %5 = alloca i8**, align 8 store i32 0, i32* %3, align 4 store i32 %0, i32* %4, align 4 call void @llvm.dbg.declare(metadata i32* %4, metadata !16, metadata !DIExpression()), !dbg !17 store i8** %1, i8*** %5, align 8 call void @llvm.dbg.declare(metadata i8*** %5, metadata !18, metadata !DIExpression()), !dbg !19 %6 = load i32, i32* %4, align 4, !dbg !20 switch i32 %6, label %9 [ i32 0, label %7 i32 10, label %8 ], !dbg !21
7: ; preds = %2
call void @funcA(), !dbg !22 br label %10, !dbg !24
8: ; preds = %2
br label %9, !dbg !24
9: ; preds = %2, %8
call void @funcB(), !dbg !25 br label %10, !dbg !26
10: ; preds = %9, %7
%11 = load i32, i32* %3, align 4, !dbg !27 ret i32 %11, !dbg !27
}
label 7 and label 8 both have branches but label 8's branch uses the same debug location as label 7's branch. This resolves to disassembly such as:
LBB0_5:
.loc 1 0 5 Documents/test.c:0:5
movl -20(%rbp), %eax 4-byte Reload
.loc 1 5 5 Documents/test.c:5:5
subl $10, %eax
je LBB0_2
jmp LBB0_3
LBB0_1:
Ltmp1:
.loc 1 7 13 is_stmt 1 Documents/test.c:7:13
callq _funcA
.loc 1 8 13 Documents/test.c:8:13
jmp LBB0_4
LBB0_2:
jmp LBB0_3
LBB0_3:
.loc 1 11 13 Documents/test.c:11:13
callq _funcB
LBB0_2 does not get a .loc in this case
Is the default statement special in a meaningful way here, or could a more general patch also work for a switch statement like:
In other words, should wee just unconditionally emit a stop point?