<div dir="ltr">This change breaks the build:<div><br></div><div><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/12486/steps/check-llvm%20ubsan/logs/stdio" class="cremed">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/12486/steps/check-llvm%20ubsan/logs/stdio</a></div><div><br></div><div><div>FAILED: /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm_build0/bin/clang++   -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools/llvm-pdbdump -I/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/llvm-pdbdump -Iinclude -I/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include -fsanitize=undefined -w -fPIC -fvisibility-inlines-hidden -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -std=c++11 -fno-omit-frame-pointer -O1 -fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all -fcolor-diagnostics -g    -fno-exceptions -fno-rtti -MMD -MT tools/llvm-pdbdump/CMakeFiles/llvm-pdbdump.dir/llvm-pdbdump.cpp.o -MF tools/llvm-pdbdump/CMakeFiles/llvm-pdbdump.dir/llvm-pdbdump.cpp.o.d -o tools/llvm-pdbdump/CMakeFiles/llvm-pdbdump.dir/llvm-pdbdump.cpp.o -c /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp</div><div>/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp:157:30: error: no matching function for call to 'min'</div><div>    uint32_t BytesThisLine = std::min(Bytes.size(), BytesPerRow);</div><div>                             ^~~~~~~~</div><div>/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/algorithmfwd.h:367:5: note: candidate template ignored: deduced conflicting types for parameter '_Tp' ('unsigned long' vs. 'unsigned int')</div><div>    min(const _Tp&, const _Tp&);</div><div>    ^</div><div>/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_algo.h:3444:5: note: candidate template ignored: could not match 'initializer_list<type-parameter-0-0>' against 'unsigned long'</div><div>    min(initializer_list<_Tp> __l, _Compare __comp)</div><div>    ^</div><div>/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/algorithmfwd.h:371:5: note: candidate function template not viable: requires 3 arguments, but 2 were provided</div><div>    min(const _Tp&, const _Tp&, _Compare);</div><div>    ^</div><div>/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_algo.h:3439:5: note: candidate function template not viable: requires single argument '__l', but 2 arguments were provided</div><div>    min(initializer_list<_Tp> __l)</div><div>    ^</div><div>1 error generated.</div><div><br></div><br><div class="gmail_quote"><div dir="ltr">On Tue, May 3, 2016 at 3:24 PM Zachary Turner via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: zturner<br>
Date: Tue May  3 17:18:17 2016<br>
New Revision: 268454<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=268454&view=rev" rel="noreferrer" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project?rev=268454&view=rev</a><br>
Log:<br>
Move CodeViewTypeStream to DebugInfo/CodeView<br>
<br>
Ability to parse codeview type streams is also needed by<br>
DebugInfoPDB for parsing PDBs, so moving this into a library<br>
gives us this option.  Since DebugInfoPDB had already hand<br>
rolled some code to do this, that code is now convereted over<br>
to using this common abstraction.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D19887" rel="noreferrer" target="_blank" class="cremed">http://reviews.llvm.org/D19887</a><br>
Reviewed By: dblaikie, amccarth<br>
<br>
Added:<br>
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h<br>
Modified:<br>
    llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h<br>
    llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp<br>
    llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp<br>
    llvm/trunk/tools/llvm-readobj/COFFDumper.cpp<br>
<br>
Added: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h?rev=268454&view=auto" rel="noreferrer" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h?rev=268454&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h (added)<br>
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h Tue May  3 17:18:17 2016<br>
@@ -0,0 +1,130 @@<br>
+//===- TypeStream.h ---------------------------------------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESTREAM_H<br>
+#define LLVM_DEBUGINFO_CODEVIEW_TYPESTREAM_H<br>
+<br>
+#include "llvm/ADT/iterator_range.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/DebugInfo/CodeView/CodeView.h"<br>
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"<br>
+#include "llvm/Object/Error.h"<br>
+#include "llvm/Support/Endian.h"<br>
+#include "llvm/Support/ErrorOr.h"<br>
+<br>
+#include <stdint.h><br>
+<br>
+namespace llvm {<br>
+namespace codeview {<br>
+<br>
+/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if<br>
+/// there are not enough bytes remaining. Reinterprets the consumed bytes as a<br>
+/// T object and points 'Res' at them.<br>
+template <typename T><br>
+inline std::error_code consumeObject(StringRef &Data, const T *&Res) {<br>
+  if (Data.size() < sizeof(*Res))<br>
+    return object::object_error::parse_failed;<br>
+  Res = reinterpret_cast<const T *>(Data.data());<br>
+  Data = Data.drop_front(sizeof(*Res));<br>
+  return std::error_code();<br>
+}<br>
+<br>
+inline std::error_code consumeUInt32(StringRef &Data, uint32_t &Res) {<br>
+  const support::ulittle32_t *IntPtr;<br>
+  if (auto EC = consumeObject(Data, IntPtr))<br>
+    return EC;<br>
+  Res = *IntPtr;<br>
+  return std::error_code();<br>
+}<br>
+<br>
+// A const input iterator interface to the CodeView type stream.<br>
+class TypeIterator {<br>
+public:<br>
+  struct TypeRecord {<br>
+    std::size_t Length;<br>
+    TypeLeafKind Leaf;<br>
+    StringRef LeafData;<br>
+  };<br>
+<br>
+  explicit TypeIterator(const StringRef &SectionData)<br>
+      : Data(SectionData), AtEnd(false) {<br>
+    next(); // Prime the pump<br>
+  }<br>
+<br>
+  TypeIterator() : AtEnd(true) {}<br>
+<br>
+  // For iterators to compare equal, they must both point at the same record<br>
+  // in the same data stream, or they must both be at the end of a stream.<br>
+  friend bool operator==(const TypeIterator &lhs, const TypeIterator &rhs) {<br>
+    return (lhs.Data.begin() == rhs.Data.begin()) || (lhs.AtEnd && rhs.AtEnd);<br>
+  }<br>
+<br>
+  friend bool operator!=(const TypeIterator &lhs, const TypeIterator &rhs) {<br>
+    return !(lhs == rhs);<br>
+  }<br>
+<br>
+  const TypeRecord &operator*() const {<br>
+    assert(!AtEnd);<br>
+    return Current;<br>
+  }<br>
+<br>
+  const TypeRecord *operator->() const {<br>
+    assert(!AtEnd);<br>
+    return &Current;<br>
+  }<br>
+<br>
+  TypeIterator operator++() {<br>
+    next();<br>
+    return *this;<br>
+  }<br>
+<br>
+  TypeIterator operator++(int) {<br>
+    TypeIterator Original = *this;<br>
+    ++*this;<br>
+    return Original;<br>
+  }<br>
+<br>
+private:<br>
+  void next() {<br>
+    assert(!AtEnd && "Attempted to advance more than one past the last rec");<br>
+    if (Data.empty()) {<br>
+      // We've advanced past the last record.<br>
+      AtEnd = true;<br>
+      return;<br>
+    }<br>
+<br>
+    const TypeRecordPrefix *Rec;<br>
+    if (consumeObject(Data, Rec))<br>
+      return;<br>
+    Current.Length = Rec->Len;<br>
+    Current.Leaf = static_cast<TypeLeafKind>(uint16_t(Rec->Leaf));<br>
+    Current.LeafData = Data.substr(0, Current.Length - 2);<br>
+<br>
+    // The next record starts immediately after this one.<br>
+    Data = Data.drop_front(Current.LeafData.size());<br>
+<br>
+    // FIXME: The stream contains LF_PAD bytes that we need to ignore, but those<br>
+    // are typically included in LeafData. We may need to call skipPadding() if<br>
+    // we ever find a record that doesn't count those bytes.<br>
+<br>
+    return;<br>
+  }<br>
+<br>
+  StringRef Data;<br>
+  TypeRecord Current;<br>
+  bool AtEnd;<br>
+};<br>
+<br>
+inline iterator_range<TypeIterator> makeTypeRange(StringRef Data) {<br>
+  return make_range(TypeIterator(Data), TypeIterator());<br>
+}<br>
+}<br>
+}<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h?rev=268454&r1=268453&r2=268454&view=diff" rel="noreferrer" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h?rev=268454&r1=268453&r2=268454&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Raw/TpiStream.h Tue May  3 17:18:17 2016<br>
@@ -10,6 +10,7 @@<br>
 #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H<br>
 #define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H<br>
<br>
+#include "llvm/DebugInfo/CodeView/TypeStream.h"<br>
 #include "llvm/DebugInfo/PDB/PDBTypes.h"<br>
 #include "llvm/DebugInfo/PDB/Raw/ByteStream.h"<br>
 #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"<br>
@@ -25,12 +26,6 @@ class TpiStream {<br>
   struct HeaderInfo;<br>
<br>
 public:<br>
-  struct HashedTypeRecord {<br>
-    uint32_t Hash;<br>
-    codeview::TypeLeafKind Kind;<br>
-    ArrayRef<uint8_t> Record;<br>
-  };<br>
-<br>
   TpiStream(PDBFile &File);<br>
   ~TpiStream();<br>
   std::error_code reload();<br>
@@ -41,7 +36,7 @@ public:<br>
   uint32_t TypeIndexEnd() const;<br>
   uint32_t NumTypeRecords() const;<br>
<br>
-  ArrayRef<HashedTypeRecord> records() const;<br>
+  iterator_range<codeview::TypeIterator> types() const;<br>
<br>
 private:<br>
   PDBFile &Pdb;<br>
@@ -53,7 +48,6 @@ private:<br>
   ByteStream HashValuesBuffer;<br>
   ByteStream HashAdjBuffer;<br>
<br>
-  std::vector<HashedTypeRecord> TypeRecords;<br>
   std::unique_ptr<HeaderInfo> Header;<br>
 };<br>
 }<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp?rev=268454&r1=268453&r2=268454&view=diff" rel="noreferrer" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp?rev=268454&r1=268453&r2=268454&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp Tue May  3 17:18:17 2016<br>
@@ -88,25 +88,6 @@ std::error_code TpiStream::reload() {<br>
<br>
   // The actual type records themselves come from this stream<br>
   RecordsBuffer.initialize(Reader, Header->TypeRecordBytes);<br>
-  TypeRecords.resize(TypeIndexEnd() - ::MinTypeIndex);<br>
-  StreamReader RecordsReader(RecordsBuffer);<br>
-  for (uint32_t I = TypeIndexBegin(); I < TypeIndexEnd(); ++I) {<br>
-    HashedTypeRecord &Record = TypeRecords[I - ::MinTypeIndex];<br>
-    codeview::TypeRecordPrefix Prefix;<br>
-    if (auto EC = RecordsReader.readObject(&Prefix))<br>
-      return EC;<br>
-<br>
-    Record.Kind =<br>
-        static_cast<codeview::TypeLeafKind>(static_cast<uint16_t>(Prefix.Leaf));<br>
-<br>
-    // Since we read this entire buffer into a ByteStream, we are guaranteed<br>
-    // that the entire buffer is contiguous (i.e. there's no longer a chance<br>
-    // that it splits across a page boundary.  So we can request a reference<br>
-    // directly into the stream buffer to avoid unnecessary memory copies.<br>
-    uint32_t RecordSize = Prefix.Len - sizeof(Prefix.Leaf);<br>
-    if (auto EC = RecordsReader.getArrayRef(Record.Record, RecordSize))<br>
-      return EC;<br>
-  }<br>
<br>
   // Hash indices, hash values, etc come from the hash stream.<br>
   MappedBlockStream HS(Header->HashStreamIndex, Pdb);<br>
@@ -136,8 +117,6 @@ uint32_t TpiStream::NumTypeRecords() con<br>
   return TypeIndexEnd() - TypeIndexBegin();<br>
 }<br>
<br>
-ArrayRef<TpiStream::HashedTypeRecord> TpiStream::records() const {<br>
-  const HashedTypeRecord *Begin =<br>
-      &TypeRecords[TypeIndexBegin() - ::MinTypeIndex];<br>
-  return ArrayRef<HashedTypeRecord>(Begin, NumTypeRecords());<br>
+iterator_range<codeview::TypeIterator> TpiStream::types() const {<br>
+  return codeview::makeTypeRange(RecordsBuffer.str());<br>
 }<br>
<br>
Modified: llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp?rev=268454&r1=268453&r2=268454&view=diff" rel="noreferrer" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp?rev=268454&r1=268453&r2=268454&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp (original)<br>
+++ llvm/trunk/tools/llvm-pdbdump/llvm-pdbdump.cpp Tue May  3 17:18:17 2016<br>
@@ -149,27 +149,24 @@ cl::opt<bool> NoEnumDefs("no-enum-defini<br>
                          cl::cat(FilterCategory));<br>
 }<br>
<br>
-static void dumpBytes(raw_ostream &S, ArrayRef<uint8_t> Bytes,<br>
-                      uint32_t BytesPerRow, uint32_t Indent) {<br>
+static void dumpBytes(raw_ostream &S, StringRef Bytes, uint32_t BytesPerRow,<br>
+                      uint32_t Indent) {<br>
   S << "[";<br>
-  uint32_t I = 0;<br>
<br>
-  uint32_t BytesRemaining = Bytes.size();<br>
-  while (BytesRemaining > 0) {<br>
-    uint32_t BytesThisLine = std::min(BytesRemaining, BytesPerRow);<br>
-    for (size_t L = 0; L < BytesThisLine; ++L, ++I) {<br>
-      S << format_hex_no_prefix(Bytes[I], 2, true);<br>
-      if (L + 1 < BytesThisLine)<br>
+  while (!Bytes.empty()) {<br>
+    uint32_t BytesThisLine = std::min(Bytes.size(), BytesPerRow);<br>
+    while (BytesThisLine > 0) {<br>
+      S << format_hex_no_prefix(uint8_t(Bytes.front()), 2, true);<br>
+      Bytes = Bytes.drop_front();<br>
+      if (--BytesThisLine > 0)<br>
         S << ' ';<br>
     }<br>
-    BytesRemaining -= BytesThisLine;<br>
-    if (BytesRemaining > 0) {<br>
+    if (!Bytes.empty()) {<br>
       S << '\n';<br>
       S.indent(Indent);<br>
     }<br>
   }<br>
   S << ']';<br>
-  S.flush();<br>
 }<br>
<br>
 static void dumpStructure(RawSession &RS) {<br>
@@ -321,10 +318,10 @@ static void dumpStructure(RawSession &RS<br>
   TpiStream &Tpi = File.getPDBTpiStream();<br>
   outs() << "TPI Version: " << Tpi.getTpiVersion() << '\n';<br>
   outs() << "Record count: " << Tpi.NumTypeRecords() << '\n';<br>
-  for (auto &Record : Tpi.records()) {<br>
-    outs().indent(2) << "Kind: 0x" << Record.Kind;<br>
+  for (auto &Type : Tpi.types()) {<br>
+    outs().indent(2) << "Kind: 0x" << Type.Leaf;<br>
     outs().indent(2) << "Bytes: ";<br>
-    dumpBytes(outs(), Record.Record, 16, 24);<br>
+    dumpBytes(outs(), Type.LeafData, 16, 24);<br>
     outs() << '\n';<br>
   }<br>
 }<br>
<br>
Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=268454&r1=268453&r2=268454&view=diff" rel="noreferrer" target="_blank" class="cremed">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=268454&r1=268453&r2=268454&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)<br>
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Tue May  3 17:18:17 2016<br>
@@ -28,6 +28,7 @@<br>
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"<br>
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"<br>
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"<br>
+#include "llvm/DebugInfo/CodeView/TypeStream.h"<br>
 #include "llvm/Object/COFF.h"<br>
 #include "llvm/Object/ObjectFile.h"<br>
 #include "llvm/Support/COFF.h"<br>
@@ -958,26 +959,6 @@ void COFFDumper::printCodeViewDebugInfo(<br>
   }<br>
 }<br>
<br>
-/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if<br>
-/// there are not enough bytes remaining. Reinterprets the consumed bytes as a<br>
-/// T object and points 'Res' at them.<br>
-template <typename T><br>
-static std::error_code consumeObject(StringRef &Data, const T *&Res) {<br>
-  if (Data.size() < sizeof(*Res))<br>
-    return object_error::parse_failed;<br>
-  Res = reinterpret_cast<const T *>(Data.data());<br>
-  Data = Data.drop_front(sizeof(*Res));<br>
-  return std::error_code();<br>
-}<br>
-<br>
-static std::error_code consumeUInt32(StringRef &Data, uint32_t &Res) {<br>
-  const ulittle32_t *IntPtr;<br>
-  if (auto EC = consumeObject(Data, IntPtr))<br>
-    return EC;<br>
-  Res = *IntPtr;<br>
-  return std::error_code();<br>
-}<br>
-<br>
 void COFFDumper::initializeFileAndStringTables(StringRef Data) {<br>
   while (!Data.empty() && (CVFileChecksumTable.data() == nullptr ||<br>
                            CVStringTable.data() == nullptr)) {<br>
@@ -1964,113 +1945,6 @@ static StringRef getLeafTypeName(TypeLea<br>
   return "UnknownLeaf";<br>
 }<br>
<br>
-// A const input iterator interface to the CodeView type stream.<br>
-class CodeViewTypeIterator {<br>
-public:<br>
-  struct TypeRecord {<br>
-    std::size_t Length;<br>
-    TypeLeafKind Leaf;<br>
-    StringRef LeafData;<br>
-  };<br>
-<br>
-  explicit CodeViewTypeIterator(const StringRef &SectionData)<br>
-      : Data(SectionData), AtEnd(false) {<br>
-    if (Data.size() >= 4) {<br>
-      Magic = *reinterpret_cast<const ulittle32_t *>(Data.data());<br>
-      Data = Data.drop_front(4);<br>
-    }<br>
-    next(); // Prime the pump<br>
-  }<br>
-<br>
-  CodeViewTypeIterator() : AtEnd(true) {}<br>
-<br>
-  // For iterators to compare equal, they must both point at the same record<br>
-  // in the same data stream, or they must both be at the end of a stream.<br>
-  friend bool operator==(const CodeViewTypeIterator &lhs,<br>
-                         const CodeViewTypeIterator &rhs);<br>
-<br>
-  friend bool operator!=(const CodeViewTypeIterator &lhs,<br>
-                         const CodeViewTypeIterator &rhs);<br>
-<br>
-  unsigned getMagic() const { return Magic; }<br>
-<br>
-  const TypeRecord &operator*() const {<br>
-    assert(!AtEnd);<br>
-    return Current;<br>
-  }<br>
-<br>
-  const TypeRecord *operator->() const {<br>
-    assert(!AtEnd);<br>
-    return &Current;<br>
-  }<br>
-<br>
-  CodeViewTypeIterator operator++() {<br>
-    next();<br>
-    return *this;<br>
-  }<br>
-<br>
-  CodeViewTypeIterator operator++(int) {<br>
-    CodeViewTypeIterator Original = *this;<br>
-    ++*this;<br>
-    return Original;<br>
-  }<br>
-<br>
-private:<br>
-  void next() {<br>
-    assert(!AtEnd && "Attempted to advance more than one past the last rec");<br>
-    if (Data.empty()) {<br>
-      // We've advanced past the last record.<br>
-      AtEnd = true;<br>
-      return;<br>
-    }<br>
-<br>
-    const TypeRecordPrefix *Rec;<br>
-    if (consumeObject(Data, Rec))<br>
-      return;<br>
-    Current.Length = Rec->Len;<br>
-    Current.Leaf = static_cast<TypeLeafKind>(uint16_t(Rec->Leaf));<br>
-    Current.LeafData = Data.substr(0, Current.Length - 2);<br>
-<br>
-    // The next record starts immediately after this one.<br>
-    Data = Data.drop_front(Current.LeafData.size());<br>
-<br>
-    // FIXME: The stream contains LF_PAD bytes that we need to ignore, but those<br>
-    // are typically included in LeafData. We may need to call skipPadding() if<br>
-    // we ever find a record that doesn't count those bytes.<br>
-<br>
-    return;<br>
-  }<br>
-<br>
-  StringRef Data;<br>
-  unsigned Magic = 0;<br>
-  TypeRecord Current;<br>
-  bool AtEnd;<br>
-};<br>
-<br>
-bool operator==(const CodeViewTypeIterator &lhs,<br>
-                const CodeViewTypeIterator &rhs) {<br>
-  return (lhs.Data.begin() == rhs.Data.begin()) || (lhs.AtEnd && rhs.AtEnd);<br>
-}<br>
-<br>
-bool operator!=(const CodeViewTypeIterator &lhs,<br>
-                const CodeViewTypeIterator &rhs) {<br>
-  return !(lhs == rhs);<br>
-}<br>
-<br>
-struct CodeViewTypeStream {<br>
-  CodeViewTypeIterator begin;<br>
-  CodeViewTypeIterator end;<br>
-  unsigned Magic;<br>
-};<br>
-<br>
-CodeViewTypeStream CreateCodeViewTypeIter(const StringRef &Data) {<br>
-  CodeViewTypeStream Stream;<br>
-  Stream.begin = CodeViewTypeIterator(Data);<br>
-  Stream.end   = CodeViewTypeIterator();<br>
-  Stream.Magic = Stream.begin.getMagic();<br>
-<br>
-  return Stream;<br>
-}<br>
<br>
 void COFFDumper::printCodeViewTypeSection(StringRef SectionName,<br>
                                           const SectionRef &Section) {<br>
@@ -2081,31 +1955,34 @@ void COFFDumper::printCodeViewTypeSectio<br>
   error(Section.getContents(Data));<br>
   if (opts::CodeViewSubsectionBytes)<br>
     W.printBinaryBlock("Data", Data);<br>
-<br>
   CVTD.dump(Data);<br>
 }<br>
<br>
 void CVTypeDumper::dump(StringRef Data) {<br>
-  CodeViewTypeStream Stream = CreateCodeViewTypeIter(Data);<br>
-  W.printHex("Magic", Stream.Magic);<br>
+  uint32_t Magic;<br>
+  if (consumeUInt32(Data, Magic))<br>
+    return;<br>
+  if (Magic != COFF::DEBUG_SECTION_MAGIC)<br>
+    return;<br>
<br>
-  for (auto Iter = Stream.begin; Iter != Stream.end; ++Iter) {<br>
-    StringRef LeafData = Iter->LeafData;<br>
+  W.printHex("Magic", Magic);<br>
+  for (const auto &Record : makeTypeRange(Data)) {<br>
+    StringRef LeafData = Record.LeafData;<br>
<br>
     // Find the name of this leaf type.<br>
-    StringRef LeafName = getLeafTypeName(Iter->Leaf);<br>
+    StringRef LeafName = getLeafTypeName(Record.Leaf);<br>
     DictScope S(W, LeafName);<br>
     unsigned NextTypeIndex = 0x1000 + CVUDTNames.size();<br>
-    W.printEnum("TypeLeafKind", unsigned(Iter->Leaf),<br>
+    W.printEnum("TypeLeafKind", unsigned(Record.Leaf),<br>
                 makeArrayRef(LeafTypeNames));<br>
     W.printHex("TypeIndex", NextTypeIndex);<br>
<br>
     // Fill this in inside the switch to get something in CVUDTNames.<br>
     StringRef Name;<br>
<br>
-    switch (Iter->Leaf) {<br>
+    switch (Record.Leaf) {<br>
     default: {<br>
-      W.printHex("Size", Iter->Length);<br>
+      W.printHex("Size", Record.Length);<br>
       break;<br>
     }<br>
<br>
@@ -2121,7 +1998,7 @@ void CVTypeDumper::dump(StringRef Data)<br>
     }<br>
<br>
     case LF_FIELDLIST: {<br>
-      W.printHex("Size", Iter->Length);<br>
+      W.printHex("Size", Record.Length);<br>
       // FieldList has no fixed prefix that can be described with a struct. All<br>
       // the bytes must be interpreted as more records.<br>
       printCodeViewFieldList(LeafData);<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank" class="cremed">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank" class="cremed">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div></div><div dir="ltr">-- <br></div>Mike<br>Sent from phone