[Debug] Annotate compiler generated range-for loop variables.
Summary:
This change aims to simplify debugging by annotating the range-for loop artificial variables (range, begin, end) with the scope depth.
Reviewers: rsmith, dblaikie
Reviewed By: dblaikie
Subscribers: dblaikie, cfe-commits
Tags: #debug-info
Differential Revision: https://reviews.llvm.org/D42813
llvm-svn: 325175
diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h
index cd58a99..1dd1675 100644
--- a/clang/include/clang/Sema/Scope.h
+++ b/clang/include/clang/Sema/Scope.h
@@ -259,6 +259,9 @@
Scope *getTemplateParamParent() { return TemplateParamParent; }
const Scope *getTemplateParamParent() const { return TemplateParamParent; }
+ /// Returns the depth of this scope. The translation-unit has scope depth 0.
+ unsigned getDepth() const { return Depth; }
+
/// Returns the number of function prototype scopes in this scope
/// chain.
unsigned getFunctionPrototypeDepth() const {
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 9390703..b770185 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2025,7 +2025,7 @@
/// Build a variable declaration for a for-range statement.
VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
- QualType Type, const char *Name) {
+ QualType Type, StringRef Name) {
DeclContext *DC = SemaRef.CurContext;
IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -2094,10 +2094,12 @@
}
// Build auto && __range = range-init
+ // Divide by 2, since the variables are in the inner scope (loop body).
+ const auto DepthStr = std::to_string(S->getDepth() / 2);
SourceLocation RangeLoc = Range->getLocStart();
VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
Context.getAutoRRefDeductType(),
- "__range");
+ std::string("__range") + DepthStr);
if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
diag::err_for_range_deduction_failure)) {
LoopVar->setInvalidDecl();
@@ -2340,10 +2342,12 @@
return StmtError();
// Build auto __begin = begin-expr, __end = end-expr.
+ // Divide by 2, since the variables are in the inner scope (loop body).
+ const auto DepthStr = std::to_string(S->getDepth() / 2);
VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
- "__begin");
+ std::string("__begin") + DepthStr);
VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
- "__end");
+ std::string("__end") + DepthStr);
// Build begin-expr and end-expr and attach to __begin and __end variables.
ExprResult BeginExpr, EndExpr;
diff --git a/clang/test/CodeGenCXX/debug-info-range-for-var-names.cpp b/clang/test/CodeGenCXX/debug-info-range-for-var-names.cpp
new file mode 100644
index 0000000..34f3b25
--- /dev/null
+++ b/clang/test/CodeGenCXX/debug-info-range-for-var-names.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+
+struct vec {
+ using itr = int*;
+ itr begin() { return nullptr; }
+ itr end() { return nullptr; }
+};
+
+void test() {
+ vec as, bs, cs;
+
+ for (auto a : as)
+ for (auto b : bs)
+ for (auto c : cs) {
+ }
+}
+
+// CHECK: define void @_Z4testv()
+// CHECK: call void @llvm.dbg.declare(metadata %struct.vec** {{.*}}, metadata ![[RANGE1:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[BEGIN1:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[END1:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata %struct.vec** {{.*}}, metadata ![[RANGE2:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[BEGIN2:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[END2:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata %struct.vec** {{.*}}, metadata ![[RANGE3:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[BEGIN3:[0-9]+]]
+// CHECK: call void @llvm.dbg.declare(metadata i32** {{.*}}, metadata ![[END3:[0-9]+]]
+// CHECK: ![[RANGE1]] = !DILocalVariable(name: "__range1",
+// CHECK: ![[BEGIN1]] = !DILocalVariable(name: "__begin1",
+// CHECK: ![[END1]] = !DILocalVariable(name: "__end1",
+// CHECK: ![[RANGE2]] = !DILocalVariable(name: "__range2",
+// CHECK: ![[BEGIN2]] = !DILocalVariable(name: "__begin2",
+// CHECK: ![[END2]] = !DILocalVariable(name: "__end2",
+// CHECK: ![[RANGE3]] = !DILocalVariable(name: "__range3",
+// CHECK: ![[BEGIN3]] = !DILocalVariable(name: "__begin3",
+// CHECK: ![[END3]] = !DILocalVariable(name: "__end3",
diff --git a/clang/test/CodeGenCXX/debug-info-scope.cpp b/clang/test/CodeGenCXX/debug-info-scope.cpp
index e81eccc..1124282 100644
--- a/clang/test/CodeGenCXX/debug-info-scope.cpp
+++ b/clang/test/CodeGenCXX/debug-info-scope.cpp
@@ -58,7 +58,7 @@
}
int x[] = {1, 2};
- // CHECK: = !DILocalVariable(name: "__range"
+ // CHECK: = !DILocalVariable(name: "__range1"
// CHECK-SAME: scope: [[RANGE_FOR:![0-9]*]]
// CHECK-NOT: line:
// CHECK-SAME: ){{$}}
diff --git a/clang/test/CodeGenCXX/vla.cpp b/clang/test/CodeGenCXX/vla.cpp
index b8652f8..273e413 100644
--- a/clang/test/CodeGenCXX/vla.cpp
+++ b/clang/test/CodeGenCXX/vla.cpp
@@ -68,8 +68,8 @@
void test2(int b) {
// CHECK-LABEL: define void {{.*}}test2{{.*}}(i32 %b)
int varr[b];
- // AMD: %__end = alloca i32*, align 8, addrspace(5)
- // AMD: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end to i32**
+ // AMD: %__end1 = alloca i32*, align 8, addrspace(5)
+ // AMD: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end1 to i32**
// get the address of %b by checking the first store that stores it
//CHECK: store i32 %b, i32* [[PTR_B:%.*]]
@@ -86,7 +86,7 @@
//CHECK: [[VLA_SIZEOF:%.*]] = mul nuw i64 4, [[VLA_NUM_ELEMENTS_PRE]]
//CHECK-NEXT: [[VLA_NUM_ELEMENTS_POST:%.*]] = udiv i64 [[VLA_SIZEOF]], 4
//CHECK-NEXT: [[VLA_END_PTR:%.*]] = getelementptr inbounds i32, i32* {{%.*}}, i64 [[VLA_NUM_ELEMENTS_POST]]
- //X64-NEXT: store i32* [[VLA_END_PTR]], i32** %__end
+ //X64-NEXT: store i32* [[VLA_END_PTR]], i32** %__end1
//AMD-NEXT: store i32* [[VLA_END_PTR]], i32** [[END]]
for (int d : varr) 0;
}
@@ -94,8 +94,8 @@
void test3(int b, int c) {
// CHECK-LABEL: define void {{.*}}test3{{.*}}(i32 %b, i32 %c)
int varr[b][c];
- // AMD: %__end = alloca i32*, align 8, addrspace(5)
- // AMD: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end to i32**
+ // AMD: %__end1 = alloca i32*, align 8, addrspace(5)
+ // AMD: [[END:%.*]] = addrspacecast i32* addrspace(5)* %__end1 to i32**
// get the address of %b by checking the first store that stores it
//CHECK: store i32 %b, i32* [[PTR_B:%.*]]
//CHECK-NEXT: store i32 %c, i32* [[PTR_C:%.*]]