]> granicus.if.org Git - llvm/commitdiff
[codeview] Check if this 'this' type of a method is a pointer
authorReid Kleckner <rnk@google.com>
Wed, 26 Dec 2018 21:52:17 +0000 (21:52 +0000)
committerReid Kleckner <rnk@google.com>
Wed, 26 Dec 2018 21:52:17 +0000 (21:52 +0000)
Fixes crash reported after r347354 for frontends that don't always emit
'this' pointers for methods. Now we will silently produce debug info
that makes functions like this look like static methods, which seems
reasonable.

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

lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
lib/CodeGen/AsmPrinter/CodeViewDebug.h
test/DebugInfo/COFF/types-this-not-ptr.ll [new file with mode: 0644]

index 990f0f4670bad95f7a040d6c1d9339b84a65a207..8cabad4ad312391a1561bf9e22a6219e71be6046 100644 (file)
@@ -1838,9 +1838,19 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
   SmallVector<TypeIndex, 8> ArgTypeIndices;
   TypeIndex ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
 
+  // If the first argument is a pointer type and this isn't a static method,
+  // treat it as the special 'this' parameter, which is encoded separately from
+  // the arguments.
   TypeIndex ThisTypeIndex;
-  if (!IsStaticMethod && ReturnAndArgs.size() > 1)
-    ThisTypeIndex = getTypeIndexForThisPtr(ReturnAndArgs[Index++], Ty);
+  if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
+    if (const DIDerivedType *PtrTy =
+            dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[Index].resolve())) {
+      if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
+        ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
+        Index++;
+      }
+    }
+  }
 
   while (Index < ReturnAndArgs.size())
     ArgTypeIndices.push_back(getTypeIndex(ReturnAndArgs[Index++]));
@@ -2396,9 +2406,10 @@ TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
 }
 
 codeview::TypeIndex
-CodeViewDebug::getTypeIndexForThisPtr(DITypeRef TypeRef,
+CodeViewDebug::getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
                                       const DISubroutineType *SubroutineTy) {
-  const DIType *Ty = TypeRef.resolve();
+  assert(PtrTy->getTag() == dwarf::DW_TAG_pointer_type &&
+         "this type must be a pointer type");
 
   PointerOptions Options = PointerOptions::None;
   if (SubroutineTy->getFlags() & DINode::DIFlags::FlagLValueReference)
@@ -2411,13 +2422,13 @@ CodeViewDebug::getTypeIndexForThisPtr(DITypeRef TypeRef,
   // so that the TypeIndex for the this pointer can be shared with the type
   // index for other pointers to this class type.  If there is a ref qualifier
   // then we lookup the pointer using the subroutine as the parent type.
-  auto I = TypeIndices.find({Ty, SubroutineTy});
+  auto I = TypeIndices.find({PtrTy, SubroutineTy});
   if (I != TypeIndices.end())
     return I->second;
 
   TypeLoweringScope S(*this);
-  TypeIndex TI = lowerTypePointer(cast<DIDerivedType>(Ty), Options);
-  return recordTypeIndexForDINode(Ty, TI, SubroutineTy);
+  TypeIndex TI = lowerTypePointer(PtrTy, Options);
+  return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
 }
 
 TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(DITypeRef TypeRef) {
index 1c2b9bf4d4b8a4611255c517616bffcc2cc09823..21557ed1be354326c0e985d5e9a2851e72ffefa3 100644 (file)
@@ -377,7 +377,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
                                    DITypeRef ClassTyRef = DITypeRef());
 
   codeview::TypeIndex
-  getTypeIndexForThisPtr(DITypeRef TypeRef,
+  getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
                          const DISubroutineType *SubroutineTy);
 
   codeview::TypeIndex getTypeIndexForReferenceTo(DITypeRef TypeRef);
diff --git a/test/DebugInfo/COFF/types-this-not-ptr.ll b/test/DebugInfo/COFF/types-this-not-ptr.ll
new file mode 100644 (file)
index 0000000..ae47e6f
--- /dev/null
@@ -0,0 +1,45 @@
+; RUN: llc -filetype=obj %s -o %t.obj
+; RUN: llvm-pdbutil dump -types %t.obj | FileCheck %s
+
+; Manually remove the "static" flag from the LLVM IR generated by compiling the
+; following C++ source:
+; struct Foo  {
+;   static void st_meth(int x, int y);
+; } f;
+
+; "this type" below should be <no type>.
+; CHECK: LF_MFUNCTION
+; CHECK-NEXT: return type = 0x0003 (void), # args = 2, param list = {{.*}}
+; CHECK-NEXT: class type = {{.*}}, this type = <no type>, this adjust = 0
+; CHECK-NEXT: calling conv = cdecl, options = None
+
+; ModuleID = 't.cpp'
+source_filename = "t.cpp"
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.14.26433"
+
+%struct.Foo = type { i8 }
+
+@"?f@@3UFoo@@A" = dso_local global %struct.Foo zeroinitializer, align 1, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!12, !13, !14, !15}
+!llvm.ident = !{!16}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "f", linkageName: "?f@@3UFoo@@A", scope: !2, file: !3, line: 3, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 8.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "ac580c6cde5f3f394632dcaad04873a4")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !3, line: 1, size: 8, flags: DIFlagTypePassByValue | DIFlagTrivial, elements: !7, identifier: ".?AUFoo@@")
+!7 = !{!8}
+!8 = !DISubprogram(name: "st_meth", linkageName: "?st_meth@Foo@@SAXHH@Z", scope: !6, file: !3, line: 2, type: !9, scopeLine: 2, flags: DIFlagPrototyped, spFlags: 0)
+!9 = !DISubroutineType(types: !10)
+!10 = !{null, !11, !11}
+!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!12 = !{i32 2, !"CodeView", i32 1}
+!13 = !{i32 2, !"Debug Info Version", i32 3}
+!14 = !{i32 1, !"wchar_size", i32 2}
+!15 = !{i32 7, !"PIC Level", i32 2}
+!16 = !{!"clang version 8.0.0 "}