diff options
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h | 5 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp | 4 | ||||
-rw-r--r-- | llvm/test/tools/llvm-readobj/Inputs/codeview-types.obj | bin | 0 -> 8746 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-readobj/codeview-types.test | 95 |
6 files changed, 104 insertions, 4 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h index abe385a2d48..1fa20891608 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h @@ -47,6 +47,8 @@ private: public: FieldListRecordBuilder(); + void reset() { ListRecordBuilder::reset(TypeRecordKind::FieldList); } + void writeBaseClass(const BaseClassRecord &Record); void writeEnumerator(const EnumeratorRecord &Record); void writeDataMember(const DataMemberRecord &Record); diff --git a/llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h index 2467bfd2c29..4df82ad2d18 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h @@ -28,7 +28,7 @@ protected: public: llvm::StringRef str() { return Builder.str(); } - void reset() { Builder.reset(); } + void reset(TypeRecordKind K) { Builder.reset(K); } protected: void finishSubRecord(); diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h index bc10f5a8500..30906cd93e8 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h @@ -47,7 +47,10 @@ public: uint64_t size() const { return Stream.tell(); } - void reset() { Buffer.clear(); } + void reset(TypeRecordKind K) { + Buffer.clear(); + writeTypeRecordKind(K); + } private: llvm::SmallVector<char, 256> Buffer; diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 5ee7cb17000..88211d0af95 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -111,14 +111,14 @@ void TypeStreamMerger::visitFieldList(TypeLeafKind Leaf, #define TYPE_RECORD(EnumName, EnumVal, Name) \ void TypeStreamMerger::visit##Name(TypeLeafKind LeafType, \ Name##Record &Record) { \ - FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ + FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ IndexMap.push_back(DestStream.write##Name(Record)); \ } #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #define MEMBER_RECORD(EnumName, EnumVal, Name) \ void TypeStreamMerger::visit##Name(TypeLeafKind LeafType, \ Name##Record &Record) { \ - FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ + FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); \ FieldBuilder.write##Name(Record); \ } #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) diff --git a/llvm/test/tools/llvm-readobj/Inputs/codeview-types.obj b/llvm/test/tools/llvm-readobj/Inputs/codeview-types.obj Binary files differnew file mode 100644 index 00000000000..b00a7c6a3e1 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/Inputs/codeview-types.obj diff --git a/llvm/test/tools/llvm-readobj/codeview-types.test b/llvm/test/tools/llvm-readobj/codeview-types.test new file mode 100644 index 00000000000..4545b8e01dd --- /dev/null +++ b/llvm/test/tools/llvm-readobj/codeview-types.test @@ -0,0 +1,95 @@ +// This tests that we can deserialize and reserialize every known type record. +// If you need to update the object file, enable the RUNX line below using MSVC +// from VS 2012. Newer versions of MSVC emit tons of internal types for +// attributes that pollute the test output. When Clang fully supports all these +// type records, we can regenerate the test using it instead. + +// RUNX: cl -GR- -Z7 -c -TP %s -Fo%S/Inputs/codeview-types.obj +// RUN: llvm-readobj -codeview %S/Inputs/codeview-types.obj | FileCheck %s +// RUN: llvm-readobj -codeview-merged-types %S/Inputs/codeview-types.obj | FileCheck %s + +// TYPE_RECORD +// CHECK-DAG: {{^ *Pointer (.*) {$}} +// CHECK-DAG: {{^ *Modifier (.*) {$}} +// CHECK-DAG: {{^ *Procedure (.*) {$}} +// CHECK-DAG: {{^ *MemberFunction (.*) {$}} +// CHECK-DAG: {{^ *ArgList (.*) {$}} +// CHECK-DAG: {{^ *Array (.*) {$}} +// CHECK-DAG: {{^ *Class (.*) {$}} +// CHECK-DAG: {{^ *Union (.*) {$}} +// CHECK-DAG: {{^ *Enum (.*) {$}} +// CHECK-DAG: {{^ *VFTable (.*) {$}} +// CHECK-DAG: {{^ *VFTableShape (.*) {$}} +// CHECK-DAG: {{^ *FuncId (.*) {$}} +// CHECK-DAG: {{^ *MemberFuncId (.*) {$}} +// CHECK-DAG: {{^ *BuildInfo (.*) {$}} +// CHECK-DAG: {{^ *StringId (.*) {$}} +// CHECK-DAG: {{^ *UdtSourceLine (.*) {$}} +// CHECK-DAG: {{^ *MethodOverloadList (.*) {$}} +// No TypeServer2, since that is used with /Zi + +// MEMBER_RECORD +// CHECK-DAG: {{^ *BaseClass {$}} +// CHECK-DAG: {{^ *VirtualBaseClass {$}} +// CHECK-DAG: {{^ *VFPtr {$}} +// CHECK-DAG: {{^ *StaticDataMember {$}} +// CHECK-DAG: {{^ *OverloadedMethod {$}} +// CHECK-DAG: {{^ *DataMember {$}} +// CHECK-DAG: {{^ *NestedType {$}} +// CHECK-DAG: {{^ *OneMethod {$}} +// CHECK-DAG: {{^ *Enumerator {$}} + +#if !defined(__clang__) && _MSC_VER >= 1800 +#error "use clang or MSVC 2012 to regenerate the test" +#endif + +struct VBaseA; +void FriendFunc(); + +class Class { +public: + const Class *DataMember; +private: + static int StaticDataMember; +protected: + virtual void MemberFunction(); +public: + struct Nested; + friend ::VBaseA; + friend void FriendFunc() { } + void OverloadedMethod(); + void OverloadedMethod(int); +}; + +enum Enum { + E1 = 0, + E2 = 1 +}; + +int array[4] = {1, 2, 3, 4}; + +struct Class::Nested {}; + +struct ClassWithBase : Class { + virtual void MemberFunction(); + virtual void NewVirtual(); +}; +struct VBaseA { int x; }; +struct VBaseB : virtual VBaseA { int x; }; +struct VBaseC : virtual VBaseA { int x; }; +struct VBaseD : VBaseB, VBaseC { int x; }; + +union Union { + float f; + int i; +}; + +void UseAllTypes() { + Class a; + Class::Nested b; + ClassWithBase c; + VBaseD d; + Union e; + Enum f; + FriendFunc(); +} |