DiegoAstiazaran updated this revision to Diff 208463.
DiegoAstiazaran added a comment.

Rebase after D52847 <https://reviews.llvm.org/D52847> was pushed.
Path added to parent Info in serialization, this is required after D63911 
<https://reviews.llvm.org/D63911> was pushed.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D63663/new/

https://reviews.llvm.org/D63663

Files:
  clang-tools-extra/clang-doc/BitcodeReader.cpp
  clang-tools-extra/clang-doc/BitcodeWriter.cpp
  clang-tools-extra/clang-doc/BitcodeWriter.h
  clang-tools-extra/clang-doc/Generators.cpp
  clang-tools-extra/clang-doc/Generators.h
  clang-tools-extra/clang-doc/HTMLGenerator.cpp
  clang-tools-extra/clang-doc/MDGenerator.cpp
  clang-tools-extra/clang-doc/Mapper.cpp
  clang-tools-extra/clang-doc/Representation.cpp
  clang-tools-extra/clang-doc/Representation.h
  clang-tools-extra/clang-doc/Serialize.cpp
  clang-tools-extra/clang-doc/Serialize.h
  clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
  clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
  clang-tools-extra/unittests/clang-doc/SerializeTest.cpp

Index: clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
+++ clang-tools-extra/unittests/clang-doc/SerializeTest.cpp
@@ -37,7 +37,7 @@
 
   template <typename T> bool mapDecl(const T *D) {
     auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
-                                 /*File=*/"test.cpp", Public);
+                                 /*File=*/"test.cpp", Public, "");
     if (I.first)
       EmittedInfos.emplace_back(std::move(I.first));
     if (I.second)
Index: clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
+++ clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
@@ -57,7 +57,8 @@
   <div>
     <h3>OneFunction</h3>
     <p>
-       OneFunction()
+      OneFunction(
+      )
     </p>
   </div>
   <h2>Enums</h2>
@@ -78,9 +79,10 @@
   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
 
-  I.Members.emplace_back("int", "X", AccessSpecifier::AS_private);
+  I.Members.emplace_back("int", "/path/to", "X", AccessSpecifier::AS_private);
   I.TagType = TagTypeKind::TTK_Class;
-  I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
+  I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record,
+                         llvm::SmallString<128>("/path/to"));
   I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
 
   I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
@@ -104,11 +106,14 @@
     Defined at line 10 of test.cpp
   </p>
   <p>
-    Inherits from F, G
+    Inherits from 
+    <a href="/path/to/F.html">F</a>
+    , 
+    G
   </p>
   <h2>Members</h2>
   <ul>
-    <li>private int X</li>
+    <li>private <a href="/path/to/int.html">int</a> X</li>
   </ul>
   <h2>Records</h2>
   <ul>
@@ -118,7 +123,8 @@
   <div>
     <h3>OneFunction</h3>
     <p>
-       OneFunction()
+      OneFunction(
+      )
     </p>
   </div>
   <h2>Enums</h2>
@@ -139,8 +145,8 @@
   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
 
-  I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
-  I.Params.emplace_back("int", "P");
+  I.ReturnType = TypeInfo(EmptySID, "float", InfoType::IT_default, "/path/to");
+  I.Params.emplace_back("int", "/path/to", "P");
   I.IsMethod = true;
   I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
 
@@ -156,7 +162,12 @@
 <div>
   <h3>f</h3>
   <p>
-    void f(int P)
+    <a href="/path/to/float.html">float</a>
+     
+    f(
+    <a href="/path/to/int.html">int</a>
+     P
+    )
   </p>
   <p>
     Defined at line 10 of test.cpp
@@ -250,7 +261,15 @@
 <div>
   <h3>f</h3>
   <p>
-    void f(int I, int J)
+    void
+     
+    f(
+    int
+     I
+    , 
+    int
+     J
+    )
   </p>
   <p>
     Defined at line 10 of test.cpp
Index: clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
===================================================================
--- clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -110,12 +110,13 @@
   return false;
 }
 
-// A function to extract the appropriate path name for a given info's
-// documentation. The path returned is a composite of the parent namespaces as
-// directories plus the decl name as the filename.
+// A function to extract the appropriate file name for a given info's
+// documentation. The path returned is a composite of the direcory and the
+// info's name. The directory should have been constructed in the serialization
+// phase.
 //
-// Example: Given the below, the <ext> path for class C will be <
-// root>/A/B/C.<ext>
+// Example: Given the below, the <ext> path for class C will be
+// <root>/A/B/C.<ext>
 //
 // namespace A {
 // namesapce B {
@@ -125,15 +126,7 @@
 // }
 // }
 llvm::Expected<llvm::SmallString<128>>
-getInfoOutputFile(StringRef Root,
-                  llvm::SmallVectorImpl<doc::Reference> &Namespaces,
-                  StringRef Name, StringRef Ext) {
-  std::error_code OK;
-  llvm::SmallString<128> Path;
-  llvm::sys::path::native(Root, Path);
-  for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
-    llvm::sys::path::append(Path, R->Name);
-
+getInfoOutputFile(llvm::SmallString<128> Path, StringRef Name, StringRef Ext) {
   if (CreateDirectory(Path))
     return llvm::make_error<llvm::StringError>("Unable to create directory.\n",
                                                llvm::inconvertibleErrorCode());
@@ -197,7 +190,7 @@
   // Mapping phase
   llvm::outs() << "Mapping decls...\n";
   clang::doc::ClangDocContext CDCtx = {Exec->get()->getExecutionContext(),
-                                       PublicOnly};
+                                       PublicOnly, OutDirectory};
   auto Err =
       Exec->get()->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster);
   if (Err) {
@@ -223,12 +216,10 @@
     }
 
     doc::Info *I = Reduced.get().get();
-
-    auto InfoPath = getInfoOutputFile(OutDirectory, I->Namespace,
-                                      I->extractName(), "." + Format);
+    auto InfoPath = getInfoOutputFile(I->Path, I->extractName(), "." + Format);
     if (!InfoPath) {
       llvm::errs() << toString(InfoPath.takeError()) << "\n";
-      continue;
+      return 1;
     }
     std::error_code FileErr;
     llvm::raw_fd_ostream InfoOS(InfoPath.get(), FileErr, llvm::sys::fs::F_None);
Index: clang-tools-extra/clang-doc/Serialize.h
===================================================================
--- clang-tools-extra/clang-doc/Serialize.h
+++ clang-tools-extra/clang-doc/Serialize.h
@@ -38,19 +38,19 @@
 // nullptr.
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber,
-         StringRef File, bool PublicOnly);
+         StringRef File, bool PublicOnly, StringRef OutDirectory);
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
-         StringRef File, bool PublicOnly);
+         StringRef File, bool PublicOnly, StringRef OutDirectory);
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
-         StringRef File, bool PublicOnly);
+         StringRef File, bool PublicOnly, StringRef OutDirectory);
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber,
-         StringRef File, bool PublicOnly);
+         StringRef File, bool PublicOnly, StringRef OutDirectory);
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber,
-         StringRef File, bool PublicOnly);
+         StringRef File, bool PublicOnly, StringRef OutDirectory);
 
 // Function to hash a given USR value for storage.
 // As USRs (Unified Symbol Resolution) could be large, especially for functions
Index: clang-tools-extra/clang-doc/Serialize.cpp
===================================================================
--- clang-tools-extra/clang-doc/Serialize.cpp
+++ clang-tools-extra/clang-doc/Serialize.cpp
@@ -24,6 +24,42 @@
   return llvm::SHA1::hash(arrayRefFromStringRef(USR));
 }
 
+template <typename T>
+static void
+populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
+                         const T *D, bool &IsAnonymousNamespace);
+
+// A function to extract the appropriate directory name for a given info's
+// documentation. The path returned is a composite of the parent namespaces.
+//
+// Example: Given the below, the diretory path for class C info will be
+// <root>/A/B
+//
+// namespace A {
+// namesapce B {
+//
+// class C {};
+//
+// }
+// }
+llvm::SmallString<128>
+getInfoOutputFile(llvm::StringRef Root,
+                  const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
+  std::error_code OK;
+  llvm::SmallString<128> Path;
+  llvm::sys::path::native(Root, Path);
+  for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
+    llvm::sys::path::append(Path, R->Name);
+  return Path;
+}
+
+llvm::SmallString<128> getInfoOutputFile(llvm::StringRef Root, const Decl *D) {
+  llvm::SmallVector<Reference, 4> Namespaces;
+  bool B = true;
+  populateParentNamespaces(Namespaces, D, B);
+  return getInfoOutputFile(Root, Namespaces);
+}
+
 class ClangDocCommentVisitor
     : public ConstCommentVisitor<ClangDocCommentVisitor> {
 public:
@@ -194,7 +230,8 @@
   return false; // otherwise, linkage is some form of internal linkage
 }
 
-static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly) {
+static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly,
+                        llvm::StringRef OutDirectory) {
   for (const FieldDecl *F : D->fields()) {
     if (PublicOnly && !isPublic(F->getAccessUnsafe(), F->getLinkageInternal()))
       continue;
@@ -203,13 +240,15 @@
       // valid, as opposed to an assert.
       if (const auto *N = dyn_cast<EnumDecl>(T)) {
         I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
-                               InfoType::IT_enum, F->getNameAsString(),
-                               N->getAccessUnsafe());
+                               InfoType::IT_enum,
+                               getInfoOutputFile(OutDirectory, N),
+                               F->getNameAsString(), N->getAccessUnsafe());
         continue;
       } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
         I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
-                               InfoType::IT_record, F->getNameAsString(),
-                               N->getAccessUnsafe());
+                               InfoType::IT_record,
+                               getInfoOutputFile(OutDirectory, N),
+                               F->getNameAsString(), N->getAccessUnsafe());
         continue;
       }
     }
@@ -223,16 +262,19 @@
     I.Members.emplace_back(E->getNameAsString());
 }
 
-static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
+static void parseParameters(FunctionInfo &I, const FunctionDecl *D,
+                            llvm::StringRef OutDirectory) {
   for (const ParmVarDecl *P : D->parameters()) {
     if (const auto *T = getDeclForType(P->getOriginalType())) {
       if (const auto *N = dyn_cast<EnumDecl>(T)) {
-        I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
-                              InfoType::IT_enum, P->getNameAsString());
+        I.Params.emplace_back(
+            getUSRForDecl(N), N->getNameAsString(), InfoType::IT_enum,
+            getInfoOutputFile(OutDirectory, N), P->getNameAsString());
         continue;
       } else if (const auto *N = dyn_cast<RecordDecl>(T)) {
-        I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
-                              InfoType::IT_record, P->getNameAsString());
+        I.Params.emplace_back(
+            getUSRForDecl(N), N->getNameAsString(), InfoType::IT_record,
+            getInfoOutputFile(OutDirectory, N), P->getNameAsString());
         continue;
       }
     }
@@ -241,7 +283,8 @@
   }
 }
 
-static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
+static void parseBases(RecordInfo &I, const CXXRecordDecl *D,
+                       llvm::StringRef OutDirectory) {
   // Don't parse bases if this isn't a definition.
   if (!D->isThisDeclarationADefinition())
     return;
@@ -254,14 +297,16 @@
                              InfoType::IT_record);
     } else if (const RecordDecl *P = getDeclForType(B.getType()))
       I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
-                             InfoType::IT_record);
+                             InfoType::IT_record,
+                             getInfoOutputFile(OutDirectory, P));
     else
       I.Parents.emplace_back(B.getType().getAsString());
   }
   for (const CXXBaseSpecifier &B : D->vbases()) {
     if (const auto *P = getDeclForType(B.getType()))
       I.VirtualParents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
-                                    InfoType::IT_record);
+                                    InfoType::IT_record,
+                                    getInfoOutputFile(OutDirectory, P));
     else
       I.VirtualParents.emplace_back(B.getType().getAsString());
   }
@@ -270,14 +315,14 @@
 template <typename T>
 static void
 populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
-                         const T *D, bool &IsAnonymousNamespace) {
+                         const T *D, bool &IsInAnonymousNamespace) {
   const auto *DC = dyn_cast<DeclContext>(D);
   while ((DC = DC->getParent())) {
     if (const auto *N = dyn_cast<NamespaceDecl>(DC)) {
       std::string Namespace;
       if (N->isAnonymousNamespace()) {
         Namespace = "@nonymous_namespace";
-        IsAnonymousNamespace = true;
+        IsInAnonymousNamespace = true;
       } else
         Namespace = N->getNameAsString();
       Namespaces.emplace_back(getUSRForDecl(N), Namespace,
@@ -320,24 +365,27 @@
 static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
                                  const FullComment *FC, int LineNumber,
                                  StringRef Filename,
-                                 bool &IsInAnonymousNamespace) {
+                                 bool &IsInAnonymousNamespace,
+                                 llvm::StringRef OutDirectory) {
   populateSymbolInfo(I, D, FC, LineNumber, Filename, IsInAnonymousNamespace);
   if (const auto *T = getDeclForType(D->getReturnType())) {
     if (dyn_cast<EnumDecl>(T))
       I.ReturnType =
-          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_enum);
+          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_enum,
+                   getInfoOutputFile(OutDirectory, T));
     else if (dyn_cast<RecordDecl>(T))
       I.ReturnType =
-          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_record);
+          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_record,
+                   getInfoOutputFile(OutDirectory, T));
   } else {
     I.ReturnType = TypeInfo(D->getReturnType().getAsString());
   }
-  parseParameters(I, D);
+  parseParameters(I, D, OutDirectory);
 }
 
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const NamespaceDecl *D, const FullComment *FC, int LineNumber,
-         llvm::StringRef File, bool PublicOnly) {
+         llvm::StringRef File, bool PublicOnly, llvm::StringRef OutDirectory) {
   auto I = llvm::make_unique<NamespaceInfo>();
   bool IsInAnonymousNamespace = false;
   populateInfo(*I, D, FC, IsInAnonymousNamespace);
@@ -347,21 +395,25 @@
   I->Name = D->isAnonymousNamespace()
                 ? llvm::SmallString<16>("@nonymous_namespace")
                 : I->Name;
+  I->Path = getInfoOutputFile(OutDirectory, I->Namespace);
   if (I->Namespace.empty() && I->USR == SymbolID())
     return {std::unique_ptr<Info>{std::move(I)}, nullptr};
 
-  SymbolID ParentUSR = I->Namespace.empty() ? SymbolID() : I->Namespace[0].USR;
-
-  auto Parent = llvm::make_unique<NamespaceInfo>();
-  Parent->USR = ParentUSR;
-  Parent->ChildNamespaces.emplace_back(I->USR, I->Name, InfoType::IT_namespace);
+  auto ParentI = llvm::make_unique<NamespaceInfo>();
+  ParentI->USR = I->Namespace.empty() ? SymbolID() : I->Namespace[0].USR;
+  ParentI->ChildNamespaces.emplace_back(I->USR, I->Name,
+                                        InfoType::IT_namespace);
+  if (!I->Namespace.empty())
+    ParentI->Namespace = llvm::SmallVector<Reference, 4>(
+        I->Namespace.begin() + 1, I->Namespace.end());
+  ParentI->Path = getInfoOutputFile(OutDirectory, ParentI->Namespace);
   return {std::unique_ptr<Info>{std::move(I)},
-          std::unique_ptr<Info>{std::move(Parent)}};
+          std::unique_ptr<Info>{std::move(ParentI)}};
 }
 
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
-         llvm::StringRef File, bool PublicOnly) {
+         llvm::StringRef File, bool PublicOnly, llvm::StringRef OutDirectory) {
   auto I = llvm::make_unique<RecordInfo>();
   bool IsInAnonymousNamespace = false;
   populateSymbolInfo(*I, D, FC, LineNumber, File, IsInAnonymousNamespace);
@@ -370,37 +422,45 @@
     return {};
 
   I->TagType = D->getTagKind();
-  parseFields(*I, D, PublicOnly);
+  parseFields(*I, D, PublicOnly, OutDirectory);
   if (const auto *C = dyn_cast<CXXRecordDecl>(D)) {
     if (const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
       I->Name = TD->getNameAsString();
       I->IsTypeDef = true;
     }
-    parseBases(*I, C);
+    parseBases(*I, C, OutDirectory);
   }
+  I->Path = getInfoOutputFile(OutDirectory, I->Namespace);
 
   if (I->Namespace.empty()) {
-    auto Parent = llvm::make_unique<NamespaceInfo>();
-    Parent->USR = SymbolID();
-    Parent->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+    auto ParentI = llvm::make_unique<NamespaceInfo>();
+    ParentI->USR = SymbolID();
+    ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+    ParentI->Path = getInfoOutputFile(OutDirectory, ParentI->Namespace);
     return {std::unique_ptr<Info>{std::move(I)},
-            std::unique_ptr<Info>{std::move(Parent)}};
+            std::unique_ptr<Info>{std::move(ParentI)}};
   }
 
   switch (I->Namespace[0].RefType) {
   case InfoType::IT_namespace: {
-    auto Parent = llvm::make_unique<NamespaceInfo>();
-    Parent->USR = I->Namespace[0].USR;
-    Parent->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+    auto ParentI = llvm::make_unique<NamespaceInfo>();
+    ParentI->USR = I->Namespace[0].USR;
+    ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+    ParentI->Namespace = llvm::SmallVector<Reference, 4>(
+        I->Namespace.begin() + 1, I->Namespace.end());
+    ParentI->Path = getInfoOutputFile(OutDirectory, ParentI->Namespace);
     return {std::unique_ptr<Info>{std::move(I)},
-            std::unique_ptr<Info>{std::move(Parent)}};
+            std::unique_ptr<Info>{std::move(ParentI)}};
   }
   case InfoType::IT_record: {
-    auto Parent = llvm::make_unique<RecordInfo>();
-    Parent->USR = I->Namespace[0].USR;
-    Parent->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+    auto ParentI = llvm::make_unique<RecordInfo>();
+    ParentI->USR = I->Namespace[0].USR;
+    ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+    ParentI->Namespace = llvm::SmallVector<Reference, 4>(
+        I->Namespace.begin() + 1, I->Namespace.end());
+    ParentI->Path = getInfoOutputFile(OutDirectory, ParentI->Namespace);
     return {std::unique_ptr<Info>{std::move(I)},
-            std::unique_ptr<Info>{std::move(Parent)}};
+            std::unique_ptr<Info>{std::move(ParentI)}};
   }
   default:
     llvm_unreachable("Invalid reference type");
@@ -409,10 +469,11 @@
 
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const FunctionDecl *D, const FullComment *FC, int LineNumber,
-         llvm::StringRef File, bool PublicOnly) {
+         llvm::StringRef File, bool PublicOnly, llvm::StringRef OutDirectory) {
   FunctionInfo Func;
   bool IsInAnonymousNamespace = false;
-  populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace);
+  populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace,
+                       OutDirectory);
   if (PublicOnly && ((IsInAnonymousNamespace ||
                       !isPublic(D->getAccess(), D->getLinkageInternal()))))
     return {};
@@ -420,22 +481,27 @@
   Func.Access = clang::AccessSpecifier::AS_none;
 
   // Wrap in enclosing scope
-  auto I = llvm::make_unique<NamespaceInfo>();
+  auto ParentI = llvm::make_unique<NamespaceInfo>();
   if (!Func.Namespace.empty())
-    I->USR = Func.Namespace[0].USR;
+    ParentI->USR = Func.Namespace[0].USR;
   else
-    I->USR = SymbolID();
-  I->ChildFunctions.emplace_back(std::move(Func));
-  // Info es wrapped in its parent scope so it's returned in the second position
-  return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+    ParentI->USR = SymbolID();
+  ParentI->ChildFunctions.emplace_back(std::move(Func));
+  if (!Func.Namespace.empty())
+    ParentI->Namespace = llvm::SmallVector<Reference, 4>(
+        Func.Namespace.begin(), Func.Namespace.end() - 1);
+  ParentI->Path = getInfoOutputFile(OutDirectory, ParentI->Namespace);
+  // Info is wrapped in its parent scope so it's returned in the second position
+  return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
 }
 
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const CXXMethodDecl *D, const FullComment *FC, int LineNumber,
-         llvm::StringRef File, bool PublicOnly) {
+         llvm::StringRef File, bool PublicOnly, llvm::StringRef OutDirectory) {
   FunctionInfo Func;
   bool IsInAnonymousNamespace = false;
-  populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace);
+  populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace,
+                       OutDirectory);
   if (PublicOnly && ((IsInAnonymousNamespace ||
                       !isPublic(D->getAccess(), D->getLinkageInternal()))))
     return {};
@@ -455,16 +521,20 @@
   Func.Access = D->getAccess();
 
   // Wrap in enclosing scope
-  auto I = llvm::make_unique<RecordInfo>();
-  I->USR = ParentUSR;
-  I->ChildFunctions.emplace_back(std::move(Func));
+  auto ParentI = llvm::make_unique<RecordInfo>();
+  ParentI->USR = ParentUSR;
+  ParentI->ChildFunctions.emplace_back(std::move(Func));
+  if (!Func.Namespace.empty())
+    ParentI->Namespace = llvm::SmallVector<Reference, 4>(
+        Func.Namespace.begin() + 1, Func.Namespace.end());
+  ParentI->Path = getInfoOutputFile(OutDirectory, ParentI->Namespace);
   // Info is wrapped in its parent scope so it's returned in the second position
-  return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+  return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
 }
 
 std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
 emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
-         llvm::StringRef File, bool PublicOnly) {
+         llvm::StringRef File, bool PublicOnly, llvm::StringRef OutDirectory) {
   EnumInfo Enum;
   bool IsInAnonymousNamespace = false;
   populateSymbolInfo(Enum, D, FC, LineNumber, File, IsInAnonymousNamespace);
@@ -479,20 +549,26 @@
   if (!Enum.Namespace.empty()) {
     switch (Enum.Namespace[0].RefType) {
     case InfoType::IT_namespace: {
-      auto I = llvm::make_unique<NamespaceInfo>();
-      I->USR = Enum.Namespace[0].USR;
-      I->ChildEnums.emplace_back(std::move(Enum));
+      auto ParentI = llvm::make_unique<NamespaceInfo>();
+      ParentI->USR = Enum.Namespace[0].USR;
+      ParentI->ChildEnums.emplace_back(std::move(Enum));
+      ParentI->Namespace = llvm::SmallVector<Reference, 4>(
+          Enum.Namespace.begin() + 1, Enum.Namespace.end());
+      ParentI->Path = getInfoOutputFile(OutDirectory, ParentI->Namespace);
       // Info is wrapped in its parent scope so it's returned in the second
       // position
-      return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+      return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
     }
     case InfoType::IT_record: {
-      auto I = llvm::make_unique<RecordInfo>();
-      I->USR = Enum.Namespace[0].USR;
-      I->ChildEnums.emplace_back(std::move(Enum));
+      auto ParentI = llvm::make_unique<RecordInfo>();
+      ParentI->USR = Enum.Namespace[0].USR;
+      ParentI->ChildEnums.emplace_back(std::move(Enum));
+      ParentI->Namespace = llvm::SmallVector<Reference, 4>(
+          Enum.Namespace.begin() + 1, Enum.Namespace.end());
+      ParentI->Path = getInfoOutputFile(OutDirectory, ParentI->Namespace);
       // Info is wrapped in its parent scope so it's returned in the second
       // position
-      return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+      return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
     }
     default:
       break;
@@ -500,11 +576,12 @@
   }
 
   // Put in global namespace
-  auto I = llvm::make_unique<NamespaceInfo>();
-  I->USR = SymbolID();
-  I->ChildEnums.emplace_back(std::move(Enum));
+  auto ParentI = llvm::make_unique<NamespaceInfo>();
+  ParentI->USR = SymbolID();
+  ParentI->ChildEnums.emplace_back(std::move(Enum));
+  ParentI->Path = getInfoOutputFile(OutDirectory, ParentI->Namespace);
   // Info is wrapped in its parent scope so it's returned in the second position
-  return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+  return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
 }
 
 } // namespace serialize
Index: clang-tools-extra/clang-doc/Representation.h
===================================================================
--- clang-tools-extra/clang-doc/Representation.h
+++ clang-tools-extra/clang-doc/Representation.h
@@ -114,8 +114,11 @@
 struct Reference {
   Reference() = default;
   Reference(llvm::StringRef Name) : Name(Name) {}
+  Reference(llvm::StringRef Name, StringRef Path) : Name(Name), Path(Path) {}
   Reference(SymbolID USR, StringRef Name, InfoType IT)
       : USR(USR), Name(Name), RefType(IT) {}
+  Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef Path)
+      : USR(USR), Name(Name), RefType(IT), Path(Path) {}
 
   bool operator==(const Reference &Other) const {
     return std::tie(USR, Name, RefType) ==
@@ -127,6 +130,8 @@
   InfoType RefType = InfoType::IT_default; // Indicates the type of this
                                            // Reference (namespace, record,
                                            // function, enum, default).
+  llvm::SmallString<128> Path; // Path of directory where the clang-doc
+                               // generated file will be saved
 };
 
 // A base struct for TypeInfos
@@ -134,7 +139,10 @@
   TypeInfo() = default;
   TypeInfo(SymbolID Type, StringRef Field, InfoType IT)
       : Type(Type, Field, IT) {}
+  TypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path)
+      : Type(Type, Field, IT, Path) {}
   TypeInfo(llvm::StringRef RefName) : Type(RefName) {}
+  TypeInfo(llvm::StringRef RefName, StringRef Path) : Type(RefName, Path) {}
 
   bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }
 
@@ -144,11 +152,13 @@
 // Info for field types.
 struct FieldTypeInfo : public TypeInfo {
   FieldTypeInfo() = default;
-  FieldTypeInfo(SymbolID Type, StringRef Field, InfoType IT,
+  FieldTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path,
                 llvm::StringRef Name)
-      : TypeInfo(Type, Field, IT), Name(Name) {}
+      : TypeInfo(Type, Field, IT, Path), Name(Name) {}
   FieldTypeInfo(llvm::StringRef RefName, llvm::StringRef Name)
       : TypeInfo(RefName), Name(Name) {}
+  FieldTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name)
+      : TypeInfo(RefName, Path), Name(Name) {}
 
   bool operator==(const FieldTypeInfo &Other) const {
     return std::tie(Type, Name) == std::tie(Other.Type, Other.Name);
@@ -160,12 +170,15 @@
 // Info for member types.
 struct MemberTypeInfo : public FieldTypeInfo {
   MemberTypeInfo() = default;
-  MemberTypeInfo(SymbolID Type, StringRef Field, InfoType IT,
+  MemberTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path,
                  llvm::StringRef Name, AccessSpecifier Access)
-      : FieldTypeInfo(Type, Field, IT, Name), Access(Access) {}
+      : FieldTypeInfo(Type, Field, IT, Path, Name), Access(Access) {}
   MemberTypeInfo(llvm::StringRef RefName, llvm::StringRef Name,
                  AccessSpecifier Access)
       : FieldTypeInfo(RefName, Name), Access(Access) {}
+  MemberTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name,
+                 AccessSpecifier Access)
+      : FieldTypeInfo(RefName, Path, Name), Access(Access) {}
 
   bool operator==(const MemberTypeInfo &Other) const {
     return std::tie(Type, Name, Access) ==
@@ -220,6 +233,8 @@
   llvm::SmallVector<Reference, 4>
       Namespace; // List of parent namespaces for this decl.
   std::vector<CommentInfo> Description; // Comment description of this decl.
+  llvm::SmallString<128> Path;          // Path of directory where the clang-doc
+                                        // generated file will be saved
 
   void mergeBase(Info &&I);
   bool mergeable(const Info &Other);
@@ -334,6 +349,7 @@
 struct ClangDocContext {
   tooling::ExecutionContext *ECtx;
   bool PublicOnly;
+  std::string OutDirectory;
 };
 
 } // namespace doc
Index: clang-tools-extra/clang-doc/Representation.cpp
===================================================================
--- clang-tools-extra/clang-doc/Representation.cpp
+++ clang-tools-extra/clang-doc/Representation.cpp
@@ -118,6 +118,8 @@
     USR = Other.USR;
   if (Name == "")
     Name = Other.Name;
+  if (Path == "")
+    Path = Other.Path;
   if (Namespace.empty())
     Namespace = std::move(Other.Namespace);
   // Unconditionally extend the description, since each decl may have a comment.
Index: clang-tools-extra/clang-doc/Mapper.cpp
===================================================================
--- clang-tools-extra/clang-doc/Mapper.cpp
+++ clang-tools-extra/clang-doc/Mapper.cpp
@@ -39,7 +39,7 @@
 
   auto I = serialize::emitInfo(
       D, getComment(D, D->getASTContext()), getLine(D, D->getASTContext()),
-      getFile(D, D->getASTContext()), CDCtx.PublicOnly);
+      getFile(D, D->getASTContext()), CDCtx.PublicOnly, CDCtx.OutDirectory);
 
   // A null in place of I indicates that the serializer is skipping this decl
   // for some reason (e.g. we're only reporting public decls).
Index: clang-tools-extra/clang-doc/MDGenerator.cpp
===================================================================
--- clang-tools-extra/clang-doc/MDGenerator.cpp
+++ clang-tools-extra/clang-doc/MDGenerator.cpp
@@ -20,14 +20,30 @@
 
 // Markdown generation
 
-static std::string genItalic(const Twine &Text) { return "*" + Text.str() + "*"; }
+static std::string genItalic(const Twine &Text) {
+  return "*" + Text.str() + "*";
+}
 
-static std::string genEmphasis(const Twine &Text) { return "**" + Text.str() + "**"; }
+static std::string genEmphasis(const Twine &Text) {
+  return "**" + Text.str() + "**";
+}
 
 static std::string genLink(const Twine &Text, const Twine &Link) {
   return "[" + Text.str() + "](" + Link.str() + ")";
 }
 
+static std::string
+genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
+  std::string Buffer;
+  llvm::raw_string_ostream Stream(Buffer);
+  for (const auto &R : Refs) {
+    if (&R != Refs.begin())
+      Stream << ", ";
+    Stream << R.Name;
+  }
+  return Stream.str();
+}
+
 static void writeLine(const Twine &Text, raw_ostream &OS) {
   OS << Text << "\n\n";
 }
Index: clang-tools-extra/clang-doc/HTMLGenerator.cpp
===================================================================
--- clang-tools-extra/clang-doc/HTMLGenerator.cpp
+++ clang-tools-extra/clang-doc/HTMLGenerator.cpp
@@ -33,6 +33,7 @@
     TAG_P,
     TAG_UL,
     TAG_LI,
+    TAG_A,
   };
 
   HTMLTag() = default;
@@ -58,8 +59,8 @@
 };
 
 struct TextNode : public HTMLNode {
-  TextNode(llvm::StringRef Text, bool Indented)
-      : Text(Text), Indented(Indented) {}
+  TextNode(const Twine &Text, bool Indented = true)
+      : Text(Text.str()), Indented(Indented) {}
 
   std::string Text; // Content of node
   bool Indented; // Indicates if an indentation must be rendered before the text
@@ -114,6 +115,7 @@
   case HTMLTag::TAG_P:
   case HTMLTag::TAG_UL:
   case HTMLTag::TAG_LI:
+  case HTMLTag::TAG_A:
     return false;
   }
 }
@@ -126,6 +128,7 @@
   case HTMLTag::TAG_H2:
   case HTMLTag::TAG_H3:
   case HTMLTag::TAG_LI:
+  case HTMLTag::TAG_A:
     return true;
   case HTMLTag::TAG_DIV:
   case HTMLTag::TAG_P:
@@ -154,6 +157,8 @@
     return llvm::SmallString<16>("ul");
   case HTMLTag::TAG_LI:
     return llvm::SmallString<16>("li");
+  case HTMLTag::TAG_A:
+    return llvm::SmallString<16>("a");
   }
 }
 
@@ -188,6 +193,31 @@
 
 // HTML generation
 
+static std::unique_ptr<TagNode> genLink(const Twine &Text, const Twine &Link) {
+  auto LinkNode = llvm::make_unique<TagNode>(HTMLTag::TAG_A, Text);
+  LinkNode->Attributes.try_emplace("href", Link.str());
+  return LinkNode;
+}
+
+static std::unique_ptr<HTMLNode> genTypeReference(const Reference &Type) {
+  if (Type.Path.empty())
+    return llvm::make_unique<TextNode>(Type.Name);
+  llvm::SmallString<128> Path = Type.Path;
+  ::llvm::sys::path::append(Path, Type.Name + ".html");
+  return genLink(Type.Name, Path);
+}
+
+static std::vector<std::unique_ptr<HTMLNode>>
+genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
+  std::vector<std::unique_ptr<HTMLNode>> Out;
+  for (const auto &R : Refs) {
+    if (&R != Refs.begin())
+      Out.emplace_back(llvm::make_unique<TextNode>(", "));
+    Out.emplace_back(genTypeReference(R));
+  }
+  return Out;
+}
+
 static std::vector<std::unique_ptr<TagNode>> genHTML(const EnumInfo &I);
 static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I);
 
@@ -249,8 +279,11 @@
     std::string Access = getAccess(M.Access);
     if (Access != "")
       Access = Access + " ";
-    ULBody->Children.emplace_back(llvm::make_unique<TagNode>(
-        HTMLTag::TAG_LI, Access + M.Type.Name + " " + M.Name));
+    auto LIBody = llvm::make_unique<TagNode>(HTMLTag::TAG_LI);
+    LIBody->Children.emplace_back(llvm::make_unique<TextNode>(Access));
+    LIBody->Children.emplace_back(genTypeReference(M.Type));
+    LIBody->Children.emplace_back(llvm::make_unique<TextNode>(" " + M.Name));
+    ULBody->Children.emplace_back(std::move(LIBody));
   }
   return Out;
 }
@@ -343,21 +376,28 @@
   std::vector<std::unique_ptr<TagNode>> Out;
   Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name));
 
-  std::string Buffer;
-  llvm::raw_string_ostream Stream(Buffer);
-  for (const auto &P : I.Params) {
-    if (&P != I.Params.begin())
-      Stream << ", ";
-    Stream << P.Type.Name + " " + P.Name;
-  }
+  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P));
+  auto &FunctionHeader = Out.back();
 
   std::string Access = getAccess(I.Access);
   if (Access != "")
-    Access = Access + " ";
+    FunctionHeader->Children.emplace_back(
+        llvm::make_unique<TextNode>(Access + " "));
+  if (I.ReturnType.Type.Name != "") {
+    FunctionHeader->Children.emplace_back(genTypeReference(I.ReturnType.Type));
+    FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(" "));
+  }
+  FunctionHeader->Children.emplace_back(
+      llvm::make_unique<TextNode>(I.Name + "("));
 
-  Out.emplace_back(llvm::make_unique<TagNode>(
-      HTMLTag::TAG_P, Access + I.ReturnType.Type.Name + " " + I.Name + "(" +
-                          Stream.str() + ")"));
+  for (const auto &P : I.Params) {
+    if (&P != I.Params.begin())
+      FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(", "));
+    FunctionHeader->Children.emplace_back(genTypeReference(P.Type));
+    FunctionHeader->Children.emplace_back(
+        llvm::make_unique<TextNode>(" " + P.Name));
+  }
+  FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(")"));
 
   if (I.DefLoc)
     Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
@@ -415,18 +455,26 @@
   if (!I.Description.empty())
     Out.emplace_back(genHTML(I.Description));
 
-  std::string Parents = genReferenceList(I.Parents);
-  std::string VParents = genReferenceList(I.VirtualParents);
+  Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P));
+  auto &PBody = Out.back();
+  PBody->Children.emplace_back(llvm::make_unique<TextNode>("Inherits from "));
+  std::vector<std::unique_ptr<HTMLNode>> Parents = genReferenceList(I.Parents);
+  std::vector<std::unique_ptr<HTMLNode>> VParents =
+      genReferenceList(I.VirtualParents);
   if (!Parents.empty() || !VParents.empty()) {
     if (Parents.empty())
-      Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P,
-                                                  "Inherits from " + VParents));
+      std::move(VParents.begin(), VParents.end(),
+                std::back_inserter(PBody->Children));
     else if (VParents.empty())
-      Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P,
-                                                  "Inherits from " + Parents));
-    else
-      Out.emplace_back(llvm::make_unique<TagNode>(
-          HTMLTag::TAG_P, "Inherits from " + Parents + ", " + VParents));
+      std::move(Parents.begin(), Parents.end(),
+                std::back_inserter(PBody->Children));
+    else {
+      std::move(Parents.begin(), Parents.end(),
+                std::back_inserter(PBody->Children));
+      PBody->Children.emplace_back(llvm::make_unique<TextNode>(", "));
+      std::move(VParents.begin(), VParents.end(),
+                std::back_inserter(PBody->Children));
+    }
   }
 
   std::vector<std::unique_ptr<TagNode>> Members =
Index: clang-tools-extra/clang-doc/Generators.h
===================================================================
--- clang-tools-extra/clang-doc/Generators.h
+++ clang-tools-extra/clang-doc/Generators.h
@@ -38,8 +38,6 @@
 
 std::string getTagType(TagTypeKind AS);
 
-std::string genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs);
-
 } // namespace doc
 } // namespace clang
 
Index: clang-tools-extra/clang-doc/Generators.cpp
===================================================================
--- clang-tools-extra/clang-doc/Generators.cpp
+++ clang-tools-extra/clang-doc/Generators.cpp
@@ -57,19 +57,6 @@
   llvm_unreachable("Unknown TagTypeKind");
 }
 
-// Generates a comma-separated list of Refs
-// Used to display the parents of a record
-std::string genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
-  std::string Buffer;
-  llvm::raw_string_ostream Stream(Buffer);
-  for (const auto &R : Refs) {
-    if (&R != Refs.begin())
-      Stream << ", ";
-    Stream << R.Name;
-  }
-  return Stream.str();
-}
-
 // This anchor is used to force the linker to link in the generated object file
 // and thus register the generators.
 extern volatile int YAMLGeneratorAnchorSource;
Index: clang-tools-extra/clang-doc/BitcodeWriter.h
===================================================================
--- clang-tools-extra/clang-doc/BitcodeWriter.h
+++ clang-tools-extra/clang-doc/BitcodeWriter.h
@@ -91,6 +91,7 @@
   MEMBER_TYPE_ACCESS,
   NAMESPACE_USR,
   NAMESPACE_NAME,
+  NAMESPACE_PATH,
   ENUM_USR,
   ENUM_NAME,
   ENUM_DEFLOCATION,
@@ -99,6 +100,7 @@
   ENUM_SCOPED,
   RECORD_USR,
   RECORD_NAME,
+  RECORD_PATH,
   RECORD_DEFLOCATION,
   RECORD_LOCATION,
   RECORD_TAG_TYPE,
@@ -106,6 +108,7 @@
   REFERENCE_USR,
   REFERENCE_NAME,
   REFERENCE_TYPE,
+  REFERENCE_PATH,
   REFERENCE_FIELD,
   RI_LAST,
   RI_FIRST = VERSION
Index: clang-tools-extra/clang-doc/BitcodeWriter.cpp
===================================================================
--- clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -148,6 +148,7 @@
           {MEMBER_TYPE_ACCESS, {"Access", &IntAbbrev}},
           {NAMESPACE_USR, {"USR", &SymbolIDAbbrev}},
           {NAMESPACE_NAME, {"Name", &StringAbbrev}},
+          {NAMESPACE_PATH, {"Path", &StringAbbrev}},
           {ENUM_USR, {"USR", &SymbolIDAbbrev}},
           {ENUM_NAME, {"Name", &StringAbbrev}},
           {ENUM_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
@@ -156,6 +157,7 @@
           {ENUM_SCOPED, {"Scoped", &BoolAbbrev}},
           {RECORD_USR, {"USR", &SymbolIDAbbrev}},
           {RECORD_NAME, {"Name", &StringAbbrev}},
+          {RECORD_PATH, {"Path", &StringAbbrev}},
           {RECORD_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
           {RECORD_LOCATION, {"Location", &LocationAbbrev}},
           {RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
@@ -169,6 +171,7 @@
           {REFERENCE_USR, {"USR", &SymbolIDAbbrev}},
           {REFERENCE_NAME, {"Name", &StringAbbrev}},
           {REFERENCE_TYPE, {"RefType", &IntAbbrev}},
+          {REFERENCE_PATH, {"Path", &StringAbbrev}},
           {REFERENCE_FIELD, {"Field", &IntAbbrev}}};
       assert(Inits.size() == RecordIdCount);
       for (const auto &Init : Inits) {
@@ -199,18 +202,20 @@
          {ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_MEMBER,
           ENUM_SCOPED}},
         // Namespace Block
-        {BI_NAMESPACE_BLOCK_ID, {NAMESPACE_USR, NAMESPACE_NAME}},
+        {BI_NAMESPACE_BLOCK_ID,
+         {NAMESPACE_USR, NAMESPACE_NAME, NAMESPACE_PATH}},
         // Record Block
         {BI_RECORD_BLOCK_ID,
-         {RECORD_USR, RECORD_NAME, RECORD_DEFLOCATION, RECORD_LOCATION,
-          RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF}},
+         {RECORD_USR, RECORD_NAME, RECORD_PATH, RECORD_DEFLOCATION,
+          RECORD_LOCATION, RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF}},
         // Function Block
         {BI_FUNCTION_BLOCK_ID,
          {FUNCTION_USR, FUNCTION_NAME, FUNCTION_DEFLOCATION, FUNCTION_LOCATION,
           FUNCTION_ACCESS, FUNCTION_IS_METHOD}},
         // Reference Block
         {BI_REFERENCE_BLOCK_ID,
-         {REFERENCE_USR, REFERENCE_NAME, REFERENCE_TYPE, REFERENCE_FIELD}}};
+         {REFERENCE_USR, REFERENCE_NAME, REFERENCE_TYPE, REFERENCE_PATH,
+          REFERENCE_FIELD}}};
 
 // AbbreviationMap
 
@@ -381,6 +386,7 @@
   emitRecord(R.USR, REFERENCE_USR);
   emitRecord(R.Name, REFERENCE_NAME);
   emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
+  emitRecord(R.Path, REFERENCE_PATH);
   emitRecord((unsigned)Field, REFERENCE_FIELD);
 }
 
@@ -428,6 +434,7 @@
   StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
   emitRecord(I.USR, NAMESPACE_USR);
   emitRecord(I.Name, NAMESPACE_NAME);
+  emitRecord(I.Path, NAMESPACE_PATH);
   for (const auto &N : I.Namespace)
     emitBlock(N, FieldId::F_namespace);
   for (const auto &CI : I.Description)
@@ -463,6 +470,7 @@
   StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
   emitRecord(I.USR, RECORD_USR);
   emitRecord(I.Name, RECORD_NAME);
+  emitRecord(I.Path, RECORD_PATH);
   for (const auto &N : I.Namespace)
     emitBlock(N, FieldId::F_namespace);
   for (const auto &CI : I.Description)
Index: clang-tools-extra/clang-doc/BitcodeReader.cpp
===================================================================
--- clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -148,6 +148,8 @@
     return decodeRecord(R, I->USR, Blob);
   case NAMESPACE_NAME:
     return decodeRecord(R, I->Name, Blob);
+  case NAMESPACE_PATH:
+    return decodeRecord(R, I->Path, Blob);
   default:
     return llvm::make_error<llvm::StringError>(
         "Invalid field for NamespaceInfo.\n", llvm::inconvertibleErrorCode());
@@ -161,6 +163,8 @@
     return decodeRecord(R, I->USR, Blob);
   case RECORD_NAME:
     return decodeRecord(R, I->Name, Blob);
+  case RECORD_PATH:
+    return decodeRecord(R, I->Path, Blob);
   case RECORD_DEFLOCATION:
     return decodeRecord(R, I->DefLoc, Blob);
   case RECORD_LOCATION:
@@ -286,6 +290,8 @@
     return decodeRecord(R, I->Name, Blob);
   case REFERENCE_TYPE:
     return decodeRecord(R, I->RefType, Blob);
+  case REFERENCE_PATH:
+    return decodeRecord(R, I->Path, Blob);
   case REFERENCE_FIELD:
     return decodeRecord(R, F, Blob);
   default:
@@ -684,7 +690,7 @@
   std::unique_ptr<Info> I = llvm::make_unique<T>();
   if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
     return std::move(Err);
-  return std::unique_ptr<Info>{std::move(I)};;
+  return std::unique_ptr<Info>{std::move(I)};
 }
 
 llvm::Expected<std::unique_ptr<Info>>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to