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

In tag nodes with children that are not inline, two text nodes that are 
adjacent won't have a new line between them. Tag nodes are still rendered in 
their own line.

  <p>
    A
     B
    <a>C<a>
    D
  </p>

is now rendered as

  <p>
    A B
    <a>C<a>
    D
  </p>


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/Representation.cpp
  clang-tools-extra/clang-doc/Representation.h
  clang-tools-extra/clang-doc/Serialize.cpp
  clang-tools-extra/clang-doc/YAMLGenerator.cpp
  clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
  clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp
  clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp

Index: clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
===================================================================
--- clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
+++ clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp
@@ -25,6 +25,7 @@
 TEST(YAMLGeneratorTest, emitNamespaceYAML) {
   NamespaceInfo I;
   I.Name = "Namespace";
+  I.Path = "path/to/A";
   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
 
   I.ChildNamespaces.emplace_back(EmptySID, "ChildNamespace",
@@ -45,6 +46,7 @@
       R"raw(---
 USR:             '0000000000000000000000000000000000000000'
 Name:            'Namespace'
+Path:            'path/to/A'
 Namespace:       
   - Type:            Namespace
     Name:            'A'
@@ -69,15 +71,18 @@
 TEST(YAMLGeneratorTest, emitRecordYAML) {
   RecordInfo I;
   I.Name = "r";
+  I.Path = "path/to/r";
   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
 
   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/int", "X",
+                         AccessSpecifier::AS_private);
   I.TagType = TagTypeKind::TTK_Class;
-  I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
-  I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
+  I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "path/to/F");
+  I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,
+                                "path/to/G");
 
   I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
   I.ChildFunctions.emplace_back();
@@ -95,6 +100,7 @@
       R"raw(---
 USR:             '0000000000000000000000000000000000000000'
 Name:            'r'
+Path:            'path/to/r'
 Namespace:       
   - Type:            Namespace
     Name:            'A'
@@ -108,14 +114,17 @@
 Members:         
   - Type:            
       Name:            'int'
+      Path:            'path/to/int'
     Name:            'X'
     Access:          Private
 Parents:         
   - Type:            Record
     Name:            'F'
+    Path:            'path/to/F'
 VirtualParents:  
   - Type:            Record
     Name:            'G'
+    Path:            'path/to/G'
 ChildRecords:    
   - Type:            Record
     Name:            'ChildStruct'
@@ -139,8 +148,9 @@
   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, "void", InfoType::IT_default, "path/to/void");
+  I.Params.emplace_back("int", "path/to/int", "P");
   I.IsMethod = true;
   I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
 
@@ -170,10 +180,12 @@
 Params:          
   - Type:            
       Name:            'int'
+      Path:            'path/to/int'
     Name:            'P'
 ReturnType:      
   Type:            
     Name:            'void'
+    Path:            'path/to/void'
 ...
 )raw";
   EXPECT_EQ(Expected, Actual.str());
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,7 @@
   <div>
     <h3>OneFunction</h3>
     <p>
-       OneFunction()
+      OneFunction()
     </p>
   </div>
   <h2>Enums</h2>
@@ -73,14 +73,16 @@
 TEST(HTMLGeneratorTest, emitRecordHTML) {
   RecordInfo I;
   I.Name = "r";
+  I.Path = "X/Y/Z";
   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
 
   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", "X/Y", "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,13 @@
     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="../int.html">int</a> X</li>
   </ul>
   <h2>Records</h2>
   <ul>
@@ -118,7 +122,7 @@
   <div>
     <h3>OneFunction</h3>
     <p>
-       OneFunction()
+      OneFunction()
     </p>
   </div>
   <h2>Enums</h2>
@@ -139,8 +143,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 +160,10 @@
 <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
@@ -261,8 +268,7 @@
          Brief description.
       </p>
       <p>
-         Extended description that
-         continues onto the next line.
+         Extended description that continues onto the next line.
       </p>
     </div>
   </div>
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 output directory, the
+// info's relative path and name and the extension. The relative path 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 {
@@ -124,16 +125,14 @@
 //
 // }
 // }
-llvm::Expected<llvm::SmallString<128>>
-getInfoOutputFile(StringRef Root,
-                  llvm::SmallVectorImpl<doc::Reference> &Namespaces,
-                  StringRef Name, StringRef Ext) {
+llvm::Expected<llvm::SmallString<128>> getInfoOutputFile(StringRef Root,
+                                                         StringRef RelativePath,
+                                                         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);
-
+  llvm::sys::path::append(Path, RelativePath);
   if (CreateDirectory(Path))
     return llvm::make_error<llvm::StringError>("Unable to create directory.\n",
                                                llvm::inconvertibleErrorCode());
@@ -223,12 +222,11 @@
     }
 
     doc::Info *I = Reduced.get().get();
-
-    auto InfoPath = getInfoOutputFile(OutDirectory, I->Namespace,
-                                      I->extractName(), "." + Format);
+    auto InfoPath = getInfoOutputFile(OutDirectory, 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/YAMLGenerator.cpp
===================================================================
--- clang-tools-extra/clang-doc/YAMLGenerator.cpp
+++ clang-tools-extra/clang-doc/YAMLGenerator.cpp
@@ -113,6 +113,7 @@
 static void InfoMapping(IO &IO, Info &I) {
   IO.mapRequired("USR", I.USR);
   IO.mapOptional("Name", I.Name, SmallString<16>());
+  IO.mapOptional("Path", I.Path, SmallString<128>());
   IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector<Reference, 4>());
   IO.mapOptional("Description", I.Description);
 }
@@ -154,6 +155,7 @@
     IO.mapOptional("Type", Ref.RefType, InfoType::IT_default);
     IO.mapOptional("Name", Ref.Name, SmallString<16>());
     IO.mapOptional("USR", Ref.USR, SymbolID());
+    IO.mapOptional("Path", Ref.Path, SmallString<128>());
   }
 };
 
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,43 @@
   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 relative path 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>
+getInfoRelativePath(const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
+  std::error_code OK;
+  llvm::SmallString<128> Path;
+  for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
+    llvm::sys::path::append(Path, R->Name);
+  return Path;
+}
+
+llvm::SmallString<128> getInfoRelativePath(const Decl *D) {
+  llvm::SmallVector<Reference, 4> Namespaces;
+  // The third arg in populateParentNamespaces is a boolean passed by reference,
+  // its value is not relevant in here so it's not used anywhere besides the
+  // function call
+  bool B = true;
+  populateParentNamespaces(Namespaces, D, B);
+  return getInfoRelativePath(Namespaces);
+}
+
 class ClangDocCommentVisitor
     : public ConstCommentVisitor<ClangDocCommentVisitor> {
 public:
@@ -203,13 +240,13 @@
       // 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, getInfoRelativePath(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, getInfoRelativePath(N),
+                               F->getNameAsString(), N->getAccessUnsafe());
         continue;
       }
     }
@@ -228,11 +265,13 @@
     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());
+                              InfoType::IT_enum, getInfoRelativePath(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());
+                              InfoType::IT_record, getInfoRelativePath(N),
+                              P->getNameAsString());
         continue;
       }
     }
@@ -254,14 +293,15 @@
                              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, getInfoRelativePath(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,
+                                    getInfoRelativePath(P));
     else
       I.VirtualParents.emplace_back(B.getType().getAsString());
   }
@@ -270,14 +310,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,
@@ -324,11 +364,11 @@
   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);
+      I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
+                              InfoType::IT_enum, getInfoRelativePath(T));
     else if (dyn_cast<RecordDecl>(T))
-      I.ReturnType =
-          TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_record);
+      I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
+                              InfoType::IT_record, getInfoRelativePath(T));
   } else {
     I.ReturnType = TypeInfo(D->getReturnType().getAsString());
   }
@@ -347,16 +387,18 @@
   I->Name = D->isAnonymousNamespace()
                 ? llvm::SmallString<16>("@nonymous_namespace")
                 : I->Name;
+  I->Path = getInfoRelativePath(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->Path = getInfoRelativePath(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>>
@@ -378,32 +420,34 @@
     }
     parseBases(*I, C);
   }
+  I->Path = getInfoRelativePath(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 = getInfoRelativePath(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);
     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);
     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");
+    llvm_unreachable("Invalid reference type for parent namespace");
   }
 }
 
@@ -420,14 +464,16 @@
   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();
+  if (Func.Namespace.empty())
+    ParentI->Path = getInfoRelativePath(ParentI->Namespace);
+  ParentI->ChildFunctions.emplace_back(std::move(Func));
+  // 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>>
@@ -455,11 +501,13 @@
   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;
+  if (Func.Namespace.empty())
+    ParentI->Path = getInfoRelativePath(ParentI->Namespace);
+  ParentI->ChildFunctions.emplace_back(std::move(Func));
   // 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>>
@@ -475,36 +523,38 @@
   Enum.Scoped = D->isScoped();
   parseEnumerators(Enum, D);
 
-  // Wrap in enclosing scope
-  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));
-      // Info is wrapped in its parent scope so it's returned in the second
-      // position
-      return {nullptr, std::unique_ptr<Info>{std::move(I)}};
-    }
-    case InfoType::IT_record: {
-      auto I = llvm::make_unique<RecordInfo>();
-      I->USR = Enum.Namespace[0].USR;
-      I->ChildEnums.emplace_back(std::move(Enum));
-      // Info is wrapped in its parent scope so it's returned in the second
-      // position
-      return {nullptr, std::unique_ptr<Info>{std::move(I)}};
-    }
-    default:
-      break;
-    }
+  // Put in global namespace
+  if (Enum.Namespace.empty()) {
+    auto ParentI = llvm::make_unique<NamespaceInfo>();
+    ParentI->USR = SymbolID();
+    ParentI->ChildEnums.emplace_back(std::move(Enum));
+    ParentI->Path = getInfoRelativePath(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)}};
   }
 
-  // Put in global namespace
-  auto I = llvm::make_unique<NamespaceInfo>();
-  I->USR = SymbolID();
-  I->ChildEnums.emplace_back(std::move(Enum));
-  // Info is wrapped in its parent scope so it's returned in the second position
-  return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+  // Wrap in enclosing scope
+  switch (Enum.Namespace[0].RefType) {
+  case InfoType::IT_namespace: {
+    auto ParentI = llvm::make_unique<NamespaceInfo>();
+    ParentI->USR = Enum.Namespace[0].USR;
+    ParentI->ChildEnums.emplace_back(std::move(Enum));
+    // Info is wrapped in its parent scope so it's returned in the second
+    // position
+    return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
+  }
+  case InfoType::IT_record: {
+    auto ParentI = llvm::make_unique<RecordInfo>();
+    ParentI->USR = Enum.Namespace[0].USR;
+    ParentI->ChildEnums.emplace_back(std::move(Enum));
+    // Info is wrapped in its parent scope so it's returned in the second
+    // position
+    return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
+  }
+  default:
+    llvm_unreachable("Invalid reference type for parent namespace");
+  }
 }
 
 } // 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);
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/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
@@ -18,13 +18,6 @@
 namespace clang {
 namespace doc {
 
-template <typename Derived, typename Base,
-          typename = std::enable_if<std::is_base_of<Derived, Base>::value>>
-static void AppendVector(std::vector<Derived> &&New,
-                         std::vector<Base> &Original) {
-  std::move(New.begin(), New.end(), std::back_inserter(Original));
-}
-
 namespace {
 
 class HTMLTag {
@@ -40,6 +33,7 @@
     TAG_P,
     TAG_UL,
     TAG_LI,
+    TAG_A,
   };
 
   HTMLTag() = default;
@@ -58,15 +52,22 @@
   TagType Value;
 };
 
+enum NodeType {
+  NODE_TEXT,
+  NODE_TAG,
+};
+
 struct HTMLNode {
+  HTMLNode(NodeType Type) : Type(Type) {}
   virtual ~HTMLNode() = default;
 
   virtual void Render(llvm::raw_ostream &OS, int IndentationLevel) = 0;
+  NodeType Type; // Type of node
 };
 
 struct TextNode : public HTMLNode {
-  TextNode(llvm::StringRef Text, bool Indented)
-      : Text(Text), Indented(Indented) {}
+  TextNode(const Twine &Text, bool Indented = true)
+      : HTMLNode(NodeType::NODE_TEXT), Text(Text.str()), Indented(Indented) {}
 
   std::string Text; // Content of node
   bool Indented; // Indicates if an indentation must be rendered before the text
@@ -75,7 +76,8 @@
 
 struct TagNode : public HTMLNode {
   TagNode(HTMLTag Tag)
-      : Tag(Tag), InlineChildren(Tag.HasInlineChildren()),
+      : HTMLNode(NodeType::NODE_TAG), Tag(Tag),
+        InlineChildren(Tag.HasInlineChildren()),
         SelfClosing(Tag.IsSelfClosing()) {}
   TagNode(HTMLTag Tag, const Twine &Text) : TagNode(Tag) {
     Children.emplace_back(
@@ -121,6 +123,7 @@
   case HTMLTag::TAG_P:
   case HTMLTag::TAG_UL:
   case HTMLTag::TAG_LI:
+  case HTMLTag::TAG_A:
     return false;
   }
 }
@@ -133,6 +136,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:
@@ -161,6 +165,8 @@
     return llvm::SmallString<16>("ul");
   case HTMLTag::TAG_LI:
     return llvm::SmallString<16>("li");
+  case HTMLTag::TAG_A:
+    return llvm::SmallString<16>("a");
   }
 }
 
@@ -182,21 +188,87 @@
   OS << ">";
   if (!InlineChildren)
     OS << "\n";
-  int ChildrenIndentation = InlineChildren ? 0 : IndentationLevel + 1;
+  bool NewLineRendered = true;
   for (const auto &C : Children) {
+    int ChildrenIndentation =
+        InlineChildren || !NewLineRendered ? 0 : IndentationLevel + 1;
     C->Render(OS, ChildrenIndentation);
-    if (!InlineChildren)
+    if (!InlineChildren && (C == Children.back() ||
+                            (C->Type != NodeType::NODE_TEXT ||
+                             (&C + 1)->get()->Type != NodeType::NODE_TEXT))) {
       OS << "\n";
+      NewLineRendered = true;
+    } else
+      NewLineRendered = false;
   }
   if (!InlineChildren)
     OS.indent(IndentationLevel * 2);
   OS << "</" << Tag.ToString() << ">";
 }
 
+template <typename Derived, typename Base,
+          typename = std::enable_if<std::is_base_of<Derived, Base>::value>>
+static void AppendVector(std::vector<Derived> &&New,
+                         std::vector<Base> &Original) {
+  std::move(New.begin(), New.end(), std::back_inserter(Original));
+}
+
+// Compute the relative path that names the file path relative to the given
+// directory.
+static SmallString<128> computeRelativePath(StringRef FilePath,
+                                            StringRef Directory) {
+  StringRef Path = FilePath;
+  while (!Path.empty()) {
+    if (Directory == Path)
+      return FilePath.substr(Path.size());
+    Path = llvm::sys::path::parent_path(Path);
+  }
+
+  StringRef Dir = Directory;
+  SmallString<128> Result;
+  while (!Dir.empty()) {
+    if (Dir == FilePath)
+      break;
+    Dir = llvm::sys::path::parent_path(Dir);
+    llvm::sys::path::append(Result, "..");
+  }
+  llvm::sys::path::append(Result, FilePath.substr(Dir.size()));
+  return Result;
+}
+
 // 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,
+                                                  StringRef CurrentDirectory) {
+  if (Type.Path.empty())
+    return llvm::make_unique<TextNode>(Type.Name);
+  llvm::SmallString<128> Path =
+      computeRelativePath(Type.Path, CurrentDirectory);
+  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,
+                 const StringRef &CurrentDirectory) {
+  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, CurrentDirectory));
+  }
+  return Out;
+}
+
 static std::vector<std::unique_ptr<TagNode>> genHTML(const EnumInfo &I);
-static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I);
+static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I,
+                                                     StringRef ParentInfoDir);
 
 static std::vector<std::unique_ptr<TagNode>>
 genEnumsBlock(const std::vector<EnumInfo> &Enums) {
@@ -226,7 +298,8 @@
 }
 
 static std::vector<std::unique_ptr<TagNode>>
-genFunctionsBlock(const std::vector<FunctionInfo> &Functions) {
+genFunctionsBlock(const std::vector<FunctionInfo> &Functions,
+                  StringRef ParentInfoDir) {
   if (Functions.empty())
     return {};
 
@@ -235,14 +308,15 @@
   Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_DIV));
   auto &DivBody = Out.back();
   for (const auto &F : Functions) {
-    std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(F);
+    std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(F, ParentInfoDir);
     AppendVector(std::move(Nodes), DivBody->Children);
   }
   return Out;
 }
 
 static std::vector<std::unique_ptr<TagNode>>
-genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members) {
+genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members,
+                      StringRef ParentInfoDir) {
   if (Members.empty())
     return {};
 
@@ -254,8 +328,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, ParentInfoDir));
+    LIBody->Children.emplace_back(llvm::make_unique<TextNode>(" " + M.Name));
+    ULBody->Children.emplace_back(std::move(LIBody));
   }
   return Out;
 }
@@ -343,25 +420,35 @@
   return Out;
 }
 
-static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I) {
+static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I,
+                                                     StringRef ParentInfoDir) {
   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, ParentInfoDir));
+    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, ParentInfoDir));
+    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()));
@@ -395,7 +482,7 @@
   AppendVector(std::move(ChildRecords), Out);
 
   std::vector<std::unique_ptr<TagNode>> ChildFunctions =
-      genFunctionsBlock(I.ChildFunctions);
+      genFunctionsBlock(I.ChildFunctions, I.Path);
   AppendVector(std::move(ChildFunctions), Out);
   std::vector<std::unique_ptr<TagNode>> ChildEnums =
       genEnumsBlock(I.ChildEnums);
@@ -417,29 +504,34 @@
   if (!I.Description.empty())
     Out.emplace_back(genHTML(I.Description));
 
-  std::string Parents = genReferenceList(I.Parents);
-  std::string VParents = genReferenceList(I.VirtualParents);
+  std::vector<std::unique_ptr<HTMLNode>> Parents =
+      genReferenceList(I.Parents, I.Path);
+  std::vector<std::unique_ptr<HTMLNode>> VParents =
+      genReferenceList(I.VirtualParents, I.Path);
   if (!Parents.empty() || !VParents.empty()) {
+    Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P));
+    auto &PBody = Out.back();
+    PBody->Children.emplace_back(llvm::make_unique<TextNode>("Inherits from "));
     if (Parents.empty())
-      Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P,
-                                                  "Inherits from " + VParents));
+      AppendVector(std::move(VParents), 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));
+      AppendVector(std::move(Parents), PBody->Children);
+    else {
+      AppendVector(std::move(Parents), PBody->Children);
+      PBody->Children.emplace_back(llvm::make_unique<TextNode>(", "));
+      AppendVector(std::move(VParents), PBody->Children);
+    }
   }
 
   std::vector<std::unique_ptr<TagNode>> Members =
-      genRecordMembersBlock(I.Members);
+      genRecordMembersBlock(I.Members, I.Path);
   AppendVector(std::move(Members), Out);
   std::vector<std::unique_ptr<TagNode>> ChildRecords =
       genReferencesBlock(I.ChildRecords, "Records");
   AppendVector(std::move(ChildRecords), Out);
 
   std::vector<std::unique_ptr<TagNode>> ChildFunctions =
-      genFunctionsBlock(I.ChildFunctions);
+      genFunctionsBlock(I.ChildFunctions, I.Path);
   AppendVector(std::move(ChildFunctions), Out);
   std::vector<std::unique_ptr<TagNode>> ChildEnums =
       genEnumsBlock(I.ChildEnums);
@@ -489,7 +581,7 @@
   }
   case InfoType::IT_function: {
     std::vector<std::unique_ptr<TagNode>> Nodes =
-        genHTML(*static_cast<clang::doc::FunctionInfo *>(I));
+        genHTML(*static_cast<clang::doc::FunctionInfo *>(I), "");
     AppendVector(std::move(Nodes), MainContentNode->Children);
     break;
   }
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