[llvm] r272927 - Revert "[pdb] Change type visitor pattern to be dynamic."

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 16 11:09:05 PDT 2016


Author: zturner
Date: Thu Jun 16 13:09:04 2016
New Revision: 272927

URL: http://llvm.org/viewvc/llvm-project?rev=272927&view=rev
Log:
Revert "[pdb] Change type visitor pattern to be dynamic."

This reverts commit fb0dd311e1ad945827b8ffd5354f4810e2be1579.

This breaks some llvm-readobj tests.

Removed:
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
    llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
    llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
    llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
    llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp
    llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
    llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
    llvm/trunk/tools/llvm-readobj/COFFDumper.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h Thu Jun 16 13:09:04 2016
@@ -11,31 +11,151 @@
 #define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
 
 #include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorOr.h"
 
 namespace llvm {
 namespace codeview {
 
+template <typename Derived>
 class CVTypeVisitor {
 public:
-  explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
+  CVTypeVisitor() {}
 
-  Error visitTypeRecord(const CVRecord<TypeLeafKind> &Record);
+  bool hadError() const { return HadError; }
 
-  /// Visits the type records in Data. Sets the error flag on parse failures.
-  Error visitTypeStream(const CVTypeArray &Types);
+  template <typename T>
+  bool consumeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
+    if (Data.size() < sizeof(*Res)) {
+      HadError = true;
+      return false;
+    }
+    Res = reinterpret_cast<const T *>(Data.data());
+    Data = Data.drop_front(sizeof(*Res));
+    return true;
+  }
+
+  /// Actions to take on known types. By default, they do nothing. Visit methods
+  /// for member records take the FieldData by non-const reference and are
+  /// expected to consume the trailing bytes used by the field.
+  /// FIXME: Make the visitor interpret the trailing bytes so that clients don't
+  /// need to.
+#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
+  void visit##Name(Name##Record &Record) {}
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
+  void visit##Name(Name##Record &Record) {}
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "TypeRecords.def"
+
+  void visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
+    ArrayRef<uint8_t> LeafData = Record.Data;
+    auto *DerivedThis = static_cast<Derived *>(this);
+    DerivedThis->visitTypeBegin(Record);
+    switch (Record.Type) {
+    default:
+      DerivedThis->visitUnknownType(Record);
+      break;
+    case LF_FIELDLIST:
+      DerivedThis->visitFieldList(Record.Type, LeafData);
+      break;
+#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
+  case EnumName: {                                                             \
+    TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName);                 \
+    auto Result = Name##Record::deserialize(RK, LeafData);                     \
+    if (Result.getError())                                                     \
+      return parseError();                                                     \
+    DerivedThis->visit##Name(*Result);                                         \
+    break;                                                                     \
+  }
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
+  TYPE_RECORD(EnumVal, EnumVal, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name)
+#include "TypeRecords.def"
+      }
+      DerivedThis->visitTypeEnd(Record);
+  }
 
-  Error skipPadding(ArrayRef<uint8_t> &Data);
+  /// Visits the type records in Data. Sets the error flag on parse failures.
+  void visitTypeStream(const CVTypeArray &Types) {
+    for (const auto &I : Types) {
+      visitTypeRecord(I);
+      if (hadError())
+        break;
+    }
+  }
+
+  /// Action to take on unknown types. By default, they are ignored.
+  void visitUnknownType(const CVRecord<TypeLeafKind> &Record) {}
+
+  /// Paired begin/end actions for all types. Receives all record data,
+  /// including the fixed-length record prefix.
+  void visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {}
+  void visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {}
+
+  ArrayRef<uint8_t> skipPadding(ArrayRef<uint8_t> Data) {
+    if (Data.empty())
+      return Data;
+    uint8_t Leaf = Data.front();
+    if (Leaf < LF_PAD0)
+      return Data;
+    // Leaf is greater than 0xf0. We should advance by the number of bytes in
+    // the low 4 bits.
+    unsigned BytesToAdvance = Leaf & 0x0F;
+    if (Data.size() < BytesToAdvance) {
+      parseError();
+      return None;
+    }
+    return Data.drop_front(BytesToAdvance);
+  }
 
   /// Visits individual member records of a field list record. Member records do
   /// not describe their own length, and need special handling.
-  Error visitFieldList(const CVRecord<TypeLeafKind> &Record);
+  void visitFieldList(TypeLeafKind Leaf, ArrayRef<uint8_t> FieldData) {
+    auto *DerivedThis = static_cast<Derived *>(this);
+    while (!FieldData.empty()) {
+      const ulittle16_t *LeafPtr;
+      if (!CVTypeVisitor::consumeObject(FieldData, LeafPtr))
+        return;
+      TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
+      switch (Leaf) {
+      default:
+        // Field list records do not describe their own length, so we cannot
+        // continue parsing past an unknown member type.
+        DerivedThis->visitUnknownMember(Leaf);
+        return parseError();
+#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
+  case EnumName: {                                                             \
+    TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName);                 \
+    auto Result = Name##Record::deserialize(RK, FieldData);                    \
+    if (Result.getError())                                                     \
+      return parseError();                                                     \
+    DerivedThis->visit##Name(*Result);                                         \
+    break;                                                                     \
+  }
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
+  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
+#include "TypeRecords.def"
+      }
+      FieldData = skipPadding(FieldData);
+      if (hadError())
+        break;
+    }
+  }
+
+  /// Action to take on unknown members. By default, they are ignored. Member
+  /// record parsing cannot recover from an unknown member record, so this
+  /// method is only called at most once per field list record.
+  void visitUnknownMember(TypeLeafKind Leaf) {}
+
+  /// Helper for returning from a void function when the stream is corrupted.
+  void parseError() { HadError = true; }
 
 private:
-  /// The interface to the class that gets notified of each visitation.
-  TypeVisitorCallbacks &Callbacks;
+  /// Whether a type stream parsing error was encountered.
+  bool HadError = false;
 };
 
 } // end namespace codeview

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h Thu Jun 16 13:09:04 2016
@@ -14,7 +14,6 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
 
 namespace llvm {
 class ScopedPrinter;
@@ -22,7 +21,7 @@ class ScopedPrinter;
 namespace codeview {
 
 /// Dumper for CodeView type streams found in COFF object files and PDB files.
-class CVTypeDumper : public TypeVisitorCallbacks {
+class CVTypeDumper {
 public:
   CVTypeDumper(ScopedPrinter *W, bool PrintRecordBytes)
       : W(W), PrintRecordBytes(PrintRecordBytes) {}
@@ -34,17 +33,17 @@ public:
   /// and true otherwise.  This should be called in order, since the dumper
   /// maintains state about previous records which are necessary for cross
   /// type references.
-  Error dump(const CVRecord<TypeLeafKind> &Record);
+  bool dump(const CVRecord<TypeLeafKind> &Record);
 
   /// Dumps the type records in Types. Returns false if there was a type stream
   /// parse error, and true otherwise.
-  Error dump(const CVTypeArray &Types);
+  bool dump(const CVTypeArray &Types);
 
   /// Dumps the type records in Data. Returns false if there was a type stream
   /// parse error, and true otherwise. Use this method instead of the
   /// CVTypeArray overload when type records are laid out contiguously in
   /// memory.
-  Error dump(ArrayRef<uint8_t> Data);
+  bool dump(ArrayRef<uint8_t> Data);
 
   /// Gets the type index for the next type record.
   unsigned getNextTypeIndex() const {
@@ -62,35 +61,11 @@ public:
   void setPrinter(ScopedPrinter *P);
   ScopedPrinter *getPrinter() { return W; }
 
-  /// Action to take on unknown types. By default, they are ignored.
-  Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) override;
-  Error visitUnknownMember(const CVRecord<TypeLeafKind> &Record) override;
-
-  /// Paired begin/end actions for all types. Receives all record data,
-  /// including the fixed-length record prefix.
-  Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
-  Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
-
-#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  Error visit##Name(Name##Record &Record) override;
-#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  TYPE_RECORD(EnumName, EnumVal, Name)
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "TypeRecords.def"
-
 private:
-  void printMemberAttributes(MemberAttributes Attrs);
-  void printMemberAttributes(MemberAccess Access, MethodKind Kind,
-                             MethodOptions Options);
-
   ScopedPrinter *W;
 
   bool PrintRecordBytes = false;
 
-  /// Name of the current type. Only valid before visitTypeEnd.
-  StringRef Name;
-
   /// All user defined type records in .debug$T live in here. Type indices
   /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
   /// index into this vector.

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def Thu Jun 16 13:09:04 2016
@@ -83,7 +83,6 @@ TYPE_RECORD(LF_STRING_ID, 0x1605, String
 TYPE_RECORD(LF_UDT_SRC_LINE, 0x1606, UdtSourceLine)
 TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine)
 
-
 TYPE_RECORD(LF_METHODLIST, 0x1206, MethodOverloadList)
 
 
@@ -196,8 +195,6 @@ CV_TYPE(LF_MODIFIER_EX, 0x1518)
 CV_TYPE(LF_VECTOR, 0x151b)
 CV_TYPE(LF_MATRIX, 0x151c)
 
-// ID leaf records. Subsequent leaf types may be referenced from .debug$S.
-
 // Numeric leaf types. These are generally contained in other records, and not
 // encountered in the main type stream.
 

Removed: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h?rev=272926&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h (removed)
@@ -1,53 +0,0 @@
-//===- TypeVisitorCallbacks.h -----------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPEVISITORCALLBACKS_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/Support/Error.h"
-
-namespace llvm {
-namespace codeview {
-class TypeVisitorCallbacks {
-  friend class CVTypeVisitor;
-
-public:
-  virtual ~TypeVisitorCallbacks() {}
-
-  /// Action to take on unknown types. By default, they are ignored.
-  virtual Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
-    return Error::success();
-  }
-  virtual Error visitUnknownMember(const CVRecord<TypeLeafKind> &Record) {
-    return Error::success();
-  }
-
-  /// Paired begin/end actions for all types. Receives all record data,
-  /// including the fixed-length record prefix.
-  virtual Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {
-    return Error::success();
-  }
-  virtual Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
-    return Error::success();
-  }
-
-#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  virtual Error visit##Name(Name##Record &Record) { return Error::success(); }
-#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  TYPE_RECORD(EnumName, EnumVal, Name)
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "TypeRecords.def"
-};
-}
-}
-
-#endif
\ No newline at end of file

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/RawError.h Thu Jun 16 13:09:04 2016
@@ -25,7 +25,6 @@ enum class raw_error_code {
   index_out_of_bounds,
   invalid_block_address,
   not_writable,
-  invalid_tpi_hash,
 };
 
 /// Base class for errors originating when parsing raw PDB files

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Thu Jun 16 13:09:04 2016
@@ -322,9 +322,10 @@ void CodeViewDebug::emitTypeInformation(
           ScopedPrinter SP(CommentOS);
           SP.setPrefix(CommentPrefix);
           CVTD.setPrinter(&SP);
-          Error EC = CVTD.dump({Record.bytes_begin(), Record.bytes_end()});
-          assert(!EC && "produced malformed type record");
-          consumeError(std::move(EC));
+          bool DumpSuccess =
+              CVTD.dump({Record.bytes_begin(), Record.bytes_end()});
+          (void)DumpSuccess;
+          assert(DumpSuccess && "produced malformed type record");
           // emitRawComment will insert its own tab and comment string before
           // the first line, so strip off our first one. It also prints its own
           // newline.

Modified: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt Thu Jun 16 13:09:04 2016
@@ -1,7 +1,6 @@
 add_llvm_library(LLVMDebugInfoCodeView
   ByteStream.cpp
   CodeViewError.cpp
-  CVTypeVisitor.cpp
   EnumTables.cpp
   FieldListRecordBuilder.cpp
   Line.cpp

Removed: llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp?rev=272926&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp (removed)
@@ -1,119 +0,0 @@
-//===- CVTypeVisitor.cpp ----------------------------------------*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-template <typename T>
-static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
-  if (Data.size() < sizeof(*Res))
-    return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
-  Res = reinterpret_cast<const T *>(Data.data());
-  Data = Data.drop_front(sizeof(*Res));
-  return Error::success();
-}
-
-CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
-    : Callbacks(Callbacks) {}
-
-Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
-  ArrayRef<uint8_t> LeafData = Record.Data;
-  if (auto EC = Callbacks.visitTypeBegin(Record))
-    return EC;
-  switch (Record.Type) {
-  default:
-    if (auto EC = Callbacks.visitUnknownType(Record))
-      return EC;
-    break;
-  case LF_FIELDLIST:
-    if (auto EC = visitFieldList(Record))
-      return EC;
-    break;
-#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  case EnumName: {                                                             \
-    TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName);                 \
-    auto Result = Name##Record::deserialize(RK, LeafData);                     \
-    if (Result.getError())                                                     \
-      return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);   \
-    if (auto EC = Callbacks.visit##Name(*Result))                              \
-      return EC;                                                               \
-    break;                                                                     \
-  }
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
-  TYPE_RECORD(EnumVal, EnumVal, AliasName)
-#define MEMBER_RECORD(EnumName, EnumVal, Name)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-  }
-  if (auto EC = Callbacks.visitTypeEnd(Record))
-    return EC;
-  return Error::success();
-}
-
-/// Visits the type records in Data. Sets the error flag on parse failures.
-Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
-  for (const auto &I : Types) {
-    if (auto EC = visitTypeRecord(I))
-      return EC;
-  }
-  return Error::success();
-}
-
-Error CVTypeVisitor::skipPadding(ArrayRef<uint8_t> &Data) {
-  if (Data.empty())
-    return Error::success();
-  uint8_t Leaf = Data.front();
-  if (Leaf < LF_PAD0)
-    return Error::success();
-  // Leaf is greater than 0xf0. We should advance by the number of bytes in
-  // the low 4 bits.
-  unsigned BytesToAdvance = Leaf & 0x0F;
-  if (Data.size() < BytesToAdvance) {
-    return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
-                                           "Invalid padding bytes!");
-  }
-  Data = Data.drop_front(BytesToAdvance);
-  return Error::success();
-}
-
-/// Visits individual member records of a field list record. Member records do
-/// not describe their own length, and need special handling.
-Error CVTypeVisitor::visitFieldList(const CVRecord<TypeLeafKind> &Record) {
-  ArrayRef<uint8_t> RecordData = Record.Data;
-  while (!RecordData.empty()) {
-    const ulittle16_t *LeafPtr;
-    if (auto EC = takeObject(RecordData, LeafPtr))
-      return EC;
-    TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
-    switch (Leaf) {
-    default:
-      // Field list records do not describe their own length, so we cannot
-      // continue parsing past an unknown member type.
-      if (auto EC = Callbacks.visitUnknownMember(Record))
-        return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
-#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  case EnumName: {                                                             \
-    TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName);                 \
-    auto Result = Name##Record::deserialize(RK, RecordData);                   \
-    if (Result.getError())                                                     \
-      return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);   \
-    if (auto EC = Callbacks.visit##Name(*Result))                              \
-      return EC;                                                               \
-    break;                                                                     \
-  }
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
-  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-    }
-    if (auto EC = skipPadding(RecordData))
-      return EC;
-  }
-  return Error::success();
-}

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp Thu Jun 16 13:09:04 2016
@@ -189,6 +189,55 @@ static const EnumEntry<uint8_t> Function
 
 #undef ENUM_ENTRY
 
+
+namespace {
+
+/// Use this private dumper implementation to keep implementation details about
+/// the visitor out of TypeDumper.h.
+class CVTypeDumperImpl : public CVTypeVisitor<CVTypeDumperImpl> {
+public:
+  CVTypeDumperImpl(CVTypeDumper &CVTD, ScopedPrinter &W, bool PrintRecordBytes)
+      : CVTD(CVTD), W(W), PrintRecordBytes(PrintRecordBytes) {}
+
+  /// CVTypeVisitor overrides.
+#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
+  void visit##Name(Name##Record &Record);
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
+  void visit##Name(Name##Record &Record);
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+
+  void visitUnknownMember(TypeLeafKind Leaf);
+  void visitUnknownType(const CVRecord<TypeLeafKind> &Record);
+
+  void visitTypeBegin(const CVRecord<TypeLeafKind> &Record);
+  void visitTypeEnd(const CVRecord<TypeLeafKind> &Record);
+
+  void printMemberAttributes(MemberAttributes Attrs);
+  void printMemberAttributes(MemberAccess Access, MethodKind Kind,
+                             MethodOptions Options);
+
+private:
+  /// Forwards to the dumper, which holds the persistent state from visitation.
+  StringRef getTypeName(TypeIndex TI) {
+    return CVTD.getTypeName(TI);
+  }
+
+  void printTypeIndex(StringRef FieldName, TypeIndex TI) {
+    CVTD.printTypeIndex(FieldName, TI);
+  }
+
+  CVTypeDumper &CVTD;
+  ScopedPrinter &W;
+  bool PrintRecordBytes = false;
+
+  /// Name of the current type. Only valid before visitTypeEnd.
+  StringRef Name;
+};
+
+} // end anonymous namespace
+
 static StringRef getLeafTypeName(TypeLeafKind LT) {
   switch (LT) {
 #define TYPE_RECORD(ename, value, name)                                        \
@@ -201,44 +250,39 @@ static StringRef getLeafTypeName(TypeLea
   return "UnknownLeaf";
 }
 
-Error CVTypeDumper::visitTypeBegin(const CVRecord<TypeLeafKind> &Record) {
+void CVTypeDumperImpl::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
   // Reset Name to the empty string. If the visitor sets it, we know it.
   Name = "";
 
-  W->startLine() << getLeafTypeName(Record.Type) << " ("
-                 << HexNumber(getNextTypeIndex()) << ") {\n";
-  W->indent();
-  W->printEnum("TypeLeafKind", unsigned(Record.Type),
-               makeArrayRef(LeafTypeNames));
-  return Error::success();
+  W.startLine() << getLeafTypeName(Rec.Type) << " ("
+                << HexNumber(CVTD.getNextTypeIndex()) << ") {\n";
+  W.indent();
+  W.printEnum("TypeLeafKind", unsigned(Rec.Type), makeArrayRef(LeafTypeNames));
 }
 
-Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
+void CVTypeDumperImpl::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
   // Always record some name for every type, even if Name is empty. CVUDTNames
   // is indexed by type index, and must have one entry for every type.
-  recordType(Name);
-
+  CVTD.recordType(Name);
   if (PrintRecordBytes)
-    W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
+    W.printBinaryBlock("LeafData", getBytesAsCharacters(Rec.Data));
 
-  W->unindent();
-  W->startLine() << "}\n";
-  return Error::success();
+  W.unindent();
+  W.startLine() << "}\n";
 }
 
-Error CVTypeDumper::visitStringId(StringIdRecord &String) {
+void CVTypeDumperImpl::visitStringId(StringIdRecord &String) {
   printTypeIndex("Id", String.getId());
-  W->printString("StringData", String.getString());
+  W.printString("StringData", String.getString());
   // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
   Name = String.getString();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitArgList(ArgListRecord &Args) {
+void CVTypeDumperImpl::visitArgList(ArgListRecord &Args) {
   auto Indices = Args.getIndices();
   uint32_t Size = Indices.size();
-  W->printNumber("NumArgs", Size);
-  ListScope Arguments(*W, "Arguments");
+  W.printNumber("NumArgs", Size);
+  ListScope Arguments(W, "Arguments");
   SmallString<256> TypeName("(");
   for (uint32_t I = 0; I < Size; ++I) {
     printTypeIndex("ArgType", Indices[I]);
@@ -248,84 +292,77 @@ Error CVTypeDumper::visitArgList(ArgList
       TypeName.append(", ");
   }
   TypeName.push_back(')');
-  Name = saveName(TypeName);
-  return Error::success();
+  Name = CVTD.saveName(TypeName);
 }
 
-Error CVTypeDumper::visitClass(ClassRecord &Class) {
+void CVTypeDumperImpl::visitClass(ClassRecord &Class) {
   uint16_t Props = static_cast<uint16_t>(Class.getOptions());
-  W->printNumber("MemberCount", Class.getMemberCount());
-  W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+  W.printNumber("MemberCount", Class.getMemberCount());
+  W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
   printTypeIndex("FieldList", Class.getFieldList());
   printTypeIndex("DerivedFrom", Class.getDerivationList());
   printTypeIndex("VShape", Class.getVTableShape());
-  W->printNumber("SizeOf", Class.getSize());
-  W->printString("Name", Class.getName());
+  W.printNumber("SizeOf", Class.getSize());
+  W.printString("Name", Class.getName());
   if (Props & uint16_t(ClassOptions::HasUniqueName))
-    W->printString("LinkageName", Class.getUniqueName());
+    W.printString("LinkageName", Class.getUniqueName());
   Name = Class.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitUnion(UnionRecord &Union) {
+void CVTypeDumperImpl::visitUnion(UnionRecord &Union) {
   uint16_t Props = static_cast<uint16_t>(Union.getOptions());
-  W->printNumber("MemberCount", Union.getMemberCount());
-  W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+  W.printNumber("MemberCount", Union.getMemberCount());
+  W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
   printTypeIndex("FieldList", Union.getFieldList());
-  W->printNumber("SizeOf", Union.getSize());
-  W->printString("Name", Union.getName());
+  W.printNumber("SizeOf", Union.getSize());
+  W.printString("Name", Union.getName());
   if (Props & uint16_t(ClassOptions::HasUniqueName))
-    W->printString("LinkageName", Union.getUniqueName());
+    W.printString("LinkageName", Union.getUniqueName());
   Name = Union.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitEnum(EnumRecord &Enum) {
-  W->printNumber("NumEnumerators", Enum.getMemberCount());
-  W->printFlags("Properties", uint16_t(Enum.getOptions()),
-                makeArrayRef(ClassOptionNames));
+void CVTypeDumperImpl::visitEnum(EnumRecord &Enum) {
+  W.printNumber("NumEnumerators", Enum.getMemberCount());
+  W.printFlags("Properties", uint16_t(Enum.getOptions()),
+               makeArrayRef(ClassOptionNames));
   printTypeIndex("UnderlyingType", Enum.getUnderlyingType());
   printTypeIndex("FieldListType", Enum.getFieldList());
-  W->printString("Name", Enum.getName());
+  W.printString("Name", Enum.getName());
   Name = Enum.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitArray(ArrayRecord &AT) {
+void CVTypeDumperImpl::visitArray(ArrayRecord &AT) {
   printTypeIndex("ElementType", AT.getElementType());
   printTypeIndex("IndexType", AT.getIndexType());
-  W->printNumber("SizeOf", AT.getSize());
-  W->printString("Name", AT.getName());
+  W.printNumber("SizeOf", AT.getSize());
+  W.printString("Name", AT.getName());
   Name = AT.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) {
+void CVTypeDumperImpl::visitVFTable(VFTableRecord &VFT) {
   printTypeIndex("CompleteClass", VFT.getCompleteClass());
   printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
-  W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
-  W->printString("VFTableName", VFT.getName());
+  W.printHex("VFPtrOffset", VFT.getVFPtrOffset());
+  W.printString("VFTableName", VFT.getName());
   for (auto N : VFT.getMethodNames())
-    W->printString("MethodName", N);
+    W.printString("MethodName", N);
   Name = VFT.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) {
+void CVTypeDumperImpl::visitMemberFuncId(MemberFuncIdRecord &Id) {
   printTypeIndex("ClassType", Id.getClassType());
   printTypeIndex("FunctionType", Id.getFunctionType());
-  W->printString("Name", Id.getName());
+  W.printString("Name", Id.getName());
   Name = Id.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) {
+void CVTypeDumperImpl::visitProcedure(ProcedureRecord &Proc) {
   printTypeIndex("ReturnType", Proc.getReturnType());
-  W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
-               makeArrayRef(CallingConventions));
-  W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()),
-                makeArrayRef(FunctionOptionEnum));
-  W->printNumber("NumParameters", Proc.getParameterCount());
+  W.printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
+              makeArrayRef(CallingConventions));
+  W.printFlags("FunctionOptions", uint8_t(Proc.getOptions()),
+               makeArrayRef(FunctionOptionEnum));
+  W.printNumber("NumParameters", Proc.getParameterCount());
   printTypeIndex("ArgListType", Proc.getArgumentList());
 
   StringRef ReturnTypeName = getTypeName(Proc.getReturnType());
@@ -333,21 +370,20 @@ Error CVTypeDumper::visitProcedure(Proce
   SmallString<256> TypeName(ReturnTypeName);
   TypeName.push_back(' ');
   TypeName.append(ArgListTypeName);
-  Name = saveName(TypeName);
-  return Error::success();
+  Name = CVTD.saveName(TypeName);
 }
 
-Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) {
+void CVTypeDumperImpl::visitMemberFunction(MemberFunctionRecord &MF) {
   printTypeIndex("ReturnType", MF.getReturnType());
   printTypeIndex("ClassType", MF.getClassType());
   printTypeIndex("ThisType", MF.getThisType());
-  W->printEnum("CallingConvention", uint8_t(MF.getCallConv()),
-               makeArrayRef(CallingConventions));
-  W->printFlags("FunctionOptions", uint8_t(MF.getOptions()),
-                makeArrayRef(FunctionOptionEnum));
-  W->printNumber("NumParameters", MF.getParameterCount());
+  W.printEnum("CallingConvention", uint8_t(MF.getCallConv()),
+              makeArrayRef(CallingConventions));
+  W.printFlags("FunctionOptions", uint8_t(MF.getOptions()),
+               makeArrayRef(FunctionOptionEnum));
+  W.printNumber("NumParameters", MF.getParameterCount());
   printTypeIndex("ArgListType", MF.getArgumentList());
-  W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
+  W.printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
 
   StringRef ReturnTypeName = getTypeName(MF.getReturnType());
   StringRef ClassTypeName = getTypeName(MF.getClassType());
@@ -357,56 +393,52 @@ Error CVTypeDumper::visitMemberFunction(
   TypeName.append(ClassTypeName);
   TypeName.append("::");
   TypeName.append(ArgListTypeName);
-  Name = saveName(TypeName);
-  return Error::success();
+  Name = CVTD.saveName(TypeName);
 }
 
-Error CVTypeDumper::visitMethodOverloadList(
+void CVTypeDumperImpl::visitMethodOverloadList(
     MethodOverloadListRecord &MethodList) {
   for (auto &M : MethodList.getMethods()) {
-    ListScope S(*W, "Method");
+    ListScope S(W, "Method");
     printMemberAttributes(M.getAccess(), M.getKind(), M.getOptions());
     printTypeIndex("Type", M.getType());
     if (M.isIntroducingVirtual())
-      W->printHex("VFTableOffset", M.getVFTableOffset());
+      W.printHex("VFTableOffset", M.getVFTableOffset());
   }
-  return Error::success();
 }
 
-Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) {
+void CVTypeDumperImpl::visitFuncId(FuncIdRecord &Func) {
   printTypeIndex("ParentScope", Func.getParentScope());
   printTypeIndex("FunctionType", Func.getFunctionType());
-  W->printString("Name", Func.getName());
+  W.printString("Name", Func.getName());
   Name = Func.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) {
-  W->printBinary("Signature", TS.getGuid());
-  W->printNumber("Age", TS.getAge());
-  W->printString("Name", TS.getName());
+void CVTypeDumperImpl::visitTypeServer2(TypeServer2Record &TS) {
+  W.printBinary("Signature", TS.getGuid());
+  W.printNumber("Age", TS.getAge());
+  W.printString("Name", TS.getName());
   Name = TS.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitPointer(PointerRecord &Ptr) {
+void CVTypeDumperImpl::visitPointer(PointerRecord &Ptr) {
   printTypeIndex("PointeeType", Ptr.getReferentType());
-  W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
-  W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
-               makeArrayRef(PtrKindNames));
-  W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames));
-
-  W->printNumber("IsFlat", Ptr.isFlat());
-  W->printNumber("IsConst", Ptr.isConst());
-  W->printNumber("IsVolatile", Ptr.isVolatile());
-  W->printNumber("IsUnaligned", Ptr.isUnaligned());
+  W.printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
+  W.printEnum("PtrType", unsigned(Ptr.getPointerKind()),
+              makeArrayRef(PtrKindNames));
+  W.printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames));
+
+  W.printNumber("IsFlat", Ptr.isFlat());
+  W.printNumber("IsConst", Ptr.isConst());
+  W.printNumber("IsVolatile", Ptr.isVolatile());
+  W.printNumber("IsUnaligned", Ptr.isUnaligned());
 
   if (Ptr.isPointerToMember()) {
     const MemberPointerInfo &MI = Ptr.getMemberInfo();
 
     printTypeIndex("ClassType", MI.getContainingType());
-    W->printEnum("Representation", uint16_t(MI.getRepresentation()),
-                 makeArrayRef(PtrMemberRepNames));
+    W.printEnum("Representation", uint16_t(MI.getRepresentation()),
+                makeArrayRef(PtrMemberRepNames));
 
     StringRef PointeeName = getTypeName(Ptr.getReferentType());
     StringRef ClassName = getTypeName(MI.getContainingType());
@@ -414,7 +446,7 @@ Error CVTypeDumper::visitPointer(Pointer
     TypeName.push_back(' ');
     TypeName.append(ClassName);
     TypeName.append("::*");
-    Name = saveName(TypeName);
+    Name = CVTD.saveName(TypeName);
   } else {
     SmallString<256> TypeName;
     if (Ptr.isConst())
@@ -434,15 +466,14 @@ Error CVTypeDumper::visitPointer(Pointer
       TypeName.append("*");
 
     if (!TypeName.empty())
-      Name = saveName(TypeName);
+      Name = CVTD.saveName(TypeName);
   }
-  return Error::success();
 }
 
-Error CVTypeDumper::visitModifier(ModifierRecord &Mod) {
+void CVTypeDumperImpl::visitModifier(ModifierRecord &Mod) {
   uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
   printTypeIndex("ModifiedType", Mod.getModifiedType());
-  W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
+  W.printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
 
   StringRef ModifiedName = getTypeName(Mod.getModifiedType());
   SmallString<256> TypeName;
@@ -453,162 +484,146 @@ Error CVTypeDumper::visitModifier(Modifi
   if (Mods & uint16_t(ModifierOptions::Unaligned))
     TypeName.append("__unaligned ");
   TypeName.append(ModifiedName);
-  Name = saveName(TypeName);
-  return Error::success();
+  Name = CVTD.saveName(TypeName);
 }
 
-Error CVTypeDumper::visitBitField(BitFieldRecord &BitField) {
+void CVTypeDumperImpl::visitBitField(BitFieldRecord &BitField) {
   printTypeIndex("Type", BitField.getType());
-  W->printNumber("BitSize", BitField.getBitSize());
-  W->printNumber("BitOffset", BitField.getBitOffset());
-  return Error::success();
+  W.printNumber("BitSize", BitField.getBitSize());
+  W.printNumber("BitOffset", BitField.getBitOffset());
 }
 
-Error CVTypeDumper::visitVFTableShape(VFTableShapeRecord &Shape) {
-  W->printNumber("VFEntryCount", Shape.getEntryCount());
-  return Error::success();
+void CVTypeDumperImpl::visitVFTableShape(VFTableShapeRecord &Shape) {
+  W.printNumber("VFEntryCount", Shape.getEntryCount());
 }
 
-Error CVTypeDumper::visitUdtSourceLine(UdtSourceLineRecord &Line) {
+void CVTypeDumperImpl::visitUdtSourceLine(UdtSourceLineRecord &Line) {
   printTypeIndex("UDT", Line.getUDT());
   printTypeIndex("SourceFile", Line.getSourceFile());
-  W->printNumber("LineNumber", Line.getLineNumber());
-  return Error::success();
+  W.printNumber("LineNumber", Line.getLineNumber());
 }
 
-Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
+void CVTypeDumperImpl::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
   printTypeIndex("UDT", Line.getUDT());
   printTypeIndex("SourceFile", Line.getSourceFile());
-  W->printNumber("LineNumber", Line.getLineNumber());
-  W->printNumber("Module", Line.getModule());
-  return Error::success();
+  W.printNumber("LineNumber", Line.getLineNumber());
+  W.printNumber("Module", Line.getModule());
 }
 
-Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) {
-  W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
+void CVTypeDumperImpl::visitBuildInfo(BuildInfoRecord &Args) {
+  W.printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
 
-  ListScope Arguments(*W, "Arguments");
+  ListScope Arguments(W, "Arguments");
   for (auto Arg : Args.getArgs()) {
     printTypeIndex("ArgType", Arg);
   }
-  return Error::success();
 }
 
-void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) {
+void CVTypeDumperImpl::printMemberAttributes(MemberAttributes Attrs) {
   return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
                                Attrs.getFlags());
 }
 
-void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind,
-                                         MethodOptions Options) {
-  W->printEnum("AccessSpecifier", uint8_t(Access),
-               makeArrayRef(MemberAccessNames));
+void CVTypeDumperImpl::printMemberAttributes(MemberAccess Access,
+                                             MethodKind Kind,
+                                             MethodOptions Options) {
+  W.printEnum("AccessSpecifier", uint8_t(Access),
+              makeArrayRef(MemberAccessNames));
   // Data members will be vanilla. Don't try to print a method kind for them.
   if (Kind != MethodKind::Vanilla)
-    W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
+    W.printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
   if (Options != MethodOptions::None) {
-    W->printFlags("MethodOptions", unsigned(Options),
-                  makeArrayRef(MethodOptionNames));
+    W.printFlags("MethodOptions", unsigned(Options),
+                 makeArrayRef(MethodOptionNames));
   }
 }
 
-Error CVTypeDumper::visitUnknownMember(const CVRecord<TypeLeafKind> &Record) {
-  W->printHex("UnknownMember", unsigned(Record.Type));
-  return Error::success();
+void CVTypeDumperImpl::visitUnknownMember(TypeLeafKind Leaf) {
+  W.printHex("UnknownMember", unsigned(Leaf));
 }
 
-Error CVTypeDumper::visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
-  DictScope S(*W, "UnknownType");
-  W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames));
-  W->printNumber("Length", uint32_t(Record.Data.size()));
-  return Error::success();
+void CVTypeDumperImpl::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
+  DictScope S(W, "UnknownType");
+  W.printEnum("Kind", uint16_t(Rec.Type), makeArrayRef(LeafTypeNames));
+  W.printNumber("Length", uint32_t(Rec.Data.size()));
 }
 
-Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) {
-  DictScope S(*W, "NestedType");
+void CVTypeDumperImpl::visitNestedType(NestedTypeRecord &Nested) {
+  DictScope S(W, "NestedType");
   printTypeIndex("Type", Nested.getNestedType());
-  W->printString("Name", Nested.getName());
+  W.printString("Name", Nested.getName());
   Name = Nested.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) {
-  DictScope S(*W, "OneMethod");
+void CVTypeDumperImpl::visitOneMethod(OneMethodRecord &Method) {
+  DictScope S(W, "OneMethod");
   MethodKind K = Method.getKind();
   printMemberAttributes(Method.getAccess(), K, Method.getOptions());
   printTypeIndex("Type", Method.getType());
   // If virtual, then read the vftable offset.
   if (Method.isIntroducingVirtual())
-    W->printHex("VFTableOffset", Method.getVFTableOffset());
-  W->printString("Name", Method.getName());
+    W.printHex("VFTableOffset", Method.getVFTableOffset());
+  W.printString("Name", Method.getName());
   Name = Method.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) {
-  DictScope S(*W, "OverloadedMethod");
-  W->printHex("MethodCount", Method.getNumOverloads());
+void CVTypeDumperImpl::visitOverloadedMethod(OverloadedMethodRecord &Method) {
+  DictScope S(W, "OverloadedMethod");
+  W.printHex("MethodCount", Method.getNumOverloads());
   printTypeIndex("MethodListIndex", Method.getMethodList());
-  W->printString("Name", Method.getName());
+  W.printString("Name", Method.getName());
   Name = Method.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) {
-  DictScope S(*W, "DataMember");
+void CVTypeDumperImpl::visitDataMember(DataMemberRecord &Field) {
+  DictScope S(W, "DataMember");
   printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
   printTypeIndex("Type", Field.getType());
-  W->printHex("FieldOffset", Field.getFieldOffset());
-  W->printString("Name", Field.getName());
+  W.printHex("FieldOffset", Field.getFieldOffset());
+  W.printString("Name", Field.getName());
   Name = Field.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) {
-  DictScope S(*W, "StaticDataMember");
+void CVTypeDumperImpl::visitStaticDataMember(StaticDataMemberRecord &Field) {
+  DictScope S(W, "StaticDataMember");
   printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
   printTypeIndex("Type", Field.getType());
-  W->printString("Name", Field.getName());
+  W.printString("Name", Field.getName());
   Name = Field.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitVFPtr(VFPtrRecord &VFTable) {
-  DictScope S(*W, "VFPtr");
+void CVTypeDumperImpl::visitVFPtr(VFPtrRecord &VFTable) {
+  DictScope S(W, "VFPtr");
   printTypeIndex("Type", VFTable.getType());
-  return Error::success();
 }
 
-Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) {
-  DictScope S(*W, "Enumerator");
+void CVTypeDumperImpl::visitEnumerator(EnumeratorRecord &Enum) {
+  DictScope S(W, "Enumerator");
   printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
-  W->printNumber("EnumValue", Enum.getValue());
-  W->printString("Name", Enum.getName());
+  W.printNumber("EnumValue", Enum.getValue());
+  W.printString("Name", Enum.getName());
   Name = Enum.getName();
-  return Error::success();
 }
 
-Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
-  DictScope S(*W, "BaseClass");
+void CVTypeDumperImpl::visitBaseClass(BaseClassRecord &Base) {
+  DictScope S(W, "BaseClass");
   printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
   printTypeIndex("BaseType", Base.getBaseType());
-  W->printHex("BaseOffset", Base.getBaseOffset());
-  return Error::success();
+  W.printHex("BaseOffset", Base.getBaseOffset());
 }
 
-Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
-  DictScope S(*W, "VirtualBaseClass");
+void CVTypeDumperImpl::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
+  DictScope S(W, "VirtualBaseClass");
   printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
   printTypeIndex("BaseType", Base.getBaseType());
   printTypeIndex("VBPtrType", Base.getVBPtrType());
-  W->printHex("VBPtrOffset", Base.getVBPtrOffset());
-  W->printHex("VBTableIndex", Base.getVTableIndex());
-  return Error::success();
+  W.printHex("VBPtrOffset", Base.getVBPtrOffset());
+  W.printHex("VBTableIndex", Base.getVTableIndex());
 }
 
 StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
@@ -648,29 +663,28 @@ void CVTypeDumper::printTypeIndex(String
     W->printHex(FieldName, TI.getIndex());
 }
 
-Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
+bool CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
   assert(W && "printer should not be null");
-  CVTypeVisitor Visitor(*this);
-
-  if (auto EC = Visitor.visitTypeRecord(Record))
-    return EC;
-  return Error::success();
+  CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes);
+  Dumper.visitTypeRecord(Record);
+  return !Dumper.hadError();
 }
 
-Error CVTypeDumper::dump(const CVTypeArray &Types) {
+bool CVTypeDumper::dump(const CVTypeArray &Types) {
   assert(W && "printer should not be null");
-  CVTypeVisitor Visitor(*this);
-  if (auto EC = Visitor.visitTypeStream(Types))
-    return EC;
-  return Error::success();
+  CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes);
+  Dumper.visitTypeStream(Types);
+  return !Dumper.hadError();
 }
 
-Error CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
+bool CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
   ByteStream<> Stream(Data);
   CVTypeArray Types;
   StreamReader Reader(Stream);
-  if (auto EC = Reader.readArray(Types, Reader.getLength()))
-    return EC;
+  if (auto EC = Reader.readArray(Types, Reader.getLength())) {
+    consumeError(std::move(EC));
+    return false;
+  }
 
   return dump(Types);
 }

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp Thu Jun 16 13:09:04 2016
@@ -15,8 +15,6 @@
 #include "llvm/DebugInfo/CodeView/StreamRef.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-#include "llvm/Support/Error.h"
 #include "llvm/Support/ScopedPrinter.h"
 
 using namespace llvm;
@@ -51,30 +49,32 @@ namespace {
 /// - If the type record already exists in the destination stream, discard it
 ///   and update the type index map to forward the source type index to the
 ///   existing destination type index.
-class TypeStreamMerger : public TypeVisitorCallbacks {
+class TypeStreamMerger : public CVTypeVisitor<TypeStreamMerger> {
 public:
   TypeStreamMerger(TypeTableBuilder &DestStream) : DestStream(DestStream) {
     assert(!hadError());
   }
 
-/// TypeVisitorCallbacks overrides.
+  /// CVTypeVisitor overrides.
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  Error visit##Name(Name##Record &Record) override;
-#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  TYPE_RECORD(EnumName, EnumVal, Name)
+  void visit##Name(Name##Record &Record);
 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
+  void visit##Name(Name##Record &Record);
 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
 
-  Error visitUnknownType(const CVRecord<TypeLeafKind> &Record) override;
+  void visitUnknownType(const CVRecord<TypeLeafKind> &Record);
+
+  void visitTypeBegin(const CVRecord<TypeLeafKind> &Record);
+  void visitTypeEnd(const CVRecord<TypeLeafKind> &Record);
 
-  Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
-  Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
+  void visitFieldList(TypeLeafKind Leaf, ArrayRef<uint8_t> FieldData);
 
   bool mergeStream(const CVTypeArray &Types);
 
 private:
-  bool hadError() { return FoundBadTypeIndex; }
+  bool hadError() { return FoundBadTypeIndex || CVTypeVisitor::hadError(); }
 
   bool FoundBadTypeIndex = false;
 
@@ -91,46 +91,45 @@ private:
 
 } // end anonymous namespace
 
-Error TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
+void TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
   BeginIndexMapSize = IndexMap.size();
-  return Error::success();
 }
 
-Error TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
+void TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
   assert(IndexMap.size() == BeginIndexMapSize + 1);
-  return Error::success();
+}
+
+void TypeStreamMerger::visitFieldList(TypeLeafKind Leaf,
+                                      ArrayRef<uint8_t> FieldData) {
+  CVTypeVisitor::visitFieldList(Leaf, FieldData);
+  IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
+  FieldBuilder.reset();
 }
 
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  Error TypeStreamMerger::visit##Name(Name##Record &Record) {                  \
+  void TypeStreamMerger::visit##Name(Name##Record &Record) {                   \
     FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);                   \
     IndexMap.push_back(DestStream.write##Name(Record));                        \
-    return Error::success();                                                   \
   }
 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  Error TypeStreamMerger::visit##Name(Name##Record &Record) {                  \
+  void TypeStreamMerger::visit##Name(Name##Record &Record) {                   \
     FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);                   \
     FieldBuilder.write##Name(Record);                                          \
-    return Error::success();                                                   \
   }
 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
 
-Error TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
+void TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
   // We failed to translate a type. Translate this index as "not translated".
   IndexMap.push_back(
       TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct));
-  return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
+  parseError();
 }
 
 bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
   assert(IndexMap.empty());
-  CVTypeVisitor Visitor(*this);
-  if (auto EC = Visitor.visitTypeStream(Types)) {
-    consumeError(std::move(EC));
-    return false;
-  }
+  visitTypeStream(Types);
   IndexMap.clear();
   return !hadError();
 }

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/RawError.cpp Thu Jun 16 13:09:04 2016
@@ -32,8 +32,6 @@ public:
       return "The specified block address is not valid.";
     case raw_error_code::not_writable:
       return "The PDB does not support writing.";
-    case raw_error_code::invalid_tpi_hash:
-      return "The Type record has an invalid hash value.";
     }
     llvm_unreachable("Unrecognized raw_error_code");
   }

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp Thu Jun 16 13:09:04 2016
@@ -84,44 +84,39 @@ template <typename T> static uint32_t ge
 }
 
 namespace {
-class TpiHashVerifier : public TypeVisitorCallbacks {
+class TpiHashVerifier : public CVTypeVisitor<TpiHashVerifier> {
 public:
   TpiHashVerifier(FixedStreamArray<support::ulittle32_t> &HashValues,
                   uint32_t NumHashBuckets)
       : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
 
-  Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override {
-    return verifySourceLine(Rec);
-  }
+  void visitUdtSourceLine(UdtSourceLineRecord &Rec) { verifySourceLine(Rec); }
 
-  Error visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override {
-    return verifySourceLine(Rec);
+  void visitUdtModSourceLine(UdtModSourceLineRecord &Rec) {
+    verifySourceLine(Rec);
   }
 
-  Error visitClass(ClassRecord &Rec) override { return verify(Rec); }
-  Error visitEnum(EnumRecord &Rec) override { return verify(Rec); }
-  Error visitUnion(UnionRecord &Rec) override { return verify(Rec); }
-
-  Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override {
-    ++Index;
-    return Error::success();
-  }
+  void visitClass(ClassRecord &Rec) { verify(Rec); }
+  void visitEnum(EnumRecord &Rec) { verify(Rec); }
+  void visitInterface(ClassRecord &Rec) { verify(Rec); }
+  void visitStruct(ClassRecord &Rec) { verify(Rec); }
+  void visitUnion(UnionRecord &Rec) { verify(Rec); }
+
+  void visitTypeEnd(const CVRecord<TypeLeafKind> &Record) { ++Index; }
 
 private:
-  template <typename T> Error verify(T &Rec) {
+  template <typename T> void verify(T &Rec) {
     uint32_t Hash = getTpiHash(Rec);
     if (Hash && Hash % NumHashBuckets != HashValues[Index])
-      return make_error<RawError>(raw_error_code::invalid_tpi_hash);
-    return Error::success();
+      parseError();
   }
 
-  template <typename T> Error verifySourceLine(T &Rec) {
+  template <typename T> void verifySourceLine(T &Rec) {
     char Buf[4];
     support::endian::write32le(Buf, Rec.getUDT().getIndex());
     uint32_t Hash = hashStringV1(StringRef(Buf, 4));
     if (Hash % NumHashBuckets != HashValues[Index])
-      return make_error<RawError>(raw_error_code::invalid_tpi_hash);
-    return Error::success();
+      parseError();
   }
 
   FixedStreamArray<support::ulittle32_t> HashValues;
@@ -134,8 +129,11 @@ private:
 // Currently we only verify SRC_LINE records.
 Error TpiStream::verifyHashValues() {
   TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets);
-  CVTypeVisitor Visitor(Verifier);
-  return Visitor.visitTypeStream(TypeRecords);
+  Verifier.visitTypeStream(TypeRecords);
+  if (Verifier.hadError())
+    return make_error<RawError>(raw_error_code::corrupt_file,
+                                "Corrupt TPI hash table.");
+  return Error::success();
 }
 
 Error TpiStream::reload() {

Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp Thu Jun 16 13:09:04 2016
@@ -328,10 +328,8 @@ Error LLVMOutputStyle::dumpTpiStream(uin
     for (auto &Type : Tpi->types(&HadError)) {
       DictScope DD(P, "");
 
-      if (DumpRecords) {
-        if (auto EC = TD.dump(Type))
-          return EC;
-      }
+      if (DumpRecords)
+        TD.dump(Type);
 
       if (DumpRecordBytes)
         P.printBinaryBlock("Bytes", Type.Data);
@@ -349,10 +347,8 @@ Error LLVMOutputStyle::dumpTpiStream(uin
     TD.setPrinter(nullptr);
 
     bool HadError = false;
-    for (auto &Type : Tpi->types(&HadError)) {
-      if (auto EC = TD.dump(Type))
-        return EC;
-    }
+    for (auto &Type : Tpi->types(&HadError))
+      TD.dump(Type);
 
     TD.setPrinter(OldP);
     dumpTpiHash(P, *Tpi);

Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=272927&r1=272926&r2=272927&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Thu Jun 16 13:09:04 2016
@@ -1108,9 +1108,9 @@ void COFFDumper::printCodeViewTypeSectio
   if (Magic != COFF::DEBUG_SECTION_MAGIC)
     return error(object_error::parse_failed);
 
-  if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()})) {
+  if (!CVTD.dump({Data.bytes_begin(), Data.bytes_end()})) {
     W.flush();
-    error(llvm::errorToErrorCode(std::move(EC)));
+    error(object_error::parse_failed);
   }
 }
 




More information about the llvm-commits mailing list