[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