r332975 - [CodeView] Enable debugging of captured variables within C++ lambdas

Brock Wyma via cfe-commits cfe-commits at lists.llvm.org
Tue May 22 05:41:19 PDT 2018


Author: bwyma
Date: Tue May 22 05:41:19 2018
New Revision: 332975

URL: http://llvm.org/viewvc/llvm-project?rev=332975&view=rev
Log:

[CodeView] Enable debugging of captured variables within C++ lambdas

This change will help Visual Studio resolve forward references to C++ lambda
routines used by captured variables.

Differential Revision: https://reviews.llvm.org/D45438


Added:
    cfe/trunk/test/CodeGen/debug-info-codeview-unnamed.c
    cfe/trunk/test/CodeGenCXX/debug-info-codeview-unnamed.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=332975&r1=332974&r2=332975&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Tue May 22 05:41:19 2018
@@ -801,22 +801,46 @@ static bool hasCXXMangling(const TagDecl
   }
 }
 
-/// In C++ mode, types have linkage, so we can rely on the ODR and
-/// on their mangled names, if they're external.
-static SmallString<256> getUniqueTagTypeName(const TagType *Ty,
-                                             CodeGenModule &CGM,
-                                             llvm::DICompileUnit *TheCU) {
-  SmallString<256> FullName;
+// Determines if the tag declaration will require a type identifier.
+static bool needsTypeIdentifier(const TagDecl *TD,
+                                CodeGenModule& CGM,
+                                llvm::DICompileUnit *TheCU) {
+  // We only add a type identifier for types with C++ name mangling.
+  if (!hasCXXMangling(TD, TheCU))
+    return false;
+
+  // CodeView types with C++ mangling need a type identifier.
+  if (CGM.getCodeGenOpts().EmitCodeView)
+    return true;
+
+  // Externally visible types with C++ mangling need a type identifier.
+  if (TD->isExternallyVisible())
+    return true;
+
+  return false;
+}
+
+// When emitting CodeView debug information we need to produce a type
+// identifier for all types which have a C++ mangling.  Until a GUID is added
+// to the identifier (not currently implemented) the result will not be unique
+// across compilation units.
+// When emitting DWARF debug information, we need to produce a type identifier
+// for all externally visible types with C++ name mangling. This identifier
+// should be unique across ODR-compliant compilation units.
+static SmallString<256> getTypeIdentifier(const TagType *Ty,
+                                          CodeGenModule &CGM,
+                                          llvm::DICompileUnit *TheCU) {
+  SmallString<256> Identifier;
   const TagDecl *TD = Ty->getDecl();
 
-  if (!hasCXXMangling(TD, TheCU) || !TD->isExternallyVisible())
-    return FullName;
+  if (!needsTypeIdentifier(TD, CGM, TheCU))
+    return Identifier;
 
   // TODO: This is using the RTTI name. Is there a better way to get
   // a unique string for a type?
-  llvm::raw_svector_ostream Out(FullName);
+  llvm::raw_svector_ostream Out(Identifier);
   CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(QualType(Ty, 0), Out);
-  return FullName;
+  return Identifier;
 }
 
 /// \return the appropriate DWARF tag for a composite type.
@@ -849,10 +873,10 @@ CGDebugInfo::getOrCreateRecordFwdDecl(co
   uint32_t Align = 0;
 
   // Create the type.
-  SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+  SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
   llvm::DICompositeType *RetTy = DBuilder.createReplaceableCompositeType(
       getTagForRecord(RD), RDName, Ctx, DefUnit, Line, 0, Size, Align,
-      llvm::DINode::FlagFwdDecl, FullName);
+      llvm::DINode::FlagFwdDecl, Identifier);
   if (CGM.getCodeGenOpts().DebugFwdTemplateParams)
     if (auto *TSpecial = dyn_cast<ClassTemplateSpecializationDecl>(RD))
       DBuilder.replaceArrays(RetTy, llvm::DINodeArray(),
@@ -2477,7 +2501,7 @@ llvm::DIType *CGDebugInfo::CreateEnumTyp
     Align = getDeclAlignIfRequired(ED, CGM.getContext());
   }
 
-  SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+  SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
 
   bool isImportedFromModule =
       DebugTypeExtRefs && ED->isFromASTFile() && ED->getDefinition();
@@ -2500,7 +2524,7 @@ llvm::DIType *CGDebugInfo::CreateEnumTyp
     StringRef EDName = ED->getName();
     llvm::DIType *RetTy = DBuilder.createReplaceableCompositeType(
         llvm::dwarf::DW_TAG_enumeration_type, EDName, EDContext, DefUnit, Line,
-        0, Size, Align, llvm::DINode::FlagFwdDecl, FullName);
+        0, Size, Align, llvm::DINode::FlagFwdDecl, Identifier);
 
     ReplaceMap.emplace_back(
         std::piecewise_construct, std::make_tuple(Ty),
@@ -2520,7 +2544,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDef
     Align = getDeclAlignIfRequired(ED, CGM.getContext());
   }
 
-  SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+  SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
 
   // Create elements for each enumerator.
   SmallVector<llvm::Metadata *, 16> Enumerators;
@@ -2542,7 +2566,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDef
   llvm::DIType *ClassTy = getOrCreateType(ED->getIntegerType(), DefUnit);
   return DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit,
                                         Line, Size, Align, EltArray, ClassTy,
-                                        FullName, ED->isFixed());
+                                        Identifier, ED->isFixed());
 }
 
 llvm::DIMacro *CGDebugInfo::CreateMacro(llvm::DIMacroFile *Parent,
@@ -2843,7 +2867,7 @@ llvm::DICompositeType *CGDebugInfo::Crea
   uint64_t Size = CGM.getContext().getTypeSize(Ty);
   auto Align = getDeclAlignIfRequired(D, CGM.getContext());
 
-  SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+  SmallString<256> Identifier = getTypeIdentifier(Ty, CGM, TheCU);
 
   // Explicitly record the calling convention for C++ records.
   auto Flags = llvm::DINode::FlagZero;
@@ -2856,7 +2880,7 @@ llvm::DICompositeType *CGDebugInfo::Crea
 
   llvm::DICompositeType *RealDecl = DBuilder.createReplaceableCompositeType(
       getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align,
-      Flags, FullName);
+      Flags, Identifier);
 
   // Elements of composite types usually have back to the type, creating
   // uniquing cycles.  Distinct nodes are more efficient.
@@ -2870,7 +2894,7 @@ llvm::DICompositeType *CGDebugInfo::Crea
     // so they don't tend to be involved in uniquing cycles and there is some
     // chance of merging them when linking together two modules.  Only make
     // them distinct if they are ODR-uniqued.
-    if (FullName.empty())
+    if (Identifier.empty())
       break;
     LLVM_FALLTHROUGH;
 

Added: cfe/trunk/test/CodeGen/debug-info-codeview-unnamed.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/debug-info-codeview-unnamed.c?rev=332975&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/debug-info-codeview-unnamed.c (added)
+++ cfe/trunk/test/CodeGen/debug-info-codeview-unnamed.c Tue May 22 05:41:19 2018
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck --check-prefix LINUX %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=limited -gcodeview -S -emit-llvm -o - %s | FileCheck --check-prefix MSVC %s
+
+int main(int argc, char* argv[], char* arge[]) {
+
+  // In both DWARF and CodeView, an unnamed C structure type will generate a
+  // DICompositeType without a name or identifier attribute;
+  //
+  struct { int bar; } one = {42};
+  //
+  // LINUX:      !{{[0-9]+}} = !DILocalVariable(name: "one"
+  // LINUX-SAME:     type: [[TYPE_OF_ONE:![0-9]+]]
+  // LINUX-SAME:     )
+  // LINUX:      [[TYPE_OF_ONE]] = distinct !DICompositeType(
+  // LINUX-SAME:     tag: DW_TAG_structure_type
+  // LINUX-NOT:      name:
+  // LINUX-NOT:      identifier:
+  // LINUX-SAME:     )
+  //
+  // MSVC:       !{{[0-9]+}} = !DILocalVariable(name: "one"
+  // MSVC-SAME:      type: [[TYPE_OF_ONE:![0-9]+]]
+  // MSVC-SAME:      )
+  // MSVC:       [[TYPE_OF_ONE]] = distinct !DICompositeType
+  // MSVC-SAME:      tag: DW_TAG_structure_type
+  // MSVC-NOT:       name:
+  // MSVC-NOT:       identifier:
+  // MSVC-SAME:      )
+
+  return 0;
+}

Added: cfe/trunk/test/CodeGenCXX/debug-info-codeview-unnamed.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-codeview-unnamed.cpp?rev=332975&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/debug-info-codeview-unnamed.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/debug-info-codeview-unnamed.cpp Tue May 22 05:41:19 2018
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -debug-info-kind=limited -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix LINUX %s
+// RUN: %clang_cc1 -triple x86_64-windows-msvc -debug-info-kind=limited -gcodeview -S -emit-llvm -std=c++11 -o - %s | FileCheck --check-prefix MSVC %s
+
+int main(int argc, char* argv[], char* arge[]) {
+  //
+  // In CodeView, the LF_MFUNCTION entry for "bar()" refers to the forward
+  // reference of the unnamed struct. Visual Studio requires a unique
+  // identifier to match the LF_STRUCTURE forward reference to the definition.
+  //
+  struct { void bar() {} } one;
+  //
+  // LINUX:      !{{[0-9]+}} = !DILocalVariable(name: "one"
+  // LINUX-SAME:     type: [[TYPE_OF_ONE:![0-9]+]]
+  // LINUX-SAME:     )
+  // LINUX:      [[TYPE_OF_ONE]] = distinct !DICompositeType(
+  // LINUX-SAME:     tag: DW_TAG_structure_type
+  // LINUX-NOT:      name:
+  // LINUX-NOT:      identifier:
+  // LINUX-SAME:     )
+  //
+  // MSVC:       !{{[0-9]+}} = !DILocalVariable(name: "one"
+  // MSVC-SAME:      type: [[TYPE_OF_ONE:![0-9]+]]
+  // MSVC-SAME:      )
+  // MSVC:       [[TYPE_OF_ONE]] = distinct !DICompositeType
+  // MSVC-SAME:      tag: DW_TAG_structure_type
+  // MSVC-SAME:      name: "<unnamed-type-one>"
+  // MSVC-SAME:      identifier: ".?AU<unnamed-type-one>@?1??main@@9@"
+  // MSVC-SAME:      )
+
+
+  // In CodeView, the LF_POINTER entry for "ptr2unnamed" refers to the forward
+  // reference of the unnamed struct. Visual Studio requires a unique
+  // identifier to match the LF_STRUCTURE forward reference to the definition.
+  //
+  struct { int bar; } two = { 42 };
+  int decltype(two)::*ptr2unnamed = &decltype(two)::bar;
+  //
+  // LINUX:      !{{[0-9]+}} = !DILocalVariable(name: "two"
+  // LINUX-SAME:     type: [[TYPE_OF_TWO:![0-9]+]]
+  // LINUX-SAME:     )
+  // LINUX:      [[TYPE_OF_TWO]] = distinct !DICompositeType(
+  // LINUX-SAME:     tag: DW_TAG_structure_type
+  // LINUX-NOT:      name:
+  // LINUX-NOT:      identifier:
+  // LINUX-SAME:     )
+  //
+  // MSVC:       !{{[0-9]+}} = !DILocalVariable(name: "two"
+  // MSVC-SAME:      type: [[TYPE_OF_TWO:![0-9]+]]
+  // MSVC-SAME:      )
+  // MSVC:       [[TYPE_OF_TWO]] = distinct !DICompositeType
+  // MSVC-SAME:      tag: DW_TAG_structure_type
+  // MSVC-SAME:      name: "<unnamed-type-two>"
+  // MSVC-SAME:      identifier: ".?AU<unnamed-type-two>@?2??main@@9@"
+  // MSVC-SAME:      )
+
+
+  // In DWARF, named structures which are not externally visibile do not
+  // require an identifier.  In CodeView, named structures are given an
+  // identifier.
+  //
+  struct named { int bar; int named::* p2mem; } three = { 42, &named::bar };
+  //
+  // LINUX:      !{{[0-9]+}} = !DILocalVariable(name: "three"
+  // LINUX-SAME:     type: [[TYPE_OF_THREE:![0-9]+]]
+  // LINUX-SAME:     )
+  // LINUX:      [[TYPE_OF_THREE]] = distinct !DICompositeType(
+  // LINUX-SAME:     tag: DW_TAG_structure_type
+  // LINUX-SAME:     name: "named"
+  // LINUX-NOT:      identifier:
+  // LINUX-SAME:     )
+  //
+  // MSVC:       !{{[0-9]+}} = !DILocalVariable(name: "three"
+  // MSVC-SAME:      type: [[TYPE_OF_THREE:![0-9]+]]
+  // MSVC-SAME:      )
+  // MSVC:       [[TYPE_OF_THREE]] = distinct !DICompositeType
+  // MSVC-SAME:      tag: DW_TAG_structure_type
+  // MSVC-SAME:      name: "named"
+  // MSVC-SAME:      identifier: ".?AUnamed@?1??main@@9@"
+  // MSVC-SAME:      )
+
+
+  // In CodeView, the LF_MFUNCTION entry for the lambda "operator()" routine
+  // refers to the forward reference of the unnamed LF_CLASS for the lambda.
+  // Visual Studio requires a unique identifier to match the forward reference
+  // of the LF_CLASS to its definition.
+  //
+  auto four = [argc](int i) -> int { return argc == i ? 1 : 0; };
+  //
+  // LINUX:      !{{[0-9]+}} = !DILocalVariable(name: "four"
+  // LINUX-SAME:     type: [[TYPE_OF_FOUR:![0-9]+]]
+  // LINUX-SAME:     )
+  // LINUX:      [[TYPE_OF_FOUR]] = distinct !DICompositeType(
+  // LINUX-SAME:     tag: DW_TAG_class_type
+  // LINUX-NOT:      name:
+  // LINUX-NOT:      identifier:
+  // LINUX-SAME:     )
+  //
+  // MSVC:       !{{[0-9]+}} = !DILocalVariable(name: "four"
+  // MSVC-SAME:      type: [[TYPE_OF_FOUR:![0-9]+]]
+  // MSVC-SAME:      )
+  // MSVC:       [[TYPE_OF_FOUR]] = distinct !DICompositeType
+  // MSVC-SAME:      tag: DW_TAG_class_type
+  // MSVC-NOT:       name:
+  // MSVC-SAME:      identifier: ".?AV<lambda_0>@?0??main@@9@"
+  // MSVC-SAME:      )
+
+  return 0;
+}




More information about the cfe-commits mailing list