<div dir="ltr">Hopefully fixed in r305753.</div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jun 19, 2017 at 2:04 PM Vitaly Buka <<a href="mailto:vitalybuka@google.com">vitalybuka@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><pre><span class="m_-5941297394699053405gmail-stdout"><font color="#000000" face="Courier New, courier, monotype, monospace" size="3"><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/5713/steps/check-llvm%20msan/logs/stdio" target="_blank">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/5713/steps/check-llvm%20msan/logs/stdio</a><br></font></span></pre><pre><span class="m_-5941297394699053405gmail-stdout"><font color="#000000" face="Courier New, courier, monotype, monospace" size="3"><br></font></span></pre><pre style="font-family:"Courier New",courier,monotype,monospace;color:rgb(0,0,0);font-size:medium"><span class="m_-5941297394699053405gmail-stdout">-- Testing: 21046 tests, 32 threads --
Testing: 0 
FAIL: LLVM-Unit :: DebugInfo/CodeView/DebugInfoCodeViewTests/RandomAccessVisitorTest.CrossChunkName (1141 of 21046)
******************** TEST 'LLVM-Unit :: DebugInfo/CodeView/DebugInfoCodeViewTests/RandomAccessVisitorTest.CrossChunkName' FAILED ********************
Note: Google Test filter = RandomAccessVisitorTest.CrossChunkName
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from RandomAccessVisitorTest
[ RUN      ] RandomAccessVisitorTest.CrossChunkName
==15642==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x53d6c4 in llvm::codeview::CodeViewRecordIO::writeEncodedUnsignedInteger(unsigned long const&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp:235:7
    #1 0x53ec58 in llvm::codeview::CodeViewRecordIO::mapEncodedInteger(unsigned long&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp:137:19
    #2 0x5247ad in llvm::codeview::TypeRecordMapping::visitKnownRecord(llvm::codeview::CVRecord<llvm::codeview::TypeLeafKind>&, llvm::codeview::ClassRecord&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp:224:3
    #3 0x4a6379 in visitKnownRecordImpl<llvm::codeview::ClassRecord> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h:116:20
    #4 0x4a6379 in visitKnownRecord /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def:50
    #5 0x4a6379 in llvm::codeview::TypeIndex llvm::codeview::TypeTableBuilder::writeKnownType<llvm::codeview::ClassRecord>(llvm::codeview::ClassRecord&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h:58
    #6 0x4a48b7 in RandomAccessVisitorTest_CrossChunkName_Test::TestBody() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp:366:33
    #7 0x5bd5c6 in HandleExceptionsInMethodIfSupported<testing::Test, void> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2458:12
    #8 0x5bd5c6 in testing::Test::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2474
    #9 0x5bfc30 in testing::TestInfo::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2656:11
    #10 0x5c14cf in testing::TestCase::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2774:28
    #11 0x5defd9 in testing::internal::UnitTestImpl::RunAllTests() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:4649:43
    #12 0x5ddef8 in HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:2458:12
    #13 0x5ddef8 in testing::UnitTest::Run() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/src/gtest.cc:4257
    #14 0x5a4c7b in RUN_ALL_TESTS /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/include/gtest/gtest.h:2233:46
    #15 0x5a4c7b in main /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/UnitTestMain/TestMain.cpp:51
    #16 0x7f264ca5982f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #17 0x428c68 in _start (/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm_build_msan/unittests/DebugInfo/CodeView/DebugInfoCodeViewTests+0x428c68)

SUMMARY: MemorySanitizer: use-of-uninitialized-value /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp:235:7 in llvm::codeview::CodeViewRecordIO::writeEncodedUnsignedInteger(unsigned long const&)
Exiting

********************
Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90.. 
Testing Time: 169.44s
********************
Failing Tests (1):
    LLVM-Unit :: DebugInfo/CodeView/DebugInfoCodeViewTests/RandomAccessVisitorTest.CrossChunkName</span></pre></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jun 16, 2017 at 4:42 PM, Zachary Turner via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: zturner<br>
Date: Fri Jun 16 18:42:44 2017<br>
New Revision: 305612<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=305612&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=305612&view=rev</a><br>
Log:<br>
[CodeView] Fix random access of type names.<br>
<br>
Suppose we had a type index offsets array with a boundary at type index<br>
N. Then you request the name of the type with index N+1, and that name<br>
requires the name of index N-1 (think a parameter list, for example). We<br>
didn't handle this, and we would print something like (<unknown UDT>,<br>
<unknown UDT>).<br>
<br>
The fix for this is not entirely trivial, and speaks to a larger<br>
problem. I think we need to kill TypeDatabase, or at the very least kill<br>
TypeDatabaseVisitor. We need a thing that doesn't do any caching<br>
whatsoever, just given a type index it can compute the type name "the<br>
slow way". The reason for the bug is that we don't have anything like<br>
that. Everything goes through the type database, and if we've visited a<br>
record, then we're "done". It doesn't know how to do the expensive thing<br>
of re-visiting dependent records if they've not yet been visited.<br>
<br>
What I've done here is more or less copied the code (albeit greatly<br>
simplified) from TypeDatabaseVisitor, but wrapped it in an interface<br>
that just returns a std::string. The logic of caching the name is now in<br>
LazyRandomTypeCollection. Eventually I'd like to move the record<br>
database here as well and the visited record bitfield here as well, at<br>
which point we can actually just delete TypeDatabase. I don't see any<br>
reason for it if a "sequential" collection is just a special case of a<br>
random access collection with an empty partial offsets array.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D34297" rel="noreferrer" target="_blank">https://reviews.llvm.org/D34297</a><br>
<br>
Added:<br>
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeName.h<br>
    llvm/trunk/lib/DebugInfo/CodeView/TypeName.cpp<br>
Modified:<br>
    llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h<br>
    llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt<br>
    llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp<br>
    llvm/trunk/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h?rev=305612&r1=305611&r2=305612&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h?rev=305612&r1=305611&r2=305612&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h Fri Jun 16 18:42:44 2017<br>
@@ -76,6 +76,11 @@ private:<br>
   Error visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);<br>
   Error visitOneRecord(TypeIndex TI, uint32_t Offset, CVType &Record);<br>
<br>
+  BumpPtrAllocator Allocator;<br>
+  StringSaver NameStorage;<br>
+<br>
+  SmallVector<StringRef, 10> TypeNames;<br>
+<br>
   /// Visited records get automatically added to the type database.<br>
   TypeDatabase Database;<br>
<br>
<br>
Added: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeName.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeName.h?rev=305612&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeName.h?rev=305612&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeName.h (added)<br>
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeName.h Fri Jun 16 18:42:44 2017<br>
@@ -0,0 +1,22 @@<br>
+//===- TypeName.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_TYPENAME_H<br>
+#define LLVM_DEBUGINFO_CODEVIEW_TYPENAME_H<br>
+<br>
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"<br>
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"<br>
+<br>
+namespace llvm {<br>
+namespace codeview {<br>
+std::string computeTypeName(TypeCollection &Types, TypeIndex Index);<br>
+}<br>
+} // namespace llvm<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt?rev=305612&r1=305611&r2=305612&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt?rev=305612&r1=305611&r2=305612&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt (original)<br>
+++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt Fri Jun 16 18:42:44 2017<br>
@@ -29,6 +29,7 @@ add_llvm_library(LLVMDebugInfoCodeView<br>
   TypeDumpVisitor.cpp<br>
   TypeIndex.cpp<br>
   TypeIndexDiscovery.cpp<br>
+  TypeName.cpp<br>
   TypeRecordMapping.cpp<br>
   TypeSerializer.cpp<br>
   TypeStreamMerger.cpp<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp?rev=305612&r1=305611&r2=305612&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp?rev=305612&r1=305611&r2=305612&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp Fri Jun 16 18:42:44 2017<br>
@@ -12,6 +12,7 @@<br>
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"<br>
 #include "llvm/DebugInfo/CodeView/CodeViewError.h"<br>
 #include "llvm/DebugInfo/CodeView/TypeDatabase.h"<br>
+#include "llvm/DebugInfo/CodeView/TypeName.h"<br>
 #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"<br>
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"<br>
<br>
@@ -31,8 +32,8 @@ LazyRandomTypeCollection::LazyRandomType<br>
 LazyRandomTypeCollection::LazyRandomTypeCollection(<br>
     const CVTypeArray &Types, uint32_t RecordCountHint,<br>
     PartialOffsetArray PartialOffsets)<br>
-    : Database(RecordCountHint), Types(Types), DatabaseVisitor(Database),<br>
-      PartialOffsets(PartialOffsets) {<br>
+    : NameStorage(Allocator), Database(RecordCountHint), Types(Types),<br>
+      DatabaseVisitor(Database), PartialOffsets(PartialOffsets) {<br>
   KnownOffsets.resize(Database.capacity());<br>
 }<br>
<br>
@@ -71,15 +72,18 @@ CVType LazyRandomTypeCollection::getType<br>
 }<br>
<br>
 StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) {<br>
-  if (!Index.isSimple()) {<br>
-    // Try to make sure the type exists.  Even if it doesn't though, it may be<br>
-    // because we're dumping a symbol stream with no corresponding type stream<br>
-    // present, in which case we still want to be able to print <unknown UDT><br>
-    // for the type names.<br>
-    consumeError(ensureTypeExists(Index));<br>
-  }<br>
+  if (Index.isNoneType() || Index.isSimple())<br>
+    return TypeIndex::simpleTypeName(Index);<br>
<br>
-  return Database.getTypeName(Index);<br>
+  uint32_t I = Index.toArrayIndex();<br>
+  if (I >= TypeNames.size())<br>
+    TypeNames.resize(I + 1);<br>
+<br>
+  if (TypeNames[I].data() == nullptr) {<br>
+    StringRef Result = NameStorage.save(computeTypeName(*this, Index));<br>
+    TypeNames[I] = Result;<br>
+  }<br>
+  return TypeNames[I];<br>
 }<br>
<br>
 bool LazyRandomTypeCollection::contains(TypeIndex Index) {<br>
<br>
Added: llvm/trunk/lib/DebugInfo/CodeView/TypeName.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeName.cpp?rev=305612&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeName.cpp?rev=305612&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/CodeView/TypeName.cpp (added)<br>
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeName.cpp Fri Jun 16 18:42:44 2017<br>
@@ -0,0 +1,243 @@<br>
+//===- TypeName.cpp ------------------------------------------- *- 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>
+#include "llvm/DebugInfo/CodeView/TypeName.h"<br>
+<br>
+#include "llvm/ADT/SmallString.h"<br>
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"<br>
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"<br>
+#include "llvm/Support/FormatVariadic.h"<br>
+<br>
+using namespace llvm;<br>
+using namespace llvm::codeview;<br>
+<br>
+namespace {<br>
+class TypeNameComputer : public TypeVisitorCallbacks {<br>
+  /// The type collection.  Used to calculate names of nested types.<br>
+  TypeCollection &Types;<br>
+  TypeIndex CurrentTypeIndex = TypeIndex::None();<br>
+<br>
+  /// Name of the current type. Only valid before visitTypeEnd.<br>
+  SmallString<256> Name;<br>
+<br>
+public:<br>
+  explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {}<br>
+<br>
+  StringRef name() const { return Name; }<br>
+<br>
+  /// Paired begin/end actions for all types. Receives all record data,<br>
+  /// including the fixed-length record prefix.<br>
+  Error visitTypeBegin(CVType &Record) override;<br>
+  Error visitTypeBegin(CVType &Record, TypeIndex Index) override;<br>
+  Error visitTypeEnd(CVType &Record) override;<br>
+<br>
+#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \<br>
+  Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;<br>
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)<br>
+#define MEMBER_RECORD(EnumName, EnumVal, Name)<br>
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"<br>
+};<br>
+} // namespace<br>
+<br>
+Error TypeNameComputer::visitTypeBegin(CVType &Record) {<br>
+  llvm_unreachable("Must call visitTypeBegin with a TypeIndex!");<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) {<br>
+  // Reset Name to the empty string. If the visitor sets it, we know it.<br>
+  Name = "";<br>
+  CurrentTypeIndex = Index;<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); }<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,<br>
+                                         FieldListRecord &FieldList) {<br>
+  Name = "<field list>";<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,<br>
+                                         StringIdRecord &String) {<br>
+  Name = String.getString();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {<br>
+  auto Indices = Args.getIndices();<br>
+  uint32_t Size = Indices.size();<br>
+  Name = "(";<br>
+  for (uint32_t I = 0; I < Size; ++I) {<br>
+    assert(Indices[I] < CurrentTypeIndex);<br>
+<br>
+    Name.append(Types.getTypeName(Indices[I]));<br>
+    if (I + 1 != Size)<br>
+      Name.append(", ");<br>
+  }<br>
+  Name.push_back(')');<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,<br>
+                                         StringListRecord &Strings) {<br>
+  auto Indices = Strings.getIndices();<br>
+  uint32_t Size = Indices.size();<br>
+  Name = "\"";<br>
+  for (uint32_t I = 0; I < Size; ++I) {<br>
+    Name.append(Types.getTypeName(Indices[I]));<br>
+    if (I + 1 != Size)<br>
+      Name.append("\" \"");<br>
+  }<br>
+  Name.push_back('\"');<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) {<br>
+  Name = Class.getName();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) {<br>
+  Name = Union.getName();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {<br>
+  Name = Enum.getName();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {<br>
+  Name = AT.getName();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {<br>
+  Name = VFT.getName();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {<br>
+  Name = Id.getName();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {<br>
+  StringRef Ret = Types.getTypeName(Proc.getReturnType());<br>
+  StringRef Params = Types.getTypeName(Proc.getArgumentList());<br>
+  Name = formatv("{0} {1}", Ret, Params).sstr<256>();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,<br>
+                                         MemberFunctionRecord &MF) {<br>
+  StringRef Ret = Types.getTypeName(MF.getReturnType());<br>
+  StringRef Class = Types.getTypeName(MF.getClassType());<br>
+  StringRef Params = Types.getTypeName(MF.getArgumentList());<br>
+  Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {<br>
+  Name = Func.getName();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {<br>
+  Name = TS.getName();<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {<br>
+<br>
+  if (Ptr.isPointerToMember()) {<br>
+    const MemberPointerInfo &MI = Ptr.getMemberInfo();<br>
+<br>
+    StringRef Pointee = Types.getTypeName(Ptr.getReferentType());<br>
+    StringRef Class = Types.getTypeName(MI.getContainingType());<br>
+    Name = formatv("{0} {1}::*", Pointee, Class);<br>
+  } else {<br>
+    if (Ptr.isConst())<br>
+      Name.append("const ");<br>
+    if (Ptr.isVolatile())<br>
+      Name.append("volatile ");<br>
+    if (Ptr.isUnaligned())<br>
+      Name.append("__unaligned ");<br>
+<br>
+    Name.append(Types.getTypeName(Ptr.getReferentType()));<br>
+<br>
+    if (Ptr.getMode() == PointerMode::LValueReference)<br>
+      Name.append("&");<br>
+    else if (Ptr.getMode() == PointerMode::RValueReference)<br>
+      Name.append("&&");<br>
+    else if (Ptr.getMode() == PointerMode::Pointer)<br>
+      Name.append("*");<br>
+  }<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {<br>
+  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());<br>
+<br>
+  SmallString<256> TypeName;<br>
+  if (Mods & uint16_t(ModifierOptions::Const))<br>
+    Name.append("const ");<br>
+  if (Mods & uint16_t(ModifierOptions::Volatile))<br>
+    Name.append("volatile ");<br>
+  if (Mods & uint16_t(ModifierOptions::Unaligned))<br>
+    Name.append("__unaligned ");<br>
+  Name.append(Types.getTypeName(Mod.getModifiedType()));<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,<br>
+                                         VFTableShapeRecord &Shape) {<br>
+  Name = formatv("<vftable {0} methods>", Shape.getEntryCount());<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(<br>
+    CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,<br>
+                                         UdtSourceLineRecord &SourceLine) {<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR,<br>
+                                         MethodOverloadListRecord &Overloads) {<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {<br>
+  return Error::success();<br>
+}<br>
+<br>
+Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) {<br>
+  return Error::success();<br>
+}<br>
+<br>
+std::string llvm::codeview::computeTypeName(TypeCollection &Types,<br>
+                                            TypeIndex Index) {<br>
+  TypeNameComputer Computer(Types);<br>
+  CVType Record = Types.getType(Index);<br>
+  if (auto EC = visitTypeRecord(Record, Index, Computer)) {<br>
+    consumeError(std::move(EC));<br>
+    return "<unknown UDT>";<br>
+  }<br>
+  return Computer.name();<br>
+}<br>
<br>
Modified: llvm/trunk/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp?rev=305612&r1=305611&r2=305612&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp?rev=305612&r1=305611&r2=305612&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp (original)<br>
+++ llvm/trunk/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp Fri Jun 16 18:42:44 2017<br>
@@ -351,3 +351,54 @@ TEST_F(RandomAccessVisitorTest, InnerChu<br>
   for (auto &I : enumerate(IndicesToVisit))<br>
     EXPECT_TRUE(ValidateVisitedRecord(I.index(), I.value()));<br>
 }<br>
+<br>
+TEST_F(RandomAccessVisitorTest, CrossChunkName) {<br>
+  TypeTableBuilder Builder(GlobalState->Allocator);<br>
+<br>
+  // TypeIndex 0<br>
+  ClassRecord Class(TypeRecordKind::Class);<br>
+  Class.Name = "FooClass";<br>
+  Class.Options = ClassOptions::None;<br>
+  Class.MemberCount = 0;<br>
+  Class.DerivationList = TypeIndex::fromArrayIndex(0);<br>
+  Class.FieldList = TypeIndex::fromArrayIndex(0);<br>
+  Class.VTableShape = TypeIndex::fromArrayIndex(0);<br>
+  TypeIndex IndexZero = Builder.writeKnownType(Class);<br>
+<br>
+  // TypeIndex 1 refers to type index 0.<br>
+  ModifierRecord Modifier(TypeRecordKind::Modifier);<br>
+  Modifier.ModifiedType = TypeIndex::fromArrayIndex(0);<br>
+  Modifier.Modifiers = ModifierOptions::Const;<br>
+  TypeIndex IndexOne = Builder.writeKnownType(Modifier);<br>
+<br>
+  // set up a type stream that refers to the above two serialized records.<br>
+  std::vector<CVType> TypeArray;<br>
+  TypeArray.push_back(<br>
+      CVType(static_cast<TypeLeafKind>(Class.Kind), Builder.records()[0]));<br>
+  TypeArray.push_back(<br>
+      CVType(static_cast<TypeLeafKind>(Modifier.Kind), Builder.records()[1]));<br>
+  BinaryItemStream<CVType> ItemStream(llvm::support::little);<br>
+  ItemStream.setItems(TypeArray);<br>
+  VarStreamArray<CVType> TypeStream(ItemStream);<br>
+<br>
+  // Figure out the byte offset of the second item.<br>
+  auto ItemOneIter = TypeStream.begin();<br>
+  ++ItemOneIter;<br>
+<br>
+  // Set up a partial offsets buffer that contains the first and second items<br>
+  // in separate chunks.<br>
+  std::vector<TypeIndexOffset> TIO;<br>
+  TIO.push_back({IndexZero, ulittle32_t(0u)});<br>
+  TIO.push_back({IndexOne, ulittle32_t(ItemOneIter.offset())});<br>
+  ArrayRef<uint8_t> Buffer(reinterpret_cast<const uint8_t *>(TIO.data()),<br>
+                           TIO.size() * sizeof(TypeIndexOffset));<br>
+<br>
+  BinaryStreamReader Reader(Buffer, llvm::support::little);<br>
+  FixedStreamArray<TypeIndexOffset> PartialOffsets;<br>
+  ASSERT_THAT_ERROR(Reader.readArray(PartialOffsets, 2), Succeeded());<br>
+<br>
+  LazyRandomTypeCollection Types(TypeStream, 2, PartialOffsets);<br>
+<br>
+  StringRef Name = Types.getTypeName(IndexOne);<br>
+  EXPECT_EQ("const FooClass", Name);<br>
+}<br>
\ No newline at end of file<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</blockquote></div>