https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/170219
>From a81102bd098882ecadbe895b9cd4132d1fc58c4f Mon Sep 17 00:00:00 2001 From: Paul Kirth <[email protected]> Date: Fri, 21 Nov 2025 14:26:36 -0800 Subject: [PATCH] [clang-doc] Use DiagnosticsEngine to handle diagnostic output Right now we use a combination of outs() and errs() to handle tool output. Instead, we can use existing diagnostic support in clang and LLVM to ensure our tool has a consistent behavior with other tools. --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 25 ++-- clang-tools-extra/clang-doc/BitcodeReader.h | 4 +- clang-tools-extra/clang-doc/BitcodeWriter.cpp | 4 +- clang-tools-extra/clang-doc/BitcodeWriter.h | 5 +- clang-tools-extra/clang-doc/Generators.cpp | 9 +- .../clang-doc/HTMLMustacheGenerator.cpp | 1 + clang-tools-extra/clang-doc/Mapper.cpp | 4 +- .../clang-doc/Representation.cpp | 7 +- clang-tools-extra/clang-doc/Representation.h | 14 +- clang-tools-extra/clang-doc/Serialize.cpp | 19 +-- clang-tools-extra/clang-doc/Serialize.h | 2 +- .../clang-doc/tool/ClangDocMain.cpp | 72 ++++++---- .../unittests/clang-doc/BitcodeTest.cpp | 86 ++++++------ .../unittests/clang-doc/ClangDocTest.cpp | 15 +++ .../unittests/clang-doc/ClangDocTest.h | 17 +++ .../unittests/clang-doc/HTMLGeneratorTest.cpp | 49 ++++--- .../clang-doc/HTMLMustacheGeneratorTest.cpp | 35 +++-- .../unittests/clang-doc/JSONGeneratorTest.cpp | 10 +- .../unittests/clang-doc/MDGeneratorTest.cpp | 22 ++-- .../unittests/clang-doc/MergeTest.cpp | 10 +- .../unittests/clang-doc/SerializeTest.cpp | 124 ++++++++++-------- .../unittests/clang-doc/YAMLGeneratorTest.cpp | 30 +++-- 22 files changed, 344 insertions(+), 220 deletions(-) diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index dd5bbcd998784..e096264d929c7 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -8,6 +8,7 @@ #include "BitcodeReader.h" #include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" #include <optional> @@ -15,6 +16,8 @@ namespace clang { namespace doc { +static llvm::ExitOnError ExitOnErr("clang-doc error: "); + using Record = llvm::SmallVector<uint64_t, 1024>; // This implements decode for SmallString. @@ -716,8 +719,8 @@ llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) { template <typename T, typename ChildInfoType> static void addChild(T I, ChildInfoType &&R) { - llvm::errs() << "invalid child type for info"; - exit(1); + ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid child type for info")); } // Namespace children: @@ -766,8 +769,9 @@ template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) { // parameters) or TemplateSpecializationInfo (for the specialization's // parameters). template <typename T> static void addTemplateParam(T I, TemplateParamInfo &&P) { - llvm::errs() << "invalid container for template parameter"; - exit(1); + ExitOnErr( + llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid container for template parameter")); } template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) { I->Params.emplace_back(std::move(P)); @@ -779,8 +783,8 @@ void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) { // Template info. These apply to either records or functions. template <typename T> static void addTemplate(T I, TemplateInfo &&P) { - llvm::errs() << "invalid container for template info"; - exit(1); + ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid container for template info")); } template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) { I->Template.emplace(std::move(P)); @@ -798,8 +802,9 @@ template <> void addTemplate(FriendInfo *I, TemplateInfo &&P) { // Template specializations go only into template records. template <typename T> static void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI) { - llvm::errs() << "invalid container for template specialization info"; - exit(1); + ExitOnErr(llvm::createStringError( + llvm::inconvertibleErrorCode(), + "invalid container for template specialization info")); } template <> void addTemplateSpecialization(TemplateInfo *I, @@ -808,8 +813,8 @@ void addTemplateSpecialization(TemplateInfo *I, } template <typename T> static void addConstraint(T I, ConstraintInfo &&C) { - llvm::errs() << "invalid container for constraint info"; - exit(1); + ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(), + "invalid container for constraint info")); } template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) { I->Constraints.emplace_back(std::move(C)); diff --git a/clang-tools-extra/clang-doc/BitcodeReader.h b/clang-tools-extra/clang-doc/BitcodeReader.h index d51ac8bb83311..86d6f76998926 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.h +++ b/clang-tools-extra/clang-doc/BitcodeReader.h @@ -27,7 +27,8 @@ namespace doc { // Class to read bitstream into an InfoSet collection class ClangDocBitcodeReader { public: - ClangDocBitcodeReader(llvm::BitstreamCursor &Stream) : Stream(Stream) {} + ClangDocBitcodeReader(llvm::BitstreamCursor &Stream, DiagnosticsEngine &Diags) + : Stream(Stream), Diags(Diags) {} // Main entry point, calls readBlock to read each block in the given stream. llvm::Expected<std::vector<std::unique_ptr<Info>>> readBitcode(); @@ -72,6 +73,7 @@ class ClangDocBitcodeReader { llvm::BitstreamCursor &Stream; std::optional<llvm::BitstreamBlockInfo> BlockInfo; FieldId CurrentReferenceField; + DiagnosticsEngine &Diags; }; } // namespace doc diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index 3a7ac6e2abcdd..650501d1d7606 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -769,7 +769,9 @@ bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) { emitBlock(*static_cast<FriendInfo *>(I)); break; case InfoType::IT_default: - llvm::errs() << "Unexpected info, unable to write.\n"; + unsigned ID = Diags.getCustomDiagID(DiagnosticsEngine::Error, + "Unexpected info, unable to write."); + Diags.Report(ID); return true; } return false; diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.h b/clang-tools-extra/clang-doc/BitcodeWriter.h index 9c1b6abe983bb..6d1b9e9a7ebf2 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.h +++ b/clang-tools-extra/clang-doc/BitcodeWriter.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H #include "Representation.h" +#include "clang/Basic/Diagnostic.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Bitstream/BitstreamWriter.h" #include <vector> @@ -175,7 +176,8 @@ enum class FieldId { class ClangDocBitcodeWriter { public: - ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream) : Stream(Stream) { + ClangDocBitcodeWriter(llvm::BitstreamWriter &Stream, DiagnosticsEngine &Diags) + : Stream(Stream), Diags(Diags) { emitHeader(); emitBlockInfoBlock(); emitVersionBlock(); @@ -260,6 +262,7 @@ class ClangDocBitcodeWriter { SmallVector<uint32_t, BitCodeConstants::RecordSize> Record; llvm::BitstreamWriter &Stream; AbbreviationMap Abbrevs; + DiagnosticsEngine &Diags; }; } // namespace doc diff --git a/clang-tools-extra/clang-doc/Generators.cpp b/clang-tools-extra/clang-doc/Generators.cpp index 667e5d5a318f0..c5adbb27113ba 100644 --- a/clang-tools-extra/clang-doc/Generators.cpp +++ b/clang-tools-extra/clang-doc/Generators.cpp @@ -121,10 +121,11 @@ Error MustacheGenerator::generateDocumentation( auto File = MemoryBuffer::getFile(Path); if (EC = File.getError(); EC) { - // TODO: Buffer errors to report later, look into using Clang - // diagnostics. - llvm::errs() << "Failed to open file: " << Path << " " << EC.message() - << '\n'; + unsigned ID = CDCtx.Diags.getCustomDiagID(DiagnosticsEngine::Warning, + "Failed to open file: %0 %1"); + CDCtx.Diags.Report(ID) << Path << EC.message(); + JSONIter.increment(EC); + continue; } auto Parsed = json::parse((*File)->getBuffer()); diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index c09f908c7eb22..d33b77feb84be 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -15,6 +15,7 @@ #include "Generators.h" #include "Representation.h" #include "support/File.h" +#include "clang/Basic/Diagnostic.h" #include "llvm/Support/Error.h" #include "llvm/Support/Path.h" diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp index 497b80cf97463..24e798af52e62 100644 --- a/clang-tools-extra/clang-doc/Mapper.cpp +++ b/clang-tools-extra/clang-doc/Mapper.cpp @@ -95,10 +95,10 @@ bool MapASTVisitor::mapDecl(const T *D, bool IsDefinition) { // this decl for some reason (e.g. we're only reporting public decls). if (Child) CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(Child->USR)), - serialize::serialize(Child)); + serialize::serialize(Child, CDCtx.Diags)); if (Parent) CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(Parent->USR)), - serialize::serialize(Parent)); + serialize::serialize(Parent, CDCtx.Diags)); } return true; } diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index 929112f01fb43..ffa0eaa5a0a38 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -481,10 +481,11 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx, StringRef RepositoryUrl, StringRef RepositoryLinePrefix, StringRef Base, std::vector<std::string> UserStylesheets, + clang::DiagnosticsEngine &Diags, bool FTimeTrace) - : ECtx(ECtx), ProjectName(ProjectName), PublicOnly(PublicOnly), - FTimeTrace(FTimeTrace), OutDirectory(OutDirectory), - UserStylesheets(UserStylesheets), Base(Base) { + : ECtx(ECtx), ProjectName(ProjectName), OutDirectory(OutDirectory), + SourceRoot(std::string(SourceRoot)), UserStylesheets(UserStylesheets), + Base(Base), Diags(Diags), PublicOnly(PublicOnly), FTimeTrace(FTimeTrace) { llvm::SmallString<128> SourceRootDir(SourceRoot); if (SourceRoot.empty()) // If no SourceRoot was provided the current path is used as the default diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 1ae067f736476..8eba7e82c7aed 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H #include "clang/AST/Type.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/Specifiers.h" #include "clang/Tooling/Execution.h" #include "llvm/ADT/SmallVector.h" @@ -598,17 +599,13 @@ llvm::Expected<std::unique_ptr<Info>> mergeInfos(std::vector<std::unique_ptr<Info>> &Values); struct ClangDocContext { - ClangDocContext() = default; ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName, bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot, StringRef RepositoryUrl, StringRef RepositoryCodeLinePrefix, StringRef Base, std::vector<std::string> UserStylesheets, - bool FTimeTrace = false); + clang::DiagnosticsEngine &Diags, bool FTimeTrace = false); tooling::ExecutionContext *ECtx; - std::string ProjectName; // Name of project clang-doc is documenting. - bool PublicOnly; // Indicates if only public declarations are documented. - bool FTimeTrace; // Indicates if ftime trace is turned on - int Granularity; // Granularity of ftime trace + std::string ProjectName; // Name of project clang-doc is documenting. std::string OutDirectory; // Directory for outputting generated files. std::string SourceRoot; // Directory where processed files are stored. Links // to definition locations will only be generated if @@ -627,7 +624,12 @@ struct ClangDocContext { // Maps mustache template types to specific mustache template files. // Ex. comment-template -> /path/to/comment-template.mustache llvm::StringMap<std::string> MustacheTemplates; + // A pointer to a DiagnosticsEngine for error reporting. + clang::DiagnosticsEngine &Diags; Index Idx; + int Granularity; // Granularity of ftime trace + bool PublicOnly; // Indicates if only public declarations are documented. + bool FTimeTrace; // Indicates if ftime trace is turned on }; } // namespace doc diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index e1d60570da4ca..29f8faf94713d 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -337,28 +337,29 @@ static std::string getSourceCode(const Decl *D, const SourceRange &R) { .str(); } -template <typename T> static std::string serialize(T &I) { +template <typename T> +static std::string serialize(T &I, DiagnosticsEngine &Diags) { SmallString<2048> Buffer; llvm::BitstreamWriter Stream(Buffer); - ClangDocBitcodeWriter Writer(Stream); + ClangDocBitcodeWriter Writer(Stream, Diags); Writer.emitBlock(I); return Buffer.str().str(); } -std::string serialize(std::unique_ptr<Info> &I) { +std::string serialize(std::unique_ptr<Info> &I, DiagnosticsEngine &Diags) { switch (I->IT) { case InfoType::IT_namespace: - return serialize(*static_cast<NamespaceInfo *>(I.get())); + return serialize(*static_cast<NamespaceInfo *>(I.get()), Diags); case InfoType::IT_record: - return serialize(*static_cast<RecordInfo *>(I.get())); + return serialize(*static_cast<RecordInfo *>(I.get()), Diags); case InfoType::IT_enum: - return serialize(*static_cast<EnumInfo *>(I.get())); + return serialize(*static_cast<EnumInfo *>(I.get()), Diags); case InfoType::IT_function: - return serialize(*static_cast<FunctionInfo *>(I.get())); + return serialize(*static_cast<FunctionInfo *>(I.get()), Diags); case InfoType::IT_concept: - return serialize(*static_cast<ConceptInfo *>(I.get())); + return serialize(*static_cast<ConceptInfo *>(I.get()), Diags); case InfoType::IT_variable: - return serialize(*static_cast<VarInfo *>(I.get())); + return serialize(*static_cast<VarInfo *>(I.get()), Diags); case InfoType::IT_friend: case InfoType::IT_typedef: case InfoType::IT_default: diff --git a/clang-tools-extra/clang-doc/Serialize.h b/clang-tools-extra/clang-doc/Serialize.h index 30ed836d57de3..cfba5c987c237 100644 --- a/clang-tools-extra/clang-doc/Serialize.h +++ b/clang-tools-extra/clang-doc/Serialize.h @@ -80,7 +80,7 @@ emitInfo(const VarDecl *D, const FullComment *FC, const Location &Loc, // memory (vs storing USRs directly). SymbolID hashUSR(llvm::StringRef USR); -std::string serialize(std::unique_ptr<Info> &I); +std::string serialize(std::unique_ptr<Info> &I, DiagnosticsEngine &Diags); } // namespace serialize } // namespace doc diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 62fa6a17df2ee..d8469bdc69818 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -22,6 +22,9 @@ #include "Generators.h" #include "Representation.h" #include "support/Utils.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Tooling/AllTUsExecution.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Execution.h" @@ -206,9 +209,12 @@ static llvm::Error getDefaultAssetFiles(const char *Argv0, static llvm::Error getHtmlAssetFiles(const char *Argv0, clang::doc::ClangDocContext &CDCtx) { if (!UserAssetPath.empty() && - !llvm::sys::fs::is_directory(std::string(UserAssetPath))) - llvm::outs() << "Asset path supply is not a directory: " << UserAssetPath - << " falling back to default\n"; + !llvm::sys::fs::is_directory(std::string(UserAssetPath))) { + unsigned ID = CDCtx.Diags.getCustomDiagID( + DiagnosticsEngine::Warning, + "Asset path supply is not a directory: %0 falling back to default"); + CDCtx.Diags.Report(ID) << UserAssetPath; + } if (llvm::sys::fs::is_directory(std::string(UserAssetPath))) return getAssetFiles(CDCtx); return getDefaultAssetFiles(Argv0, CDCtx); @@ -217,9 +223,12 @@ static llvm::Error getHtmlAssetFiles(const char *Argv0, static llvm::Error getMustacheHtmlFiles(const char *Argv0, clang::doc::ClangDocContext &CDCtx) { bool IsDir = llvm::sys::fs::is_directory(UserAssetPath); - if (!UserAssetPath.empty() && !IsDir) - llvm::outs() << "Asset path supply is not a directory: " << UserAssetPath - << " falling back to default\n"; + if (!UserAssetPath.empty() && !IsDir) { + unsigned ID = CDCtx.Diags.getCustomDiagID( + DiagnosticsEngine::Note, + "Asset path supply is not a directory: %0 falling back to default"); + CDCtx.Diags.Report(ID) << UserAssetPath; + } if (IsDir) { getMustacheHtmlFiles(UserAssetPath, CDCtx); return llvm::Error::success(); @@ -255,13 +264,16 @@ sortUsrToInfo(llvm::StringMap<std::unique_ptr<doc::Info>> &USRToInfo) { } } -static llvm::Error handleMappingFailures(llvm::Error Err) { +static llvm::Error handleMappingFailures(DiagnosticsEngine &Diags, + llvm::Error Err) { if (!Err) return llvm::Error::success(); if (IgnoreMappingFailures) { - llvm::errs() << "Error mapping decls in files. Clang-doc will ignore these " - "files and continue:\n" - << toString(std::move(Err)) << "\n"; + unsigned ID = Diags.getCustomDiagID( + DiagnosticsEngine::Warning, + "Error mapping decls in files. Clang-doc will ignore these files and " + "continue:\n%0"); + Diags.Report(ID) << toString(std::move(Err)); return llvm::Error::success(); } return Err; @@ -313,17 +325,16 @@ Example usage for a project using a compile commands database: tooling::ArgumentInsertPosition::END), ArgAdjuster); - clang::doc::ClangDocContext CDCtx = { - Executor->getExecutionContext(), - ProjectName, - PublicOnly, - OutDirectory, - SourceRoot, - RepositoryUrl, - RepositoryCodeLinePrefix, - BaseDirectory, - {UserStylesheets.begin(), UserStylesheets.end()}, - FTimeTrace}; + auto DiagOpts = std::make_unique<DiagnosticOptions>(); + TextDiagnosticPrinter *DiagClient = + new TextDiagnosticPrinter(llvm::errs(), *DiagOpts); + IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); + DiagnosticsEngine Diags(DiagID, *DiagOpts, DiagClient); + + clang::doc::ClangDocContext CDCtx( + Executor->getExecutionContext(), ProjectName, PublicOnly, OutDirectory, + SourceRoot, RepositoryUrl, RepositoryCodeLinePrefix, BaseDirectory, + {UserStylesheets.begin(), UserStylesheets.end()}, Diags, FTimeTrace); if (Format == "html") { ExitOnErr(getHtmlAssetFiles(argv[0], CDCtx)); @@ -335,6 +346,7 @@ Example usage for a project using a compile commands database: // Mapping phase llvm::outs() << "Mapping decls...\n"; ExitOnErr(handleMappingFailures( + Diags, Executor->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster))); llvm::timeTraceProfilerEnd(); @@ -360,13 +372,18 @@ Example usage for a project using a compile commands database: std::atomic<bool> Error; Error = false; llvm::sys::Mutex IndexMutex; + llvm::sys::Mutex DiagMutex; + unsigned DiagIDBitcodeReading = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "error reading bitcode: %0"); + unsigned DiagIDBitcodeMerging = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "error merging bitcode: %0"); // ExecutorConcurrency is a flag exposed by AllTUsExecution.h llvm::DefaultThreadPool Pool( llvm::hardware_concurrency(ExecutorConcurrency)); { llvm::TimeTraceScope TS("Reduce"); for (auto &Group : USRToBitcode) { - Pool.async([&]() { // time trace decoding bitcode + Pool.async([&, &Diags = Diags]() { // time trace decoding bitcode if (FTimeTrace) llvm::timeTraceProfilerInitialize(200, "clang-doc"); @@ -375,10 +392,13 @@ Example usage for a project using a compile commands database: llvm::TimeTraceScope Red("decoding bitcode"); for (auto &Bitcode : Group.getValue()) { llvm::BitstreamCursor Stream(Bitcode); - doc::ClangDocBitcodeReader Reader(Stream); + doc::ClangDocBitcodeReader Reader(Stream, Diags); auto ReadInfos = Reader.readBitcode(); if (!ReadInfos) { - llvm::errs() << toString(ReadInfos.takeError()) << "\n"; + std::lock_guard<llvm::sys::Mutex> Guard(DiagMutex); + + Diags.Report(DiagIDBitcodeReading) + << toString(ReadInfos.takeError()); Error = true; return; } @@ -394,7 +414,9 @@ Example usage for a project using a compile commands database: auto ExpReduced = doc::mergeInfos(Infos); if (!ExpReduced) { - llvm::errs() << llvm::toString(ExpReduced.takeError()); + std::lock_guard<llvm::sys::Mutex> Guard(DiagMutex); + Diags.Report(DiagIDBitcodeMerging) + << toString(ExpReduced.takeError()); return; } Reduced = std::move(*ExpReduced); diff --git a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp index d88b0c91bb9a9..918c7b3eca879 100644 --- a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp @@ -10,6 +10,8 @@ #include "BitcodeWriter.h" #include "ClangDocTest.h" #include "Representation.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" #include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Bitstream/BitstreamWriter.h" #include "gtest/gtest.h" @@ -17,41 +19,42 @@ namespace clang { namespace doc { -template <typename T> static std::string writeInfo(T &I) { +template <typename T> +static std::string writeInfo(T &I, DiagnosticsEngine &Diags) { SmallString<2048> Buffer; llvm::BitstreamWriter Stream(Buffer); - ClangDocBitcodeWriter Writer(Stream); + ClangDocBitcodeWriter Writer(Stream, Diags); Writer.emitBlock(I); return Buffer.str().str(); } -static std::string writeInfo(Info *I) { +static std::string writeInfo(Info *I, DiagnosticsEngine &Diags) { switch (I->IT) { case InfoType::IT_namespace: - return writeInfo(*static_cast<NamespaceInfo *>(I)); + return writeInfo(*static_cast<NamespaceInfo *>(I), Diags); case InfoType::IT_record: - return writeInfo(*static_cast<RecordInfo *>(I)); + return writeInfo(*static_cast<RecordInfo *>(I), Diags); case InfoType::IT_enum: - return writeInfo(*static_cast<EnumInfo *>(I)); + return writeInfo(*static_cast<EnumInfo *>(I), Diags); case InfoType::IT_function: - return writeInfo(*static_cast<FunctionInfo *>(I)); + return writeInfo(*static_cast<FunctionInfo *>(I), Diags); case InfoType::IT_typedef: - return writeInfo(*static_cast<TypedefInfo *>(I)); + return writeInfo(*static_cast<TypedefInfo *>(I), Diags); case InfoType::IT_concept: - return writeInfo(*static_cast<ConceptInfo *>(I)); + return writeInfo(*static_cast<ConceptInfo *>(I), Diags); case InfoType::IT_variable: - return writeInfo(*static_cast<VarInfo *>(I)); + return writeInfo(*static_cast<VarInfo *>(I), Diags); case InfoType::IT_friend: - return writeInfo(*static_cast<FriendInfo *>(I)); + return writeInfo(*static_cast<FriendInfo *>(I), Diags); case InfoType::IT_default: return ""; } } -static std::vector<std::unique_ptr<Info>> readInfo(StringRef Bitcode, - size_t NumInfos) { +static std::vector<std::unique_ptr<Info>> +readInfo(StringRef Bitcode, size_t NumInfos, DiagnosticsEngine &Diags) { llvm::BitstreamCursor Stream(Bitcode); - doc::ClangDocBitcodeReader Reader(Stream); + doc::ClangDocBitcodeReader Reader(Stream, Diags); auto Infos = Reader.readBitcode(); // Check that there was no error in the read. @@ -60,7 +63,9 @@ static std::vector<std::unique_ptr<Info>> readInfo(StringRef Bitcode, return std::move(Infos.get()); } -TEST(BitcodeTest, emitNamespaceInfoBitcode) { +class BitcodeTest : public ClangDocContextTest {}; + +TEST_F(BitcodeTest, emitNamespaceInfoBitcode) { NamespaceInfo I; I.Name = "r"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -71,14 +76,15 @@ TEST(BitcodeTest, emitNamespaceInfoBitcode) { I.Children.Functions.emplace_back(); I.Children.Enums.emplace_back(); - std::string WriteResult = writeInfo(&I); + std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); - std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); + std::vector<std::unique_ptr<Info>> ReadResults = + readInfo(WriteResult, 1, this->Diags); CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0].get())); } -TEST(BitcodeTest, emitRecordInfoBitcode) { +TEST_F(BitcodeTest, emitRecordInfoBitcode) { RecordInfo I; I.Name = "r"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -113,14 +119,15 @@ TEST(BitcodeTest, emitRecordInfoBitcode) { I.Children.Functions.emplace_back(); I.Children.Enums.emplace_back(); - std::string WriteResult = writeInfo(&I); + std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); - std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); + std::vector<std::unique_ptr<Info>> ReadResults = + readInfo(WriteResult, 1, this->Diags); CheckRecordInfo(&I, InfoAsRecord(ReadResults[0].get())); } -TEST(BitcodeTest, emitFunctionInfoBitcode) { +TEST_F(BitcodeTest, emitFunctionInfoBitcode) { FunctionInfo I; I.Name = "f"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -133,14 +140,15 @@ TEST(BitcodeTest, emitFunctionInfoBitcode) { I.Access = AccessSpecifier::AS_none; - std::string WriteResult = writeInfo(&I); + std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); - std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); + std::vector<std::unique_ptr<Info>> ReadResults = + readInfo(WriteResult, 1, this->Diags); CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get())); } -TEST(BitcodeTest, emitMethodInfoBitcode) { +TEST_F(BitcodeTest, emitMethodInfoBitcode) { FunctionInfo I; I.Name = "f"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -155,14 +163,15 @@ TEST(BitcodeTest, emitMethodInfoBitcode) { I.Access = AccessSpecifier::AS_public; - std::string WriteResult = writeInfo(&I); + std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); - std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); + std::vector<std::unique_ptr<Info>> ReadResults = + readInfo(WriteResult, 1, this->Diags); CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get())); } -TEST(BitcodeTest, emitEnumInfoBitcode) { +TEST_F(BitcodeTest, emitEnumInfoBitcode) { EnumInfo I; I.Name = "e"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -173,14 +182,15 @@ TEST(BitcodeTest, emitEnumInfoBitcode) { I.Members.emplace_back("X"); I.Scoped = true; - std::string WriteResult = writeInfo(&I); + std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); - std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); + std::vector<std::unique_ptr<Info>> ReadResults = + readInfo(WriteResult, 1, this->Diags); CheckEnumInfo(&I, InfoAsEnum(ReadResults[0].get())); } -TEST(BitcodeTest, emitTypedefInfoBitcode) { +TEST_F(BitcodeTest, emitTypedefInfoBitcode) { TypedefInfo I; I.Name = "MyInt"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -200,9 +210,10 @@ TEST(BitcodeTest, emitTypedefInfoBitcode) { I.Description.emplace_back(std::move(Top)); - std::string WriteResult = writeInfo(&I); + std::string WriteResult = writeInfo(&I, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); - std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); + std::vector<std::unique_ptr<Info>> ReadResults = + readInfo(WriteResult, 1, this->Diags); CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0].get())); @@ -212,13 +223,13 @@ TEST(BitcodeTest, emitTypedefInfoBitcode) { I2.IsUsing = false; I2.Underlying = TypeInfo("int"); - WriteResult = writeInfo(&I2); + WriteResult = writeInfo(&I2, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); - ReadResults = readInfo(WriteResult, 1); + ReadResults = readInfo(WriteResult, 1, this->Diags); CheckTypedefInfo(&I2, InfoAsTypedef(ReadResults[0].get())); } -TEST(SerializeTest, emitInfoWithCommentBitcode) { +TEST_F(BitcodeTest, emitInfoWithCommentBitcode) { FunctionInfo F; F.Name = "F"; F.ReturnType = TypeInfo("void"); @@ -329,9 +340,10 @@ TEST(SerializeTest, emitInfoWithCommentBitcode) { F.Description.emplace_back(std::move(Top)); - std::string WriteResult = writeInfo(&F); + std::string WriteResult = writeInfo(&F, this->Diags); EXPECT_TRUE(WriteResult.size() > 0); - std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); + std::vector<std::unique_ptr<Info>> ReadResults = + readInfo(WriteResult, 1, this->Diags); CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0].get())); } diff --git a/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp b/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp index f408c91077f6b..73891abd53f99 100644 --- a/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp @@ -9,11 +9,26 @@ #include "ClangDocTest.h" #include "Representation.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/DiagnosticOptions.h" #include "gtest/gtest.h" namespace clang { namespace doc { +ClangDocContextTest::ClangDocContextTest() + : DiagID(new DiagnosticIDs()), + Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()) {} + +ClangDocContextTest::~ClangDocContextTest() = default; + +ClangDocContext ClangDocContextTest::getClangDocContext( + std::vector<std::string> UserStylesheets, StringRef RepositoryUrl, + StringRef RepositoryLinePrefix, StringRef Base) { + return ClangDocContext(nullptr, "test-project", false, "", "", RepositoryUrl, + RepositoryLinePrefix, Base, UserStylesheets, Diags, + false); +} + NamespaceInfo *InfoAsNamespace(Info *I) { assert(I->IT == InfoType::IT_namespace); return static_cast<NamespaceInfo *>(I); diff --git a/clang-tools-extra/unittests/clang-doc/ClangDocTest.h b/clang-tools-extra/unittests/clang-doc/ClangDocTest.h index 2e189caa48650..2875cf1cb2d6a 100644 --- a/clang-tools-extra/unittests/clang-doc/ClangDocTest.h +++ b/clang-tools-extra/unittests/clang-doc/ClangDocTest.h @@ -12,6 +12,8 @@ #include "ClangDocTest.h" #include "Representation.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" #include "gtest/gtest.h" namespace clang { @@ -49,6 +51,21 @@ void CheckBaseRecordInfo(BaseRecordInfo *Expected, BaseRecordInfo *Actual); void CheckIndex(Index &Expected, Index &Actual); +class ClangDocContextTest : public ::testing::Test { +protected: + ClangDocContextTest(); + ~ClangDocContextTest() override; + + ClangDocContext + getClangDocContext(std::vector<std::string> UserStylesheets = {}, + StringRef RepositoryUrl = "", + StringRef RepositoryLinePrefix = "", StringRef Base = ""); + + DiagnosticOptions DiagOpts; + llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID; + DiagnosticsEngine Diags; +}; + } // namespace doc } // namespace clang diff --git a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp index 143414354d36c..2fe443d9db5c5 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp @@ -25,21 +25,32 @@ static std::unique_ptr<Generator> getHTMLGenerator() { return std::move(G.get()); } -static ClangDocContext -getClangDocContext(std::vector<std::string> UserStylesheets = {}, - StringRef RepositoryUrl = "", - StringRef RepositoryLinePrefix = "", StringRef Base = "") { - ClangDocContext CDCtx{ - {}, "test-project", {}, {}, {}, RepositoryUrl, RepositoryLinePrefix, - Base, UserStylesheets}; - CDCtx.UserStylesheets.insert( - CDCtx.UserStylesheets.begin(), - "../share/clang/clang-doc-default-stylesheet.css"); - CDCtx.JsScripts.emplace_back("index.js"); - return CDCtx; -} - -TEST(HTMLGeneratorTest, emitNamespaceHTML) { +class HTMLGeneratorTest : public ClangDocContextTest { +protected: + ClangDocContext + getClangDocContext(std::vector<std::string> UserStylesheets = {}, + StringRef RepositoryUrl = "", + StringRef RepositoryLinePrefix = "", StringRef Base = "") { + ClangDocContext CDCtx{nullptr, + "test-project", + false, + "", + "", + RepositoryUrl, + RepositoryLinePrefix, + Base, + UserStylesheets, + Diags, + false}; + CDCtx.UserStylesheets.insert( + CDCtx.UserStylesheets.begin(), + "../share/clang/clang-doc-default-stylesheet.css"); + CDCtx.JsScripts.emplace_back("index.js"); + return CDCtx; + } +}; + +TEST_F(HTMLGeneratorTest, emitNamespaceHTML) { NamespaceInfo I; I.Name = "Namespace"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -150,7 +161,7 @@ TEST(HTMLGeneratorTest, emitNamespaceHTML) { EXPECT_EQ(Expected, Actual.str()); } -TEST(HTMLGeneratorTest, emitRecordHTML) { +TEST_F(HTMLGeneratorTest, emitRecordHTML) { RecordInfo I; I.Name = "r"; I.Path = "X/Y/Z"; @@ -278,7 +289,7 @@ TEST(HTMLGeneratorTest, emitRecordHTML) { EXPECT_EQ(Expected, Actual.str()); } -TEST(HTMLGeneratorTest, emitFunctionHTML) { +TEST_F(HTMLGeneratorTest, emitFunctionHTML) { FunctionInfo I; I.Name = "f"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -338,7 +349,7 @@ TEST(HTMLGeneratorTest, emitFunctionHTML) { EXPECT_EQ(Expected, Actual.str()); } -TEST(HTMLGeneratorTest, emitEnumHTML) { +TEST_F(HTMLGeneratorTest, emitEnumHTML) { EnumInfo I; I.Name = "e"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -397,7 +408,7 @@ TEST(HTMLGeneratorTest, emitEnumHTML) { EXPECT_EQ(Expected, Actual.str()); } -TEST(HTMLGeneratorTest, emitCommentHTML) { +TEST_F(HTMLGeneratorTest, emitCommentHTML) { FunctionInfo I; I.Name = "f"; I.DefLoc = Location(10, 10, "test.cpp", true); diff --git a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp index c7ac387ecf7c3..7bbd299d7b59c 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp @@ -34,19 +34,30 @@ static std::unique_ptr<Generator> getHTMLMustacheGenerator() { return std::move(G.get()); } -static ClangDocContext -getClangDocContext(std::vector<std::string> UserStylesheets = {}, - StringRef RepositoryUrl = "", - StringRef RepositoryLinePrefix = "", StringRef Base = "") { - ClangDocContext CDCtx{ - {}, "test-project", {}, {}, {}, RepositoryUrl, RepositoryLinePrefix, - Base, UserStylesheets}; - CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(), ""); - CDCtx.JsScripts.emplace_back(""); - return CDCtx; -} +class HTMLMustacheGeneratorTest : public ClangDocContextTest { +protected: + ClangDocContext + getClangDocContext(std::vector<std::string> UserStylesheets = {}, + StringRef RepositoryUrl = "", + StringRef RepositoryLinePrefix = "", StringRef Base = "") { + ClangDocContext CDCtx{nullptr, + "test-project", + false, + "", + "", + RepositoryUrl, + RepositoryLinePrefix, + Base, + UserStylesheets, + Diags, + false}; + CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(), ""); + CDCtx.JsScripts.emplace_back(""); + return CDCtx; + } +}; -TEST(HTMLMustacheGeneratorTest, createResources) { +TEST_F(HTMLMustacheGeneratorTest, createResources) { auto G = getHTMLMustacheGenerator(); ASSERT_THAT(G, NotNull()) << "Could not find HTMLMustacheGenerator"; ClangDocContext CDCtx = getClangDocContext(); diff --git a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp index 2706a5145ebfd..bd437553961f6 100644 --- a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp @@ -13,7 +13,9 @@ static std::unique_ptr<Generator> getJSONGenerator() { return std::move(G.get()); } -TEST(JSONGeneratorTest, emitRecordJSON) { +class JSONGeneratorTest : public ClangDocContextTest {}; + +TEST_F(JSONGeneratorTest, emitRecordJSON) { RecordInfo I; I.Name = "Foo"; I.IsTypeDef = false; @@ -55,7 +57,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw({ "Bases": [ @@ -186,7 +188,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) { EXPECT_EQ(Expected, Actual.str()); } -TEST(JSONGeneratorTest, emitNamespaceJSON) { +TEST_F(JSONGeneratorTest, emitNamespaceJSON) { NamespaceInfo I; I.Name = "Namespace"; I.Path = "path/to/A"; @@ -208,7 +210,7 @@ TEST(JSONGeneratorTest, emitNamespaceJSON) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw({ "Enums": [ diff --git a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp index f4c69cf868a1f..b44b09b28e90f 100644 --- a/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp @@ -21,7 +21,9 @@ static std::unique_ptr<Generator> getMDGenerator() { return std::move(G.get()); } -TEST(MDGeneratorTest, emitNamespaceMD) { +class MDGeneratorTest : public ClangDocContextTest {}; + +TEST_F(MDGeneratorTest, emitNamespaceMD) { NamespaceInfo I; I.Name = "Namespace"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -39,7 +41,7 @@ TEST(MDGeneratorTest, emitNamespaceMD) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(# namespace Namespace @@ -77,7 +79,7 @@ TEST(MDGeneratorTest, emitNamespaceMD) { EXPECT_EQ(Expected, Actual.str()); } -TEST(MDGeneratorTest, emitRecordMD) { +TEST_F(MDGeneratorTest, emitRecordMD) { RecordInfo I; I.Name = "r"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -100,7 +102,7 @@ TEST(MDGeneratorTest, emitRecordMD) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(# class r @@ -144,7 +146,7 @@ ChildStruct EXPECT_EQ(Expected, Actual.str()); } -TEST(MDGeneratorTest, emitFunctionMD) { +TEST_F(MDGeneratorTest, emitFunctionMD) { FunctionInfo I; I.Name = "f"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -163,7 +165,7 @@ TEST(MDGeneratorTest, emitFunctionMD) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(### f @@ -176,7 +178,7 @@ TEST(MDGeneratorTest, emitFunctionMD) { EXPECT_EQ(Expected, Actual.str()); } -TEST(MDGeneratorTest, emitEnumMD) { +TEST_F(MDGeneratorTest, emitEnumMD) { EnumInfo I; I.Name = "e"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -191,7 +193,7 @@ TEST(MDGeneratorTest, emitEnumMD) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(| enum class e | @@ -207,7 +209,7 @@ TEST(MDGeneratorTest, emitEnumMD) { EXPECT_EQ(Expected, Actual.str()); } -TEST(MDGeneratorTest, emitCommentMD) { +TEST_F(MDGeneratorTest, emitCommentMD) { FunctionInfo I; I.Name = "f"; @@ -325,7 +327,7 @@ TEST(MDGeneratorTest, emitCommentMD) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(### f diff --git a/clang-tools-extra/unittests/clang-doc/MergeTest.cpp b/clang-tools-extra/unittests/clang-doc/MergeTest.cpp index ade744e58ab0d..6bffd98d3e4e8 100644 --- a/clang-tools-extra/unittests/clang-doc/MergeTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/MergeTest.cpp @@ -13,7 +13,9 @@ namespace clang { namespace doc { -TEST(MergeTest, mergeNamespaceInfos) { +class MergeTest : public ClangDocContextTest {}; + +TEST_F(MergeTest, mergeNamespaceInfos) { NamespaceInfo One; One.Name = "Namespace"; One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -75,7 +77,7 @@ TEST(MergeTest, mergeNamespaceInfos) { InfoAsNamespace(Actual.get().get())); } -TEST(MergeTest, mergeRecordInfos) { +TEST_F(MergeTest, mergeRecordInfos) { RecordInfo One; One.Name = "r"; One.IsTypeDef = true; @@ -153,7 +155,7 @@ TEST(MergeTest, mergeRecordInfos) { InfoAsRecord(Actual.get().get())); } -TEST(MergeTest, mergeFunctionInfos) { +TEST_F(MergeTest, mergeFunctionInfos) { FunctionInfo One; One.Name = "f"; One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -228,7 +230,7 @@ TEST(MergeTest, mergeFunctionInfos) { InfoAsFunction(Actual.get().get())); } -TEST(MergeTest, mergeEnumInfos) { +TEST_F(MergeTest, mergeEnumInfos) { EnumInfo One; One.Name = "e"; One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); diff --git a/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp b/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp index 6d5e7da689c5c..f59ea02f9e1a3 100644 --- a/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/SerializeTest.cpp @@ -16,6 +16,8 @@ namespace clang { namespace doc { +class SerializeTest : public ClangDocContextTest {}; + class ClangDocSerializeTestVisitor : public RecursiveASTVisitor<ClangDocSerializeTestVisitor> { @@ -32,7 +34,8 @@ class ClangDocSerializeTestVisitor } public: - ClangDocSerializeTestVisitor(EmittedInfoList &EmittedInfos, bool Public) + ClangDocSerializeTestVisitor(EmittedInfoList &EmittedInfos, bool Public, + DiagnosticsEngine &Diags) : EmittedInfos(EmittedInfos), Public(Public) {} template <typename T> bool mapDecl(const T *D) { @@ -49,7 +52,7 @@ class ClangDocSerializeTestVisitor bool VisitFunctionDecl(const FunctionDecl *D) { // Don't visit CXXMethodDecls twice - if (dyn_cast<CXXMethodDecl>(D)) + if (isa<CXXMethodDecl>(D)) return true; return mapDecl(D); } @@ -65,21 +68,24 @@ class ClangDocSerializeTestVisitor bool VisitTypeAliasDecl(const TypeAliasDecl *D) { return mapDecl(D); } }; -void ExtractInfosFromCode(StringRef Code, size_t NumExpectedInfos, bool Public, - EmittedInfoList &EmittedInfos) { +static void extractInfosFromCode(StringRef Code, size_t NumExpectedInfos, + bool Public, EmittedInfoList &EmittedInfos, + DiagnosticsEngine &Diags) { auto ASTUnit = clang::tooling::buildASTFromCode(Code); - auto TU = ASTUnit->getASTContext().getTranslationUnitDecl(); - ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public); + TranslationUnitDecl *TU = ASTUnit->getASTContext().getTranslationUnitDecl(); + ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public, Diags); Visitor.TraverseTranslationUnitDecl(TU); ASSERT_EQ(NumExpectedInfos, EmittedInfos.size()); } -void ExtractInfosFromCodeWithArgs(StringRef Code, size_t NumExpectedInfos, - bool Public, EmittedInfoList &EmittedInfos, - std::vector<std::string> &Args) { +static void extractInfosFromCodeWithArgs(StringRef Code, + size_t NumExpectedInfos, bool Public, + EmittedInfoList &EmittedInfos, + std::vector<std::string> &Args, + DiagnosticsEngine &Diags) { auto ASTUnit = clang::tooling::buildASTFromCodeWithArgs(Code, Args); - auto TU = ASTUnit->getASTContext().getTranslationUnitDecl(); - ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public); + TranslationUnitDecl *TU = ASTUnit->getASTContext().getTranslationUnitDecl(); + ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public, Diags); Visitor.TraverseTranslationUnitDecl(TU); ASSERT_EQ(NumExpectedInfos, EmittedInfos.size()); } @@ -105,10 +111,10 @@ CommentInfo MakeOneLineCommentInfo(const std::string &Text) { */ // Test serialization of namespace declarations. -TEST(SerializeTest, emitNamespaceInfo) { +TEST_F(SerializeTest, emitNamespaceInfo) { EmittedInfoList Infos; - ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 5, - /*Public=*/false, Infos); + extractInfosFromCode("namespace A { namespace B { void f() {} } }", 5, + /*Public=*/false, Infos, this->Diags); NamespaceInfo *A = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedA(EmptySID, "A"); @@ -132,9 +138,10 @@ TEST(SerializeTest, emitNamespaceInfo) { CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); } -TEST(SerializeTest, emitAnonymousNamespaceInfo) { +TEST_F(SerializeTest, emitAnonymousNamespaceInfo) { EmittedInfoList Infos; - ExtractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos); + extractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos, + this->Diags); NamespaceInfo *A = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedA(EmptySID); @@ -142,10 +149,9 @@ TEST(SerializeTest, emitAnonymousNamespaceInfo) { CheckNamespaceInfo(&ExpectedA, A); } -// Test serialization of record declarations. -TEST(SerializeTest, emitRecordInfo) { +TEST_F(SerializeTest, emitRecordInfo) { EmittedInfoList Infos; - ExtractInfosFromCode(R"raw(class E { + extractInfosFromCode(R"raw(class E { public: E() {} @@ -161,7 +167,7 @@ struct F { template <> void F<int>::TemplateMethod(); typedef struct {} G;)raw", - 10, /*Public=*/false, Infos); + 10, /*Public=*/false, Infos, this->Diags); RecordInfo *E = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); @@ -259,10 +265,10 @@ typedef struct {} G;)raw", } // Test serialization of enum declarations. -TEST(SerializeTest, emitEnumInfo) { +TEST_F(SerializeTest, emitEnumInfo) { EmittedInfoList Infos; - ExtractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2, - /*Public=*/false, Infos); + extractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2, + /*Public=*/false, Infos, this->Diags); NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedNamespaceWithEnum(EmptySID); @@ -286,9 +292,9 @@ TEST(SerializeTest, emitEnumInfo) { CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum); } -TEST(SerializeTest, emitUndefinedRecordInfo) { +TEST_F(SerializeTest, emitUndefinedRecordInfo) { EmittedInfoList Infos; - ExtractInfosFromCode("class E;", 2, /*Public=*/false, Infos); + extractInfosFromCode("class E;", 2, /*Public=*/false, Infos, this->Diags); RecordInfo *E = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); @@ -299,9 +305,10 @@ TEST(SerializeTest, emitUndefinedRecordInfo) { CheckRecordInfo(&ExpectedE, E); } -TEST(SerializeTest, emitRecordMemberInfo) { +TEST_F(SerializeTest, emitRecordMemberInfo) { EmittedInfoList Infos; - ExtractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos); + extractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos, + this->Diags); RecordInfo *E = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); @@ -314,9 +321,10 @@ TEST(SerializeTest, emitRecordMemberInfo) { CheckRecordInfo(&ExpectedE, E); } -TEST(SerializeTest, emitInternalRecordInfo) { +TEST_F(SerializeTest, emitInternalRecordInfo) { EmittedInfoList Infos; - ExtractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos); + extractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos, + this->Diags); RecordInfo *E = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace"); @@ -338,15 +346,16 @@ TEST(SerializeTest, emitInternalRecordInfo) { CheckRecordInfo(&ExpectedG, G); } -TEST(SerializeTest, emitPublicAnonymousNamespaceInfo) { +TEST_F(SerializeTest, emitPublicAnonymousNamespaceInfo) { EmittedInfoList Infos; - ExtractInfosFromCode("namespace { class A; }", 0, /*Public=*/true, Infos); + extractInfosFromCode("namespace { class A; }", 0, /*Public=*/true, Infos, + this->Diags); } -TEST(SerializeTest, emitPublicFunctionInternalInfo) { +TEST_F(SerializeTest, emitPublicFunctionInternalInfo) { EmittedInfoList Infos; - ExtractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true, - Infos); + extractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true, + Infos, this->Diags); NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedBWithFunction(EmptySID); @@ -359,9 +368,10 @@ TEST(SerializeTest, emitPublicFunctionInternalInfo) { CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); } -TEST(SerializeTest, emitInlinedFunctionInfo) { +TEST_F(SerializeTest, emitInlinedFunctionInfo) { EmittedInfoList Infos; - ExtractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos); + extractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos, + this->Diags); NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedBWithFunction(EmptySID); @@ -375,16 +385,16 @@ TEST(SerializeTest, emitInlinedFunctionInfo) { CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction); } -TEST(SerializeTest, emitInheritedRecordInfo) { +TEST_F(SerializeTest, emitInheritedRecordInfo) { EmittedInfoList Infos; - ExtractInfosFromCode(R"raw(class F { protected: void set(int N); }; + extractInfosFromCode(R"raw(class F { protected: void set(int N); }; class G { public: int get() { return 1; } protected: int I; }; class E : public F, virtual private G {}; class H : private E {}; template <typename T> class I {} ; class J : public I<int> {} ;)raw", - 14, /*Public=*/false, Infos); + 14, /*Public=*/false, Infos, this->Diags); RecordInfo *F = InfoAsRecord(Infos[0].get()); RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace"); @@ -517,15 +527,15 @@ class J : public I<int> {} ;)raw", CheckRecordInfo(&ExpectedJ, J); } -TEST(SerializeTest, emitModulePublicLFunctions) { +TEST_F(SerializeTest, emitModulePublicLFunctions) { EmittedInfoList Infos; std::vector<std::string> Args; Args.push_back("-fmodules-ts"); - ExtractInfosFromCodeWithArgs(R"raw(export module M; + extractInfosFromCodeWithArgs(R"raw(export module M; int moduleFunction(int x, double d = 3.2 - 1.0); static int staticModuleFunction(int x); export double exportedModuleFunction(double y);)raw", - 2, /*Public=*/true, Infos, Args); + 2, /*Public=*/true, Infos, Args, this->Diags); NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get()); NamespaceInfo ExpectedBWithFunction(EmptySID); @@ -555,10 +565,10 @@ export double exportedModuleFunction(double y);)raw", } // Test serialization of child records in namespaces and other records -TEST(SerializeTest, emitChildRecords) { +TEST_F(SerializeTest, emitChildRecords) { EmittedInfoList Infos; - ExtractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8, - /*Public=*/false, Infos); + extractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8, + /*Public=*/false, Infos, this->Diags); NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get()); NamespaceInfo ExpectedParentA(EmptySID); @@ -582,10 +592,10 @@ TEST(SerializeTest, emitChildRecords) { } // Test serialization of child namespaces -TEST(SerializeTest, emitChildNamespaces) { +TEST_F(SerializeTest, emitChildNamespaces) { EmittedInfoList Infos; - ExtractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false, - Infos); + extractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false, + Infos, this->Diags); NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get()); NamespaceInfo ExpectedParentA(EmptySID); @@ -600,10 +610,10 @@ TEST(SerializeTest, emitChildNamespaces) { CheckNamespaceInfo(&ExpectedParentB, ParentB); } -TEST(SerializeTests, emitTypedefs) { +TEST_F(SerializeTest, emitTypedefs) { EmittedInfoList Infos; - ExtractInfosFromCode("typedef int MyInt; using MyDouble = double;", 2, - /*Public=*/false, Infos); + extractInfosFromCode("typedef int MyInt; using MyDouble = double;", 2, + /*Public=*/false, Infos, this->Diags); // First info will be the global namespace with the typedef in it. NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get()); @@ -627,13 +637,13 @@ TEST(SerializeTests, emitTypedefs) { EXPECT_EQ("double", SecondTD.Underlying.Type.Name); } -TEST(SerializeTests, emitFunctionTemplate) { +TEST_F(SerializeTest, emitFunctionTemplate) { EmittedInfoList Infos; // A template and a specialization. - ExtractInfosFromCode("template<typename T = int> bool GetFoo(T);\n" + extractInfosFromCode("template<typename T = int> bool GetFoo(T);\n" "template<> bool GetFoo<bool>(bool);", 2, - /*Public=*/false, Infos); + /*Public=*/false, Infos, this->Diags); // First info will be the global namespace. NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get()); @@ -669,18 +679,18 @@ TEST(SerializeTests, emitFunctionTemplate) { EXPECT_EQ("bool", Func2.ReturnType.Type.Name); } -TEST(SerializeTests, emitClassTemplate) { +TEST_F(SerializeTest, emitClassTemplate) { EmittedInfoList Infos; // This will generate 2x the number of infos: each Record will be followed by // a copy of the global namespace containing it (this test checks the data // pre-merge). - ExtractInfosFromCode( + extractInfosFromCode( "template<int I> class MyTemplate { int i[I]; };\n" "template<> class MyTemplate<0> {};\n" "template<typename T, int U = 1> class OtherTemplate {};\n" "template<int U> class OtherTemplate<MyTemplate<0>, U> {};", 8, - /*Public=*/false, Infos); + /*Public=*/false, Infos, this->Diags); // First record. const RecordInfo *Rec1 = InfoAsRecord(Infos[0].get()); diff --git a/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp index a9e7c6413cf13..db62c9246ceb4 100644 --- a/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp @@ -22,7 +22,9 @@ static std::unique_ptr<Generator> getYAMLGenerator() { return std::move(G.get()); } -TEST(YAMLGeneratorTest, emitNamespaceYAML) { +class YAMLGeneratorTest : public ClangDocContextTest {}; + +TEST_F(YAMLGeneratorTest, emitNamespaceYAML) { NamespaceInfo I; I.Name = "Namespace"; I.Path = "path/to/A"; @@ -44,7 +46,7 @@ TEST(YAMLGeneratorTest, emitNamespaceYAML) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(--- @@ -77,7 +79,7 @@ Path: 'path/to/A' EXPECT_EQ(Expected, Actual.str()); } -TEST(YAMLGeneratorTest, emitRecordYAML) { +TEST_F(YAMLGeneratorTest, emitRecordYAML) { RecordInfo I; I.Name = "r"; I.Path = "path/to/A"; @@ -124,7 +126,7 @@ TEST(YAMLGeneratorTest, emitRecordYAML) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(--- @@ -202,7 +204,7 @@ IsTypeDef: true EXPECT_EQ(Expected, Actual.str()); } -TEST(YAMLGeneratorTest, emitFunctionYAML) { +TEST_F(YAMLGeneratorTest, emitFunctionYAML) { FunctionInfo I; I.Name = "f"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -223,7 +225,7 @@ TEST(YAMLGeneratorTest, emitFunctionYAML) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(--- @@ -267,7 +269,7 @@ IsMethod: true // namespace A { // enum e { X }; // } -TEST(YAMLGeneratorTest, emitSimpleEnumYAML) { +TEST_F(YAMLGeneratorTest, emitSimpleEnumYAML) { EnumInfo I; I.Name = "e"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); @@ -282,7 +284,7 @@ TEST(YAMLGeneratorTest, emitSimpleEnumYAML) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(--- @@ -308,7 +310,7 @@ Name: 'e' // Tests the equivalent of: // enum class e : short { X = FOO_BAR + 2 }; -TEST(YAMLGeneratorTest, enumTypedScopedEnumYAML) { +TEST_F(YAMLGeneratorTest, enumTypedScopedEnumYAML) { EnumInfo I; I.Name = "e"; @@ -320,7 +322,7 @@ TEST(YAMLGeneratorTest, enumTypedScopedEnumYAML) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(--- @@ -340,7 +342,7 @@ Scoped: true EXPECT_EQ(Expected, Actual.str()); } -TEST(YAMLGeneratorTest, enumTypedefYAML) { +TEST_F(YAMLGeneratorTest, enumTypedefYAML) { TypedefInfo I; I.Name = "MyUsing"; I.Underlying = TypeInfo("int"); @@ -350,7 +352,7 @@ TEST(YAMLGeneratorTest, enumTypedefYAML) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(--- @@ -365,7 +367,7 @@ IsUsing: true EXPECT_EQ(Expected, Actual.str()); } -TEST(YAMLGeneratorTest, emitCommentYAML) { +TEST_F(YAMLGeneratorTest, emitCommentYAML) { FunctionInfo I; I.Name = "f"; I.DefLoc = Location(10, 10, "test.cpp"); @@ -482,7 +484,7 @@ TEST(YAMLGeneratorTest, emitCommentYAML) { assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); - auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext()); + auto Err = G->generateDocForInfo(&I, Actual, getClangDocContext()); assert(!Err); std::string Expected = R"raw(--- _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
