krisb updated this revision to Diff 434541.
krisb marked an inline comment as done.
krisb added a comment.

Applied review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125695/new/

https://reviews.llvm.org/D125695

Files:
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/CodeGen/CGDebugInfo.h
  clang/lib/CodeGen/CGDecl.cpp
  clang/test/CodeGenCXX/debug-info-local-types.cpp

Index: clang/test/CodeGenCXX/debug-info-local-types.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/debug-info-local-types.cpp
@@ -0,0 +1,101 @@
+// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=limited -debugger-tuning=gdb %s -o - | FileCheck %s --check-prefixes=CHECK,LIMITED
+// RUN: %clang_cc1 -triple x86_64-none-linux-gnu -emit-llvm -debug-info-kind=unused-types -debugger-tuning=gdb %s -o - | FileCheck %s --check-prefixes=UNUSED_TYPES
+
+void test() {
+  {
+    struct S { int a; };
+    class C { int b; };
+    S s;
+    {
+      C c;
+    }
+  }
+
+  {
+    typedef char Char;
+    using Int = int;
+    Char c;
+    {
+      Int i;
+    }
+  }
+
+  {
+    enum E { a, b, c };
+    enum class T { aa, bb, cc };
+    E e = E::a;
+    {
+      T t = T::aa;
+    }
+  }
+
+  {
+    union U { int i; char c; };
+    U u = { 256 };
+  }
+}
+
+// LIMITED: distinct !DICompileUnit
+// LIMITED-NOT: retainedTypes:
+
+// CHECK: !DILocalVariable(name: "s", scope: [[LBSCOPE_1:![0-9]+]]
+// CHECK-SAME:                        type: [[STRUCT:![0-9]+]]
+// CHECK: [[LBSCOPE_1]] = distinct !DILexicalBlock({{.*}}, localDecls: [[LB1_DECLS:![0-9]+]]
+// CHECK: [[LB1_DECLS]] = !{[[STRUCT]], [[CLASS:![0-9]+]]}
+// CHECK: [[STRUCT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "S", scope: [[LBSCOPE_1]]
+// CHECK: [[CLASS]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "C", scope: [[LBSCOPE_1]]
+// CHECK: !DILocalVariable(name: "c", scope: [[LBSCOPE_11:![0-9]+]]
+// CHECK-SAME:                        type: [[CLASS]]
+// CHECK: [[LBSCOPE_11]] = distinct !DILexicalBlock(scope: [[LBSCOPE_1]]
+//
+// CHECK: !DILocalVariable(name: "c", scope: [[LBSCOPE_2:![0-9]+]]
+// CHECK-SAME:                        type: [[TYPEDEF:![0-9]+]]
+// CHECK: [[LBSCOPE_2]] = distinct !DILexicalBlock({{.*}}, localDecls: [[LB2_DECLS:![0-9]+]]
+// CHECK: [[LB2_DECLS]] = !{[[TYPEDEF]], [[USING:![0-9]+]]}
+// CHECK: [[TYPEDEF]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Char", scope: [[LBSCOPE_2]]
+// CHECK: [[USING]] = !DIDerivedType(tag: DW_TAG_typedef, name: "Int", scope: [[LBSCOPE_2]]
+// CHECK: !DILocalVariable(name: "i", scope: [[LBSCOPE_21:![0-9]+]]
+// CHECK-SAME:                        type: [[USING]]
+// CHECK: [[LBSCOPE_21]] = distinct !DILexicalBlock(scope: [[LBSCOPE_2]]
+//
+// CHECK: !DILocalVariable(name: "e", scope: [[LBSCOPE_3:![0-9]+]]
+// CHECK-SAME:                        type: [[ENUM:![0-9]+]]
+// CHECK: [[LBSCOPE_3]] = distinct !DILexicalBlock({{.*}}, localDecls: [[LB3_DECLS:![0-9]+]]
+// CHECK: [[LB3_DECLS]] = !{[[ENUM]], [[ENUM_CLASS:![0-9]+]]}
+// CHECK: [[ENUM]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E", scope: [[LBSCOPE_3]]
+// CHECK: [[ENUM_CLASS]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "T", scope: [[LBSCOPE_3]]
+// CHECK: !DILocalVariable(name: "t", scope: [[LBSCOPE_31:![0-9]+]]
+// CHECK-SAME:                        type: [[ENUM_CLASS]]
+// CHECK: [[LBSCOPE_31]] = distinct !DILexicalBlock(scope: [[LBSCOPE_3]]
+//
+// CHECK: !DILocalVariable(name: "u", scope: [[LBSCOPE_4:![0-9]+]]
+// CHECK-SAME:                        type: [[UNION:![0-9]+]]
+// CHECK: [[LBSCOPE_4]] = distinct !DILexicalBlock({{.*}}, localDecls: [[LB4_DECLS:![0-9]+]]
+// CHECK: [[LB4_DECLS]] = !{[[UNION]]}
+// CHECK: [[UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "U", scope: [[LBSCOPE_4]]
+
+void test_unused() {
+  {
+    struct X {};
+    typedef int Y; // typedef doesn't go to retainedTypes.
+    enum Z { z };
+  }
+}
+
+// UNUSED_TYPES: distinct !DICompileUnit
+// UNUSED_TYPES-SAME: retainedTypes: [[RETAINED_TYPES:![0-9]+]]
+//
+// struct, class, char, int, enum, enum class, union, unused struct, unused enum, <lambda()>::F
+// UNUSED_TYPES: [[RETAINED_TYPES]] = !{!{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, !{{[0-9]+}}, [[UNUSED_STRUCT:![0-9]+]], [[UNUSED_ENUM:![0-9]+]], !{{.*}}}
+// UNUSED_TYPES: [[UNUSED_STRUCT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", scope: [[UNUSED_LB:![0-9]+]]
+// UNUSED_TYPES: [[UNUSED_LB]] = distinct !DILexicalBlock({{.*}}, localDecls: [[UNUSED_LB_DECLS:![0-9]+]]
+// UNUSED_TYPES: [[UNUSED_LB_DECLS]] = !{[[UNUSED_STRUCT]], [[UNUSED_ENUM]]}
+// UNUSED_TYPES: [[UNUSED_ENUM]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Z", scope: [[UNUSED_LB]]
+
+void test_lambda() {
+  auto t = []() { struct F {}; return F(); };
+  auto v = t();
+}
+
+// TODO: <lambda()>::F doesn't have its scope specified.
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "F", file
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -103,17 +103,21 @@
     llvm_unreachable("Declaration should not be in declstmts!");
   case Decl::Record:    // struct/union/class X;
   case Decl::CXXRecord: // struct/union/class X; [C++]
-    if (CGDebugInfo *DI = getDebugInfo())
+    if (CGDebugInfo *DI = getDebugInfo()) {
+      DI->recordDeclarationLexicalScope(D);
       if (cast<RecordDecl>(D).getDefinition())
         DI->EmitAndRetainType(getContext().getRecordType(cast<RecordDecl>(&D)));
+    }
     return;
   case Decl::Enum:      // enum X;
-    if (CGDebugInfo *DI = getDebugInfo())
+    if (CGDebugInfo *DI = getDebugInfo()) {
+      DI->recordDeclarationLexicalScope(D);
       if (cast<EnumDecl>(D).getDefinition())
         DI->EmitAndRetainType(getContext().getEnumType(cast<EnumDecl>(&D)));
+    }
     return;
-  case Decl::Function:     // void X();
   case Decl::EnumConstant: // enum ? { X = ? }
+  case Decl::Function:     // void X();
   case Decl::StaticAssert: // static_assert(X, ""); [C++0x]
   case Decl::Label:        // __label__ x;
   case Decl::Import:
@@ -133,11 +137,11 @@
 
   case Decl::NamespaceAlias:
     if (CGDebugInfo *DI = getDebugInfo())
-        DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(D));
+      DI->EmitNamespaceAlias(cast<NamespaceAliasDecl>(D));
     return;
   case Decl::Using:          // using X; [C++]
     if (CGDebugInfo *DI = getDebugInfo())
-        DI->EmitUsingDecl(cast<UsingDecl>(D));
+      DI->EmitUsingDecl(cast<UsingDecl>(D));
     return;
   case Decl::UsingEnum: // using enum X; [C++]
     if (CGDebugInfo *DI = getDebugInfo())
@@ -173,8 +177,10 @@
   case Decl::Typedef:      // typedef int X;
   case Decl::TypeAlias: {  // using X = int; [C++0x]
     QualType Ty = cast<TypedefNameDecl>(D).getUnderlyingType();
-    if (CGDebugInfo *DI = getDebugInfo())
+    if (CGDebugInfo *DI = getDebugInfo()) {
+      DI->recordDeclarationLexicalScope(D);
       DI->EmitAndRetainType(Ty);
+    }
     if (Ty->isVariablyModifiedType())
       EmitVariablyModifiedType(Ty);
     return;
Index: clang/lib/CodeGen/CGDebugInfo.h
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.h
+++ clang/lib/CodeGen/CGDebugInfo.h
@@ -138,6 +138,11 @@
 
   /// Keep track of our current nested lexical block.
   std::vector<llvm::TypedTrackingMDRef<llvm::DIScope>> LexicalBlockStack;
+
+  /// Map of AST declaration to its lexical block scope.
+  llvm::DenseMap<const Decl *, llvm::TypedTrackingMDRef<llvm::DIScope>>
+      LexicalBlockMap;
+
   llvm::DenseMap<const Decl *, llvm::TrackingMDRef> RegionMap;
   /// Keep track of LexicalBlockStack counter at the beginning of a
   /// function. This is used to pop unbalanced regions at the end of a
@@ -550,6 +555,12 @@
   /// Emit an Objective-C interface type standalone debug info.
   llvm::DIType *getOrCreateInterfaceType(QualType Ty, SourceLocation Loc);
 
+  /// Map AST declaration to its lexical block scope if available.
+  void recordDeclarationLexicalScope(const Decl &D);
+
+  /// Get lexical scope of AST declaration.
+  llvm::DIScope *getDeclarationLexicalScope(const Decl *D);
+
   /// Emit standalone debug info for a type.
   llvm::DIType *getOrCreateStandaloneType(QualType Ty, SourceLocation Loc);
 
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -227,6 +227,23 @@
   return Default;
 }
 
+void CGDebugInfo::recordDeclarationLexicalScope(const Decl &D) {
+  if (LexicalBlockStack.empty())
+    return;
+
+  if (!LexicalBlockMap.insert({&D, LexicalBlockStack.back()}).second)
+    llvm_unreachable("D is already mapped to a lexical block scope!");
+}
+
+llvm::DIScope *CGDebugInfo::getDeclarationLexicalScope(const Decl *D) {
+  if (CGM.getCodeGenOpts().getDebuggerTuning() == llvm::DebuggerKind::GDB) {
+    auto I = LexicalBlockMap.find(D);
+    if (I != LexicalBlockMap.end())
+      return I->second;
+  }
+  return getDeclContextDescriptor(cast<Decl>(D));
+}
+
 PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
   PrintingPolicy PP = CGM.getContext().getPrintingPolicy();
 
@@ -1295,13 +1312,13 @@
   // declared.
   SourceLocation Loc = Ty->getDecl()->getLocation();
 
+  llvm::DIScope *TDContext = getDeclarationLexicalScope(Ty->getDecl());
   uint32_t Align = getDeclAlignIfRequired(Ty->getDecl(), CGM.getContext());
   // Typedefs are derived from some other type.
   llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(Ty->getDecl());
   return DBuilder.createTypedef(Underlying, Ty->getDecl()->getName(),
                                 getOrCreateFile(Loc), getLineNumber(Loc),
-                                getDeclContextDescriptor(Ty->getDecl()), Align,
-                                Annotations);
+                                TDContext, Align, Annotations);
 }
 
 static unsigned getDwarfCC(CallingConv CC) {
@@ -3195,7 +3212,7 @@
     // entered into the ReplaceMap: finalize() will replace the first
     // FwdDecl with the second and then replace the second with
     // complete type.
-    llvm::DIScope *EDContext = getDeclContextDescriptor(ED);
+    llvm::DIScope *EDContext = getDeclarationLexicalScope(ED);
     llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());
     llvm::TempDIScope TmpContext(DBuilder.createReplaceableCompositeType(
         llvm::dwarf::DW_TAG_enumeration_type, "", TheCU, DefUnit, 0));
@@ -3238,7 +3255,7 @@
 
   llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());
   unsigned Line = getLineNumber(ED->getLocation());
-  llvm::DIScope *EnumContext = getDeclContextDescriptor(ED);
+  llvm::DIScope *EnumContext = getDeclarationLexicalScope(ED);
   llvm::DIType *ClassTy = getOrCreateType(ED->getIntegerType(), DefUnit);
   return DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit,
                                         Line, Size, Align, EltArray, ClassTy,
@@ -3547,7 +3564,7 @@
     Line = getLineNumber(Loc);
   }
 
-  llvm::DIScope *RDContext = getDeclContextDescriptor(RD);
+  llvm::DIScope *RDContext = getDeclarationLexicalScope(RD);
 
   // If we ended up creating the type during the context chain construction,
   // just return that.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to