[clang-tools-extra] r364674 - [clang-doc] Handle anonymous namespaces

Julie Hockett via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 28 12:07:56 PDT 2019


Author: juliehockett
Date: Fri Jun 28 12:07:56 2019
New Revision: 364674

URL: http://llvm.org/viewvc/llvm-project?rev=364674&view=rev
Log:
[clang-doc] Handle anonymous namespaces

Improves output for anonymous decls, and updates the '--public' flag to exclude everything under an anonymous namespace.

Differential Revision: https://reviews.llvm.org/D52847

Modified:
    clang-tools-extra/trunk/clang-doc/Representation.cpp
    clang-tools-extra/trunk/clang-doc/Representation.h
    clang-tools-extra/trunk/clang-doc/Serialize.cpp
    clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp
    clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp

Modified: clang-tools-extra/trunk/clang-doc/Representation.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Representation.cpp?rev=364674&r1=364673&r2=364674&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Representation.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/Representation.cpp Fri Jun 28 12:07:56 2019
@@ -21,6 +21,7 @@
 //===----------------------------------------------------------------------===//
 #include "Representation.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/Path.h"
 
 namespace clang {
 namespace doc {
@@ -194,5 +195,37 @@ void FunctionInfo::merge(FunctionInfo &&
   SymbolInfo::merge(std::move(Other));
 }
 
+llvm::SmallString<16> Info::extractName() {
+  if (!Name.empty())
+    return Name;
+
+  switch (IT) {
+  case InfoType::IT_namespace:
+    // Cover the case where the project contains a base namespace called
+    // 'GlobalNamespace' (i.e. a namespace at the same level as the global
+    // namespace, which would conflict with the hard-coded global namespace name
+    // below.)
+    if (Name == "GlobalNamespace" && Namespace.empty())
+      return llvm::SmallString<16>("@GlobalNamespace");
+    // The case of anonymous namespaces is taken care of in serialization,
+    // so here we can safely assume an unnamed namespace is the global
+    // one.
+    return llvm::SmallString<16>("GlobalNamespace");
+  case InfoType::IT_record:
+    return llvm::SmallString<16>("@nonymous_record_" +
+                                 toHex(llvm::toStringRef(USR)));
+  case InfoType::IT_enum:
+    return llvm::SmallString<16>("@nonymous_enum_" +
+                                 toHex(llvm::toStringRef(USR)));
+  case InfoType::IT_function:
+    return llvm::SmallString<16>("@nonymous_function_" +
+                                 toHex(llvm::toStringRef(USR)));
+  case InfoType::IT_default:
+    return llvm::SmallString<16>("@nonymous_" + toHex(llvm::toStringRef(USR)));
+  }
+  llvm_unreachable("Invalid InfoType.");
+  return llvm::SmallString<16>("");
+}
+
 } // namespace doc
 } // namespace clang

Modified: clang-tools-extra/trunk/clang-doc/Representation.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Representation.h?rev=364674&r1=364673&r2=364674&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Representation.h (original)
+++ clang-tools-extra/trunk/clang-doc/Representation.h Fri Jun 28 12:07:56 2019
@@ -223,6 +223,8 @@ struct Info {
   void mergeBase(Info &&I);
   bool mergeable(const Info &Other);
 
+  llvm::SmallString<16> extractName();
+
   // Returns a reference to the parent scope (that is, the immediate parent
   // namespace or class in which this decl resides).
   llvm::Expected<Reference> getEnclosingScope();

Modified: clang-tools-extra/trunk/clang-doc/Serialize.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Serialize.cpp?rev=364674&r1=364673&r2=364674&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Serialize.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/Serialize.cpp Fri Jun 28 12:07:56 2019
@@ -270,13 +270,19 @@ static void parseBases(RecordInfo &I, co
 template <typename T>
 static void
 populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
-                         const T *D) {
+                         const T *D, bool &IsAnonymousNamespace) {
   const auto *DC = dyn_cast<DeclContext>(D);
   while ((DC = DC->getParent())) {
-    if (const auto *N = dyn_cast<NamespaceDecl>(DC))
-      Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
+    if (const auto *N = dyn_cast<NamespaceDecl>(DC)) {
+      std::string Namespace;
+      if (N->isAnonymousNamespace()) {
+        Namespace = "@nonymous_namespace";
+        IsAnonymousNamespace = true;
+      } else
+        Namespace = N->getNameAsString();
+      Namespaces.emplace_back(getUSRForDecl(N), Namespace,
                               InfoType::IT_namespace);
-    else if (const auto *N = dyn_cast<RecordDecl>(DC))
+    } else if (const auto *N = dyn_cast<RecordDecl>(DC))
       Namespaces.emplace_back(getUSRForDecl(N), N->getNameAsString(),
                               InfoType::IT_record);
     else if (const auto *N = dyn_cast<FunctionDecl>(DC))
@@ -289,10 +295,11 @@ populateParentNamespaces(llvm::SmallVect
 }
 
 template <typename T>
-static void populateInfo(Info &I, const T *D, const FullComment *C) {
+static void populateInfo(Info &I, const T *D, const FullComment *C,
+                         bool &IsInAnonymousNamespace) {
   I.USR = getUSRForDecl(D);
   I.Name = D->getNameAsString();
-  populateParentNamespaces(I.Namespace, D);
+  populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace);
   if (C) {
     I.Description.emplace_back();
     parseFullComment(C, I.Description.back());
@@ -301,8 +308,9 @@ static void populateInfo(Info &I, const
 
 template <typename T>
 static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
-                               int LineNumber, StringRef Filename) {
-  populateInfo(I, D, C);
+                               int LineNumber, StringRef Filename,
+                               bool &IsInAnonymousNamespace) {
+  populateInfo(I, D, C, IsInAnonymousNamespace);
   if (D->isThisDeclarationADefinition())
     I.DefLoc.emplace(LineNumber, Filename);
   else
@@ -311,8 +319,9 @@ static void populateSymbolInfo(SymbolInf
 
 static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
                                  const FullComment *FC, int LineNumber,
-                                 StringRef Filename) {
-  populateSymbolInfo(I, D, FC, LineNumber, Filename);
+                                 StringRef Filename,
+                                 bool &IsInAnonymousNamespace) {
+  populateSymbolInfo(I, D, FC, LineNumber, Filename, IsInAnonymousNamespace);
   if (const auto *T = getDeclForType(D->getReturnType())) {
     if (dyn_cast<EnumDecl>(T))
       I.ReturnType =
@@ -329,21 +338,28 @@ static void populateFunctionInfo(Functio
 std::unique_ptr<Info> emitInfo(const NamespaceDecl *D, const FullComment *FC,
                                int LineNumber, llvm::StringRef File,
                                bool PublicOnly) {
-  if (PublicOnly && ((D->isAnonymousNamespace()) ||
+  auto I = llvm::make_unique<NamespaceInfo>();
+  bool IsInAnonymousNamespace = false;
+  populateInfo(*I, D, FC, IsInAnonymousNamespace);
+  if (PublicOnly && ((IsInAnonymousNamespace || D->isAnonymousNamespace()) ||
                      !isPublic(D->getAccess(), D->getLinkageInternal())))
     return nullptr;
-  auto I = llvm::make_unique<NamespaceInfo>();
-  populateInfo(*I, D, FC);
+  I->Name = D->isAnonymousNamespace()
+                ? llvm::SmallString<16>("@nonymous_namespace")
+                : I->Name;
   return std::unique_ptr<Info>{std::move(I)};
 }
 
 std::unique_ptr<Info> emitInfo(const RecordDecl *D, const FullComment *FC,
                                int LineNumber, llvm::StringRef File,
                                bool PublicOnly) {
-  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
-    return nullptr;
   auto I = llvm::make_unique<RecordInfo>();
-  populateSymbolInfo(*I, D, FC, LineNumber, File);
+  bool IsInAnonymousNamespace = false;
+  populateSymbolInfo(*I, D, FC, LineNumber, File, IsInAnonymousNamespace);
+  if (PublicOnly && ((IsInAnonymousNamespace ||
+                      !isPublic(D->getAccess(), D->getLinkageInternal()))))
+    return nullptr;
+
   I->TagType = D->getTagKind();
   parseFields(*I, D, PublicOnly);
   if (const auto *C = dyn_cast<CXXRecordDecl>(D)) {
@@ -359,10 +375,13 @@ std::unique_ptr<Info> emitInfo(const Rec
 std::unique_ptr<Info> emitInfo(const FunctionDecl *D, const FullComment *FC,
                                int LineNumber, llvm::StringRef File,
                                bool PublicOnly) {
-  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
-    return nullptr;
   FunctionInfo Func;
-  populateFunctionInfo(Func, D, FC, LineNumber, File);
+  bool IsInAnonymousNamespace = false;
+  populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace);
+  if (PublicOnly && ((IsInAnonymousNamespace ||
+                      !isPublic(D->getAccess(), D->getLinkageInternal()))))
+    return nullptr;
+
   Func.Access = clang::AccessSpecifier::AS_none;
 
   // Wrap in enclosing scope
@@ -378,10 +397,13 @@ std::unique_ptr<Info> emitInfo(const Fun
 std::unique_ptr<Info> emitInfo(const CXXMethodDecl *D, const FullComment *FC,
                                int LineNumber, llvm::StringRef File,
                                bool PublicOnly) {
-  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
-    return nullptr;
   FunctionInfo Func;
-  populateFunctionInfo(Func, D, FC, LineNumber, File);
+  bool IsInAnonymousNamespace = false;
+  populateFunctionInfo(Func, D, FC, LineNumber, File, IsInAnonymousNamespace);
+  if (PublicOnly && ((IsInAnonymousNamespace ||
+                      !isPublic(D->getAccess(), D->getLinkageInternal()))))
+    return nullptr;
+
   Func.IsMethod = true;
 
   const NamedDecl *Parent = nullptr;
@@ -406,10 +428,13 @@ std::unique_ptr<Info> emitInfo(const CXX
 std::unique_ptr<Info> emitInfo(const EnumDecl *D, const FullComment *FC,
                                int LineNumber, llvm::StringRef File,
                                bool PublicOnly) {
-  if (PublicOnly && !isPublic(D->getAccess(), D->getLinkageInternal()))
-    return nullptr;
   EnumInfo Enum;
-  populateSymbolInfo(Enum, D, FC, LineNumber, File);
+  bool IsInAnonymousNamespace = false;
+  populateSymbolInfo(Enum, D, FC, LineNumber, File, IsInAnonymousNamespace);
+  if (PublicOnly && ((IsInAnonymousNamespace ||
+                      !isPublic(D->getAccess(), D->getLinkageInternal()))))
+    return nullptr;
+
   Enum.Scoped = D->isScoped();
   parseEnumerators(Enum, D);
 

Modified: clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp?rev=364674&r1=364673&r2=364674&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp Fri Jun 28 12:07:56 2019
@@ -132,9 +132,6 @@ getInfoOutputFile(StringRef Root,
   if (CreateDirectory(Path))
     return llvm::make_error<llvm::StringError>("Unable to create directory.\n",
                                                llvm::inconvertibleErrorCode());
-
-  if (Name.empty())
-    Name = "GlobalNamespace";
   llvm::sys::path::append(Path, Name + Ext);
   return Path;
 }
@@ -222,8 +219,8 @@ int main(int argc, const char **argv) {
 
     doc::Info *I = Reduced.get().get();
 
-    auto InfoPath =
-        getInfoOutputFile(OutDirectory, I->Namespace, I->Name, "." + Format);
+    auto InfoPath = getInfoOutputFile(OutDirectory, I->Namespace,
+                                      I->extractName(), "." + Format);
     if (!InfoPath) {
       llvm::errs() << toString(InfoPath.takeError()) << "\n";
       continue;

Modified: clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp?rev=364674&r1=364673&r2=364674&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp Fri Jun 28 12:07:56 2019
@@ -131,6 +131,7 @@ TEST(SerializeTest, emitAnonymousNamespa
 
   NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
   NamespaceInfo ExpectedA(EmptySID);
+  ExpectedA.Name = "@nonymous_namespace";
   CheckNamespaceInfo(&ExpectedA, A);
 }
 




More information about the cfe-commits mailing list