]> granicus.if.org Git - clang/commitdiff
[Debug] Annotate compiler generated range-for loop variables.
authorMatt Davis <Matthew.Davis@sony.com>
Wed, 14 Feb 2018 21:22:11 +0000 (21:22 +0000)
committerMatt Davis <Matthew.Davis@sony.com>
Wed, 14 Feb 2018 21:22:11 +0000 (21:22 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325175 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Scope.h
lib/Sema/SemaStmt.cpp
test/CodeGenCXX/debug-info-range-for-var-names.cpp [new file with mode: 0644]
test/CodeGenCXX/debug-info-scope.cpp
test/CodeGenCXX/vla.cpp

index cd58a9910f98ea31ed9d8acc9630423eed9f3f61..1dd1675561ba3f0ab407e8bdc041e3a4fcfd1bbd 100644 (file)
@@ -259,6 +259,9 @@ public:
   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 {
index 93907038e05f9bd50054b260ec4f9fefb6818d3e..b77018503af430973434a4d36bd99ff6553b42d9 100644 (file)
@@ -2025,7 +2025,7 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
 
 /// 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 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
   }
 
   // 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 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation CoawaitLoc,
       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/test/CodeGenCXX/debug-info-range-for-var-names.cpp b/test/CodeGenCXX/debug-info-range-for-var-names.cpp
new file mode 100644 (file)
index 0000000..34f3b25
--- /dev/null
@@ -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",
index e81eccc5168f23c72db205d3f71e6a899edb9e97..1124282697492c8a72078a38e588eaaf7648ce96 100644 (file)
@@ -58,7 +58,7 @@ void func() {
   }
 
   int x[] = {1, 2};
-  // CHECK: = !DILocalVariable(name: "__range"
+  // CHECK: = !DILocalVariable(name: "__range1"
   // CHECK-SAME:               scope: [[RANGE_FOR:![0-9]*]]
   // CHECK-NOT:                line:
   // CHECK-SAME:               ){{$}}
index b8652f8329a57603434c244c98c1da891b8261fc..273e413c3f481540383b27cb0753bdfe9afd41f0 100644 (file)
@@ -68,8 +68,8 @@ void test0(void *array, int n) {
 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 @@ void test2(int b) {
   //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 test2(int b) {
 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:%.*]]