diff options
Diffstat (limited to 'clang-tools-extra')
483 files changed, 5968 insertions, 5397 deletions
diff --git a/clang-tools-extra/Maintainers.rst b/clang-tools-extra/Maintainers.rst index 2603eba..094f115 100644 --- a/clang-tools-extra/Maintainers.rst +++ b/clang-tools-extra/Maintainers.rst @@ -33,6 +33,9 @@ clang-tidy | Piotr Zegar | me@piotrzegar.pl (email), PiotrZSL (GitHub), PiotrZSL (Discourse), PiotrZSL (Discord) +| Victor Baranov +| bar.victor.2002@gmail.com (email), vbvictor (GitHub), vbvictor (Discourse), vbvictor (Discord) + clang-query ----------- diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index 4efbbd3..817981a 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "BitcodeReader.h" -#include "llvm/ADT/IndexedMap.h" #include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" #include <optional> @@ -16,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. @@ -717,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: @@ -767,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)); @@ -780,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)); @@ -799,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, @@ -809,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)); @@ -847,9 +851,11 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) { while (true) { unsigned BlockOrCode = 0; - Cursor Res = skipUntilRecordOrBlock(BlockOrCode); + llvm::Expected<Cursor> C = skipUntilRecordOrBlock(BlockOrCode); + if (!C) + return C.takeError(); - switch (Res) { + switch (*C) { case Cursor::BadBlock: return llvm::createStringError(llvm::inconvertibleErrorCode(), "bad block found"); @@ -985,45 +991,39 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) { } } -ClangDocBitcodeReader::Cursor +llvm::Expected<ClangDocBitcodeReader::Cursor> ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) { llvm::TimeTraceScope("Reducing infos", "skipUntilRecordOrBlock"); BlockOrRecordID = 0; while (!Stream.AtEndOfStream()) { - Expected<unsigned> MaybeCode = Stream.ReadCode(); - if (!MaybeCode) { - // FIXME this drops the error on the floor. - consumeError(MaybeCode.takeError()); - return Cursor::BadBlock; - } + Expected<unsigned> Code = Stream.ReadCode(); + if (!Code) + return Code.takeError(); - unsigned Code = MaybeCode.get(); - if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) { - BlockOrRecordID = Code; + if (*Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) { + BlockOrRecordID = *Code; return Cursor::Record; } - switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) { + switch (static_cast<llvm::bitc::FixedAbbrevIDs>(*Code)) { case llvm::bitc::ENTER_SUBBLOCK: if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID()) BlockOrRecordID = MaybeID.get(); - else { - // FIXME this drops the error on the floor. - consumeError(MaybeID.takeError()); - } + else + return MaybeID.takeError(); return Cursor::BlockBegin; case llvm::bitc::END_BLOCK: if (Stream.ReadBlockEnd()) - return Cursor::BadBlock; + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "error at end of block"); return Cursor::BlockEnd; case llvm::bitc::DEFINE_ABBREV: - if (llvm::Error Err = Stream.ReadAbbrevRecord()) { - // FIXME this drops the error on the floor. - consumeError(std::move(Err)); - } + if (llvm::Error Err = Stream.ReadAbbrevRecord()) + return std::move(Err); continue; case llvm::bitc::UNABBREV_RECORD: - return Cursor::BadBlock; + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "found unabbreviated record"); case llvm::bitc::FIRST_APPLICATION_ABBREV: llvm_unreachable("Unexpected abbrev id."); } @@ -1149,10 +1149,8 @@ ClangDocBitcodeReader::readBitcode() { return std::move(Err); continue; default: - if (llvm::Error Err = Stream.SkipBlock()) { - // FIXME this drops the error on the floor. - consumeError(std::move(Err)); - } + if (llvm::Error Err = Stream.SkipBlock()) + return std::move(Err); continue; } } diff --git a/clang-tools-extra/clang-doc/BitcodeReader.h b/clang-tools-extra/clang-doc/BitcodeReader.h index 4947721..8c1f9d6 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.h +++ b/clang-tools-extra/clang-doc/BitcodeReader.h @@ -17,8 +17,6 @@ #include "BitcodeWriter.h" #include "Representation.h" -#include "clang/AST/AST.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Support/Error.h" #include <optional> @@ -29,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(); @@ -59,7 +58,7 @@ private: // Helper function to step through blocks to find and dispatch the next record // or block to be read. - Cursor skipUntilRecordOrBlock(unsigned &BlockOrRecordID); + llvm::Expected<Cursor> skipUntilRecordOrBlock(unsigned &BlockOrRecordID); // Helper function to set up the appropriate type of Info. llvm::Expected<std::unique_ptr<Info>> readBlockToInfo(unsigned ID); @@ -74,6 +73,7 @@ private: 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 3a7ac6e..650501d 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 688f886..6d1b9e9 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.h +++ b/clang-tools-extra/clang-doc/BitcodeWriter.h @@ -16,12 +16,9 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_BITCODEWRITER_H #include "Representation.h" -#include "clang/AST/AST.h" +#include "clang/Basic/Diagnostic.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Bitstream/BitstreamWriter.h" -#include <initializer_list> #include <vector> namespace clang { @@ -179,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(); @@ -264,6 +262,7 @@ private: SmallVector<uint32_t, BitCodeConstants::RecordSize> Record; llvm::BitstreamWriter &Stream; AbbreviationMap Abbrevs; + DiagnosticsEngine &Diags; }; } // namespace doc diff --git a/clang-tools-extra/clang-doc/CMakeLists.txt b/clang-tools-extra/clang-doc/CMakeLists.txt index 5989e5f..7a375d7 100644 --- a/clang-tools-extra/clang-doc/CMakeLists.txt +++ b/clang-tools-extra/clang-doc/CMakeLists.txt @@ -16,7 +16,6 @@ add_clang_library(clangDoc STATIC Representation.cpp Serialize.cpp YAMLGenerator.cpp - HTMLMustacheGenerator.cpp JSONGenerator.cpp DEPENDS diff --git a/clang-tools-extra/clang-doc/ClangDoc.cpp b/clang-tools-extra/clang-doc/ClangDoc.cpp index da4165a..ec802d6 100644 --- a/clang-tools-extra/clang-doc/ClangDoc.cpp +++ b/clang-tools-extra/clang-doc/ClangDoc.cpp @@ -15,13 +15,9 @@ #include "ClangDoc.h" #include "Mapper.h" #include "Representation.h" -#include "clang/AST/AST.h" #include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendActions.h" namespace clang { namespace doc { diff --git a/clang-tools-extra/clang-doc/ClangDoc.h b/clang-tools-extra/clang-doc/ClangDoc.h index 1f0c43d..860b670 100644 --- a/clang-tools-extra/clang-doc/ClangDoc.h +++ b/clang-tools-extra/clang-doc/ClangDoc.h @@ -17,8 +17,6 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_CLANGDOC_H #include "Representation.h" -#include "clang/Tooling/Execution.h" -#include "clang/Tooling/StandaloneExecution.h" #include "clang/Tooling/Tooling.h" namespace clang { diff --git a/clang-tools-extra/clang-doc/Generators.cpp b/clang-tools-extra/clang-doc/Generators.cpp index a5f6f1c..d6c1cc9 100644 --- a/clang-tools-extra/clang-doc/Generators.cpp +++ b/clang-tools-extra/clang-doc/Generators.cpp @@ -7,9 +7,15 @@ //===----------------------------------------------------------------------===// #include "Generators.h" +#include "support/File.h" +#include "llvm/Support/TimeProfiler.h" LLVM_INSTANTIATE_REGISTRY(clang::doc::GeneratorRegistry) +using namespace llvm; +using namespace llvm::json; +using namespace llvm::mustache; + namespace clang { namespace doc { @@ -42,6 +48,143 @@ std::string getTagType(TagTypeKind AS) { llvm_unreachable("Unknown TagTypeKind"); } +Error createFileOpenError(StringRef FileName, std::error_code EC) { + return createFileError("cannot open file " + FileName, EC); +} + +Error MustacheGenerator::setupTemplate( + std::unique_ptr<MustacheTemplateFile> &Template, StringRef TemplatePath, + std::vector<std::pair<StringRef, StringRef>> Partials) { + auto T = MustacheTemplateFile::createMustacheFile(TemplatePath); + if (Error Err = T.takeError()) + return Err; + Template = std::move(T.get()); + for (const auto &[Name, FileName] : Partials) + if (auto Err = Template->registerPartialFile(Name, FileName)) + return Err; + return Error::success(); +} + +Error MustacheGenerator::generateDocumentation( + StringRef RootDir, StringMap<std::unique_ptr<doc::Info>> Infos, + const clang::doc::ClangDocContext &CDCtx, std::string DirName) { + { + llvm::TimeTraceScope TS("Setup Templates"); + if (auto Err = setupTemplateFiles(CDCtx)) + return Err; + } + + { + llvm::TimeTraceScope TS("Generate JSON for Mustache"); + if (auto JSONGenerator = findGeneratorByName("json")) { + if (Error Err = JSONGenerator.get()->generateDocumentation( + RootDir, std::move(Infos), CDCtx)) + return Err; + } else + return JSONGenerator.takeError(); + } + + SmallString<128> JSONDirPath(RootDir); + SmallString<128> DocsDirPath(RootDir); + { + TimeTraceScope TS("Create Output Directories"); + sys::path::append(JSONDirPath, "json"); + if (auto EC = sys::fs::create_directories(JSONDirPath)) + return createFileError(JSONDirPath, EC); + sys::path::append(DocsDirPath, DirName); + if (auto EC = sys::fs::create_directories(DocsDirPath)) + return createFileError(DocsDirPath, EC); + } + + { + llvm::TimeTraceScope TS("Iterate JSON files"); + std::error_code EC; + sys::fs::recursive_directory_iterator JSONIter(JSONDirPath, EC); + std::vector<json::Value> JSONFiles; + JSONFiles.reserve(Infos.size()); + if (EC) + return createStringError("Failed to create directory iterator."); + + while (JSONIter != sys::fs::recursive_directory_iterator()) { + // create the same directory structure in the docs format dir + if (JSONIter->type() == sys::fs::file_type::directory_file) { + SmallString<128> DocsClonedPath(JSONIter->path()); + sys::path::replace_path_prefix(DocsClonedPath, JSONDirPath, + DocsDirPath); + if (auto EC = sys::fs::create_directories(DocsClonedPath)) { + return createFileError(DocsClonedPath, EC); + } + } + + if (EC) + return createFileError("Failed to iterate: " + JSONIter->path(), EC); + + auto Path = StringRef(JSONIter->path()); + if (!Path.ends_with(".json")) { + JSONIter.increment(EC); + continue; + } + + auto File = MemoryBuffer::getFile(Path); + if (EC = File.getError(); EC) { + 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()); + if (!Parsed) + return Parsed.takeError(); + auto ValidJSON = Parsed.get(); + + std::error_code FileErr; + SmallString<128> DocsFilePath(JSONIter->path()); + sys::path::replace_path_prefix(DocsFilePath, JSONDirPath, DocsDirPath); + sys::path::replace_extension(DocsFilePath, DirName); + raw_fd_ostream InfoOS(DocsFilePath, FileErr, sys::fs::OF_None); + if (FileErr) + return createFileOpenError(Path, FileErr); + + auto RelativeRootPath = getRelativePathToRoot(DocsFilePath, DocsDirPath); + auto InfoTypeStr = + getInfoTypeStr(Parsed->getAsObject(), sys::path::stem(DocsFilePath)); + if (!InfoTypeStr) + return InfoTypeStr.takeError(); + if (Error Err = generateDocForJSON(*Parsed, InfoOS, CDCtx, + InfoTypeStr.get(), RelativeRootPath)) + return Err; + JSONIter.increment(EC); + } + } + + return Error::success(); +} + +Expected<std::string> MustacheGenerator::getInfoTypeStr(Object *Info, + StringRef Filename) { + auto StrValue = (*Info)["InfoType"]; + if (StrValue.kind() != json::Value::Kind::String) + return createStringError("JSON file '%s' does not contain key: 'InfoType'.", + Filename.str().c_str()); + auto ObjTypeStr = StrValue.getAsString(); + if (!ObjTypeStr.has_value()) + return createStringError( + "JSON file '%s' does not contain 'InfoType' field as a string.", + Filename.str().c_str()); + return ObjTypeStr.value().str(); +} + +SmallString<128> +MustacheGenerator::getRelativePathToRoot(StringRef PathToFile, + StringRef DocsRootPath) { + SmallString<128> PathVec(PathToFile); + // Remove filename, or else the relative path will have an extra "../" + sys::path::remove_filename(PathVec); + return computeRelativePath(DocsRootPath, PathVec); +} + llvm::Error Generator::createResources(ClangDocContext &CDCtx) { return llvm::Error::success(); } @@ -100,8 +243,6 @@ void Generator::addInfoToIndex(Index &Idx, const doc::Info *Info) { [[maybe_unused]] static int YAMLGeneratorAnchorDest = YAMLGeneratorAnchorSource; [[maybe_unused]] static int MDGeneratorAnchorDest = MDGeneratorAnchorSource; [[maybe_unused]] static int HTMLGeneratorAnchorDest = HTMLGeneratorAnchorSource; -[[maybe_unused]] static int MHTMLGeneratorAnchorDest = - MHTMLGeneratorAnchorSource; [[maybe_unused]] static int JSONGeneratorAnchorDest = JSONGeneratorAnchorSource; } // namespace doc } // namespace clang diff --git a/clang-tools-extra/clang-doc/Generators.h b/clang-tools-extra/clang-doc/Generators.h index 92d3006..a50f1ac 100644 --- a/clang-tools-extra/clang-doc/Generators.h +++ b/clang-tools-extra/clang-doc/Generators.h @@ -14,6 +14,8 @@ #include "Representation.h" #include "llvm/Support/Error.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/Mustache.h" #include "llvm/Support/Registry.h" namespace clang { @@ -27,10 +29,9 @@ public: // Write out the decl info for the objects in the given map in the specified // format. - virtual llvm::Error - generateDocs(StringRef RootDir, - llvm::StringMap<std::unique_ptr<doc::Info>> Infos, - const ClangDocContext &CDCtx) = 0; + virtual llvm::Error generateDocumentation( + StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const ClangDocContext &CDCtx, std::string DirName = "") = 0; // This function writes a file with the index previously constructed. // It can be overwritten by any of the inherited generators. @@ -52,12 +53,90 @@ findGeneratorByName(llvm::StringRef Format); std::string getTagType(TagTypeKind AS); +llvm::Error createFileOpenError(StringRef FileName, std::error_code EC); + +class MustacheTemplateFile { + llvm::BumpPtrAllocator Allocator; + llvm::StringSaver Saver; + llvm::mustache::MustacheContext Ctx; + llvm::mustache::Template T; + std::unique_ptr<llvm::MemoryBuffer> Buffer; + +public: + static Expected<std::unique_ptr<MustacheTemplateFile>> + createMustacheFile(StringRef FileName) { + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrError = + llvm::MemoryBuffer::getFile(FileName); + if (auto EC = BufferOrError.getError()) + return createFileOpenError(FileName, EC); + return std::make_unique<MustacheTemplateFile>( + std::move(BufferOrError.get())); + } + + llvm::Error registerPartialFile(StringRef Name, StringRef FileName) { + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> BufferOrError = + llvm::MemoryBuffer::getFile(FileName); + if (auto EC = BufferOrError.getError()) + return createFileOpenError(FileName, EC); + + std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrError.get()); + StringRef FileContent = Buffer->getBuffer(); + T.registerPartial(Name.str(), FileContent.str()); + return llvm::Error::success(); + } + + void render(llvm::json::Value &V, raw_ostream &OS) { T.render(V, OS); } + + MustacheTemplateFile(std::unique_ptr<llvm::MemoryBuffer> &&B) + : Saver(Allocator), Ctx(Allocator, Saver), T(B->getBuffer(), Ctx), + Buffer(std::move(B)) {} +}; + +struct MustacheGenerator : public Generator { + Expected<std::string> getInfoTypeStr(llvm::json::Object *Info, + StringRef Filename); + + /// Used to find the relative path from the file to the format's docs root. + /// Mainly used for the HTML resource paths. + SmallString<128> getRelativePathToRoot(StringRef PathToFile, + StringRef DocsRootPath); + virtual ~MustacheGenerator() = default; + + /// Initializes the template files from disk and calls setupTemplate to + /// register partials + virtual llvm::Error setupTemplateFiles(const ClangDocContext &CDCtx) = 0; + + /// Populates templates with data from JSON and calls any specifics for the + /// format. For example, for HTML it will render the paths for CSS and JS. + virtual llvm::Error generateDocForJSON(llvm::json::Value &JSON, + llvm::raw_fd_ostream &OS, + const ClangDocContext &CDCtx, + StringRef ObjectTypeStr, + StringRef RelativeRootPath) = 0; + + /// Registers partials to templates. + llvm::Error + setupTemplate(std::unique_ptr<MustacheTemplateFile> &Template, + StringRef TemplatePath, + std::vector<std::pair<StringRef, StringRef>> Partials); + + /// \brief The main orchestrator for Mustache-based documentation. + /// + /// 1. Initializes templates files from disk by calling setupTemplateFiles. + /// 2. Calls the JSON generator to write JSON to disk. + /// 3. Iterates over the JSON files, recreates the directory structure from + /// JSON, and calls generateDocForJSON for each file. + /// 4. A file of the desired format is created. + llvm::Error generateDocumentation( + StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const clang::doc::ClangDocContext &CDCtx, std::string DirName) override; +}; + // This anchor is used to force the linker to link in the generated object file // and thus register the generators. extern volatile int YAMLGeneratorAnchorSource; extern volatile int MDGeneratorAnchorSource; extern volatile int HTMLGeneratorAnchorSource; -extern volatile int MHTMLGeneratorAnchorSource; extern volatile int JSONGeneratorAnchorSource; } // namespace doc diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp index 8294ff9..6f58c3d 100644 --- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -5,1146 +5,169 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the implementation of the HTMLGenerator class, +/// which is a Clang-Doc generator for HTML using Mustache templates. +/// +//===----------------------------------------------------------------------===// #include "Generators.h" #include "Representation.h" #include "support/File.h" -#include "clang/Basic/Version.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/JSON.h" +#include "llvm/Support/Error.h" #include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <optional> -#include <string> using namespace llvm; +using namespace llvm::json; +using namespace llvm::mustache; namespace clang { namespace doc { -namespace { - -class HTMLTag { -public: - // Any other tag can be added if required - enum TagType { - TAG_A, - TAG_DIV, - TAG_FOOTER, - TAG_H1, - TAG_H2, - TAG_H3, - TAG_HEADER, - TAG_LI, - TAG_LINK, - TAG_MAIN, - TAG_META, - TAG_OL, - TAG_P, - TAG_SCRIPT, - TAG_SPAN, - TAG_TITLE, - TAG_UL, - TAG_TABLE, - TAG_THEAD, - TAG_TBODY, - TAG_TR, - TAG_TD, - TAG_TH - }; - - HTMLTag() = default; - constexpr HTMLTag(TagType Value) : Value(Value) {} - - operator TagType() const { return Value; } - operator bool() = delete; - - bool isSelfClosing() const; - StringRef toString() const; - -private: - 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(const Twine &Text) - : HTMLNode(NodeType::NODE_TEXT), Text(Text.str()) {} - - std::string Text; // Content of node - void render(llvm::raw_ostream &OS, int IndentationLevel) override; -}; - -struct TagNode : public HTMLNode { - TagNode(HTMLTag Tag) : HTMLNode(NodeType::NODE_TAG), Tag(Tag) {} - TagNode(HTMLTag Tag, const Twine &Text) : TagNode(Tag) { - Children.emplace_back(std::make_unique<TextNode>(Text.str())); - } - - HTMLTag Tag; // Name of HTML Tag (p, div, h1) - std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes - std::vector<std::pair<std::string, std::string>> - Attributes; // List of key-value attributes for tag - - void render(llvm::raw_ostream &OS, int IndentationLevel) override; -}; - -struct HTMLFile { - std::vector<std::unique_ptr<HTMLNode>> Children; // List of child nodes - void render(llvm::raw_ostream &OS) { - OS << "<!DOCTYPE html>\n"; - for (const auto &C : Children) { - C->render(OS, 0); - OS << "\n"; - } - } -}; - -} // namespace - -bool HTMLTag::isSelfClosing() const { - switch (Value) { - case HTMLTag::TAG_META: - case HTMLTag::TAG_LINK: - return true; - case HTMLTag::TAG_A: - case HTMLTag::TAG_DIV: - case HTMLTag::TAG_FOOTER: - case HTMLTag::TAG_H1: - case HTMLTag::TAG_H2: - case HTMLTag::TAG_H3: - case HTMLTag::TAG_HEADER: - case HTMLTag::TAG_LI: - case HTMLTag::TAG_MAIN: - case HTMLTag::TAG_OL: - case HTMLTag::TAG_P: - case HTMLTag::TAG_SCRIPT: - case HTMLTag::TAG_SPAN: - case HTMLTag::TAG_TITLE: - case HTMLTag::TAG_UL: - case HTMLTag::TAG_TABLE: - case HTMLTag::TAG_THEAD: - case HTMLTag::TAG_TBODY: - case HTMLTag::TAG_TR: - case HTMLTag::TAG_TD: - case HTMLTag::TAG_TH: - return false; - } - llvm_unreachable("Unhandled HTMLTag::TagType"); -} - -StringRef HTMLTag::toString() const { - switch (Value) { - case HTMLTag::TAG_A: - return "a"; - case HTMLTag::TAG_DIV: - return "div"; - case HTMLTag::TAG_FOOTER: - return "footer"; - case HTMLTag::TAG_H1: - return "h1"; - case HTMLTag::TAG_H2: - return "h2"; - case HTMLTag::TAG_H3: - return "h3"; - case HTMLTag::TAG_HEADER: - return "header"; - case HTMLTag::TAG_LI: - return "li"; - case HTMLTag::TAG_LINK: - return "link"; - case HTMLTag::TAG_MAIN: - return "main"; - case HTMLTag::TAG_META: - return "meta"; - case HTMLTag::TAG_OL: - return "ol"; - case HTMLTag::TAG_P: - return "p"; - case HTMLTag::TAG_SCRIPT: - return "script"; - case HTMLTag::TAG_SPAN: - return "span"; - case HTMLTag::TAG_TITLE: - return "title"; - case HTMLTag::TAG_UL: - return "ul"; - case HTMLTag::TAG_TABLE: - return "table"; - case HTMLTag::TAG_THEAD: - return "thead"; - case HTMLTag::TAG_TBODY: - return "tbody"; - case HTMLTag::TAG_TR: - return "tr"; - case HTMLTag::TAG_TD: - return "td"; - case HTMLTag::TAG_TH: - return "th"; - } - llvm_unreachable("Unhandled HTMLTag::TagType"); -} - -void TextNode::render(llvm::raw_ostream &OS, int IndentationLevel) { - OS.indent(IndentationLevel * 2); - printHTMLEscaped(Text, OS); -} - -void TagNode::render(llvm::raw_ostream &OS, int IndentationLevel) { - // Children nodes are rendered in the same line if all of them are text nodes - bool InlineChildren = true; - for (const auto &C : Children) - if (C->Type == NodeType::NODE_TAG) { - InlineChildren = false; - break; - } - OS.indent(IndentationLevel * 2); - OS << "<" << Tag.toString(); - for (const auto &A : Attributes) - OS << " " << A.first << "=\"" << A.second << "\""; - if (Tag.isSelfClosing()) { - OS << "/>"; - return; - } - OS << ">"; - if (!InlineChildren) - OS << "\n"; - bool NewLineRendered = true; - for (const auto &C : Children) { - int ChildrenIndentation = - InlineChildren || !NewLineRendered ? 0 : IndentationLevel + 1; - C->render(OS, ChildrenIndentation); - 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)); -} - -// HTML generation - -static std::vector<std::unique_ptr<TagNode>> -genStylesheetsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) { - std::vector<std::unique_ptr<TagNode>> Out; - for (const auto &FilePath : CDCtx.UserStylesheets) { - auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_LINK); - LinkNode->Attributes.emplace_back("rel", "stylesheet"); - SmallString<128> StylesheetPath = computeRelativePath("", InfoPath); - llvm::sys::path::append(StylesheetPath, - llvm::sys::path::filename(FilePath)); - // Paths in HTML must be in posix-style - llvm::sys::path::native(StylesheetPath, llvm::sys::path::Style::posix); - LinkNode->Attributes.emplace_back("href", std::string(StylesheetPath)); - Out.emplace_back(std::move(LinkNode)); - } - return Out; -} - -static std::vector<std::unique_ptr<TagNode>> -genJsScriptsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) { - std::vector<std::unique_ptr<TagNode>> Out; - - // index_json.js is part of every generated HTML file - SmallString<128> IndexJSONPath = computeRelativePath("", InfoPath); - auto IndexJSONNode = std::make_unique<TagNode>(HTMLTag::TAG_SCRIPT); - llvm::sys::path::append(IndexJSONPath, "index_json.js"); - llvm::sys::path::native(IndexJSONPath, llvm::sys::path::Style::posix); - IndexJSONNode->Attributes.emplace_back("src", std::string(IndexJSONPath)); - Out.emplace_back(std::move(IndexJSONNode)); - - for (const auto &FilePath : CDCtx.JsScripts) { - SmallString<128> ScriptPath = computeRelativePath("", InfoPath); - auto ScriptNode = std::make_unique<TagNode>(HTMLTag::TAG_SCRIPT); - llvm::sys::path::append(ScriptPath, llvm::sys::path::filename(FilePath)); - // Paths in HTML must be in posix-style - llvm::sys::path::native(ScriptPath, llvm::sys::path::Style::posix); - ScriptNode->Attributes.emplace_back("src", std::string(ScriptPath)); - Out.emplace_back(std::move(ScriptNode)); - } - return Out; -} - -static std::unique_ptr<TagNode> genLink(const Twine &Text, const Twine &Link) { - auto LinkNode = std::make_unique<TagNode>(HTMLTag::TAG_A, Text); - LinkNode->Attributes.emplace_back("href", Link.str()); - return LinkNode; -} - -static std::unique_ptr<HTMLNode> -genReference(const Reference &Type, StringRef CurrentDirectory, - std::optional<StringRef> JumpToSection = std::nullopt) { - if (Type.Path.empty()) { - if (!JumpToSection) - return std::make_unique<TextNode>(Type.Name); - return genLink(Type.Name, "#" + *JumpToSection); - } - llvm::SmallString<64> Path = Type.getRelativeFilePath(CurrentDirectory); - llvm::sys::path::append(Path, Type.getFileBaseName() + ".html"); - - // Paths in HTML must be in posix-style - llvm::sys::path::native(Path, llvm::sys::path::Style::posix); - if (JumpToSection) - Path += ("#" + *JumpToSection).str(); - 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(std::make_unique<TextNode>(", ")); - Out.emplace_back(genReference(R, CurrentDirectory)); - } - return Out; -} - -static std::vector<std::unique_ptr<TagNode>> -genHTML(const EnumInfo &I, const ClangDocContext &CDCtx); -static std::vector<std::unique_ptr<TagNode>> -genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx, - StringRef ParentInfoDir); -static std::unique_ptr<TagNode> genHTML(const std::vector<CommentInfo> &C); - -static std::vector<std::unique_ptr<TagNode>> -genEnumsBlock(const std::vector<EnumInfo> &Enums, - const ClangDocContext &CDCtx) { - if (Enums.empty()) - return {}; - - std::vector<std::unique_ptr<TagNode>> Out; - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Enums")); - Out.back()->Attributes.emplace_back("id", "Enums"); - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV)); - auto &DivBody = Out.back(); - for (const auto &E : Enums) { - std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(E, CDCtx); - appendVector(std::move(Nodes), DivBody->Children); - } - return Out; -} - -static std::unique_ptr<TagNode> -genEnumMembersBlock(const llvm::SmallVector<EnumValueInfo, 4> &Members) { - if (Members.empty()) - return nullptr; - - auto List = std::make_unique<TagNode>(HTMLTag::TAG_TBODY); - - for (const auto &M : Members) { - auto TRNode = std::make_unique<TagNode>(HTMLTag::TAG_TR); - TRNode->Children.emplace_back( - std::make_unique<TagNode>(HTMLTag::TAG_TD, M.Name)); - // Use user supplied value if it exists, otherwise use the value - if (!M.ValueExpr.empty()) { - TRNode->Children.emplace_back( - std::make_unique<TagNode>(HTMLTag::TAG_TD, M.ValueExpr)); - } else { - TRNode->Children.emplace_back( - std::make_unique<TagNode>(HTMLTag::TAG_TD, M.Value)); - } - if (!M.Description.empty()) { - auto TD = std::make_unique<TagNode>(HTMLTag::TAG_TD); - TD->Children.emplace_back(genHTML(M.Description)); - TRNode->Children.emplace_back(std::move(TD)); - } - List->Children.emplace_back(std::move(TRNode)); - } - return List; -} - -static std::vector<std::unique_ptr<TagNode>> -genFunctionsBlock(const std::vector<FunctionInfo> &Functions, - const ClangDocContext &CDCtx, StringRef ParentInfoDir) { - if (Functions.empty()) - return {}; - - std::vector<std::unique_ptr<TagNode>> Out; - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Functions")); - Out.back()->Attributes.emplace_back("id", "Functions"); - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_DIV)); - auto &DivBody = Out.back(); - for (const auto &F : Functions) { - std::vector<std::unique_ptr<TagNode>> Nodes = - genHTML(F, CDCtx, ParentInfoDir); - appendVector(std::move(Nodes), DivBody->Children); - } - return Out; -} - -static std::vector<std::unique_ptr<TagNode>> -genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members, - StringRef ParentInfoDir) { - if (Members.empty()) - return {}; - - std::vector<std::unique_ptr<TagNode>> Out; - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, "Members")); - Out.back()->Attributes.emplace_back("id", "Members"); - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL)); - auto &ULBody = Out.back(); - for (const auto &M : Members) { - StringRef Access = getAccessSpelling(M.Access); - auto LIBody = std::make_unique<TagNode>(HTMLTag::TAG_LI); - auto MemberDecl = std::make_unique<TagNode>(HTMLTag::TAG_DIV); - if (!Access.empty()) - MemberDecl->Children.emplace_back( - std::make_unique<TextNode>(Access + " ")); - if (M.IsStatic) - MemberDecl->Children.emplace_back(std::make_unique<TextNode>("static ")); - MemberDecl->Children.emplace_back(genReference(M.Type, ParentInfoDir)); - MemberDecl->Children.emplace_back(std::make_unique<TextNode>(" " + M.Name)); - if (!M.Description.empty()) - LIBody->Children.emplace_back(genHTML(M.Description)); - LIBody->Children.emplace_back(std::move(MemberDecl)); - ULBody->Children.emplace_back(std::move(LIBody)); - } - return Out; -} - -static std::vector<std::unique_ptr<TagNode>> -genReferencesBlock(const std::vector<Reference> &References, - llvm::StringRef Title, StringRef ParentPath) { - if (References.empty()) - return {}; - - std::vector<std::unique_ptr<TagNode>> Out; - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H2, Title)); - Out.back()->Attributes.emplace_back("id", std::string(Title)); - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_UL)); - auto &ULBody = Out.back(); - for (const auto &R : References) { - auto LiNode = std::make_unique<TagNode>(HTMLTag::TAG_LI); - LiNode->Children.emplace_back(genReference(R, ParentPath)); - ULBody->Children.emplace_back(std::move(LiNode)); - } - return Out; -} -static std::unique_ptr<TagNode> writeSourceFileRef(const ClangDocContext &CDCtx, - const Location &L) { - - if (!L.IsFileInRootDir && !CDCtx.RepositoryUrl) - return std::make_unique<TagNode>( - HTMLTag::TAG_P, "Defined at line " + std::to_string(L.StartLineNumber) + - " of file " + L.Filename); - - SmallString<128> FileURL(CDCtx.RepositoryUrl.value_or("")); - llvm::sys::path::append( - FileURL, llvm::sys::path::Style::posix, - // If we're on Windows, the file name will be in the wrong format, and - // append won't convert the full path being appended to the correct - // format, so we need to do that here. - llvm::sys::path::convert_to_slash( - L.Filename, - // The style here is the current style of the path, not the one we're - // targeting. If the string is already in the posix style, it will do - // nothing. - llvm::sys::path::Style::windows)); - auto Node = std::make_unique<TagNode>(HTMLTag::TAG_P); - Node->Children.emplace_back(std::make_unique<TextNode>("Defined at line ")); - auto LocNumberNode = std::make_unique<TagNode>( - HTMLTag::TAG_A, std::to_string(L.StartLineNumber)); - // The links to a specific line in the source code use the github / - // googlesource notation so it won't work for all hosting pages. - LocNumberNode->Attributes.emplace_back( - "href", - formatv("{0}#{1}{2}", FileURL, CDCtx.RepositoryLinePrefix.value_or(""), - L.StartLineNumber)); - Node->Children.emplace_back(std::move(LocNumberNode)); - Node->Children.emplace_back(std::make_unique<TextNode>(" of file ")); - auto LocFileNode = std::make_unique<TagNode>( - HTMLTag::TAG_A, llvm::sys::path::filename(FileURL)); - LocFileNode->Attributes.emplace_back("href", std::string(FileURL)); - Node->Children.emplace_back(std::move(LocFileNode)); - return Node; -} - -static void maybeWriteSourceFileRef(std::vector<std::unique_ptr<TagNode>> &Out, - const ClangDocContext &CDCtx, - const std::optional<Location> &DefLoc) { - if (DefLoc) - Out.emplace_back(writeSourceFileRef(CDCtx, *DefLoc)); -} - -static std::vector<std::unique_ptr<TagNode>> -genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList); - -// Generates a list of child nodes for the HTML head tag -// It contains a meta node, link nodes to import CSS files, and script nodes to -// import JS files -static std::vector<std::unique_ptr<TagNode>> -genFileHeadNodes(StringRef Title, StringRef InfoPath, - const ClangDocContext &CDCtx) { - std::vector<std::unique_ptr<TagNode>> Out; - auto MetaNode = std::make_unique<TagNode>(HTMLTag::TAG_META); - MetaNode->Attributes.emplace_back("charset", "utf-8"); - Out.emplace_back(std::move(MetaNode)); - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_TITLE, Title)); - std::vector<std::unique_ptr<TagNode>> StylesheetsNodes = - genStylesheetsHTML(InfoPath, CDCtx); - appendVector(std::move(StylesheetsNodes), Out); - std::vector<std::unique_ptr<TagNode>> JsNodes = - genJsScriptsHTML(InfoPath, CDCtx); - appendVector(std::move(JsNodes), Out); - return Out; -} - -// Generates a header HTML node that can be used for any file -// It contains the project name -static std::unique_ptr<TagNode> genFileHeaderNode(StringRef ProjectName) { - auto HeaderNode = std::make_unique<TagNode>(HTMLTag::TAG_HEADER, ProjectName); - HeaderNode->Attributes.emplace_back("id", "project-title"); - return HeaderNode; -} - -// Generates a main HTML node that has all the main content of an info file -// It contains both indexes and the info's documented information -// This function should only be used for the info files (not for the file that -// only has the general index) -static std::unique_ptr<TagNode> genInfoFileMainNode( - StringRef InfoPath, - std::vector<std::unique_ptr<TagNode>> &MainContentInnerNodes, - const Index &InfoIndex) { - auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN); - - auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV); - LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left"); - LeftSidebarNode->Attributes.emplace_back("path", std::string(InfoPath)); - LeftSidebarNode->Attributes.emplace_back( - "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"); - - auto MainContentNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV); - MainContentNode->Attributes.emplace_back("id", "main-content"); - MainContentNode->Attributes.emplace_back( - "class", "col-xs-12 col-sm-9 col-md-8 main-content"); - appendVector(std::move(MainContentInnerNodes), MainContentNode->Children); - - auto RightSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV); - RightSidebarNode->Attributes.emplace_back("id", "sidebar-right"); - RightSidebarNode->Attributes.emplace_back( - "class", "col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"); - std::vector<std::unique_ptr<TagNode>> InfoIndexHTML = - genHTML(InfoIndex, InfoPath, true); - appendVector(std::move(InfoIndexHTML), RightSidebarNode->Children); - - MainNode->Children.emplace_back(std::move(LeftSidebarNode)); - MainNode->Children.emplace_back(std::move(MainContentNode)); - MainNode->Children.emplace_back(std::move(RightSidebarNode)); - - return MainNode; -} - -// Generates a footer HTML node that can be used for any file -// It contains clang-doc's version -static std::unique_ptr<TagNode> genFileFooterNode() { - auto FooterNode = std::make_unique<TagNode>(HTMLTag::TAG_FOOTER); - auto SpanNode = std::make_unique<TagNode>( - HTMLTag::TAG_SPAN, clang::getClangToolFullVersion("clang-doc")); - SpanNode->Attributes.emplace_back("class", "no-break"); - FooterNode->Children.emplace_back(std::move(SpanNode)); - return FooterNode; -} - -// Generates a complete HTMLFile for an Info -static HTMLFile -genInfoFile(StringRef Title, StringRef InfoPath, - std::vector<std::unique_ptr<TagNode>> &MainContentNodes, - const Index &InfoIndex, const ClangDocContext &CDCtx) { - HTMLFile F; - - std::vector<std::unique_ptr<TagNode>> HeadNodes = - genFileHeadNodes(Title, InfoPath, CDCtx); - std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName); - std::unique_ptr<TagNode> MainNode = - genInfoFileMainNode(InfoPath, MainContentNodes, InfoIndex); - std::unique_ptr<TagNode> FooterNode = genFileFooterNode(); - - appendVector(std::move(HeadNodes), F.Children); - F.Children.emplace_back(std::move(HeaderNode)); - F.Children.emplace_back(std::move(MainNode)); - F.Children.emplace_back(std::move(FooterNode)); - - return F; -} - -template <typename T, - typename = std::enable_if<std::is_base_of<T, Info>::value>> -static Index genInfoIndexItem(const std::vector<T> &Infos, StringRef Title) { - Index Idx(Title, Title); - for (const auto &C : Infos) - Idx.Children.emplace_back(C.extractName(), - llvm::toHex(llvm::toStringRef(C.USR))); - return Idx; -} - -static std::vector<std::unique_ptr<TagNode>> -genHTML(const Index &Index, StringRef InfoPath, bool IsOutermostList) { - std::vector<std::unique_ptr<TagNode>> Out; - if (!Index.Name.empty()) { - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_SPAN)); - auto &SpanBody = Out.back(); - if (!Index.JumpToSection) - SpanBody->Children.emplace_back(genReference(Index, InfoPath)); - else - SpanBody->Children.emplace_back( - genReference(Index, InfoPath, Index.JumpToSection->str())); - } - if (Index.Children.empty()) - return Out; - // Only the outermost list should use ol, the others should use ul - HTMLTag ListHTMLTag = IsOutermostList ? HTMLTag::TAG_OL : HTMLTag::TAG_UL; - Out.emplace_back(std::make_unique<TagNode>(ListHTMLTag)); - const auto &UlBody = Out.back(); - for (const auto &C : Index.Children) { - auto LiBody = std::make_unique<TagNode>(HTMLTag::TAG_LI); - std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(C, InfoPath, false); - appendVector(std::move(Nodes), LiBody->Children); - UlBody->Children.emplace_back(std::move(LiBody)); - } - return Out; -} - -static std::unique_ptr<HTMLNode> genHTML(const CommentInfo &I) { - switch (I.Kind) { - case CommentKind::CK_FullComment: { - auto FullComment = std::make_unique<TagNode>(HTMLTag::TAG_DIV); - for (const auto &Child : I.Children) { - std::unique_ptr<HTMLNode> Node = genHTML(*Child); - if (Node) - FullComment->Children.emplace_back(std::move(Node)); - } - return std::move(FullComment); - } - - case CommentKind::CK_ParagraphComment: { - auto ParagraphComment = std::make_unique<TagNode>(HTMLTag::TAG_P); - for (const auto &Child : I.Children) { - std::unique_ptr<HTMLNode> Node = genHTML(*Child); - if (Node) - ParagraphComment->Children.emplace_back(std::move(Node)); - } - if (ParagraphComment->Children.empty()) - return nullptr; - return std::move(ParagraphComment); - } - - case CommentKind::CK_BlockCommandComment: { - auto BlockComment = std::make_unique<TagNode>(HTMLTag::TAG_DIV); - BlockComment->Children.emplace_back( - std::make_unique<TagNode>(HTMLTag::TAG_DIV, I.Name)); - for (const auto &Child : I.Children) { - std::unique_ptr<HTMLNode> Node = genHTML(*Child); - if (Node) - BlockComment->Children.emplace_back(std::move(Node)); - } - if (BlockComment->Children.empty()) - return nullptr; - return std::move(BlockComment); - } - - case CommentKind::CK_TextComment: { - if (I.Text.empty()) - return nullptr; - return std::make_unique<TextNode>(I.Text); - } - - // For now, return nullptr for unsupported comment kinds - case CommentKind::CK_InlineCommandComment: - case CommentKind::CK_HTMLStartTagComment: - case CommentKind::CK_HTMLEndTagComment: - case CommentKind::CK_ParamCommandComment: - case CommentKind::CK_TParamCommandComment: - case CommentKind::CK_VerbatimBlockComment: - case CommentKind::CK_VerbatimBlockLineComment: - case CommentKind::CK_VerbatimLineComment: - case CommentKind::CK_Unknown: - return nullptr; - } - llvm_unreachable("Unhandled CommentKind"); -} - -static std::unique_ptr<TagNode> genHTML(const std::vector<CommentInfo> &C) { - auto CommentBlock = std::make_unique<TagNode>(HTMLTag::TAG_DIV); - for (const auto &Child : C) { - if (std::unique_ptr<HTMLNode> Node = genHTML(Child)) - CommentBlock->Children.emplace_back(std::move(Node)); - } - return CommentBlock; -} - -static std::vector<std::unique_ptr<TagNode>> -genHTML(const EnumInfo &I, const ClangDocContext &CDCtx) { - std::vector<std::unique_ptr<TagNode>> Out; - std::string EnumType = I.Scoped ? "enum class " : "enum "; - // Determine if enum members have comments attached - bool HasComments = llvm::any_of( - I.Members, [](const EnumValueInfo &M) { return !M.Description.empty(); }); - std::unique_ptr<TagNode> Table = - std::make_unique<TagNode>(HTMLTag::TAG_TABLE); - std::unique_ptr<TagNode> THead = - std::make_unique<TagNode>(HTMLTag::TAG_THEAD); - std::unique_ptr<TagNode> TRow = std::make_unique<TagNode>(HTMLTag::TAG_TR); - std::unique_ptr<TagNode> TD = - std::make_unique<TagNode>(HTMLTag::TAG_TH, EnumType + I.Name); - // Span 3 columns if enum has comments - TD->Attributes.emplace_back("colspan", HasComments ? "3" : "2"); - - Table->Attributes.emplace_back("id", llvm::toHex(llvm::toStringRef(I.USR))); - TRow->Children.emplace_back(std::move(TD)); - THead->Children.emplace_back(std::move(TRow)); - Table->Children.emplace_back(std::move(THead)); - - if (std::unique_ptr<TagNode> Node = genEnumMembersBlock(I.Members)) - Table->Children.emplace_back(std::move(Node)); +static std::unique_ptr<MustacheTemplateFile> NamespaceTemplate = nullptr; - Out.emplace_back(std::move(Table)); - - maybeWriteSourceFileRef(Out, CDCtx, I.DefLoc); - - if (!I.Description.empty()) - Out.emplace_back(genHTML(I.Description)); - - return Out; -} - -static std::vector<std::unique_ptr<TagNode>> -genHTML(const FunctionInfo &I, const ClangDocContext &CDCtx, - StringRef ParentInfoDir) { - std::vector<std::unique_ptr<TagNode>> Out; - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name)); - // USR is used as id for functions instead of name to disambiguate function - // overloads. - Out.back()->Attributes.emplace_back("id", - llvm::toHex(llvm::toStringRef(I.USR))); - - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_P)); - auto &FunctionHeader = Out.back(); - - std::string Access = getAccessSpelling(I.Access).str(); - if (Access != "") - FunctionHeader->Children.emplace_back( - std::make_unique<TextNode>(Access + " ")); - if (I.IsStatic) - FunctionHeader->Children.emplace_back( - std::make_unique<TextNode>("static ")); - if (I.ReturnType.Type.Name != "") { - FunctionHeader->Children.emplace_back( - genReference(I.ReturnType.Type, ParentInfoDir)); - FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(" ")); - } - FunctionHeader->Children.emplace_back( - std::make_unique<TextNode>(I.Name + "(")); - - for (const auto &P : I.Params) { - if (&P != I.Params.begin()) - FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(", ")); - FunctionHeader->Children.emplace_back(genReference(P.Type, ParentInfoDir)); - FunctionHeader->Children.emplace_back( - std::make_unique<TextNode>(" " + P.Name)); - } - FunctionHeader->Children.emplace_back(std::make_unique<TextNode>(")")); - - maybeWriteSourceFileRef(Out, CDCtx, I.DefLoc); - - if (!I.Description.empty()) - Out.emplace_back(genHTML(I.Description)); - - return Out; -} +static std::unique_ptr<MustacheTemplateFile> RecordTemplate = nullptr; -static std::vector<std::unique_ptr<TagNode>> -genHTML(const NamespaceInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx, - std::string &InfoTitle) { - std::vector<std::unique_ptr<TagNode>> Out; - if (I.Name.str() == "") - InfoTitle = "Global Namespace"; - else - InfoTitle = ("namespace " + I.Name).str(); - - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle)); - - if (!I.Description.empty()) - Out.emplace_back(genHTML(I.Description)); - - llvm::SmallString<64> BasePath = I.getRelativeFilePath(""); - - std::vector<std::unique_ptr<TagNode>> ChildNamespaces = - genReferencesBlock(I.Children.Namespaces, "Namespaces", BasePath); - appendVector(std::move(ChildNamespaces), Out); - std::vector<std::unique_ptr<TagNode>> ChildRecords = - genReferencesBlock(I.Children.Records, "Records", BasePath); - appendVector(std::move(ChildRecords), Out); - - std::vector<std::unique_ptr<TagNode>> ChildFunctions = - genFunctionsBlock(I.Children.Functions, CDCtx, BasePath); - appendVector(std::move(ChildFunctions), Out); - std::vector<std::unique_ptr<TagNode>> ChildEnums = - genEnumsBlock(I.Children.Enums, CDCtx); - appendVector(std::move(ChildEnums), Out); - - if (!I.Children.Namespaces.empty()) - InfoIndex.Children.emplace_back("Namespaces", "Namespaces"); - if (!I.Children.Records.empty()) - InfoIndex.Children.emplace_back("Records", "Records"); - if (!I.Children.Functions.empty()) - InfoIndex.Children.emplace_back( - genInfoIndexItem(I.Children.Functions, "Functions")); - if (!I.Children.Enums.empty()) - InfoIndex.Children.emplace_back( - genInfoIndexItem(I.Children.Enums, "Enums")); - - return Out; -} - -static std::vector<std::unique_ptr<TagNode>> -genHTML(const RecordInfo &I, Index &InfoIndex, const ClangDocContext &CDCtx, - std::string &InfoTitle) { - std::vector<std::unique_ptr<TagNode>> Out; - InfoTitle = (getTagType(I.TagType) + " " + I.Name).str(); - Out.emplace_back(std::make_unique<TagNode>(HTMLTag::TAG_H1, InfoTitle)); - - maybeWriteSourceFileRef(Out, CDCtx, I.DefLoc); - - if (!I.Description.empty()) - Out.emplace_back(genHTML(I.Description)); - - 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(std::make_unique<TagNode>(HTMLTag::TAG_P)); - auto &PBody = Out.back(); - PBody->Children.emplace_back(std::make_unique<TextNode>("Inherits from ")); - if (Parents.empty()) - appendVector(std::move(VParents), PBody->Children); - else if (VParents.empty()) - appendVector(std::move(Parents), PBody->Children); - else { - appendVector(std::move(Parents), PBody->Children); - PBody->Children.emplace_back(std::make_unique<TextNode>(", ")); - appendVector(std::move(VParents), PBody->Children); - } - } - - std::vector<std::unique_ptr<TagNode>> Members = - genRecordMembersBlock(I.Members, I.Path); - appendVector(std::move(Members), Out); - std::vector<std::unique_ptr<TagNode>> ChildRecords = - genReferencesBlock(I.Children.Records, "Records", I.Path); - appendVector(std::move(ChildRecords), Out); - - std::vector<std::unique_ptr<TagNode>> ChildFunctions = - genFunctionsBlock(I.Children.Functions, CDCtx, I.Path); - appendVector(std::move(ChildFunctions), Out); - std::vector<std::unique_ptr<TagNode>> ChildEnums = - genEnumsBlock(I.Children.Enums, CDCtx); - appendVector(std::move(ChildEnums), Out); - - if (!I.Members.empty()) - InfoIndex.Children.emplace_back("Members", "Members"); - if (!I.Children.Records.empty()) - InfoIndex.Children.emplace_back("Records", "Records"); - if (!I.Children.Functions.empty()) - InfoIndex.Children.emplace_back( - genInfoIndexItem(I.Children.Functions, "Functions")); - if (!I.Children.Enums.empty()) - InfoIndex.Children.emplace_back( - genInfoIndexItem(I.Children.Enums, "Enums")); - - return Out; -} - -static std::vector<std::unique_ptr<TagNode>> -genHTML(const TypedefInfo &I, const ClangDocContext &CDCtx, - std::string &InfoTitle) { - // TODO support typedefs in HTML. - return {}; -} - -/// Generator for HTML documentation. -class HTMLGenerator : public Generator { +class HTMLGenerator : public MustacheGenerator { public: static const char *Format; - - llvm::Error generateDocs(StringRef RootDir, - llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + Error createResources(ClangDocContext &CDCtx) override; + Error generateDocForInfo(Info *I, raw_ostream &OS, const ClangDocContext &CDCtx) override; - llvm::Error createResources(ClangDocContext &CDCtx) override; - llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS, - const ClangDocContext &CDCtx) override; + Error setupTemplateFiles(const ClangDocContext &CDCtx) override; + Error generateDocForJSON(json::Value &JSON, raw_fd_ostream &OS, + const ClangDocContext &CDCtx, StringRef ObjTypeStr, + StringRef RelativeRootPath) override; + // Populates templates with CSS stylesheets, JS scripts paths. + Error setupTemplateResources(const ClangDocContext &CDCtx, json::Value &V, + SmallString<128> RelativeRootPath); + llvm::Error generateDocumentation( + StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const ClangDocContext &CDCtx, std::string DirName) override; }; -const char *HTMLGenerator::Format = "html"; - -llvm::Error -HTMLGenerator::generateDocs(StringRef RootDir, - llvm::StringMap<std::unique_ptr<doc::Info>> Infos, - const ClangDocContext &CDCtx) { - // Track which directories we already tried to create. - llvm::StringSet<> CreatedDirs; +Error HTMLGenerator::setupTemplateFiles(const ClangDocContext &CDCtx) { + // Template files need to use the native path when they're opened, + // but have to be used in POSIX style when used in HTML. + auto ConvertToNative = [](std::string &&Path) -> std::string { + SmallString<128> PathBuf(Path); + llvm::sys::path::native(PathBuf); + return PathBuf.str().str(); + }; - // Collect all output by file name and create the nexessary directories. - llvm::StringMap<std::vector<doc::Info *>> FileToInfos; - for (const auto &Group : Infos) { - doc::Info *Info = Group.getValue().get(); + std::string NamespaceFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("namespace-template")); + std::string ClassFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("class-template")); + std::string CommentFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("comment-template")); + std::string FunctionFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("function-template")); + std::string EnumFilePath = + ConvertToNative(CDCtx.MustacheTemplates.lookup("enum-template")); + std::vector<std::pair<StringRef, StringRef>> Partials = { + {"Comments", CommentFilePath}, + {"FunctionPartial", FunctionFilePath}, + {"EnumPartial", EnumFilePath}}; + + if (Error Err = setupTemplate(NamespaceTemplate, NamespaceFilePath, Partials)) + return Err; - llvm::SmallString<128> Path; - llvm::sys::path::native(RootDir, Path); - llvm::sys::path::append(Path, Info->getRelativeFilePath("")); - if (!CreatedDirs.contains(Path)) { - if (std::error_code Err = llvm::sys::fs::create_directories(Path); - Err != std::error_code()) { - return llvm::createStringError(Err, "Failed to create directory '%s'.", - Path.c_str()); - } - CreatedDirs.insert(Path); - } + if (Error Err = setupTemplate(RecordTemplate, ClassFilePath, Partials)) + return Err; - llvm::sys::path::append(Path, Info->getFileBaseName() + ".html"); - FileToInfos[Path].push_back(Info); - } + return Error::success(); +} - for (const auto &Group : FileToInfos) { - std::error_code FileErr; - llvm::raw_fd_ostream InfoOS(Group.getKey(), FileErr, - llvm::sys::fs::OF_Text); - if (FileErr) { - return llvm::createStringError(FileErr, "Error opening file '%s'", - Group.getKey().str().c_str()); - } +Error HTMLGenerator::setupTemplateResources(const ClangDocContext &CDCtx, + json::Value &V, + SmallString<128> RelativeRootPath) { + V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName}); + json::Value StylesheetArr = Array(); + sys::path::native(RelativeRootPath, sys::path::Style::posix); - // TODO: https://github.com/llvm/llvm-project/issues/59073 - // If there are multiple Infos for this file name (for example, template - // specializations), this will generate multiple complete web pages (with - // <DOCTYPE> and <title>, etc.) concatenated together. This generator needs - // some refactoring to be able to output the headers separately from the - // contents. - for (const auto &Info : Group.getValue()) { - if (llvm::Error Err = generateDocForInfo(Info, InfoOS, CDCtx)) { - return Err; - } - } + auto *SSA = StylesheetArr.getAsArray(); + SSA->reserve(CDCtx.UserStylesheets.size()); + for (const auto &FilePath : CDCtx.UserStylesheets) { + SmallString<128> StylesheetPath = RelativeRootPath; + sys::path::append(StylesheetPath, sys::path::Style::posix, + sys::path::filename(FilePath)); + SSA->emplace_back(StylesheetPath); + } + V.getAsObject()->insert({"Stylesheets", StylesheetArr}); + + json::Value ScriptArr = Array(); + auto *SCA = ScriptArr.getAsArray(); + SCA->reserve(CDCtx.JsScripts.size()); + for (auto Script : CDCtx.JsScripts) { + SmallString<128> JsPath = RelativeRootPath; + sys::path::append(JsPath, sys::path::Style::posix, + sys::path::filename(Script)); + SCA->emplace_back(JsPath); + } + V.getAsObject()->insert({"Scripts", ScriptArr}); + return Error::success(); +} + +Error HTMLGenerator::generateDocForJSON(json::Value &JSON, raw_fd_ostream &OS, + const ClangDocContext &CDCtx, + StringRef ObjTypeStr, + StringRef RelativeRootPath) { + if (ObjTypeStr == "namespace") { + if (auto Err = setupTemplateResources(CDCtx, JSON, RelativeRootPath)) + return Err; + assert(NamespaceTemplate && "NamespaceTemplate is nullptr."); + NamespaceTemplate->render(JSON, OS); + } else if (ObjTypeStr == "record") { + if (auto Err = setupTemplateResources(CDCtx, JSON, RelativeRootPath)) + return Err; + assert(RecordTemplate && "RecordTemplate is nullptr."); + RecordTemplate->render(JSON, OS); } - - return llvm::Error::success(); + return Error::success(); } -llvm::Error HTMLGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS, - const ClangDocContext &CDCtx) { - std::string InfoTitle; - std::vector<std::unique_ptr<TagNode>> MainContentNodes; - Index InfoIndex; +Error HTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, + const ClangDocContext &CDCtx) { switch (I->IT) { - case InfoType::IT_namespace: - MainContentNodes = genHTML(*static_cast<clang::doc::NamespaceInfo *>(I), - InfoIndex, CDCtx, InfoTitle); - break; - case InfoType::IT_record: - MainContentNodes = genHTML(*static_cast<clang::doc::RecordInfo *>(I), - InfoIndex, CDCtx, InfoTitle); - break; case InfoType::IT_enum: - MainContentNodes = genHTML(*static_cast<clang::doc::EnumInfo *>(I), CDCtx); - break; case InfoType::IT_function: - MainContentNodes = - genHTML(*static_cast<clang::doc::FunctionInfo *>(I), CDCtx, ""); - break; case InfoType::IT_typedef: - MainContentNodes = - genHTML(*static_cast<clang::doc::TypedefInfo *>(I), CDCtx, InfoTitle); - break; - case InfoType::IT_concept: - case InfoType::IT_variable: - case InfoType::IT_friend: - break; - case InfoType::IT_default: - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "unexpected info type"); - } - - HTMLFile F = genInfoFile(InfoTitle, I->getRelativeFilePath(""), - MainContentNodes, InfoIndex, CDCtx); - F.render(OS); - - return llvm::Error::success(); -} - -static std::string getRefType(InfoType IT) { - switch (IT) { - case InfoType::IT_default: - return "default"; case InfoType::IT_namespace: - return "namespace"; case InfoType::IT_record: - return "record"; - case InfoType::IT_function: - return "function"; - case InfoType::IT_enum: - return "enum"; - case InfoType::IT_typedef: - return "typedef"; case InfoType::IT_concept: - return "concept"; case InfoType::IT_variable: - return "variable"; case InfoType::IT_friend: - return "friend"; - } - llvm_unreachable("Unknown InfoType"); -} - -static llvm::Error serializeIndex(ClangDocContext &CDCtx) { - std::error_code OK; - std::error_code FileErr; - llvm::SmallString<128> FilePath; - llvm::sys::path::native(CDCtx.OutDirectory, FilePath); - llvm::sys::path::append(FilePath, "index_json.js"); - llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_Text); - if (FileErr != OK) { - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "error creating index file: " + - FileErr.message()); - } - llvm::SmallString<128> RootPath(CDCtx.OutDirectory); - if (llvm::sys::path::is_relative(RootPath)) { - llvm::sys::fs::make_absolute(RootPath); + break; + case InfoType::IT_default: + return createStringError(inconvertibleErrorCode(), "unexpected InfoType"); } - // Replace the escaped characters with a forward slash. It shouldn't matter - // when rendering the webpage in a web browser. This helps to prevent the - // JavaScript from escaping characters incorrectly, and introducing bad paths - // in the URLs. - std::string RootPathEscaped = RootPath.str().str(); - llvm::replace(RootPathEscaped, '\\', '/'); - OS << "var RootPath = \"" << RootPathEscaped << "\";\n"; - - llvm::SmallString<128> Base(CDCtx.Base); - std::string BaseEscaped = Base.str().str(); - llvm::replace(BaseEscaped, '\\', '/'); - OS << "var Base = \"" << BaseEscaped << "\";\n"; - - CDCtx.Idx.sort(); - llvm::json::OStream J(OS, 2); - std::function<void(Index)> IndexToJSON = [&](const Index &I) { - J.object([&] { - J.attribute("USR", toHex(llvm::toStringRef(I.USR))); - J.attribute("Name", I.Name); - J.attribute("RefType", getRefType(I.RefType)); - J.attribute("Path", I.getRelativeFilePath("")); - J.attributeArray("Children", [&] { - for (const Index &C : I.Children) - IndexToJSON(C); - }); - }); - }; - OS << "async function LoadIndex() {\nreturn"; - IndexToJSON(CDCtx.Idx); - OS << ";\n}"; - return llvm::Error::success(); + return Error::success(); } -// Generates a main HTML node that has the main content of the file that shows -// only the general index -// It contains the general index with links to all the generated files -static std::unique_ptr<TagNode> genIndexFileMainNode() { - auto MainNode = std::make_unique<TagNode>(HTMLTag::TAG_MAIN); - - auto LeftSidebarNode = std::make_unique<TagNode>(HTMLTag::TAG_DIV); - LeftSidebarNode->Attributes.emplace_back("id", "sidebar-left"); - LeftSidebarNode->Attributes.emplace_back("path", ""); - LeftSidebarNode->Attributes.emplace_back( - "class", "col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"); - LeftSidebarNode->Attributes.emplace_back("style", "flex: 0 100%;"); - - MainNode->Children.emplace_back(std::move(LeftSidebarNode)); - - return MainNode; +Error HTMLGenerator::createResources(ClangDocContext &CDCtx) { + std::string ResourcePath(CDCtx.OutDirectory + "/html"); + for (const auto &FilePath : CDCtx.UserStylesheets) + if (Error Err = copyFile(FilePath, ResourcePath)) + return Err; + for (const auto &FilePath : CDCtx.JsScripts) + if (Error Err = copyFile(FilePath, ResourcePath)) + return Err; + return Error::success(); } -static llvm::Error genIndex(const ClangDocContext &CDCtx) { - std::error_code FileErr, OK; - llvm::SmallString<128> IndexPath; - llvm::sys::path::native(CDCtx.OutDirectory, IndexPath); - llvm::sys::path::append(IndexPath, "index.html"); - llvm::raw_fd_ostream IndexOS(IndexPath, FileErr, llvm::sys::fs::OF_Text); - if (FileErr != OK) { - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "error creating main index: " + - FileErr.message()); - } - - HTMLFile F; - - std::vector<std::unique_ptr<TagNode>> HeadNodes = - genFileHeadNodes("Index", "", CDCtx); - std::unique_ptr<TagNode> HeaderNode = genFileHeaderNode(CDCtx.ProjectName); - std::unique_ptr<TagNode> MainNode = genIndexFileMainNode(); - std::unique_ptr<TagNode> FooterNode = genFileFooterNode(); - - appendVector(std::move(HeadNodes), F.Children); - F.Children.emplace_back(std::move(HeaderNode)); - F.Children.emplace_back(std::move(MainNode)); - F.Children.emplace_back(std::move(FooterNode)); - - F.render(IndexOS); - - return llvm::Error::success(); +Error HTMLGenerator::generateDocumentation( + StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const ClangDocContext &CDCtx, std::string DirName) { + return MustacheGenerator::generateDocumentation(RootDir, std::move(Infos), + CDCtx, "html"); } -llvm::Error HTMLGenerator::createResources(ClangDocContext &CDCtx) { - auto Err = serializeIndex(CDCtx); - if (Err) - return Err; - Err = genIndex(CDCtx); - if (Err) - return Err; - - for (const auto &FilePath : CDCtx.UserStylesheets) { - Err = copyFile(FilePath, CDCtx.OutDirectory); - if (Err) - return Err; - } - for (const auto &FilePath : CDCtx.JsScripts) { - Err = copyFile(FilePath, CDCtx.OutDirectory); - if (Err) - return Err; - } - return llvm::Error::success(); -} +const char *HTMLGenerator::Format = "html"; -static GeneratorRegistry::Add<HTMLGenerator> HTML(HTMLGenerator::Format, - "Generator for HTML output."); +static GeneratorRegistry::Add<HTMLGenerator> + HTML(HTMLGenerator::Format, "Generator for mustache HTML output."); // This anchor is used to force the linker to link in the generated object // file and thus register the generator. diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp deleted file mode 100644 index 1e75710..0000000 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ /dev/null @@ -1,319 +0,0 @@ -///===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// This file contains the implementation of the MustacheHTMLGenerator class, -/// which is Clang-Doc generator for HTML using Mustache templates. -/// -//===----------------------------------------------------------------------===// - -#include "Generators.h" -#include "Representation.h" -#include "support/File.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Mustache.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/TimeProfiler.h" - -using namespace llvm; -using namespace llvm::json; -using namespace llvm::mustache; - -namespace clang { -namespace doc { -static Error generateDocForJSON(json::Value &JSON, StringRef Filename, - StringRef Path, raw_fd_ostream &OS, - const ClangDocContext &CDCtx, - StringRef HTMLRootPath); - -static Error createFileOpenError(StringRef FileName, std::error_code EC) { - return createFileError("cannot open file " + FileName, EC); -} - -class MustacheHTMLGenerator : public Generator { -public: - static const char *Format; - Error generateDocs(StringRef RootDir, - StringMap<std::unique_ptr<doc::Info>> Infos, - const ClangDocContext &CDCtx) override; - Error createResources(ClangDocContext &CDCtx) override; - Error generateDocForInfo(Info *I, raw_ostream &OS, - const ClangDocContext &CDCtx) override; -}; - -class MustacheTemplateFile { - BumpPtrAllocator Allocator; - StringSaver Saver; - MustacheContext Ctx; - Template T; - std::unique_ptr<MemoryBuffer> Buffer; - -public: - static Expected<std::unique_ptr<MustacheTemplateFile>> - createMustacheFile(StringRef FileName) { - ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError = - MemoryBuffer::getFile(FileName); - if (auto EC = BufferOrError.getError()) - return createFileOpenError(FileName, EC); - return std::make_unique<MustacheTemplateFile>( - std::move(BufferOrError.get())); - } - - Error registerPartialFile(StringRef Name, StringRef FileName) { - ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError = - MemoryBuffer::getFile(FileName); - if (auto EC = BufferOrError.getError()) - return createFileOpenError(FileName, EC); - - std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrError.get()); - StringRef FileContent = Buffer->getBuffer(); - T.registerPartial(Name.str(), FileContent.str()); - return Error::success(); - } - - void render(json::Value &V, raw_ostream &OS) { T.render(V, OS); } - - MustacheTemplateFile(std::unique_ptr<MemoryBuffer> &&B) - : Saver(Allocator), Ctx(Allocator, Saver), T(B->getBuffer(), Ctx), - Buffer(std::move(B)) {} -}; - -static std::unique_ptr<MustacheTemplateFile> NamespaceTemplate = nullptr; - -static std::unique_ptr<MustacheTemplateFile> RecordTemplate = nullptr; - -static Error -setupTemplate(std::unique_ptr<MustacheTemplateFile> &Template, - StringRef TemplatePath, - std::vector<std::pair<StringRef, StringRef>> Partials) { - auto T = MustacheTemplateFile::createMustacheFile(TemplatePath); - if (Error Err = T.takeError()) - return Err; - Template = std::move(T.get()); - for (const auto &[Name, FileName] : Partials) - if (auto Err = Template->registerPartialFile(Name, FileName)) - return Err; - return Error::success(); -} - -static Error setupTemplateFiles(const clang::doc::ClangDocContext &CDCtx) { - // Template files need to use the native path when they're opened, - // but have to be used in POSIX style when used in HTML. - auto ConvertToNative = [](std::string &&Path) -> std::string { - SmallString<128> PathBuf(Path); - llvm::sys::path::native(PathBuf); - return PathBuf.str().str(); - }; - - std::string NamespaceFilePath = - ConvertToNative(CDCtx.MustacheTemplates.lookup("namespace-template")); - std::string ClassFilePath = - ConvertToNative(CDCtx.MustacheTemplates.lookup("class-template")); - std::string CommentFilePath = - ConvertToNative(CDCtx.MustacheTemplates.lookup("comment-template")); - std::string FunctionFilePath = - ConvertToNative(CDCtx.MustacheTemplates.lookup("function-template")); - std::string EnumFilePath = - ConvertToNative(CDCtx.MustacheTemplates.lookup("enum-template")); - std::vector<std::pair<StringRef, StringRef>> Partials = { - {"Comments", CommentFilePath}, - {"FunctionPartial", FunctionFilePath}, - {"EnumPartial", EnumFilePath}}; - - if (Error Err = setupTemplate(NamespaceTemplate, NamespaceFilePath, Partials)) - return Err; - - if (Error Err = setupTemplate(RecordTemplate, ClassFilePath, Partials)) - return Err; - - return Error::success(); -} - -Error MustacheHTMLGenerator::generateDocs( - StringRef RootDir, StringMap<std::unique_ptr<doc::Info>> Infos, - const clang::doc::ClangDocContext &CDCtx) { - { - llvm::TimeTraceScope TS("Setup Templates"); - if (auto Err = setupTemplateFiles(CDCtx)) - return Err; - } - - { - llvm::TimeTraceScope TS("Generate JSON for Mustache"); - if (auto JSONGenerator = findGeneratorByName("json")) { - if (Error Err = JSONGenerator.get()->generateDocs( - RootDir, std::move(Infos), CDCtx)) - return Err; - } else - return JSONGenerator.takeError(); - } - SmallString<128> JSONPath; - sys::path::native(RootDir.str() + "/json", JSONPath); - - { - llvm::TimeTraceScope TS("Iterate JSON files"); - std::error_code EC; - sys::fs::recursive_directory_iterator JSONIter(JSONPath, EC); - std::vector<json::Value> JSONFiles; - JSONFiles.reserve(Infos.size()); - if (EC) - return createStringError("Failed to create directory iterator."); - - SmallString<128> HTMLDirPath(RootDir.str() + "/html"); - if (auto EC = sys::fs::create_directories(HTMLDirPath)) - return createFileError(HTMLDirPath, EC); - while (JSONIter != sys::fs::recursive_directory_iterator()) { - // create the same directory structure in the HTML dir - if (JSONIter->type() == sys::fs::file_type::directory_file) { - SmallString<128> HTMLClonedPath(JSONIter->path()); - sys::path::replace_path_prefix(HTMLClonedPath, JSONPath, HTMLDirPath); - if (auto EC = sys::fs::create_directories(HTMLClonedPath)) - return createFileError(HTMLClonedPath, EC); - } - - if (EC) - return createFileError("Failed to iterate: " + JSONIter->path(), EC); - - auto Path = StringRef(JSONIter->path()); - if (!Path.ends_with(".json")) { - JSONIter.increment(EC); - continue; - } - - 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'; - - auto Parsed = json::parse((*File)->getBuffer()); - if (!Parsed) - return Parsed.takeError(); - - std::error_code FileErr; - SmallString<128> HTMLFilePath(JSONIter->path()); - sys::path::replace_path_prefix(HTMLFilePath, JSONPath, HTMLDirPath); - sys::path::replace_extension(HTMLFilePath, "html"); - raw_fd_ostream InfoOS(HTMLFilePath, FileErr, sys::fs::OF_None); - if (FileErr) - return createFileOpenError(Path, FileErr); - - if (Error Err = - generateDocForJSON(*Parsed, sys::path::stem(HTMLFilePath), - HTMLFilePath, InfoOS, CDCtx, HTMLDirPath)) - return Err; - JSONIter.increment(EC); - } - } - - return Error::success(); -} - -static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V, - SmallString<128> RelativeHTMLPath) { - V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName}); - json::Value StylesheetArr = Array(); - sys::path::native(RelativeHTMLPath, sys::path::Style::posix); - - auto *SSA = StylesheetArr.getAsArray(); - SSA->reserve(CDCtx.UserStylesheets.size()); - for (const auto &FilePath : CDCtx.UserStylesheets) { - SmallString<128> StylesheetPath = RelativeHTMLPath; - sys::path::append(StylesheetPath, sys::path::Style::posix, - sys::path::filename(FilePath)); - SSA->emplace_back(StylesheetPath); - } - V.getAsObject()->insert({"Stylesheets", StylesheetArr}); - - json::Value ScriptArr = Array(); - auto *SCA = ScriptArr.getAsArray(); - SCA->reserve(CDCtx.JsScripts.size()); - for (auto Script : CDCtx.JsScripts) { - SmallString<128> JsPath = RelativeHTMLPath; - sys::path::append(JsPath, sys::path::Style::posix, - sys::path::filename(Script)); - SCA->emplace_back(JsPath); - } - V.getAsObject()->insert({"Scripts", ScriptArr}); - return Error::success(); -} - -static Error generateDocForJSON(json::Value &JSON, StringRef Filename, - StringRef Path, raw_fd_ostream &OS, - const ClangDocContext &CDCtx, - StringRef HTMLRootPath) { - auto StrValue = (*JSON.getAsObject())["InfoType"]; - if (StrValue.kind() != json::Value::Kind::String) - return createStringError("JSON file '%s' does not contain key: 'InfoType'.", - Filename.str().c_str()); - auto ObjTypeStr = StrValue.getAsString(); - if (!ObjTypeStr.has_value()) - return createStringError( - "JSON file '%s' does not contain 'InfoType' field as a string.", - Filename.str().c_str()); - - SmallString<128> PathVec(Path); - // Remove filename, or else the relative path will have an extra "../" - sys::path::remove_filename(PathVec); - auto RelativeHTMLPath = computeRelativePath(HTMLRootPath, PathVec); - if (ObjTypeStr.value() == "namespace") { - if (auto Err = setupTemplateValue(CDCtx, JSON, RelativeHTMLPath)) - return Err; - assert(NamespaceTemplate && "NamespaceTemplate is nullptr."); - NamespaceTemplate->render(JSON, OS); - } else if (ObjTypeStr.value() == "record") { - if (auto Err = setupTemplateValue(CDCtx, JSON, RelativeHTMLPath)) - return Err; - assert(RecordTemplate && "RecordTemplate is nullptr."); - RecordTemplate->render(JSON, OS); - } - return Error::success(); -} - -Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, - const ClangDocContext &CDCtx) { - switch (I->IT) { - case InfoType::IT_enum: - case InfoType::IT_function: - case InfoType::IT_typedef: - case InfoType::IT_namespace: - case InfoType::IT_record: - case InfoType::IT_concept: - case InfoType::IT_variable: - case InfoType::IT_friend: - break; - case InfoType::IT_default: - return createStringError(inconvertibleErrorCode(), "unexpected InfoType"); - } - return Error::success(); -} - -Error MustacheHTMLGenerator::createResources(ClangDocContext &CDCtx) { - std::string ResourcePath(CDCtx.OutDirectory + "/html"); - for (const auto &FilePath : CDCtx.UserStylesheets) - if (Error Err = copyFile(FilePath, ResourcePath)) - return Err; - for (const auto &FilePath : CDCtx.JsScripts) - if (Error Err = copyFile(FilePath, ResourcePath)) - return Err; - return Error::success(); -} - -const char *MustacheHTMLGenerator::Format = "mustache"; - -static GeneratorRegistry::Add<MustacheHTMLGenerator> - MHTML(MustacheHTMLGenerator::Format, "Generator for mustache HTML output."); - -// This anchor is used to force the linker to link in the generated object -// file and thus register the generator. -volatile int MHTMLGeneratorAnchorSource = 0; - -} // namespace doc -} // namespace clang diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index 9a770d7..77aa879 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -12,9 +12,10 @@ class JSONGenerator : public Generator { public: static const char *Format; - Error generateDocs(StringRef RootDir, - llvm::StringMap<std::unique_ptr<doc::Info>> Infos, - const ClangDocContext &CDCtx) override; + Error generateDocumentation(StringRef RootDir, + llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const ClangDocContext &CDCtx, + std::string DirName) override; Error createResources(ClangDocContext &CDCtx) override; Error generateDocForInfo(Info *I, llvm::raw_ostream &OS, const ClangDocContext &CDCtx) override; @@ -83,8 +84,23 @@ serializeLocation(const Location &Loc, return LocationObj; } +/// Insert comments into a key in the Description object. +/// +/// \param Comment Either an Object or Array, depending on the comment type +/// \param Key The type (Brief, Code, etc.) of comment to be inserted static void insertComment(Object &Description, json::Value &Comment, StringRef Key) { + // The comment has a Children array for the actual text, with meta attributes + // alongside it in the Object. + if (auto *Obj = Comment.getAsObject()) { + if (auto *Children = Obj->getArray("Children"); Children->empty()) + return; + } + // The comment is just an array of text comments. + else if (auto *Array = Comment.getAsArray(); Array->empty()) { + return; + } + auto DescriptionIt = Description.find(Key); if (DescriptionIt == Description.end()) { @@ -97,10 +113,28 @@ static void insertComment(Object &Description, json::Value &Comment, } } +/// Takes the nested "Children" array from a comment Object. +/// +/// \return a json::Array of comments, possible json::Value::Kind::Null static json::Value extractTextComments(Object *ParagraphComment) { if (!ParagraphComment) - return json::Object(); - return *ParagraphComment->get("Children"); + return json::Value(nullptr); + json::Value *Children = ParagraphComment->get("Children"); + if (!Children) + return json::Value(nullptr); + auto ChildrenArray = *Children->getAsArray(); + auto ChildrenIt = ChildrenArray.begin(); + while (ChildrenIt != ChildrenArray.end()) { + auto *ChildObj = ChildrenIt->getAsObject(); + assert(ChildObj && "Invalid JSON object in Comment"); + auto TextComment = ChildObj->getString("TextComment"); + if (!TextComment || TextComment->empty()) { + ChildrenIt = ChildrenArray.erase(ChildrenIt); + continue; + } + ++ChildrenIt; + } + return ChildrenArray; } static json::Value extractVerbatimComments(json::Array VerbatimLines) { @@ -130,7 +164,8 @@ static Object serializeComment(const CommentInfo &I, Object &Description) { switch (I.Kind) { case CommentKind::CK_TextComment: { - Obj.insert({commentKindToString(I.Kind), I.Text}); + if (!I.Text.empty()) + Obj.insert({commentKindToString(I.Kind), I.Text}); return Obj; } @@ -140,6 +175,13 @@ static Object serializeComment(const CommentInfo &I, Object &Description) { insertComment(Description, TextCommentsArray, "BriefComments"); else if (I.Name == "return") insertComment(Description, TextCommentsArray, "ReturnComments"); + else if (I.Name == "throws" || I.Name == "throw") { + json::Value ThrowsVal = Object(); + auto &ThrowsObj = *ThrowsVal.getAsObject(); + ThrowsObj["Exception"] = I.Args.front(); + ThrowsObj["Children"] = TextCommentsArray; + insertComment(Description, ThrowsVal, "ThrowsComments"); + } return Obj; } @@ -257,6 +299,9 @@ serializeCommonAttributes(const Info &I, json::Object &Obj, if (auto *ParagraphComment = Comment.getAsObject(); ParagraphComment->get("ParagraphComment")) { auto TextCommentsArray = extractTextComments(ParagraphComment); + if (TextCommentsArray.kind() == json::Value::Null || + TextCommentsArray.getAsArray()->empty()) + continue; insertComment(Description, TextCommentsArray, "ParagraphComments"); } } @@ -589,9 +634,9 @@ static SmallString<16> determineFileName(Info *I, SmallString<128> &Path) { return FileName; } -Error JSONGenerator::generateDocs( +Error JSONGenerator::generateDocumentation( StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos, - const ClangDocContext &CDCtx) { + const ClangDocContext &CDCtx, std::string DirName) { StringSet<> CreatedDirs; StringMap<std::vector<doc::Info *>> FileToInfos; for (const auto &Group : Infos) { diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp index 6f16f5b..fcb75af 100644 --- a/clang-tools-extra/clang-doc/MDGenerator.cpp +++ b/clang-tools-extra/clang-doc/MDGenerator.cpp @@ -398,9 +398,9 @@ class MDGenerator : public Generator { public: static const char *Format; - llvm::Error generateDocs(StringRef RootDir, - llvm::StringMap<std::unique_ptr<doc::Info>> Infos, - const ClangDocContext &CDCtx) override; + llvm::Error generateDocumentation( + StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const ClangDocContext &CDCtx, std::string DirName) override; llvm::Error createResources(ClangDocContext &CDCtx) override; llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS, const ClangDocContext &CDCtx) override; @@ -408,10 +408,9 @@ public: const char *MDGenerator::Format = "md"; -llvm::Error -MDGenerator::generateDocs(StringRef RootDir, - llvm::StringMap<std::unique_ptr<doc::Info>> Infos, - const ClangDocContext &CDCtx) { +llvm::Error MDGenerator::generateDocumentation( + StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const ClangDocContext &CDCtx, std::string DirName) { // Track which directories we already tried to create. llvm::StringSet<> CreatedDirs; diff --git a/clang-tools-extra/clang-doc/Mapper.cpp b/clang-tools-extra/clang-doc/Mapper.cpp index 497b80c..24e798a 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/Mapper.h b/clang-tools-extra/clang-doc/Mapper.h index 322df6d..91e9668 100644 --- a/clang-tools-extra/clang-doc/Mapper.h +++ b/clang-tools-extra/clang-doc/Mapper.h @@ -19,7 +19,6 @@ #include "Representation.h" #include "clang/AST/RecursiveASTVisitor.h" -#include "clang/Tooling/Execution.h" using namespace clang::comments; using namespace clang::tooling; diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index 929112f..8eab5fb 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -82,12 +82,10 @@ llvm::StringRef commentKindToString(CommentKind Kind) { llvm_unreachable("Unhandled CommentKind"); } -namespace { - const SymbolID EmptySID = SymbolID(); template <typename T> -llvm::Expected<std::unique_ptr<Info>> +static llvm::Expected<std::unique_ptr<Info>> reduce(std::vector<std::unique_ptr<Info>> &Values) { if (Values.empty() || !Values[0]) return llvm::createStringError(llvm::inconvertibleErrorCode(), @@ -102,7 +100,7 @@ reduce(std::vector<std::unique_ptr<Info>> &Values) { // Return the index of the matching child in the vector, or -1 if merge is not // necessary. template <typename T> -int getChildIndexIfExists(std::vector<T> &Children, T &ChildToMerge) { +static int getChildIndexIfExists(std::vector<T> &Children, T &ChildToMerge) { for (unsigned long I = 0; I < Children.size(); I++) { if (ChildToMerge.USR == Children[I].USR) return I; @@ -111,8 +109,8 @@ int getChildIndexIfExists(std::vector<T> &Children, T &ChildToMerge) { } template <typename T> -void reduceChildren(std::vector<T> &Children, - std::vector<T> &&ChildrenToMerge) { +static void reduceChildren(std::vector<T> &Children, + std::vector<T> &&ChildrenToMerge) { for (auto &ChildToMerge : ChildrenToMerge) { int MergeIdx = getChildIndexIfExists(Children, ChildToMerge); if (MergeIdx == -1) { @@ -123,8 +121,6 @@ void reduceChildren(std::vector<T> &Children, } } -} // namespace - // Dispatch function. llvm::Expected<std::unique_ptr<Info>> mergeInfos(std::vector<std::unique_ptr<Info>> &Values) { @@ -402,7 +398,7 @@ BaseRecordInfo::BaseRecordInfo() : RecordInfo() {} BaseRecordInfo::BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual, AccessSpecifier Access, bool IsParent) - : RecordInfo(USR, Name, Path), IsVirtual(IsVirtual), Access(Access), + : RecordInfo(USR, Name, Path), Access(Access), IsVirtual(IsVirtual), IsParent(IsParent) {} llvm::SmallString<16> Info::extractName() const { @@ -481,10 +477,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 79e9bfc..a3e779a 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -15,11 +15,10 @@ #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/StandaloneExecution.h" -#include "llvm/ADT/APSInt.h" +#include "clang/Tooling/Execution.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" #include <array> #include <optional> #include <string> @@ -87,29 +86,29 @@ struct CommentInfo { // the vector. bool operator<(const CommentInfo &Other) const; - CommentKind Kind = CommentKind:: - CK_Unknown; // Kind of comment (FullComment, ParagraphComment, - // TextComment, InlineCommandComment, HTMLStartTagComment, - // HTMLEndTagComment, BlockCommandComment, - // ParamCommandComment, TParamCommandComment, - // VerbatimBlockComment, VerbatimBlockLineComment, - // VerbatimLineComment). - SmallString<64> Text; // Text of the comment. - SmallString<16> Name; // Name of the comment (for Verbatim and HTML). + std::vector<std::unique_ptr<CommentInfo>> + Children; // List of child comments for this CommentInfo. SmallString<8> Direction; // Parameter direction (for (T)ParamCommand). + SmallString<16> Name; // Name of the comment (for Verbatim and HTML). SmallString<16> ParamName; // Parameter name (for (T)ParamCommand). SmallString<16> CloseName; // Closing tag name (for VerbatimBlock). - bool SelfClosing = false; // Indicates if tag is self-closing (for HTML). - bool Explicit = false; // Indicates if the direction of a param is explicit - // (for (T)ParamCommand). + SmallString<64> Text; // Text of the comment. llvm::SmallVector<SmallString<16>, 4> AttrKeys; // List of attribute keys (for HTML). llvm::SmallVector<SmallString<16>, 4> AttrValues; // List of attribute values for each key (for HTML). llvm::SmallVector<SmallString<16>, 4> Args; // List of arguments to commands (for InlineCommand). - std::vector<std::unique_ptr<CommentInfo>> - Children; // List of child comments for this CommentInfo. + CommentKind Kind = CommentKind:: + CK_Unknown; // Kind of comment (FullComment, ParagraphComment, + // TextComment, InlineCommandComment, HTMLStartTagComment, + // HTMLEndTagComment, BlockCommandComment, + // ParamCommandComment, TParamCommandComment, + // VerbatimBlockComment, VerbatimBlockLineComment, + // VerbatimLineComment). + bool SelfClosing = false; // Indicates if tag is self-closing (for HTML). + bool Explicit = false; // Indicates if the direction of a param is explicit + // (for (T)ParamCommand). }; struct Reference { @@ -120,13 +119,13 @@ struct Reference { // "GlobalNamespace" as the name, but an empty QualName). Reference(SymbolID USR = SymbolID(), StringRef Name = StringRef(), InfoType IT = InfoType::IT_default) - : USR(USR), Name(Name), QualName(Name), RefType(IT) {} + : USR(USR), RefType(IT), Name(Name), QualName(Name) {} Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName, StringRef Path = StringRef()) - : USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path) {} + : USR(USR), RefType(IT), Name(Name), QualName(QualName), Path(Path) {} Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName, StringRef Path, SmallString<16> DocumentationFileName) - : USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path), + : USR(USR), RefType(IT), Name(Name), QualName(QualName), Path(Path), DocumentationFileName(DocumentationFileName) {} bool operator==(const Reference &Other) const { @@ -146,6 +145,10 @@ struct Reference { SymbolID USR = SymbolID(); // Unique identifier for referenced decl + InfoType RefType = InfoType::IT_default; // Indicates the type of this + // Reference (namespace, record, + // function, enum, default). + // Name of type (possibly unresolved). Not including namespaces or template // parameters (so for a std::vector<int> this would be "vector"). See also // QualName. @@ -156,9 +159,6 @@ struct Reference { // Name. SmallString<16> QualName; - InfoType RefType = InfoType::IT_default; // Indicates the type of this - // Reference (namespace, record, - // function, enum, default). // Path of directory where the clang-doc generated file will be saved // (possibly unresolved) llvm::SmallString<128> Path; @@ -278,21 +278,21 @@ struct MemberTypeInfo : public FieldTypeInfo { Other.Description); } + std::vector<CommentInfo> Description; + // Access level associated with this info (public, protected, private, none). // AS_public is set as default because the bitcode writer requires the enum // with value 0 to be used as the default. // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3) AccessSpecifier Access = AccessSpecifier::AS_public; - - std::vector<CommentInfo> Description; // Comment description of this field. bool IsStatic = false; }; struct Location { Location(int StartLineNumber = 0, int EndLineNumber = 0, StringRef Filename = StringRef(), bool IsFileInRootDir = false) - : StartLineNumber(StartLineNumber), EndLineNumber(EndLineNumber), - Filename(Filename), IsFileInRootDir(IsFileInRootDir) {} + : Filename(Filename), StartLineNumber(StartLineNumber), + EndLineNumber(EndLineNumber), IsFileInRootDir(IsFileInRootDir) {} bool operator==(const Location &Other) const { return std::tie(StartLineNumber, EndLineNumber, Filename) == @@ -310,40 +310,24 @@ struct Location { std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename); } - int StartLineNumber = 0; // Line number of this Location. + SmallString<32> Filename; + int StartLineNumber = 0; int EndLineNumber = 0; - SmallString<32> Filename; // File for this Location. - bool IsFileInRootDir = false; // Indicates if file is inside root directory + bool IsFileInRootDir = false; }; /// A base struct for Infos. struct Info { Info(InfoType IT = InfoType::IT_default, SymbolID USR = SymbolID(), StringRef Name = StringRef(), StringRef Path = StringRef()) - : USR(USR), IT(IT), Name(Name), Path(Path) {} + : Path(Path), Name(Name), USR(USR), IT(IT) {} Info(const Info &Other) = delete; Info(Info &&Other) = default; - virtual ~Info() = default; Info &operator=(Info &&Other) = default; - SymbolID USR = - SymbolID(); // Unique identifier for the decl described by this Info. - InfoType IT = InfoType::IT_default; // InfoType of this particular Info. - SmallString<16> Name; // Unqualified name of the decl. - 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 - - // The name used for the file that this info is documented in. - // In the JSON generator, infos are documented in files with mangled names. - // Thus, we keep track of the physical filename for linking purposes. - SmallString<16> DocumentationFileName; - void mergeBase(Info &&I); bool mergeable(const Info &Other); @@ -354,6 +338,29 @@ struct Info { /// Returns the basename that should be used for this Info. llvm::SmallString<16> getFileBaseName() const; + + // Path of directory where the clang-doc generated file will be saved. + llvm::SmallString<128> Path; + + // Unqualified name of the decl. + SmallString<16> Name; + + // The name used for the file that this info is documented in. + // In the JSON generator, infos are documented in files with mangled names. + // Thus, we keep track of the physical filename for linking purposes. + SmallString<16> DocumentationFileName; + + // List of parent namespaces for this decl. + llvm::SmallVector<Reference, 4> Namespace; + + // Unique identifier for the decl described by this Info. + SymbolID USR = SymbolID(); + + // InfoType of this particular Info. + InfoType IT = InfoType::IT_default; + + // Comment description of this decl. + std::vector<CommentInfo> Description; }; // Info for namespaces. @@ -427,21 +434,21 @@ struct FunctionInfo : public SymbolInfo { void merge(FunctionInfo &&I); - bool IsMethod = false; // Indicates whether this function is a class method. - Reference Parent; // Reference to the parent class decl for this method. - TypeInfo ReturnType; // Info about the return type of this function. - llvm::SmallVector<FieldTypeInfo, 4> Params; // List of parameters. + Reference Parent; + TypeInfo ReturnType; + llvm::SmallVector<FieldTypeInfo, 4> Params; + SmallString<256> Prototype; + + // When present, this function is a template or specialization. + std::optional<TemplateInfo> Template; + // Access level for this method (public, private, protected, none). // AS_public is set as default because the bitcode writer requires the enum // with value 0 to be used as the default. // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3) AccessSpecifier Access = AccessSpecifier::AS_public; - // Function Prototype - SmallString<256> Prototype; - - // When present, this function is a template or specialization. - std::optional<TemplateInfo> Template; + bool IsMethod = false; }; // TODO: Expand to allow for documenting templating, inheritance access, @@ -456,15 +463,15 @@ struct RecordInfo : public SymbolInfo { // Type of this record (struct, class, union, interface). TagTypeKind TagType = TagTypeKind::Struct; - // When present, this record is a template or specialization. - std::optional<TemplateInfo> Template; - // Indicates if the record was declared using a typedef. Things like anonymous // structs in a typedef: // typedef struct { ... } foo_t; // are converted into records with the typedef as the Name + this flag set. bool IsTypeDef = false; + // When present, this record is a template or specialization. + std::optional<TemplateInfo> Template; + llvm::SmallVector<MemberTypeInfo, 4> Members; // List of info about record members. llvm::SmallVector<Reference, 4> Parents; // List of base/parent records @@ -509,11 +516,11 @@ struct BaseRecordInfo : public RecordInfo { BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual, AccessSpecifier Access, bool IsParent); - // Indicates if base corresponds to a virtual inheritance - bool IsVirtual = false; // Access level associated with this inherited info (public, protected, // private). AccessSpecifier Access = AccessSpecifier::AS_public; + // Indicates if base corresponds to a virtual inheritance + bool IsVirtual = false; bool IsParent = false; // Indicates if this base is a direct parent }; @@ -600,17 +607,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 @@ -629,7 +632,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 7f8691d..29f8faf 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -11,7 +11,9 @@ #include "clang/AST/Attr.h" #include "clang/AST/Comment.h" +#include "clang/AST/CommentVisitor.h" #include "clang/AST/DeclFriend.h" +#include "clang/AST/ExprConcepts.h" #include "clang/AST/Mangle.h" #include "clang/Index/USRGeneration.h" #include "clang/Lex/Lexer.h" @@ -335,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 06c4d64..cfba5c9 100644 --- a/clang-tools-extra/clang-doc/Serialize.h +++ b/clang-tools-extra/clang-doc/Serialize.h @@ -16,10 +16,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_SERIALIZE_H #include "Representation.h" -#include "clang/AST/AST.h" -#include "clang/AST/CommentVisitor.h" #include <string> -#include <vector> using namespace clang::comments; @@ -83,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/YAMLGenerator.cpp b/clang-tools-extra/clang-doc/YAMLGenerator.cpp index eeccdd8..ce4ef58 100644 --- a/clang-tools-extra/clang-doc/YAMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/YAMLGenerator.cpp @@ -347,19 +347,18 @@ class YAMLGenerator : public Generator { public: static const char *Format; - llvm::Error generateDocs(StringRef RootDir, - llvm::StringMap<std::unique_ptr<doc::Info>> Infos, - const ClangDocContext &CDCtx) override; + llvm::Error generateDocumentation( + StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const ClangDocContext &CDCtx, std::string DirName) override; llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS, const ClangDocContext &CDCtx) override; }; const char *YAMLGenerator::Format = "yaml"; -llvm::Error -YAMLGenerator::generateDocs(StringRef RootDir, - llvm::StringMap<std::unique_ptr<doc::Info>> Infos, - const ClangDocContext &CDCtx) { +llvm::Error YAMLGenerator::generateDocumentation( + StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos, + const ClangDocContext &CDCtx, std::string DirName) { for (const auto &Group : Infos) { doc::Info *Info = Group.getValue().get(); diff --git a/clang-tools-extra/clang-doc/assets/class-template.mustache b/clang-tools-extra/clang-doc/assets/class-template.mustache index a320a93..bbac3ff 100644 --- a/clang-tools-extra/clang-doc/assets/class-template.mustache +++ b/clang-tools-extra/clang-doc/assets/class-template.mustache @@ -50,18 +50,21 @@ <li class="sidebar-section"> <a class="sidebar-item" href="#PublicMembers">Public Members</a> </li> - <ul> - {{#PublicMembers}} - <li class="sidebar-item-container"> - <a class="sidebar-item" href="#{{Name}}">{{Name}}</a> - </li> - {{/PublicMembers}} - </ul> + <li> + <ul> + {{#PublicMembers}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{Name}}">{{Name}}</a> + </li> + {{/PublicMembers}} + </ul> + </li> {{/HasPublicMembers}} {{#ProtectedMembers}} - <li class="sidebar-section"> - <a class="sidebar-item" href="#PublicMethods">Protected Members</a> - </li> + <li class="sidebar-section"> + <a class="sidebar-item" href="#PublicMethods">Protected Members</a> + </li> + <li> <ul> {{#Obj}} <li class="sidebar-item-container"> @@ -69,42 +72,49 @@ </li> {{/Obj}} </ul> + </li> {{/ProtectedMembers}} {{#HasPublicFunctions}} <li class="sidebar-section"> <a class="sidebar-item" href="#PublicMethods">Public Method</a> </li> - <ul> - {{#PublicFunctions}} - <li class="sidebar-item-container"> - <a class="sidebar-item" href="#{{USR}}">{{Name}}</a> - </li> - {{/PublicFunctions}} - </ul> + <li> + <ul> + {{#PublicFunctions}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{USR}}">{{Name}}</a> + </li> + {{/PublicFunctions}} + </ul> + </li> {{/HasPublicFunctions}} {{#ProtectedFunction}} <li class="sidebar-section"> <a class="sidebar-item" href="#ProtectedFunction">Protected Method</a> </li> - <ul> - {{#Obj}} - <li class="sidebar-item-container"> - <a class="sidebar-item" href="#{{ID}}">{{Name}}</a> - </li> - {{/Obj}} - </ul> + <li> + <ul> + {{#Obj}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{ID}}">{{Name}}</a> + </li> + {{/Obj}} + </ul> + </li> {{/ProtectedFunction}} {{#Enums}} <li class="sidebar-section"> <a class="sidebar-item" href="#Enums">Enums</a> </li> - <ul> - {{#Obj}} - <li class="sidebar-item-container"> - <a class="sidebar-item" href="#{{USR}}">{{EnumName}}</a> - </li> - {{/Obj}} - </ul> + <li> + <ul> + {{#Obj}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{USR}}">{{EnumName}}</a> + </li> + {{/Obj}} + </ul> + </li> {{/Enums}} {{#Typedef}} <li class="sidebar-section">Typedef</li> @@ -113,13 +123,15 @@ <li class="sidebar-section"> <a class="sidebar-item" href="#Classes">Inner Classes</a> </li> - <ul> - {{#Links}} - <li class="sidebar-item-container"> - <a class="sidebar-item" href="#{{ID}}">{{Name}}</a> - </li> - {{/Links}} - </ul> + <li> + <ul> + {{#Links}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{ID}}">{{Name}}</a> + </li> + {{/Links}} + </ul> + </li> {{/Record}} </ul> </div> @@ -128,6 +140,7 @@ <section class="hero section-container"> <div class="hero__title"> <h1 class="hero__title-large">{{TagType}} {{Name}}</h1> + <p>Defined at line {{Location.LineNumber}} of file {{Location.Filename}}</p> {{#Description}} <div class="hero__subtitle"> {{>Comments}} @@ -174,7 +187,7 @@ <h2>Public Methods</h2> <div> {{#PublicFunctions}} -{{>FunctionPartial}} + {{>FunctionPartial}} {{/PublicFunctions}} </div> </section> diff --git a/clang-tools-extra/clang-doc/assets/comment-template.mustache b/clang-tools-extra/clang-doc/assets/comment-template.mustache index 4e38e5f..1f40333 100644 --- a/clang-tools-extra/clang-doc/assets/comment-template.mustache +++ b/clang-tools-extra/clang-doc/assets/comment-template.mustache @@ -6,54 +6,62 @@ This file defines templates for generating comments }} {{#BriefComments}} - <div> - {{#.}} - <p>{{TextComment}}</p> - {{/.}} - </div> +<div> +{{#.}} + <p>{{TextComment}}</p> +{{/.}} +</div> {{/BriefComments}} {{#ParagraphComments}} - <div> - {{#.}} - <p>{{TextComment}}</p> - {{/.}} - </div> +<div> +{{#.}} + <p>{{TextComment}}</p> +{{/.}} +</div> {{/ParagraphComments}} {{#ParagraphComment}} - {{#Children}} - {{>Comments}} - {{/Children}} +{{#Children}} +{{TextComment}} +{{/Children}} {{/ParagraphComment}} {{#HasParamComments}} - <h3>Parameters</h3> - {{#ParamComments}} - <div> - <b>{{ParamName}}</b> {{#Explicit}}{{Direction}}{{/Explicit}} {{#Children}}{{>Comments}}{{/Children}} - </div> - {{/ParamComments}} +<h3>Parameters</h3> +{{#ParamComments}} +<div> + <b>{{ParamName}}</b> {{#Explicit}}{{Direction}}{{/Explicit}} {{#Children}}{{TextComment}}{{/Children}} +</div> +{{/ParamComments}} {{/HasParamComments}} {{#HasReturnComments}} - <h3>Returns</h3> - {{#ReturnComments}} - {{#.}} - <p>{{TextComment}}</p> - {{/.}} - {{/ReturnComments}} +<h3>Returns</h3> +{{#ReturnComments}} +{{#.}} +<p>{{TextComment}}</p> +{{/.}} +{{/ReturnComments}} {{/HasReturnComments}} {{#HasCodeComments}} - <h3>Code</h3> - {{#CodeComments}} - <div> - <pre class="code-block"> - <code> - {{#.}} +<h3>Code</h3> +{{#CodeComments}} +<div> + <pre class="code-block"> + <code> + {{#.}} {{.}} - {{/.}} - </code> - </pre> - </div> - {{/CodeComments}} + {{/.}} + </code> + </pre> +</div> +{{/CodeComments}} {{/HasCodeComments}} +{{#HasThrowsComments}} +<h3>Throws</h3> +{{#ThrowsComments}} +<div> + <b>{{Exception}}</b> {{#Children}}{{TextComment}}{{/Children}} +</div> +{{/ThrowsComments}} +{{/HasThrowsComments}} {{#BlockCommandComment}} <div class="block-command-comment__command"> <div class="block-command-command"> @@ -66,8 +74,3 @@ </div> </div> {{/BlockCommandComment}} -{{#TextComment}} - <div> - <p>{{TextComment}}</p> - </div> -{{/TextComment}} diff --git a/clang-tools-extra/clang-doc/assets/enum-template.mustache b/clang-tools-extra/clang-doc/assets/enum-template.mustache index 53da466..ec42df9 100644 --- a/clang-tools-extra/clang-doc/assets/enum-template.mustache +++ b/clang-tools-extra/clang-doc/assets/enum-template.mustache @@ -7,22 +7,18 @@ }} <div id="{{ID}}" class="delimiter-container"> <div> - <pre> - <code class="language-cpp code-clang-doc"> -enum {{Name}} - </code> - </pre> + <pre><code class="language-cpp code-clang-doc">enum {{Name}}</code></pre> </div> {{! Enum Values }} <table class="table-wrapper"> <tbody> - <tr> - <th>Name</th> - <th>Value</th> - {{#HasComment}} + <tr> + <th>Name</th> + <th>Value</th> + {{#HasComment}} <th>Comment</th> - {{/HasComment}} - </tr> + {{/HasComment}} + </tr> {{#Members}} <tr> <td>{{Name}}</td> @@ -34,7 +30,7 @@ enum {{Name}} <td>{{ValueExpr}}</td> {{/Value}} {{#EnumValueComments}} - <td>{{>Comments}}</td> + <td>{{>Comments}}</td> {{/EnumValueComments}} </tr> {{/Members}} diff --git a/clang-tools-extra/clang-doc/assets/function-template.mustache b/clang-tools-extra/clang-doc/assets/function-template.mustache index 2510a4d..dc787bf 100644 --- a/clang-tools-extra/clang-doc/assets/function-template.mustache +++ b/clang-tools-extra/clang-doc/assets/function-template.mustache @@ -8,11 +8,7 @@ <div class="delimiter-container"> <div id="{{USR}}"> {{! Function Prototype }} - <pre> - <code class="language-cpp code-clang-doc"> -{{ReturnType.Name}} {{Name}} ({{#Params}}{{^End}}{{Type}} {{Name}}, {{/End}}{{#End}}{{Type}} {{Name}}{{/End}}{{/Params}}) - </code> - </pre> + <pre><code class="language-cpp code-clang-doc">{{ReturnType.Name}} {{Name}} ({{#Params}}{{^End}}{{Type}} {{Name}}, {{/End}}{{#End}}{{Type}} {{Name}}{{/End}}{{/Params}})</code></pre> {{! Function Comments }} {{#Description}} <div> diff --git a/clang-tools-extra/clang-doc/assets/namespace-template.mustache b/clang-tools-extra/clang-doc/assets/namespace-template.mustache index f4a35cf..8a5be46 100644 --- a/clang-tools-extra/clang-doc/assets/namespace-template.mustache +++ b/clang-tools-extra/clang-doc/assets/namespace-template.mustache @@ -50,25 +50,29 @@ <li class="sidebar-section"> <a class="sidebar-item" href="#Enums">Enums</a> </li> - <ul> - {{#Enums}} - <li class="sidebar-item-container"> - <a class="sidebar-item" href="#{{USR}}">{{Name}}</a> - </li> - {{/Enums}} - </ul> + <li> + <ul> + {{#Enums}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{USR}}">{{Name}}</a> + </li> + {{/Enums}} + </ul> + </li> {{/HasEnums}} {{#HasRecords}} <li class="sidebar-section"> <a class="sidebar-item" href="#Classes">Inner Classes</a> </li> - <ul> - {{#Records}} - <li class="sidebar-item-container"> - <a class="sidebar-item" href="#{{USR}}">{{Name}}</a> - </li> - {{/Records}} - </ul> + <li> + <ul> + {{#Records}} + <li class="sidebar-item-container"> + <a class="sidebar-item" href="#{{USR}}">{{Name}}</a> + </li> + {{/Records}} + </ul> + </li> {{/HasRecrods}} </ul> </div> @@ -97,8 +101,8 @@ </li> {{/Records}} </ul> - {{/HasRecords}} </section> + {{/HasRecords}} </div> </div> </main> diff --git a/clang-tools-extra/clang-doc/support/File.h b/clang-tools-extra/clang-doc/support/File.h index 7036d5e6..bab988f 100644 --- a/clang-tools-extra/clang-doc/support/File.h +++ b/clang-tools-extra/clang-doc/support/File.h @@ -8,7 +8,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_FILE_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_FILE_H -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/Error.h" namespace clang { diff --git a/clang-tools-extra/clang-doc/support/Utils.cpp b/clang-tools-extra/clang-doc/support/Utils.cpp index 6ed5603..f410bfc 100644 --- a/clang-tools-extra/clang-doc/support/Utils.cpp +++ b/clang-tools-extra/clang-doc/support/Utils.cpp @@ -28,13 +28,24 @@ SmallString<128> appendPathPosix(StringRef Base, StringRef Path) { return Default; } -void getMustacheHtmlFiles(StringRef AssetsPath, - clang::doc::ClangDocContext &CDCtx) { +void getHtmlFiles(StringRef AssetsPath, clang::doc::ClangDocContext &CDCtx) { assert(!AssetsPath.empty()); assert(sys::fs::is_directory(AssetsPath)); - SmallString<128> DefaultStylesheet = - appendPathPosix(AssetsPath, "clang-doc-mustache.css"); + // TODO: Allow users to override default templates with their own. We would + // similarly have to check if a template file already exists in CDCtx. + if (CDCtx.UserStylesheets.empty()) { + SmallString<128> DefaultStylesheet = + appendPathPosix(AssetsPath, "clang-doc-mustache.css"); + CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(), + DefaultStylesheet.c_str()); + } + + if (CDCtx.JsScripts.empty()) { + SmallString<128> IndexJS = appendPathPosix(AssetsPath, "mustache-index.js"); + CDCtx.JsScripts.insert(CDCtx.JsScripts.begin(), IndexJS.c_str()); + } + SmallString<128> NamespaceTemplate = appendPathPosix(AssetsPath, "namespace-template.mustache"); SmallString<128> ClassTemplate = @@ -45,11 +56,7 @@ void getMustacheHtmlFiles(StringRef AssetsPath, appendPathPosix(AssetsPath, "function-template.mustache"); SmallString<128> CommentTemplate = appendPathPosix(AssetsPath, "comment-template.mustache"); - SmallString<128> IndexJS = appendPathPosix(AssetsPath, "mustache-index.js"); - CDCtx.JsScripts.insert(CDCtx.JsScripts.begin(), IndexJS.c_str()); - CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(), - DefaultStylesheet.c_str()); CDCtx.MustacheTemplates.insert( {"namespace-template", NamespaceTemplate.c_str()}); CDCtx.MustacheTemplates.insert({"class-template", ClassTemplate.c_str()}); diff --git a/clang-tools-extra/clang-doc/support/Utils.h b/clang-tools-extra/clang-doc/support/Utils.h index 8161c37..f4ed9ec4 100644 --- a/clang-tools-extra/clang-doc/support/Utils.h +++ b/clang-tools-extra/clang-doc/support/Utils.h @@ -20,7 +20,7 @@ llvm::SmallString<128> appendPathNative(llvm::StringRef Base, llvm::SmallString<128> appendPathPosix(llvm::StringRef Base, llvm::StringRef Path); -void getMustacheHtmlFiles(llvm::StringRef AssetsPath, - clang::doc::ClangDocContext &CDCtx); +void getHtmlFiles(llvm::StringRef AssetsPath, + clang::doc::ClangDocContext &CDCtx); #endif diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 3bb67ba..ee4c4497 100644 --- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -22,7 +22,9 @@ #include "Generators.h" #include "Representation.h" #include "support/Utils.h" -#include "clang/ASTMatchers/ASTMatchersInternal.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" @@ -41,7 +43,6 @@ #include <mutex> #include <string> -using namespace clang::ast_matchers; using namespace clang::tooling; using namespace clang; @@ -110,21 +111,20 @@ Turn on time profiler. Generates clang-doc-tracing.json)"), llvm::cl::init(false), llvm::cl::cat(ClangDocCategory)); -enum OutputFormatTy { md, yaml, html, mustache, json }; - -static llvm::cl::opt<OutputFormatTy> FormatEnum( - "format", llvm::cl::desc("Format for outputted docs."), - llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", - "Documentation in YAML format."), - clEnumValN(OutputFormatTy::md, "md", - "Documentation in MD format."), - clEnumValN(OutputFormatTy::html, "html", - "Documentation in HTML format."), - clEnumValN(OutputFormatTy::mustache, "mustache", - "Documentation in mustache HTML format"), - clEnumValN(OutputFormatTy::json, "json", - "Documentation in JSON format")), - llvm::cl::init(OutputFormatTy::yaml), llvm::cl::cat(ClangDocCategory)); +enum OutputFormatTy { md, yaml, html, json }; + +static llvm::cl::opt<OutputFormatTy> + FormatEnum("format", llvm::cl::desc("Format for outputted docs."), + llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml", + "Documentation in YAML format."), + clEnumValN(OutputFormatTy::md, "md", + "Documentation in MD format."), + clEnumValN(OutputFormatTy::html, "html", + "Documentation in HTML format."), + clEnumValN(OutputFormatTy::json, "json", + "Documentation in JSON format")), + llvm::cl::init(OutputFormatTy::yaml), + llvm::cl::cat(ClangDocCategory)); static llvm::ExitOnError ExitOnErr; @@ -136,8 +136,6 @@ static std::string getFormatString() { return "md"; case OutputFormatTy::html: return "html"; - case OutputFormatTy::mustache: - return "mustache"; case OutputFormatTy::json: return "json"; } @@ -153,6 +151,7 @@ static std::string getExecutablePath(const char *Argv0, void *MainAddr) { return llvm::sys::fs::getMainExecutable(Argv0, MainAddr); } +// TODO: Rename this, since it only gets custom CSS/JS static llvm::Error getAssetFiles(clang::doc::ClangDocContext &CDCtx) { using DirIt = llvm::sys::fs::directory_iterator; std::error_code FileErr; @@ -173,58 +172,15 @@ static llvm::Error getAssetFiles(clang::doc::ClangDocContext &CDCtx) { return llvm::Error::success(); } -static llvm::Error getDefaultAssetFiles(const char *Argv0, - clang::doc::ClangDocContext &CDCtx) { - void *MainAddr = (void *)(intptr_t)getExecutablePath; - std::string ClangDocPath = getExecutablePath(Argv0, MainAddr); - llvm::SmallString<128> NativeClangDocPath; - llvm::sys::path::native(ClangDocPath, NativeClangDocPath); - - llvm::SmallString<128> AssetsPath; - AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath); - llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc"); - llvm::SmallString<128> DefaultStylesheet = - appendPathNative(AssetsPath, "clang-doc-default-stylesheet.css"); - llvm::SmallString<128> IndexJS = appendPathNative(AssetsPath, "index.js"); - - if (!llvm::sys::fs::is_regular_file(IndexJS)) - return llvm::createStringError(llvm::inconvertibleErrorCode(), - "default index.js file missing at " + - IndexJS + "\n"); - - if (!llvm::sys::fs::is_regular_file(DefaultStylesheet)) - return llvm::createStringError( - llvm::inconvertibleErrorCode(), - "default clang-doc-default-stylesheet.css file missing at " + - DefaultStylesheet + "\n"); - - CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(), - std::string(DefaultStylesheet)); - CDCtx.JsScripts.emplace_back(IndexJS.str()); - - return llvm::Error::success(); -} - -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"; - if (llvm::sys::fs::is_directory(std::string(UserAssetPath))) - return getAssetFiles(CDCtx); - return getDefaultAssetFiles(Argv0, CDCtx); -} - -static llvm::Error getMustacheHtmlFiles(const char *Argv0, - clang::doc::ClangDocContext &CDCtx) { +static llvm::Error getHtmlFiles(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 (IsDir) { - getMustacheHtmlFiles(UserAssetPath, CDCtx); - return llvm::Error::success(); + if (auto Err = getAssetFiles(CDCtx)) + return Err; } void *MainAddr = (void *)(intptr_t)getExecutablePath; std::string ClangDocPath = getExecutablePath(Argv0, MainAddr); @@ -235,7 +191,7 @@ static llvm::Error getMustacheHtmlFiles(const char *Argv0, AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath); llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc"); - getMustacheHtmlFiles(AssetsPath, CDCtx); + getHtmlFiles(AssetsPath, CDCtx); return llvm::Error::success(); } @@ -257,13 +213,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; @@ -315,28 +274,25 @@ 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}; - - if (Format == "html") { - ExitOnErr(getHtmlAssetFiles(argv[0], CDCtx)); - } else if (Format == "mustache") { - ExitOnErr(getMustacheHtmlFiles(argv[0], CDCtx)); - } + 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(getHtmlFiles(argv[0], CDCtx)); llvm::timeTraceProfilerBegin("Executor Launch", "total runtime"); // Mapping phase llvm::outs() << "Mapping decls...\n"; ExitOnErr(handleMappingFailures( + Diags, Executor->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster))); llvm::timeTraceProfilerEnd(); @@ -362,13 +318,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"); @@ -377,10 +338,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; } @@ -396,7 +360,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); @@ -438,7 +404,8 @@ Example usage for a project using a compile commands database: // Run the generator. llvm::outs() << "Generating docs...\n"; - ExitOnErr(G->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx)); + ExitOnErr( + G->generateDocumentation(OutDirectory, std::move(USRToInfo), CDCtx)); llvm::outs() << "Generating assets for docs...\n"; ExitOnErr(G->createResources(CDCtx)); llvm::timeTraceProfilerEnd(); diff --git a/clang-tools-extra/clang-tidy/.clang-format b/clang-tools-extra/clang-tidy/.clang-format index 5b50661..fe94ed1 100644 --- a/clang-tools-extra/clang-tidy/.clang-format +++ b/clang-tools-extra/clang-tidy/.clang-format @@ -1,3 +1,8 @@ BasedOnStyle: LLVM -QualifierAlignment: Left +InsertNewlineAtEOF: true +KeepEmptyLines: + AtEndOfFile: false + AtStartOfBlock: false + AtStartOfFile: false LineEnding: LF +QualifierAlignment: Left diff --git a/clang-tools-extra/clang-tidy/.clang-tidy b/clang-tools-extra/clang-tidy/.clang-tidy index 0c2f34b..70d5731 100644 --- a/clang-tools-extra/clang-tidy/.clang-tidy +++ b/clang-tools-extra/clang-tidy/.clang-tidy @@ -1,4 +1,6 @@ InheritParentConfig: true +HeaderFilterRegex: 'clang-tools-extra/clang-tidy' +ExcludeHeaderFilterRegex: 'include-cleaner|clang-query' Checks: > bugprone-*, -bugprone-assignment-in-if-condition, @@ -7,6 +9,12 @@ Checks: > -bugprone-narrowing-conversions, -bugprone-unchecked-optional-access, -bugprone-unused-return-value, + cppcoreguidelines-init-variables, + cppcoreguidelines-missing-std-forward, + cppcoreguidelines-rvalue-reference-param-not-moved, + cppcoreguidelines-virtual-class-destructor, + google-readability-casting, + misc-const-correctness, modernize-*, -modernize-avoid-c-arrays, -modernize-pass-by-value, @@ -15,7 +23,6 @@ Checks: > performance-*, -performance-enum-size, -performance-no-int-to-ptr, - -performance-unnecessary-value-param, readability-*, -readability-avoid-nested-conditional-operator, -readability-braces-around-statements, @@ -30,8 +37,7 @@ Checks: > -readability-qualified-auto, -readability-simplify-boolean-expr, -readability-static-definition-in-anonymous-namespace, - -readability-suspicious-call-argument, - -readability-use-anyofallof + -readability-suspicious-call-argument CheckOptions: - key: performance-move-const-arg.CheckTriviallyCopyableMove diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp index 870f516..4af328c 100644 --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -23,10 +23,10 @@ #include "clang-tidy-config.h" #include "clang/AST/ASTConsumer.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/DiagnosticFrontend.h" #include "clang/Format/Format.h" #include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Lex/Preprocessor.h" @@ -455,8 +455,8 @@ ClangTidyASTConsumerFactory::createASTConsumer( if (Context.canEnableModuleHeadersParsing() && Context.getLangOpts().Modules && OverlayFS != nullptr) { - auto ModuleExpander = - std::make_unique<ExpandModularHeadersPPCallbacks>(&Compiler, OverlayFS); + auto ModuleExpander = std::make_unique<ExpandModularHeadersPPCallbacks>( + &Compiler, *OverlayFS); ModuleExpanderPP = ModuleExpander->getPreprocessor(); PP->addPPCallbacks(std::move(ModuleExpander)); } diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp index 81a9f93..16a4d13 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -478,11 +478,10 @@ bool ClangTidyDiagnosticConsumer::passesLineFilter(StringRef FileName, if (FileName.ends_with(Filter.Name)) { if (Filter.LineRanges.empty()) return true; - for (const FileFilter::LineRange &Range : Filter.LineRanges) { - if (Range.first <= LineNumber && LineNumber <= Range.second) - return true; - } - return false; + return llvm::any_of( + Filter.LineRanges, [&](const FileFilter::LineRange &Range) { + return Range.first <= LineNumber && LineNumber <= Range.second; + }); } } return false; @@ -527,7 +526,8 @@ void ClangTidyDiagnosticConsumer::forwardDiagnostic(const Diagnostic &Info) { Builder << Qualifiers::fromOpaqueValue(Info.getRawArg(Index)); break; case clang::DiagnosticsEngine::ak_qualtype: - Builder << QualType::getFromOpaquePtr((void *)Info.getRawArg(Index)); + Builder << QualType::getFromOpaquePtr( + reinterpret_cast<void *>(Info.getRawArg(Index))); break; case clang::DiagnosticsEngine::ak_declarationname: Builder << DeclarationName::getFromOpaqueInteger(Info.getRawArg(Index)); @@ -819,7 +819,6 @@ void ClangTidyDiagnosticConsumer::removeDuplicatedDiagnosticsOfAliasCheckers() { (*Inserted.first)->Message.Fix; if (CandidateFix != ExistingFix) { - // In case of a conflict, don't suggest any fix-it. ExistingError.Message.Fix.clear(); ExistingError.Notes.emplace_back( diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp index 487e5e2..9a4fc7a3 100644 --- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp +++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.cpp @@ -65,8 +65,7 @@ private: }; ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks( - CompilerInstance *CI, - IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS) + CompilerInstance *CI, llvm::vfs::OverlayFileSystem &OverlayFS) : Recorder(std::make_unique<FileRecorder>()), Compiler(*CI), InMemoryFs(new llvm::vfs::InMemoryFileSystem), Sources(Compiler.getSourceManager()), @@ -76,7 +75,7 @@ ExpandModularHeadersPPCallbacks::ExpandModularHeadersPPCallbacks( LangOpts(Compiler.getLangOpts()), HSOpts(Compiler.getHeaderSearchOpts()) { // Add a FileSystem containing the extra files needed in place of modular // headers. - OverlayFS->pushOverlay(InMemoryFs); + OverlayFS.pushOverlay(InMemoryFs); Diags.setSourceManager(&Sources); // FIXME: Investigate whatever is there better way to initialize DiagEngine diff --git a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h index 60cb01f..d72d021 100644 --- a/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h +++ b/clang-tools-extra/clang-tidy/ExpandModularHeadersPPCallbacks.h @@ -41,9 +41,8 @@ namespace tooling { /// non-modular way. class ExpandModularHeadersPPCallbacks : public PPCallbacks { public: - ExpandModularHeadersPPCallbacks( - CompilerInstance *CI, - IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS); + ExpandModularHeadersPPCallbacks(CompilerInstance *CI, + llvm::vfs::OverlayFileSystem &OverlayFS); ~ExpandModularHeadersPPCallbacks() override; /// Returns the preprocessor that provides callbacks for the whole @@ -138,7 +137,7 @@ private: std::unique_ptr<Preprocessor> PP; bool EnteredMainFile = false; bool StartedLexing = false; - Token CurrentToken; + Token CurrentToken = Token(); }; } // namespace tooling diff --git a/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.cpp b/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.cpp index a74ab00..b552ae8 100644 --- a/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.cpp +++ b/clang-tools-extra/clang-tidy/NoLintDirectiveHandler.cpp @@ -19,7 +19,6 @@ #include "clang/Basic/SourceManager.h" #include "clang/Tooling/Core/Diagnostic.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" diff --git a/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp b/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp index 8aa23b8..ea98d01 100644 --- a/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp +++ b/clang-tools-extra/clang-tidy/altera/KernelNameRestrictionCheck.cpp @@ -74,7 +74,6 @@ bool KernelNameRestrictionPPCallbacks::fileNameIsRestricted( } void KernelNameRestrictionPPCallbacks::EndOfMainFile() { - // Check main file for restricted names. OptionalFileEntryRef Entry = SM.getFileEntryRefForID(SM.getMainFileID()); const StringRef FileName = llvm::sys::path::filename(Entry->getName()); diff --git a/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.cpp b/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.cpp index 2b1312c..d90305d 100644 --- a/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.cpp +++ b/clang-tools-extra/clang-tidy/altera/StructPackAlignCheck.cpp @@ -63,9 +63,8 @@ void StructPackAlignCheck::check(const MatchFinder::MatchResult &Result) { const QualType StructFieldTy = StructField->getType(); if (StructFieldTy->isIncompleteType()) return; - const unsigned int StructFieldWidth = - (unsigned int)Result.Context->getTypeInfo(StructFieldTy.getTypePtr()) - .Width; + const unsigned int StructFieldWidth = static_cast<unsigned int>( + Result.Context->getTypeInfo(StructFieldTy.getTypePtr()).Width); FieldSizes.emplace_back(StructFieldWidth, StructField->getFieldIndex()); // FIXME: Recommend a reorganization of the struct (sort by StructField // size, largest to smallest). @@ -79,7 +78,7 @@ void StructPackAlignCheck::check(const MatchFinder::MatchResult &Result) { CharUnits::fromQuantity(std::max<clang::CharUnits::QuantityType>( std::ceil(static_cast<float>(TotalBitSize) / CharSize), 1)); const CharUnits MaxAlign = CharUnits::fromQuantity( - std::ceil((float)Struct->getMaxAlignment() / CharSize)); + std::ceil(static_cast<float>(Struct->getMaxAlignment()) / CharSize)); const CharUnits CurrAlign = Result.Context->getASTRecordLayout(Struct).getAlignment(); const CharUnits NewAlign = computeRecommendedAlignment(MinByteSize); @@ -99,8 +98,7 @@ void StructPackAlignCheck::check(const MatchFinder::MatchResult &Result) { diag(Struct->getLocation(), "accessing fields in struct %0 is inefficient due to padding; only " "needs %1 bytes but is using %2 bytes") - << Struct << (int)MinByteSize.getQuantity() - << (int)CurrSize.getQuantity() + << Struct << MinByteSize.getQuantity() << CurrSize.getQuantity() << FixItHint::CreateInsertion(Struct->getEndLoc().getLocWithOffset(1), " __attribute__((packed))"); diag(Struct->getLocation(), @@ -112,8 +110,7 @@ void StructPackAlignCheck::check(const MatchFinder::MatchResult &Result) { FixItHint FixIt; auto *Attribute = Struct->getAttr<AlignedAttr>(); - const std::string NewAlignQuantity = - std::to_string((int)NewAlign.getQuantity()); + const std::string NewAlignQuantity = std::to_string(NewAlign.getQuantity()); if (Attribute) { FixIt = FixItHint::CreateReplacement( Attribute->getRange(), @@ -130,7 +127,7 @@ void StructPackAlignCheck::check(const MatchFinder::MatchResult &Result) { diag(Struct->getLocation(), "accessing fields in struct %0 is inefficient due to poor alignment; " "currently aligned to %1 bytes, but recommended alignment is %2 bytes") - << Struct << (int)CurrAlign.getQuantity() << NewAlignQuantity << FixIt; + << Struct << CurrAlign.getQuantity() << NewAlignQuantity << FixIt; diag(Struct->getLocation(), "use \"__attribute__((aligned(%0)))\" to align struct %1 to %0 bytes", diff --git a/clang-tools-extra/clang-tidy/altera/UnrollLoopsCheck.cpp b/clang-tools-extra/clang-tidy/altera/UnrollLoopsCheck.cpp index b0cd4cd..c759e5b 100644 --- a/clang-tools-extra/clang-tidy/altera/UnrollLoopsCheck.cpp +++ b/clang-tools-extra/clang-tidy/altera/UnrollLoopsCheck.cpp @@ -208,20 +208,22 @@ bool UnrollLoopsCheck::hasLargeNumIterations(const Stmt *Statement, return true; switch (Op->getOpcode()) { case (BO_AddAssign): - Iterations = std::ceil(float(EndValue - InitValue) / ConstantValue); + Iterations = + std::ceil(static_cast<float>(EndValue - InitValue) / ConstantValue); break; case (BO_SubAssign): - Iterations = std::ceil(float(InitValue - EndValue) / ConstantValue); + Iterations = + std::ceil(static_cast<float>(InitValue - EndValue) / ConstantValue); break; case (BO_MulAssign): - Iterations = - 1 + ((std::log((double)EndValue) - std::log((double)InitValue)) / - std::log((double)ConstantValue)); + Iterations = 1 + ((std::log(static_cast<double>(EndValue)) - + std::log(static_cast<double>(InitValue))) / + std::log(static_cast<double>(ConstantValue))); break; case (BO_DivAssign): - Iterations = - 1 + ((std::log((double)InitValue) - std::log((double)EndValue)) / - std::log((double)ConstantValue)); + Iterations = 1 + ((std::log(static_cast<double>(InitValue)) - + std::log(static_cast<double>(EndValue))) / + std::log(static_cast<double>(ConstantValue))); break; default: // All other operators are not handled; assume large bounds. diff --git a/clang-tools-extra/clang-tidy/android/CloexecCheck.cpp b/clang-tools-extra/clang-tidy/android/CloexecCheck.cpp index c046578..ff86fc5 100644 --- a/clang-tools-extra/clang-tidy/android/CloexecCheck.cpp +++ b/clang-tools-extra/clang-tidy/android/CloexecCheck.cpp @@ -36,7 +36,7 @@ static std::string buildFixMsgForStringFlag(const Expr *Arg, } void CloexecCheck::registerMatchersImpl( - MatchFinder *Finder, internal::Matcher<FunctionDecl> Function) { + MatchFinder *Finder, const internal::Matcher<FunctionDecl> &Function) { // We assume all the checked APIs are C functions. Finder->addMatcher( callExpr( diff --git a/clang-tools-extra/clang-tidy/android/CloexecCheck.h b/clang-tools-extra/clang-tidy/android/CloexecCheck.h index fc1accd..a6dcb57 100644 --- a/clang-tools-extra/clang-tidy/android/CloexecCheck.h +++ b/clang-tools-extra/clang-tidy/android/CloexecCheck.h @@ -29,9 +29,9 @@ public: : ClangTidyCheck(Name, Context) {} protected: - void - registerMatchersImpl(ast_matchers::MatchFinder *Finder, - ast_matchers::internal::Matcher<FunctionDecl> Function); + void registerMatchersImpl( + ast_matchers::MatchFinder *Finder, + const ast_matchers::internal::Matcher<FunctionDecl> &Function); /// Currently, we have three types of fixes. /// diff --git a/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp index 02fc8d8..970cbd9 100644 --- a/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp +++ b/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp @@ -18,6 +18,7 @@ #include <initializer_list> #include <optional> #include <string> +#include <utility> // FixItHint - Let the docs script know that this class does provide fixits @@ -200,7 +201,6 @@ private: } // namespace utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const { - ReplacerMap Results; static const Signature SingleSig = {{0}}; static const Signature TwoSig = {{0}, {2}}; @@ -217,11 +217,11 @@ utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const { const auto AddFromStd = [&](llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer> Replacer, std::initializer_list<StringRef> Names) { - AddFrom(Replacer, Names, "std"); + AddFrom(std::move(Replacer), Names, "std"); }; const auto AddFromBoost = - [&](llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer> Replacer, + [&](const llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer> &Replacer, std::initializer_list< std::pair<StringRef, std::initializer_list<StringRef>>> NamespaceAndNames) { diff --git a/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp index 8e0f0c5..4f33670 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp @@ -75,12 +75,9 @@ static bool isFallthroughSwitchBranch(const SwitchBranch &Branch) { if (!S) return true; - for (const Attr *A : S->getAttrs()) { - if (isa<FallThroughAttr>(A)) - return false; - } - - return true; + return llvm::all_of(S->getAttrs(), [](const Attr *A) { + return !isa<FallThroughAttr>(A); + }); } } Visitor; @@ -117,7 +114,6 @@ void BranchCloneCheck::registerMatchers(MatchFinder *Finder) { /// static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, const Stmt *Stmt2, bool IgnoreSideEffects) { - if (!Stmt1 || !Stmt2) return !Stmt1 && !Stmt2; diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index baea231..6859dc9 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -30,6 +30,7 @@ #include "DynamicStaticInitializersCheck.h" #include "EasilySwappableParametersCheck.h" #include "EmptyCatchCheck.h" +#include "ExceptionCopyConstructorThrowsCheck.h" #include "ExceptionEscapeCheck.h" #include "FloatLoopCounterCheck.h" #include "FoldInitTypeCheck.h" @@ -64,6 +65,7 @@ #include "ParentVirtualCallCheck.h" #include "PointerArithmeticOnPolymorphicObjectCheck.h" #include "PosixReturnCheck.h" +#include "RandomGeneratorSeedCheck.h" #include "RawMemoryCallOnNonTrivialTypeCheck.h" #include "RedundantBranchConditionCheck.h" #include "ReservedIdentifierCheck.h" @@ -155,6 +157,8 @@ public: CheckFactories.registerCheck<EasilySwappableParametersCheck>( "bugprone-easily-swappable-parameters"); CheckFactories.registerCheck<EmptyCatchCheck>("bugprone-empty-catch"); + CheckFactories.registerCheck<ExceptionCopyConstructorThrowsCheck>( + "bugprone-exception-copy-constructor-throws"); CheckFactories.registerCheck<ExceptionEscapeCheck>( "bugprone-exception-escape"); CheckFactories.registerCheck<FloatLoopCounterCheck>( @@ -227,6 +231,8 @@ public: CheckFactories.registerCheck<ParentVirtualCallCheck>( "bugprone-parent-virtual-call"); CheckFactories.registerCheck<PosixReturnCheck>("bugprone-posix-return"); + CheckFactories.registerCheck<RandomGeneratorSeedCheck>( + "bugprone-random-generator-seed"); CheckFactories.registerCheck<RawMemoryCallOnNonTrivialTypeCheck>( "bugprone-raw-memory-call-on-non-trivial-type"); CheckFactories.registerCheck<ReservedIdentifierCheck>( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index aacaa61..db1256d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -26,6 +26,7 @@ add_clang_library(clangTidyBugproneModule STATIC DynamicStaticInitializersCheck.cpp EasilySwappableParametersCheck.cpp EmptyCatchCheck.cpp + ExceptionCopyConstructorThrowsCheck.cpp ExceptionEscapeCheck.cpp FloatLoopCounterCheck.cpp FoldInitTypeCheck.cpp @@ -65,6 +66,7 @@ add_clang_library(clangTidyBugproneModule STATIC ParentVirtualCallCheck.cpp PointerArithmeticOnPolymorphicObjectCheck.cpp PosixReturnCheck.cpp + RandomGeneratorSeedCheck.cpp RawMemoryCallOnNonTrivialTypeCheck.cpp RedundantBranchConditionCheck.cpp ReservedIdentifierCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp index a376de5..6aed454 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp @@ -44,18 +44,17 @@ AST_MATCHER(CXXRecordDecl, correctHandleCaptureThisLambda) { if (Node.hasSimpleMoveAssignment()) return false; - for (const CXXConstructorDecl *C : Node.ctors()) { - if (C->isCopyOrMoveConstructor() && C->isDefaulted() && !C->isDeleted()) - return false; - } - for (const CXXMethodDecl *M : Node.methods()) { - if (M->isCopyAssignmentOperator()) - llvm::errs() << M->isDeleted() << "\n"; - if (M->isCopyAssignmentOperator() && M->isDefaulted() && !M->isDeleted()) - return false; - if (M->isMoveAssignmentOperator() && M->isDefaulted() && !M->isDeleted()) - return false; - } + if (llvm::any_of(Node.ctors(), [](const CXXConstructorDecl *C) { + return C->isCopyOrMoveConstructor() && C->isDefaulted() && + !C->isDeleted(); + })) + return false; + if (llvm::any_of(Node.methods(), [](const CXXMethodDecl *M) { + return (M->isCopyAssignmentOperator() || + M->isMoveAssignmentOperator()) && + M->isDefaulted() && !M->isDeleted(); + })) + return false; // FIXME: find ways to identifier correct handle capture this lambda return true; } diff --git a/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp index 3d3fc78..47acc21 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp @@ -11,7 +11,6 @@ #include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include <algorithm> using namespace clang::ast_matchers; diff --git a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp index 602b63e..9067f43 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp @@ -34,7 +34,6 @@ static constexpr llvm::StringLiteral ErrorMsg = void ComparePointerToMemberVirtualFunctionCheck::registerMatchers( MatchFinder *Finder) { - auto DirectMemberVirtualFunctionPointer = unaryOperator( allOf(hasOperatorName("&"), hasUnaryOperand(declRefExpr(to(cxxMethodDecl(isVirtual())))))); diff --git a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp index 9f8e885..c95ad2b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp @@ -7,13 +7,11 @@ //===----------------------------------------------------------------------===// #include "DanglingHandleCheck.h" -#include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang::ast_matchers; -using namespace clang::tidy::matchers; namespace clang::tidy::bugprone { @@ -31,7 +29,6 @@ handleFrom(const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle, static ast_matchers::internal::Matcher<Stmt> handleFromTemporaryValue( const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle) { - const auto TemporaryExpr = anyOf( cxxBindTemporaryExpr(), cxxFunctionalCastExpr( diff --git a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp index a07a68c..496f3e5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp @@ -1589,11 +1589,9 @@ static bool lazyMapOfSetsIntersectionExists(const MapTy &Map, const ElemTy &E1, if (E1Iterator == Map.end() || E2Iterator == Map.end()) return false; - for (const auto &E1SetElem : E1Iterator->second) - if (E2Iterator->second.contains(E1SetElem)) - return true; - - return false; + return llvm::any_of(E1Iterator->second, [&E2Iterator](const auto &E1SetElem) { + return E2Iterator->second.contains(E1SetElem); + }); } /// Implements the heuristic that marks two parameters related if there is diff --git a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.cpp index 2225a90..7365845 100644 --- a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.cpp @@ -6,15 +6,16 @@ // //===----------------------------------------------------------------------===// -#include "ThrownExceptionTypeCheck.h" +#include "ExceptionCopyConstructorThrowsCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang::ast_matchers; -namespace clang::tidy::cert { +namespace clang::tidy::bugprone { -void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) { +void ExceptionCopyConstructorThrowsCheck::registerMatchers( + MatchFinder *Finder) { Finder->addMatcher( traverse( TK_AsIs, @@ -25,10 +26,11 @@ void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) { this); } -void ThrownExceptionTypeCheck::check(const MatchFinder::MatchResult &Result) { +void ExceptionCopyConstructorThrowsCheck::check( + const MatchFinder::MatchResult &Result) { const auto *E = Result.Nodes.getNodeAs<Expr>("expr"); diag(E->getExprLoc(), "thrown exception type is not nothrow copy constructible"); } -} // namespace clang::tidy::cert +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.h b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.h index 41a51452..f1d7cca 100644 --- a/clang-tools-extra/clang-tidy/cert/ThrownExceptionTypeCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.h @@ -6,20 +6,20 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_THROWNEXCEPTIONTYPECHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_THROWNEXCEPTIONTYPECHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONCOPYCONSTRUCTORTHROWSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONCOPYCONSTRUCTORTHROWSCHECK_H #include "../ClangTidyCheck.h" -namespace clang::tidy::cert { +namespace clang::tidy::bugprone { /// Checks whether a thrown object is nothrow copy constructible. /// /// For the user-facing documentation see: -/// https://clang.llvm.org/extra/clang-tidy/checks/cert/err60-cpp.html -class ThrownExceptionTypeCheck : public ClangTidyCheck { +/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/exception-copy-constructor-throws.html +class ExceptionCopyConstructorThrowsCheck : public ClangTidyCheck { public: - ThrownExceptionTypeCheck(StringRef Name, ClangTidyContext *Context) + ExceptionCopyConstructorThrowsCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) {} bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus; @@ -28,6 +28,6 @@ public: void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; -} // namespace clang::tidy::cert +} // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_THROWNEXCEPTIONTYPECHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONCOPYCONSTRUCTORTHROWSCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index 837a86f..1cfb151 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -36,13 +36,22 @@ ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), RawFunctionsThatShouldNotThrow(Options.get( "FunctionsThatShouldNotThrow", "")), - RawIgnoredExceptions(Options.get("IgnoredExceptions", "")) { + RawIgnoredExceptions(Options.get("IgnoredExceptions", "")), + RawCheckedSwapFunctions( + Options.get("CheckedSwapFunctions", "swap,iter_swap,iter_move")), + CheckDestructors(Options.get("CheckDestructors", true)), + CheckMoveMemberFunctions(Options.get("CheckMoveMemberFunctions", true)), + CheckMain(Options.get("CheckMain", true)), + CheckNothrowFunctions(Options.get("CheckNothrowFunctions", true)) { llvm::SmallVector<StringRef, 8> FunctionsThatShouldNotThrowVec, - IgnoredExceptionsVec; + IgnoredExceptionsVec, CheckedSwapFunctionsVec; RawFunctionsThatShouldNotThrow.split(FunctionsThatShouldNotThrowVec, ",", -1, false); FunctionsThatShouldNotThrow.insert_range(FunctionsThatShouldNotThrowVec); + RawCheckedSwapFunctions.split(CheckedSwapFunctionsVec, ",", -1, false); + CheckedSwapFunctions.insert_range(CheckedSwapFunctionsVec); + llvm::StringSet<> IgnoredExceptions; RawIgnoredExceptions.split(IgnoredExceptionsVec, ",", -1, false); IgnoredExceptions.insert_range(IgnoredExceptionsVec); @@ -54,20 +63,34 @@ void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "FunctionsThatShouldNotThrow", RawFunctionsThatShouldNotThrow); Options.store(Opts, "IgnoredExceptions", RawIgnoredExceptions); + Options.store(Opts, "CheckedSwapFunctions", RawCheckedSwapFunctions); + Options.store(Opts, "CheckDestructors", CheckDestructors); + Options.store(Opts, "CheckMoveMemberFunctions", CheckMoveMemberFunctions); + Options.store(Opts, "CheckMain", CheckMain); + Options.store(Opts, "CheckNothrowFunctions", CheckNothrowFunctions); } void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) { + auto MatchIf = [](bool Enabled, const auto &Matcher) { + const ast_matchers::internal::Matcher<FunctionDecl> Nothing = + unless(anything()); + return Enabled ? Matcher : Nothing; + }; Finder->addMatcher( functionDecl( isDefinition(), - anyOf(isNoThrow(), - allOf(anyOf(cxxDestructorDecl(), - cxxConstructorDecl(isMoveConstructor()), - cxxMethodDecl(isMoveAssignmentOperator()), isMain(), - allOf(hasAnyName("swap", "iter_swap", "iter_move"), - hasAtLeastOneParameter())), - unless(isExplicitThrow())), - isEnabled(FunctionsThatShouldNotThrow))) + anyOf( + MatchIf(CheckNothrowFunctions, isNoThrow()), + allOf(anyOf(MatchIf(CheckDestructors, cxxDestructorDecl()), + MatchIf( + CheckMoveMemberFunctions, + anyOf(cxxConstructorDecl(isMoveConstructor()), + cxxMethodDecl(isMoveAssignmentOperator()))), + MatchIf(CheckMain, isMain()), + allOf(isEnabled(CheckedSwapFunctions), + hasAtLeastOneParameter())), + unless(isExplicitThrow())), + isEnabled(FunctionsThatShouldNotThrow))) .bind("thrower"), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h index 31d9e85..c3bf4a4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h @@ -35,8 +35,15 @@ public: private: StringRef RawFunctionsThatShouldNotThrow; StringRef RawIgnoredExceptions; + StringRef RawCheckedSwapFunctions; + + const bool CheckDestructors; + const bool CheckMoveMemberFunctions; + const bool CheckMain; + const bool CheckNothrowFunctions; llvm::StringSet<> FunctionsThatShouldNotThrow; + llvm::StringSet<> CheckedSwapFunctions; utils::ExceptionAnalyzer Tracer; }; diff --git a/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.cpp index adf2d2b..38a0234 100644 --- a/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.cpp @@ -31,6 +31,7 @@ void FloatLoopCounterCheck::registerMatchers(MatchFinder *Finder) { void FloatLoopCounterCheck::check(const MatchFinder::MatchResult &Result) { const auto *FS = Result.Nodes.getNodeAs<ForStmt>("for"); + assert(FS && "FS should not be null"); diag(FS->getInc()->getBeginLoc(), "loop induction expression should not have " "floating-point type") diff --git a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp index 9ce6d42..553c45c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp @@ -64,7 +64,6 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) { } void IncDecInConditionsCheck::check(const MatchFinder::MatchResult &Result) { - SourceLocation ExprLoc; bool IsIncrementOp = false; diff --git a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp index 50280d2..6749c59 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp @@ -119,14 +119,9 @@ static bool isAtLeastOneCondVarChanged(const Decl *Func, const Stmt *LoopStmt, if (isVarThatIsPossiblyChanged(Func, LoopStmt, Cond, Context)) return true; - for (const Stmt *Child : Cond->children()) { - if (!Child) - continue; - - if (isAtLeastOneCondVarChanged(Func, LoopStmt, Child, Context)) - return true; - } - return false; + return llvm::any_of(Cond->children(), [&](const Stmt *Child) { + return Child && isAtLeastOneCondVarChanged(Func, LoopStmt, Child, Context); + }); } /// Return the variable names in `Cond`. @@ -240,10 +235,9 @@ static bool hasStaticLocalVariable(const Stmt *Cond) { return true; } - for (const Stmt *Child : Cond->children()) - if (Child && hasStaticLocalVariable(Child)) - return true; - return false; + return llvm::any_of(Cond->children(), [](const Stmt *Child) { + return Child && hasStaticLocalVariable(Child); + }); } /// Tests if the loop condition `Cond` involves static local variables and diff --git a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp index b16119d..6467fb5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp @@ -152,7 +152,6 @@ void MacroParenthesesPPCallbacks::replacementList(const Token &MacroNameTok, void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, const MacroInfo *MI) { - // Skip variable declaration. bool VarDecl = possibleVarDecl(MI, MI->tokens_begin()); diff --git a/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp index 067577f..127af27 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp @@ -11,7 +11,6 @@ #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" -#include <algorithm> using namespace clang::ast_matchers; diff --git a/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.cpp index 40305ca..fdb903a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.cpp @@ -15,7 +15,6 @@ namespace clang::tidy::bugprone { void NondeterministicPointerIterationOrderCheck::registerMatchers( MatchFinder *Finder) { - auto LoopVariable = varDecl(hasType( qualType(hasCanonicalType(anyOf(referenceType(), pointerType()))))); diff --git a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp index 1b1e0401..19b4fc1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp @@ -101,11 +101,9 @@ void OptionalValueConversionCheck::registerMatchers(MatchFinder *Finder) { hasName(MakeOptional), returns(BindOptionalType)))), hasArgument(0, OptionalDerefMatcher)), - callExpr( - - argumentCountIs(1), + callExpr(argumentCountIs(1), - hasArgument(0, OptionalDerefMatcher))), + hasArgument(0, OptionalDerefMatcher))), unless(anyOf(hasAncestor(typeLoc()), hasAncestor(expr(matchers::hasUnevaluatedContext()))))) .bind("expr"), diff --git a/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.cpp index b8bca72..3e32e9b 100644 --- a/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.cpp @@ -6,29 +6,28 @@ // //===----------------------------------------------------------------------===// -#include "ProperlySeededRandomGeneratorCheck.h" +#include "RandomGeneratorSeedCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/ADT/STLExtras.h" using namespace clang::ast_matchers; -namespace clang::tidy::cert { +namespace clang::tidy::bugprone { -ProperlySeededRandomGeneratorCheck::ProperlySeededRandomGeneratorCheck( - StringRef Name, ClangTidyContext *Context) +RandomGeneratorSeedCheck::RandomGeneratorSeedCheck(StringRef Name, + ClangTidyContext *Context) : ClangTidyCheck(Name, Context), RawDisallowedSeedTypes( Options.get("DisallowedSeedTypes", "time_t,std::time_t")) { RawDisallowedSeedTypes.split(DisallowedSeedTypes, ','); } -void ProperlySeededRandomGeneratorCheck::storeOptions( - ClangTidyOptions::OptionMap &Opts) { +void RandomGeneratorSeedCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "DisallowedSeedTypes", RawDisallowedSeedTypes); } -void ProperlySeededRandomGeneratorCheck::registerMatchers(MatchFinder *Finder) { +void RandomGeneratorSeedCheck::registerMatchers(MatchFinder *Finder) { auto RandomGeneratorEngineDecl = cxxRecordDecl(hasAnyName( "::std::linear_congruential_engine", "::std::mersenne_twister_engine", "::std::subtract_with_carry_engine", "::std::discard_block_engine", @@ -75,8 +74,7 @@ void ProperlySeededRandomGeneratorCheck::registerMatchers(MatchFinder *Finder) { this); } -void ProperlySeededRandomGeneratorCheck::check( - const MatchFinder::MatchResult &Result) { +void RandomGeneratorSeedCheck::check(const MatchFinder::MatchResult &Result) { const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructExpr>("ctor"); if (Ctor) checkSeed(Result, Ctor); @@ -91,8 +89,8 @@ void ProperlySeededRandomGeneratorCheck::check( } template <class T> -void ProperlySeededRandomGeneratorCheck::checkSeed( - const MatchFinder::MatchResult &Result, const T *Func) { +void RandomGeneratorSeedCheck::checkSeed(const MatchFinder::MatchResult &Result, + const T *Func) { if (Func->getNumArgs() == 0 || Func->getArg(0)->isDefaultArgument()) { diag(Func->getExprLoc(), "random number generator seeded with a default argument will generate " @@ -118,4 +116,4 @@ void ProperlySeededRandomGeneratorCheck::checkSeed( } } -} // namespace clang::tidy::cert +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h b/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.h index 8cb2e62..c9c54ea 100644 --- a/clang-tools-extra/clang-tidy/cert/ProperlySeededRandomGeneratorCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.h @@ -6,13 +6,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_PROPERLYSEEDEDRANDOMGENERATORCHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_PROPERLYSEEDEDRANDOMGENERATORCHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RANDOMGENERATORSEEDCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RANDOMGENERATORSEEDCHECK_H #include "../ClangTidyCheck.h" #include <string> -namespace clang::tidy::cert { +namespace clang::tidy::bugprone { /// Random number generator must be seeded properly. /// @@ -20,10 +20,10 @@ namespace clang::tidy::cert { /// constant expression is a security vulnerability. /// /// For the user-facing documentation see: -/// https://clang.llvm.org/extra/clang-tidy/checks/cert/msc51-cpp.html -class ProperlySeededRandomGeneratorCheck : public ClangTidyCheck { +/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/random-generator-seed.html +class RandomGeneratorSeedCheck : public ClangTidyCheck { public: - ProperlySeededRandomGeneratorCheck(StringRef Name, ClangTidyContext *Context); + RandomGeneratorSeedCheck(StringRef Name, ClangTidyContext *Context); void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; @@ -37,6 +37,6 @@ private: SmallVector<StringRef, 5> DisallowedSeedTypes; }; -} // namespace clang::tidy::cert +} // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_PROPERLYSEEDEDRANDOMGENERATORCHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RANDOMGENERATORSEEDCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp index f7f7ccb..e212301 100644 --- a/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp @@ -64,7 +64,8 @@ void RawMemoryCallOnNonTrivialTypeCheck::storeOptions( void RawMemoryCallOnNonTrivialTypeCheck::registerMatchers(MatchFinder *Finder) { using namespace ast_matchers::internal; - auto IsStructPointer = [](Matcher<CXXRecordDecl> Constraint = anything(), + auto IsStructPointer = [](const Matcher<CXXRecordDecl> &Constraint = + anything(), bool Bind = false) { return expr(unaryOperator( hasOperatorName("&"), @@ -74,8 +75,8 @@ void RawMemoryCallOnNonTrivialTypeCheck::registerMatchers(MatchFinder *Finder) { }; auto IsRecordSizeOf = expr(sizeOfExpr(hasArgumentOfType(equalsBoundNode("Record")))); - auto ArgChecker = [&](Matcher<CXXRecordDecl> RecordConstraint, - BindableMatcher<Stmt> SecondArg = expr()) { + auto ArgChecker = [&](const Matcher<CXXRecordDecl> &RecordConstraint, + const BindableMatcher<Stmt> &SecondArg = expr()) { return allOf(argumentCountIs(3), hasArgument(0, IsStructPointer(RecordConstraint, true)), hasArgument(1, SecondArg), hasArgument(2, IsRecordSizeOf)); diff --git a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp index b9a0b9e..282a3b2 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp @@ -435,7 +435,7 @@ void SignalHandlerCheck::check(const MatchFinder::MatchResult &Result) { bool SignalHandlerCheck::checkFunction( const FunctionDecl *FD, const Expr *CallOrRef, - std::function<void(bool)> ChainReporter) { + llvm::function_ref<void(bool)> ChainReporter) { const bool FunctionIsCalled = isa<CallExpr>(CallOrRef); if (isStandardFunction(FD)) { @@ -471,7 +471,7 @@ bool SignalHandlerCheck::checkFunction( bool SignalHandlerCheck::checkFunctionCPP14( const FunctionDecl *FD, const Expr *CallOrRef, - std::function<void(bool)> ChainReporter) { + llvm::function_ref<void(bool)> ChainReporter) { if (!FD->isExternC()) { diag(CallOrRef->getBeginLoc(), "functions without C linkage are not allowed as signal " diff --git a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h index 67bdc9e..324b2c8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h @@ -48,10 +48,10 @@ private: /// The bool parameter is used like \c SkipPathEnd in \c reportHandlerChain . /// \return Returns true if a diagnostic was emitted for this function. bool checkFunction(const FunctionDecl *FD, const Expr *CallOrRef, - std::function<void(bool)> ChainReporter); + llvm::function_ref<void(bool)> ChainReporter); /// Similar as \c checkFunction but only check for C++14 rules. bool checkFunctionCPP14(const FunctionDecl *FD, const Expr *CallOrRef, - std::function<void(bool)> ChainReporter); + llvm::function_ref<void(bool)> ChainReporter); /// Returns true if a standard library function is considered /// asynchronous-safe. bool isStandardFunctionAsyncSafe(const FunctionDecl *FD) const; diff --git a/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp index a093b09..fd82b1c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp @@ -15,7 +15,6 @@ using namespace clang::ast_matchers; namespace clang::tidy::bugprone { void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) { - auto HasUniqueLock = hasDescendant(declRefExpr( hasDeclaration(varDecl(hasType(recordDecl(classTemplateSpecializationDecl( hasName("::std::unique_lock"), @@ -45,9 +44,7 @@ void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) { onImplicitObjectArgument( declRefExpr(to(varDecl(hasType(references(recordDecl( hasName("::std::condition_variable")))))))), - HasUniqueLock) - - )) + HasUniqueLock))) .bind("wait")); auto HasWaitDescendantC = hasDescendant( diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp index 51ae132..63ba2ed 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp @@ -70,10 +70,8 @@ void SuspiciousMemsetUsageCheck::check(const MatchFinder::MatchResult &Result) { return; Diag << FixItHint::CreateReplacement( CharSourceRange::getTokenRange(CharRange), "0"); - } - - else if (const auto *NumFill = - Result.Nodes.getNodeAs<IntegerLiteral>("num-fill")) { + } else if (const auto *NumFill = + Result.Nodes.getNodeAs<IntegerLiteral>("num-fill")) { // Case 2: fill_char of memset() is larger in size than an unsigned char // so it gets truncated during conversion. @@ -88,9 +86,7 @@ void SuspiciousMemsetUsageCheck::check(const MatchFinder::MatchResult &Result) { diag(NumFill->getBeginLoc(), "memset fill value is out of unsigned " "character range, gets truncated"); - } - - else if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call")) { + } else if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call")) { // Case 3: byte_count of memset() is zero. This is most likely an // argument swap. diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp index cf8bc97..4f0d819 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp @@ -116,7 +116,7 @@ void SuspiciousMissingCommaCheck::check( // Warn only when concatenation is not common in this initializer list. // The current threshold is set to less than 1/5 of the string literals. - if (double(Count) / Size > RatioThreshold) + if (static_cast<double>(Count) / Size > RatioThreshold) return; diag(ConcatenatedLiteral->getBeginLoc(), diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousReallocUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousReallocUsageCheck.cpp index 7cc3630..bf31218 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousReallocUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousReallocUsageCheck.cpp @@ -92,10 +92,9 @@ public: return false; } bool VisitStmt(const Stmt *S) { - for (const Stmt *Child : S->children()) - if (Child && Visit(Child)) - return true; - return false; + return llvm::any_of(S->children(), [this](const Stmt *Child) { + return Child && Visit(Child); + }); } }; diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp index d239cbe..cb37976 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp @@ -43,7 +43,6 @@ SuspiciousStringviewDataUsageCheck::getCheckTraversalKind() const { } void SuspiciousStringviewDataUsageCheck::registerMatchers(MatchFinder *Finder) { - auto AncestorCall = anyOf( cxxConstructExpr(), callExpr(unless(cxxOperatorCallExpr())), lambdaExpr(), initListExpr( diff --git a/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp index a85a136..c0d38dc 100644 --- a/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp @@ -104,7 +104,6 @@ void TaggedUnionMemberCountCheck::storeOptions( } void TaggedUnionMemberCountCheck::registerMatchers(MatchFinder *Finder) { - auto NotFromSystemHeaderOrStdNamespace = unless(anyOf(isExpansionInSystemHeader(), isInStdNamespace())); diff --git a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h index 11086fb..62bf42d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h @@ -25,7 +25,8 @@ class UncheckedOptionalAccessCheck : public ClangTidyCheck { public: UncheckedOptionalAccessCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - ModelOptions{Options.get("IgnoreSmartPointerDereference", false)} {} + ModelOptions{Options.get("IgnoreSmartPointerDereference", false), + Options.get("IgnoreValueCalls", false)} {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { @@ -34,6 +35,7 @@ public: void storeOptions(ClangTidyOptions::OptionMap &Opts) override { Options.store(Opts, "IgnoreSmartPointerDereference", ModelOptions.IgnoreSmartPointerDereference); + Options.store(Opts, "IgnoreValueCalls", ModelOptions.IgnoreValueCalls); } private: diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp index 5524c4b..0a7467a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp @@ -266,8 +266,8 @@ void UnsafeFunctionsCheck::registerMatchers(MatchFinder *Finder) { } void UnsafeFunctionsCheck::check(const MatchFinder::MatchResult &Result) { - const Expr *SourceExpr; - const FunctionDecl *FuncDecl; + const Expr *SourceExpr = nullptr; + const FunctionDecl *FuncDecl = nullptr; if (const auto *DeclRef = Result.Nodes.getNodeAs<DeclRefExpr>(DeclRefId)) { SourceExpr = DeclRef; @@ -301,14 +301,20 @@ void UnsafeFunctionsCheck::check(const MatchFinder::MatchResult &Result) { if (Custom) { for (const auto &Entry : CustomFunctions) { if (Entry.Pattern.match(*FuncDecl)) { - const StringRef Reason = + StringRef Reason = Entry.Reason.empty() ? "is marked as unsafe" : Entry.Reason.c_str(); - if (Entry.Replacement.empty()) { + // Omit the replacement, when a fully-custom reason is given. + if (Reason.consume_front(">")) { + diag(SourceExpr->getExprLoc(), "function %0 %1") + << FuncDecl << Reason.trim() << SourceExpr->getSourceRange(); + // Do not recommend a replacement when it is not present. + } else if (Entry.Replacement.empty()) { diag(SourceExpr->getExprLoc(), "function %0 %1; it should not be used") << FuncDecl << Reason << Entry.Replacement << SourceExpr->getSourceRange(); + // Otherwise, emit the replacement. } else { diag(SourceExpr->getExprLoc(), "function %0 %1; '%2' should be used instead") diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp index dae679b..6502fc9 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp @@ -37,8 +37,8 @@ void UnusedRaiiCheck::registerMatchers(MatchFinder *Finder) { } template <typename T> -static void reportDiagnostic(DiagnosticBuilder D, const T *Node, SourceRange SR, - bool DefaultConstruction) { +static void reportDiagnostic(const DiagnosticBuilder &D, const T *Node, + SourceRange SR, bool DefaultConstruction) { const char *Replacement = " give_me_a_name"; // If this is a default ctor we have to remove the parens or we'll introduce a diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp index 6d134a0..b2e08fe 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -19,6 +19,7 @@ #include "../utils/ExprSequence.h" #include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" #include <optional> using namespace clang::ast_matchers; @@ -48,7 +49,8 @@ struct UseAfterMove { /// various internal helper functions). class UseAfterMoveFinder { public: - UseAfterMoveFinder(ASTContext *TheContext); + UseAfterMoveFinder(ASTContext *TheContext, + llvm::ArrayRef<StringRef> InvalidationFunctions); // Within the given code block, finds the first use of 'MovedVariable' that // occurs after 'MovingCall' (the expression that performs the move). If a @@ -71,6 +73,7 @@ private: llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs); ASTContext *Context; + llvm::ArrayRef<StringRef> InvalidationFunctions; std::unique_ptr<ExprSequence> Sequence; std::unique_ptr<StmtToBlockMap> BlockMap; llvm::SmallPtrSet<const CFGBlock *, 8> Visited; @@ -78,6 +81,11 @@ private: } // namespace +static auto getNameMatcher(llvm::ArrayRef<StringRef> InvalidationFunctions) { + return anyOf(hasAnyName("::std::move", "::std::forward"), + matchers::matchesAnyListedName(InvalidationFunctions)); +} + // Matches nodes that are // - Part of a decltype argument or class template argument (we check this by // seeing if they are children of a TypeLoc), or @@ -92,8 +100,9 @@ static StatementMatcher inDecltypeOrTemplateArg() { hasAncestor(expr(hasUnevaluatedContext()))); } -UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext) - : Context(TheContext) {} +UseAfterMoveFinder::UseAfterMoveFinder( + ASTContext *TheContext, llvm::ArrayRef<StringRef> InvalidationFunctions) + : Context(TheContext), InvalidationFunctions(InvalidationFunctions) {} std::optional<UseAfterMove> UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall, @@ -359,7 +368,7 @@ void UseAfterMoveFinder::getReinits( unless(parmVarDecl(hasType( references(qualType(isConstQualified())))))), unless(callee(functionDecl( - hasAnyName("::std::move", "::std::forward"))))))) + getNameMatcher(InvalidationFunctions))))))) .bind("reinit"); Stmts->clear(); @@ -388,18 +397,21 @@ void UseAfterMoveFinder::getReinits( } } -enum class MoveType { - Move, // std::move - Forward, // std::forward +enum MoveType { + Forward = 0, // std::forward + Move = 1, // std::move + Invalidation = 2, // other }; static MoveType determineMoveType(const FunctionDecl *FuncDecl) { - if (FuncDecl->getName() == "move") - return MoveType::Move; - if (FuncDecl->getName() == "forward") - return MoveType::Forward; + if (FuncDecl->isInStdNamespace()) { + if (FuncDecl->getName() == "move") + return MoveType::Move; + if (FuncDecl->getName() == "forward") + return MoveType::Forward; + } - llvm_unreachable("Invalid move type"); + return MoveType::Invalidation; } static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg, @@ -408,29 +420,38 @@ static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg, const SourceLocation UseLoc = Use.DeclRef->getExprLoc(); const SourceLocation MoveLoc = MovingCall->getExprLoc(); - const bool IsMove = (Type == MoveType::Move); - - Check->diag(UseLoc, "'%0' used after it was %select{forwarded|moved}1") - << MoveArg->getDecl()->getName() << IsMove; - Check->diag(MoveLoc, "%select{forward|move}0 occurred here", + Check->diag(UseLoc, + "'%0' used after it was %select{forwarded|moved|invalidated}1") + << MoveArg->getDecl()->getName() << Type; + Check->diag(MoveLoc, "%select{forward|move|invalidation}0 occurred here", DiagnosticIDs::Note) - << IsMove; + << Type; if (Use.EvaluationOrderUndefined) { Check->diag( UseLoc, - "the use and %select{forward|move}0 are unsequenced, i.e. " + "the use and %select{forward|move|invalidation}0 are unsequenced, i.e. " "there is no guarantee about the order in which they are evaluated", DiagnosticIDs::Note) - << IsMove; + << Type; } else if (Use.UseHappensInLaterLoopIteration) { Check->diag(UseLoc, "the use happens in a later loop iteration than the " - "%select{forward|move}0", + "%select{forward|move|invalidation}0", DiagnosticIDs::Note) - << IsMove; + << Type; } } +UseAfterMoveCheck::UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + InvalidationFunctions(utils::options::parseStringList( + Options.get("InvalidationFunctions", ""))) {} + +void UseAfterMoveCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "InvalidationFunctions", + utils::options::serializeStringList(InvalidationFunctions)); +} + void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) { // try_emplace is a common maybe-moving function that returns a // bool to tell callers whether it moved. Ignore std::move inside @@ -438,11 +459,14 @@ void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) { // the bool. auto TryEmplaceMatcher = cxxMemberCallExpr(callee(cxxMethodDecl(hasName("try_emplace")))); + auto Arg = declRefExpr().bind("arg"); + auto IsMemberCallee = callee(functionDecl(unless(isStaticStorageClass()))); auto CallMoveMatcher = - callExpr(argumentCountIs(1), - callee(functionDecl(hasAnyName("::std::move", "::std::forward")) + callExpr(callee(functionDecl(getNameMatcher(InvalidationFunctions)) .bind("move-decl")), - hasArgument(0, declRefExpr().bind("arg")), + anyOf(cxxMemberCallExpr(IsMemberCallee, on(Arg)), + callExpr(unless(cxxMemberCallExpr(IsMemberCallee)), + hasArgument(0, Arg))), unless(inDecltypeOrTemplateArg()), unless(hasParent(TryEmplaceMatcher)), expr().bind("call-move"), anyOf(hasAncestor(compoundStmt( @@ -521,7 +545,7 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) { } for (Stmt *CodeBlock : CodeBlocks) { - UseAfterMoveFinder Finder(Result.Context); + UseAfterMoveFinder Finder(Result.Context, InvalidationFunctions); if (auto Use = Finder.find(CodeBlock, MovingCall, Arg)) emitDiagnostic(MovingCall, Arg, *Use, this, Result.Context, determineMoveType(MoveDecl)); diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h index d38b29e..1bbf5c0 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h @@ -20,13 +20,16 @@ namespace clang::tidy::bugprone { /// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/use-after-move.html class UseAfterMoveCheck : public ClangTidyCheck { public: - UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus11; } void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + std::vector<StringRef> InvalidationFunctions; }; } // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp index 2f6fc4d..16d4be98 100644 --- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp @@ -13,8 +13,10 @@ #include "../bugprone/CommandProcessorCheck.h" #include "../bugprone/CopyConstructorMutatesArgumentCheck.h" #include "../bugprone/DefaultOperatorNewOnOveralignedTypeCheck.h" +#include "../bugprone/ExceptionCopyConstructorThrowsCheck.h" #include "../bugprone/FloatLoopCounterCheck.h" #include "../bugprone/PointerArithmeticOnPolymorphicObjectCheck.h" +#include "../bugprone/RandomGeneratorSeedCheck.h" #include "../bugprone/RawMemoryCallOnNonTrivialTypeCheck.h" #include "../bugprone/ReservedIdentifierCheck.h" #include "../bugprone/SignalHandlerCheck.h" @@ -32,6 +34,7 @@ #include "../google/UnnamedNamespaceInHeaderCheck.h" #include "../misc/NewDeleteOverloadsCheck.h" #include "../misc/NonCopyableObjectsCheck.h" +#include "../misc/PredictableRandCheck.h" #include "../misc/StaticAssertCheck.h" #include "../misc/ThrowByValueCatchByReferenceCheck.h" #include "../modernize/AvoidSetjmpLongjmpCheck.h" @@ -39,9 +42,6 @@ #include "../performance/MoveConstructorInitCheck.h" #include "../readability/EnumInitialValueCheck.h" #include "../readability/UppercaseLiteralSuffixCheck.h" -#include "LimitedRandomnessCheck.h" -#include "ProperlySeededRandomGeneratorCheck.h" -#include "ThrownExceptionTypeCheck.h" namespace { @@ -262,7 +262,8 @@ public: "cert-err52-cpp"); CheckFactories.registerCheck<bugprone::ThrowingStaticInitializationCheck>( "cert-err58-cpp"); - CheckFactories.registerCheck<ThrownExceptionTypeCheck>("cert-err60-cpp"); + CheckFactories.registerCheck<bugprone::ExceptionCopyConstructorThrowsCheck>( + "cert-err60-cpp"); CheckFactories.registerCheck<misc::ThrowByValueCatchByReferenceCheck>( "cert-err61-cpp"); // MEM @@ -270,8 +271,8 @@ public: .registerCheck<bugprone::DefaultOperatorNewOnOveralignedTypeCheck>( "cert-mem57-cpp"); // MSC - CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc50-cpp"); - CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>( + CheckFactories.registerCheck<misc::PredictableRandCheck>("cert-msc50-cpp"); + CheckFactories.registerCheck<bugprone::RandomGeneratorSeedCheck>( "cert-msc51-cpp"); CheckFactories.registerCheck<bugprone::SignalHandlerCheck>( "cert-msc54-cpp"); @@ -323,8 +324,8 @@ public: // MSC CheckFactories.registerCheck<bugprone::UnsafeFunctionsCheck>( "cert-msc24-c"); - CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c"); - CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>( + CheckFactories.registerCheck<misc::PredictableRandCheck>("cert-msc30-c"); + CheckFactories.registerCheck<bugprone::RandomGeneratorSeedCheck>( "cert-msc32-c"); CheckFactories.registerCheck<bugprone::UnsafeFunctionsCheck>( "cert-msc33-c"); diff --git a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt index 5abb472..3137903 100644 --- a/clang-tools-extra/clang-tidy/cert/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cert/CMakeLists.txt @@ -5,9 +5,6 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangTidyCERTModule STATIC CERTTidyModule.cpp - LimitedRandomnessCheck.cpp - ProperlySeededRandomGeneratorCheck.cpp - ThrownExceptionTypeCheck.cpp LINK_LIBS clangTidy diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp index d0f8652..1c5c854 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp @@ -19,10 +19,11 @@ namespace clang::tidy::cppcoreguidelines { namespace { AST_MATCHER_P(CXXForRangeStmt, hasRangeBeginEndStmt, ast_matchers::internal::Matcher<DeclStmt>, InnerMatcher) { - for (const DeclStmt *Stmt : {Node.getBeginStmt(), Node.getEndStmt()}) - if (Stmt != nullptr && InnerMatcher.matches(*Stmt, Finder, Builder)) - return true; - return false; + return llvm::any_of(llvm::ArrayRef{Node.getBeginStmt(), Node.getEndStmt()}, + [&](const DeclStmt *Stmt) { + return Stmt && + InnerMatcher.matches(*Stmt, Finder, Builder); + }); } AST_MATCHER(Stmt, isInsideOfRangeBeginEndStmt) { diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccessCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccessCheck.cpp index 83803a3..cf4b445 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccessCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsAvoidUncheckedContainerAccessCheck.cpp @@ -103,7 +103,6 @@ void ProBoundsAvoidUncheckedContainerAccessCheck::registerMatchers( void ProBoundsAvoidUncheckedContainerAccessCheck::check( const MatchFinder::MatchResult &Result) { - const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller"); if (FixMode == None) { @@ -177,7 +176,7 @@ void ProBoundsAvoidUncheckedContainerAccessCheck::check( } } else if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(MatchedExpr)) { // Case: a.operator[](i) or a->operator[](i) - const auto *Callee = dyn_cast<MemberExpr>(MCE->getCallee()); + const auto *Callee = cast<MemberExpr>(MCE->getCallee()); if (FixMode == At) { // Cases: a.operator[](i) => a.at(i) and a->operator[](i) => a->at(i) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp index 111c621..f267646 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp @@ -361,7 +361,8 @@ void ProTypeMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } // FIXME: Copied from clang/lib/Sema/SemaDeclCXX.cpp. -static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { +static bool isIncompleteOrZeroLengthArrayType(const ASTContext &Context, + QualType T) { if (T->isIncompleteArrayType()) return true; @@ -375,7 +376,7 @@ static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { return false; } -static bool isEmpty(ASTContext &Context, const QualType &Type) { +static bool isEmpty(const ASTContext &Context, const QualType &Type) { if (const CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl()) { return ClassDecl->isEmpty(); } @@ -431,19 +432,13 @@ static llvm::StringLiteral getInitializer(QualType QT, bool UseAssignment) { } } -void ProTypeMemberInitCheck::checkMissingMemberInitializer( - ASTContext &Context, const CXXRecordDecl &ClassDecl, - const CXXConstructorDecl *Ctor) { - const bool IsUnion = ClassDecl.isUnion(); - - if (IsUnion && ClassDecl.hasInClassInitializer()) - return; - - // Gather all fields (direct and indirect) that need to be initialized. - SmallPtrSet<const FieldDecl *, 16> FieldsToInit; +static void +computeFieldsToInit(const ASTContext &Context, const RecordDecl &Record, + bool IgnoreArrays, + SmallPtrSetImpl<const FieldDecl *> &FieldsToInit) { bool AnyMemberHasInitPerUnion = false; forEachFieldWithFilter( - ClassDecl, ClassDecl.fields(), AnyMemberHasInitPerUnion, + Record, Record.fields(), AnyMemberHasInitPerUnion, [&](const FieldDecl *F) { if (IgnoreArrays && F->getType()->isArrayType()) return; @@ -458,6 +453,19 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer( !AnyMemberHasInitPerUnion) FieldsToInit.insert(F); }); +} + +void ProTypeMemberInitCheck::checkMissingMemberInitializer( + ASTContext &Context, const CXXRecordDecl &ClassDecl, + const CXXConstructorDecl *Ctor) { + const bool IsUnion = ClassDecl.isUnion(); + + if (IsUnion && ClassDecl.hasInClassInitializer()) + return; + + // Gather all fields (direct and indirect) that need to be initialized. + SmallPtrSet<const FieldDecl *, 16> FieldsToInit; + computeFieldsToInit(Context, ClassDecl, IgnoreArrays, FieldsToInit); if (FieldsToInit.empty()) return; @@ -507,7 +515,7 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer( // Collect all fields but only suggest a fix for the first member of unions, // as initializing more than one union member is an error. SmallPtrSet<const FieldDecl *, 16> FieldsToFix; - AnyMemberHasInitPerUnion = false; + bool AnyMemberHasInitPerUnion = false; forEachFieldWithFilter(ClassDecl, ClassDecl.fields(), AnyMemberHasInitPerUnion, [&](const FieldDecl *F) { if (!FieldsToInit.contains(F)) @@ -541,7 +549,6 @@ void ProTypeMemberInitCheck::checkMissingMemberInitializer( void ProTypeMemberInitCheck::checkMissingBaseClassInitializer( const ASTContext &Context, const CXXRecordDecl &ClassDecl, const CXXConstructorDecl *Ctor) { - // Gather any base classes that need to be initialized. SmallVector<const RecordDecl *, 4> AllBases; SmallPtrSet<const RecordDecl *, 4> BasesToInit; @@ -583,6 +590,17 @@ void ProTypeMemberInitCheck::checkMissingBaseClassInitializer( void ProTypeMemberInitCheck::checkUninitializedTrivialType( const ASTContext &Context, const VarDecl *Var) { + // Verify that the record actually needs initialization + const CXXRecordDecl *Record = Var->getType()->getAsCXXRecordDecl(); + if (!Record) + return; + + SmallPtrSet<const FieldDecl *, 16> FieldsToInit; + computeFieldsToInit(Context, *Record, IgnoreArrays, FieldsToInit); + + if (FieldsToInit.empty()) + return; + const DiagnosticBuilder Diag = diag(Var->getBeginLoc(), "uninitialized record type: %0") << Var; diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp index 77a7b2b..851392f 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.cpp @@ -102,7 +102,6 @@ toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K) { static std::string join(ArrayRef<SpecialMemberFunctionsCheck::SpecialMemberFunctionKind> SMFS, llvm::StringRef AndOr) { - assert(!SMFS.empty() && "List of defined or undefined members should never be empty."); std::string Buffer; diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h index 1d41b57..6d76e07 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/SpecialMemberFunctionsCheck.h @@ -93,7 +93,7 @@ struct DenseMapInfo< "TOMBSTONE"}; } - static unsigned getHashValue(ClassDefId Val) { + static unsigned getHashValue(const ClassDefId &Val) { assert(Val != getEmptyKey() && "Cannot hash the empty key!"); assert(Val != getTombstoneKey() && "Cannot hash the tombstone key!"); diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/VirtualClassDestructorCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/VirtualClassDestructorCheck.cpp index 89f1bf1..bfa9ce3 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/VirtualClassDestructorCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/VirtualClassDestructorCheck.cpp @@ -167,7 +167,6 @@ static FixItHint changePrivateDestructorVisibilityTo( void VirtualClassDestructorCheck::check( const MatchFinder::MatchResult &Result) { - const auto *MatchedClassOrStruct = Result.Nodes.getNodeAs<CXXRecordDecl>("ProblematicClassOrStruct"); diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp index 652dec9..4a10cb4 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp @@ -17,113 +17,61 @@ namespace clang::tidy::fuchsia { namespace { AST_MATCHER(CXXRecordDecl, hasBases) { - if (Node.hasDefinition()) - return Node.getNumBases() > 0; - return false; + return Node.hasDefinition() && Node.getNumBases() > 0; } } // namespace -// Adds a node (by name) to the interface map, if it was not present in the map -// previously. -void MultipleInheritanceCheck::addNodeToInterfaceMap(const CXXRecordDecl *Node, - bool IsInterface) { - assert(Node->getIdentifier()); - const StringRef Name = Node->getIdentifier()->getName(); - InterfaceMap.insert(std::make_pair(Name, IsInterface)); -} - -// Returns "true" if the boolean "isInterface" has been set to the -// interface status of the current Node. Return "false" if the -// interface status for the current node is not yet known. -bool MultipleInheritanceCheck::getInterfaceStatus(const CXXRecordDecl *Node, - bool &IsInterface) const { - assert(Node->getIdentifier()); - const StringRef Name = Node->getIdentifier()->getName(); - auto Pair = InterfaceMap.find(Name); - if (Pair == InterfaceMap.end()) - return false; - IsInterface = Pair->second; - return true; -} - -bool MultipleInheritanceCheck::isCurrentClassInterface( - const CXXRecordDecl *Node) const { - // Interfaces should have no fields. - if (!Node->field_empty()) - return false; - - // Interfaces should have exclusively pure methods. - return llvm::none_of(Node->methods(), [](const CXXMethodDecl *M) { - return M->isUserProvided() && !M->isPureVirtual() && !M->isStatic(); - }); -} +bool MultipleInheritanceCheck::isInterface(const CXXBaseSpecifier &Base) { + const CXXRecordDecl *const Node = Base.getType()->getAsCXXRecordDecl(); + if (!Node) + return true; -bool MultipleInheritanceCheck::isInterface(const CXXRecordDecl *Node) { - if (!Node->getIdentifier()) - return false; + assert(Node->isCompleteDefinition()); // Short circuit the lookup if we have analyzed this record before. - bool PreviousIsInterfaceResult = false; - if (getInterfaceStatus(Node, PreviousIsInterfaceResult)) - return PreviousIsInterfaceResult; - - // To be an interface, all base classes must be interfaces as well. - for (const auto &I : Node->bases()) { - if (I.isVirtual()) - continue; - const auto *Base = I.getType()->getAsCXXRecordDecl(); - if (!Base) - continue; - assert(Base->isCompleteDefinition()); - if (!isInterface(Base)) { - addNodeToInterfaceMap(Node, false); - return false; - } - } - - const bool CurrentClassIsInterface = isCurrentClassInterface(Node); - addNodeToInterfaceMap(Node, CurrentClassIsInterface); + if (const auto CachedValue = InterfaceMap.find(Node); + CachedValue != InterfaceMap.end()) + return CachedValue->second; + + // To be an interface, a class must have... + const bool CurrentClassIsInterface = + // ...no bases that aren't interfaces... + llvm::none_of(Node->bases(), + [&](const CXXBaseSpecifier &I) { + return !I.isVirtual() && !isInterface(I); + }) && + // ...no fields, and... + Node->field_empty() && + // ...no methods that aren't pure virtual. + llvm::none_of(Node->methods(), [](const CXXMethodDecl *M) { + return M->isUserProvided() && !M->isPureVirtual() && !M->isStatic(); + }); + + InterfaceMap.try_emplace(Node, CurrentClassIsInterface); return CurrentClassIsInterface; } void MultipleInheritanceCheck::registerMatchers(MatchFinder *Finder) { - // Match declarations which have bases. Finder->addMatcher(cxxRecordDecl(hasBases(), isDefinition()).bind("decl"), this); } void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) { - if (const auto *D = Result.Nodes.getNodeAs<CXXRecordDecl>("decl")) { - // Check against map to see if the class inherits from multiple - // concrete classes - unsigned NumConcrete = 0; - for (const auto &I : D->bases()) { - if (I.isVirtual()) - continue; - const auto *Base = I.getType()->getAsCXXRecordDecl(); - if (!Base) - continue; - assert(Base->isCompleteDefinition()); - if (!isInterface(Base)) - NumConcrete++; - } - - // Check virtual bases to see if there is more than one concrete - // non-virtual base. - for (const auto &V : D->vbases()) { - const auto *Base = V.getType()->getAsCXXRecordDecl(); - if (!Base) - continue; - assert(Base->isCompleteDefinition()); - if (!isInterface(Base)) - NumConcrete++; - } - - if (NumConcrete > 1) { - diag(D->getBeginLoc(), "inheriting multiple classes that aren't " - "pure virtual is discouraged"); - } - } + const auto &D = *Result.Nodes.getNodeAs<CXXRecordDecl>("decl"); + // Check to see if the class inherits from multiple concrete classes. + unsigned NumConcrete = + llvm::count_if(D.bases(), [&](const CXXBaseSpecifier &I) { + return !I.isVirtual() && !isInterface(I); + }); + + // Check virtual bases to see if there is more than one concrete + // non-virtual base. + NumConcrete += llvm::count_if( + D.vbases(), [&](const CXXBaseSpecifier &V) { return !isInterface(V); }); + + if (NumConcrete > 1) + diag(D.getBeginLoc(), "inheriting multiple classes that aren't " + "pure virtual is discouraged"); } } // namespace clang::tidy::fuchsia diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h index 2e26843..4dcbd0c 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h +++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.h @@ -30,15 +30,12 @@ public: void onEndOfTranslationUnit() override { InterfaceMap.clear(); } private: - void addNodeToInterfaceMap(const CXXRecordDecl *Node, bool IsInterface); - bool getInterfaceStatus(const CXXRecordDecl *Node, bool &IsInterface) const; - bool isCurrentClassInterface(const CXXRecordDecl *Node) const; - bool isInterface(const CXXRecordDecl *Node); + bool isInterface(const CXXBaseSpecifier &Base); // Contains the identity of each named CXXRecord as an interface. This is // used to memoize lookup speeds and improve performance from O(N^2) to O(N), // where N is the number of classes. - llvm::StringMap<bool> InterfaceMap; + llvm::DenseMap<const CXXRecordDecl *, bool> InterfaceMap; }; } // namespace clang::tidy::fuchsia diff --git a/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp index b6fb22c..9c98b49 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/VirtualInheritanceCheck.cpp @@ -20,10 +20,9 @@ AST_MATCHER(CXXRecordDecl, hasDirectVirtualBaseClass) { return false; if (!Node.getNumVBases()) return false; - for (const CXXBaseSpecifier &Base : Node.bases()) - if (Base.isVirtual()) - return true; - return false; + return llvm::any_of(Node.bases(), [](const CXXBaseSpecifier &Base) { + return Base.isVirtual(); + }); } } // namespace diff --git a/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp b/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp index 6b96f71..92d590c 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/AvoidThrowingObjCExceptionCheck.cpp @@ -14,7 +14,6 @@ using namespace clang::ast_matchers; namespace clang::tidy::google::objc { void AvoidThrowingObjCExceptionCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(objcThrowStmt().bind("throwStmt"), this); Finder->addMatcher( objcMessageExpr(anyOf(hasSelector("raise:format:"), diff --git a/clang-tools-extra/clang-tidy/google/CMakeLists.txt b/clang-tools-extra/clang-tidy/google/CMakeLists.txt index 1d4229e..982a188 100644 --- a/clang-tools-extra/clang-tidy/google/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/google/CMakeLists.txt @@ -4,7 +4,6 @@ set(LLVM_LINK_COMPONENTS ) add_clang_library(clangTidyGoogleModule STATIC - AvoidCStyleCastsCheck.cpp AvoidNSObjectNewCheck.cpp AvoidThrowingObjCExceptionCheck.cpp AvoidUnderscoreInGoogletestNameCheck.cpp @@ -25,6 +24,7 @@ add_clang_library(clangTidyGoogleModule STATIC LINK_LIBS clangTidy + clangTidyModernizeModule clangTidyReadabilityModule clangTidyUtils diff --git a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp index aff8b45..ce46b3f 100644 --- a/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp @@ -9,10 +9,10 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "../modernize/AvoidCStyleCastCheck.h" #include "../readability/BracesAroundStatementsCheck.h" #include "../readability/FunctionSizeCheck.h" #include "../readability/NamespaceCommentCheck.h" -#include "AvoidCStyleCastsCheck.h" #include "AvoidNSObjectNewCheck.h" #include "AvoidThrowingObjCExceptionCheck.h" #include "AvoidUnderscoreInGoogletestNameCheck.h" @@ -67,7 +67,7 @@ public: CheckFactories .registerCheck<readability::AvoidUnderscoreInGoogletestNameCheck>( "google-readability-avoid-underscore-in-googletest-name"); - CheckFactories.registerCheck<readability::AvoidCStyleCastsCheck>( + CheckFactories.registerCheck<modernize::AvoidCStyleCastCheck>( "google-readability-casting"); CheckFactories.registerCheck<readability::TodoCommentCheck>( "google-readability-todo"); diff --git a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp index 7331b36..2789e4d 100644 --- a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.cpp @@ -11,42 +11,102 @@ #include "clang/Lex/Preprocessor.h" #include <optional> -namespace clang::tidy::google::readability { +namespace clang::tidy { + +namespace google::readability { + +enum class StyleKind { Parentheses, Hyphen }; + +} // namespace google::readability + +template <> struct OptionEnumMapping<google::readability::StyleKind> { + static ArrayRef<std::pair<google::readability::StyleKind, StringRef>> + getEnumMapping() { + static constexpr std::pair<google::readability::StyleKind, StringRef> + Mapping[] = { + {google::readability::StyleKind::Hyphen, "Hyphen"}, + {google::readability::StyleKind::Parentheses, "Parentheses"}, + }; + return {Mapping}; + } +}; + +} // namespace clang::tidy +namespace clang::tidy::google::readability { class TodoCommentCheck::TodoCommentHandler : public CommentHandler { public: TodoCommentHandler(TodoCommentCheck &Check, std::optional<std::string> User) : Check(Check), User(User ? *User : "unknown"), - TodoMatch("^// *TODO *(\\(.*\\))?:?( )?(.*)$") {} + TodoMatch(R"(^// *TODO *((\((.*)\))?:?( )?|: *(.*) *- *)?(.*)$)") { + const llvm::StringRef TodoStyleString = + Check.Options.get("Style", "Hyphen"); + for (const auto &[Value, Name] : + OptionEnumMapping<StyleKind>::getEnumMapping()) { + if (Name == TodoStyleString) { + TodoStyle = Value; + return; + } + } + Check.configurationDiag( + "invalid value '%0' for " + "google-readability-todo.Style; valid values are " + "'Parentheses' and 'Hyphen'. Defaulting to 'Hyphen'") + << TodoStyleString; + } bool HandleComment(Preprocessor &PP, SourceRange Range) override { const StringRef Text = Lexer::getSourceText(CharSourceRange::getCharRange(Range), PP.getSourceManager(), PP.getLangOpts()); - SmallVector<StringRef, 4> Matches; + SmallVector<StringRef, 7> Matches; if (!TodoMatch.match(Text, &Matches)) return false; - const StringRef Username = Matches[1]; - const StringRef Comment = Matches[3]; + const StyleKind ParsedStyle = + !Matches[3].empty() ? StyleKind::Parentheses : StyleKind::Hyphen; + const StringRef Username = + ParsedStyle == StyleKind::Parentheses ? Matches[3] : Matches[5]; + const StringRef Comment = Matches[6]; - if (!Username.empty()) + if (!Username.empty() && + (ParsedStyle == StyleKind::Parentheses || !Comment.empty())) { return false; + } - const std::string NewText = - ("// TODO(" + Twine(User) + "): " + Comment).str(); + if (Username.empty()) { + Check.diag(Range.getBegin(), "missing username/bug in TODO") + << FixItHint::CreateReplacement( + CharSourceRange::getCharRange(Range), + createReplacementString(Username, Comment)); + } + + if (Comment.empty()) + Check.diag(Range.getBegin(), "missing details in TODO"); - Check.diag(Range.getBegin(), "missing username/bug in TODO") - << FixItHint::CreateReplacement(CharSourceRange::getCharRange(Range), - NewText); return false; } + std::string createReplacementString(const StringRef Username, + const StringRef Comment) const { + if (TodoStyle == StyleKind::Parentheses) { + return ("// TODO(" + Twine(User) + + "): " + (Comment.empty() ? "some details" : Comment)) + .str(); + } + return ("// TODO: " + Twine(User) + " - " + + (Comment.empty() ? "some details" : Comment)) + .str(); + } + + StyleKind getTodoStyle() const { return TodoStyle; } + private: TodoCommentCheck &Check; std::string User; llvm::Regex TodoMatch; + StyleKind TodoStyle = StyleKind::Hyphen; }; TodoCommentCheck::TodoCommentCheck(StringRef Name, ClangTidyContext *Context) @@ -62,4 +122,8 @@ void TodoCommentCheck::registerPPCallbacks(const SourceManager &SM, PP->addCommentHandler(Handler.get()); } +void TodoCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "Style", Handler->getTodoStyle()); +} + } // namespace clang::tidy::google::readability diff --git a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h index 08cea13..800bc0f 100644 --- a/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h +++ b/clang-tools-extra/clang-tidy/google/TodoCommentCheck.h @@ -27,6 +27,8 @@ public: void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + private: class TodoCommentHandler; std::unique_ptr<TodoCommentHandler> Handler; diff --git a/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp index ea81c7c..d720986 100644 --- a/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/PreferStaticOverAnonymousNamespaceCheck.cpp @@ -77,7 +77,6 @@ void PreferStaticOverAnonymousNamespaceCheck::registerMatchers( void PreferStaticOverAnonymousNamespaceCheck::check( const MatchFinder::MatchResult &Result) { - if (const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("function")) { if (Func->isCXXClassMember()) diag(Func->getLocation(), diff --git a/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp index 55b383e..16f8786 100644 --- a/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/UseNewMLIROpBuilderCheck.cpp @@ -12,7 +12,6 @@ #include "clang/Lex/Lexer.h" #include "clang/Tooling/Transformer/RangeSelector.h" #include "clang/Tooling/Transformer/RewriteRule.h" -#include "clang/Tooling/Transformer/SourceCode.h" #include "clang/Tooling/Transformer/Stencil.h" #include "llvm/Support/Error.h" #include "llvm/Support/FormatVariadic.h" diff --git a/clang-tools-extra/clang-tidy/llvmlibc/RestrictSystemLibcHeadersCheck.cpp b/clang-tools-extra/clang-tidy/llvmlibc/RestrictSystemLibcHeadersCheck.cpp index 129b8a9..ecd8e19 100644 --- a/clang-tools-extra/clang-tidy/llvmlibc/RestrictSystemLibcHeadersCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvmlibc/RestrictSystemLibcHeadersCheck.cpp @@ -22,11 +22,11 @@ namespace { class RestrictedIncludesPPCallbacks : public portability::RestrictedIncludesPPCallbacks { public: - explicit RestrictedIncludesPPCallbacks( - RestrictSystemLibcHeadersCheck &Check, const SourceManager &SM, - const SmallString<128> CompilerIncudeDir) + explicit RestrictedIncludesPPCallbacks(RestrictSystemLibcHeadersCheck &Check, + const SourceManager &SM, + SmallString<128> CompilerIncudeDir) : portability::RestrictedIncludesPPCallbacks(Check, SM), - CompilerIncudeDir(CompilerIncudeDir) {} + CompilerIncudeDir(std::move(CompilerIncudeDir)) {} void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, @@ -61,7 +61,7 @@ void RestrictSystemLibcHeadersCheck::registerPPCallbacks( StringRef(PP->getHeaderSearchInfo().getHeaderSearchOpts().ResourceDir); llvm::sys::path::append(CompilerIncudeDir, "include"); PP->addPPCallbacks(std::make_unique<RestrictedIncludesPPCallbacks>( - *this, SM, CompilerIncudeDir)); + *this, SM, std::move(CompilerIncudeDir))); } } // namespace clang::tidy::llvm_libc diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt index 6214ee9..e8705aa 100644 --- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -33,6 +33,7 @@ add_clang_library(clangTidyMiscModule STATIC NonCopyableObjectsCheck.cpp NonPrivateMemberVariablesInClassesCheck.cpp OverrideWithDifferentVisibilityCheck.cpp + PredictableRandCheck.cpp RedundantExpressionCheck.cpp StaticAssertCheck.cpp ThrowByValueCatchByReferenceCheck.cpp diff --git a/clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp index 61d5477..418b8ae 100644 --- a/clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/ConfusableIdentifierCheck.cpp @@ -53,7 +53,6 @@ static llvm::SmallString<64U> skeleton(StringRef Name) { const char *Curr = Name.data(); const char *End = Curr + Name.size(); while (Curr < End) { - const char *Prev = Curr; UTF32 CodePoint = 0; const ConversionResult Result = convertUTF8Sequence( @@ -82,7 +81,8 @@ static llvm::SmallString<64U> skeleton(StringRef Name) { errs() << "Unicode conversion issue\n"; break; } - Skeleton.append((char *)BufferStart, (char *)IBuffer); + Skeleton.append(reinterpret_cast<char *>(BufferStart), + reinterpret_cast<char *>(IBuffer)); } } return Skeleton; diff --git a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp index a2d3d3f..75693a0 100644 --- a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.cpp @@ -67,13 +67,20 @@ static auto typeWithNameIn(const std::vector<StringRef> &Names) { hasCanonicalType(hasDeclaration(namedDecl(hasAnyName(Names))))); } +static auto functionWithNameIn(const std::vector<StringRef> &Names) { + auto Call = callExpr(callee(functionDecl(hasAnyName(Names)))); + return anyOf(expr(cxxBindTemporaryExpr(has(Call))), expr(Call)); +} + CoroutineHostileRAIICheck::CoroutineHostileRAIICheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), RAIITypesList(utils::options::parseStringList( Options.get("RAIITypesList", "std::lock_guard;std::scoped_lock"))), AllowedAwaitablesList(utils::options::parseStringList( - Options.get("AllowedAwaitablesList", ""))) {} + Options.get("AllowedAwaitablesList", ""))), + AllowedCallees( + utils::options::parseStringList(Options.get("AllowedCallees", ""))) {} void CoroutineHostileRAIICheck::registerMatchers(MatchFinder *Finder) { // A suspension happens with co_await or co_yield. @@ -81,7 +88,8 @@ void CoroutineHostileRAIICheck::registerMatchers(MatchFinder *Finder) { hasAttr(attr::Kind::ScopedLockable))))) .bind("scoped-lockable"); auto OtherRAII = varDecl(typeWithNameIn(RAIITypesList)).bind("raii"); - auto AllowedSuspend = awaitable(typeWithNameIn(AllowedAwaitablesList)); + auto AllowedSuspend = awaitable(anyOf(typeWithNameIn(AllowedAwaitablesList), + functionWithNameIn(AllowedCallees))); Finder->addMatcher( expr(anyOf(coawaitExpr(unless(AllowedSuspend)), coyieldExpr()), forEachPrevStmt( @@ -109,7 +117,9 @@ void CoroutineHostileRAIICheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "RAIITypesList", utils::options::serializeStringList(RAIITypesList)); - Options.store(Opts, "SafeAwaitableList", + Options.store(Opts, "AllowedAwaitablesList", utils::options::serializeStringList(AllowedAwaitablesList)); + Options.store(Opts, "AllowedCallees", + utils::options::serializeStringList(AllowedCallees)); } } // namespace clang::tidy::misc diff --git a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h index 768b62e..12ad1b1 100644 --- a/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h +++ b/clang-tools-extra/clang-tidy/misc/CoroutineHostileRAIICheck.h @@ -46,6 +46,9 @@ private: // List of fully qualified awaitable types which are considered safe to // co_await. std::vector<StringRef> AllowedAwaitablesList; + // List of callees whose return values are considered safe to directly + // co_await. + std::vector<StringRef> AllowedCallees; }; } // namespace clang::tidy::misc diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp index 347fa2a..03f2577 100644 --- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp @@ -23,6 +23,7 @@ #include "NonCopyableObjectsCheck.h" #include "NonPrivateMemberVariablesInClassesCheck.h" #include "OverrideWithDifferentVisibilityCheck.h" +#include "PredictableRandCheck.h" #include "RedundantExpressionCheck.h" #include "StaticAssertCheck.h" #include "ThrowByValueCatchByReferenceCheck.h" @@ -63,6 +64,9 @@ public: "misc-non-copyable-objects"); CheckFactories.registerCheck<NonPrivateMemberVariablesInClassesCheck>( "misc-non-private-member-variables-in-classes"); + CheckFactories.registerCheck<OverrideWithDifferentVisibilityCheck>( + "misc-override-with-different-visibility"); + CheckFactories.registerCheck<PredictableRandCheck>("misc-predictable-rand"); CheckFactories.registerCheck<RedundantExpressionCheck>( "misc-redundant-expression"); CheckFactories.registerCheck<StaticAssertCheck>("misc-static-assert"); @@ -82,8 +86,6 @@ public: "misc-use-anonymous-namespace"); CheckFactories.registerCheck<UseInternalLinkageCheck>( "misc-use-internal-linkage"); - CheckFactories.registerCheck<OverrideWithDifferentVisibilityCheck>( - "misc-override-with-different-visibility"); } }; diff --git a/clang-tools-extra/clang-tidy/misc/MisleadingBidirectionalCheck.cpp b/clang-tools-extra/clang-tidy/misc/MisleadingBidirectionalCheck.cpp index 4807567..8a10f70 100644 --- a/clang-tools-extra/clang-tidy/misc/MisleadingBidirectionalCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/MisleadingBidirectionalCheck.cpp @@ -52,8 +52,9 @@ static bool containsMisleadingBidi(StringRef Buffer, } llvm::UTF32 CodePoint = 0; const llvm::ConversionResult Result = llvm::convertUTF8Sequence( - (const llvm::UTF8 **)&CurPtr, (const llvm::UTF8 *)Buffer.end(), - &CodePoint, llvm::strictConversion); + reinterpret_cast<const llvm::UTF8 **>(&CurPtr), + reinterpret_cast<const llvm::UTF8 *>(Buffer.end()), &CodePoint, + llvm::strictConversion); // If conversion fails, utf-8 is designed so that we can just try next char. if (Result != llvm::conversionOK) { diff --git a/clang-tools-extra/clang-tidy/misc/MisleadingIdentifierCheck.cpp b/clang-tools-extra/clang-tidy/misc/MisleadingIdentifierCheck.cpp index 335fffc..9c0de87 100644 --- a/clang-tools-extra/clang-tidy/misc/MisleadingIdentifierCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/MisleadingIdentifierCheck.cpp @@ -125,7 +125,8 @@ static bool hasRTLCharacters(StringRef Buffer) { while (CurPtr < EndPtr) { llvm::UTF32 CodePoint = 0; const llvm::ConversionResult Result = llvm::convertUTF8Sequence( - (const llvm::UTF8 **)&CurPtr, (const llvm::UTF8 *)EndPtr, &CodePoint, + reinterpret_cast<const llvm::UTF8 **>(&CurPtr), + reinterpret_cast<const llvm::UTF8 *>(EndPtr), &CodePoint, llvm::strictConversion); if (Result != llvm::conversionOK) break; diff --git a/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp b/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp index a44e9b3..0471ba8 100644 --- a/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/NewDeleteOverloadsCheck.cpp @@ -114,17 +114,15 @@ hasCorrespondingOverloadInBaseClass(const CXXMethodDecl *MD, RD = MD->getParent(); } - for (const auto &BS : RD->bases()) { + return llvm::any_of(RD->bases(), [&](const CXXBaseSpecifier &BS) { // We can't say much about a dependent base class, but to avoid false // positives assume it can have a corresponding overload. if (BS.getType()->isDependentType()) return true; - if (const auto *BaseRD = BS.getType()->getAsCXXRecordDecl()) - if (hasCorrespondingOverloadInBaseClass(MD, BaseRD)) - return true; - } - - return false; + if (const CXXRecordDecl *BaseRD = BS.getType()->getAsCXXRecordDecl()) + return hasCorrespondingOverloadInBaseClass(MD, BaseRD); + return false; + }); } void NewDeleteOverloadsCheck::registerMatchers(MatchFinder *Finder) { diff --git a/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.cpp b/clang-tools-extra/clang-tidy/misc/PredictableRandCheck.cpp index 4fe9c6c..eed80e0 100644 --- a/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/PredictableRandCheck.cpp @@ -6,22 +6,22 @@ // //===----------------------------------------------------------------------===// -#include "LimitedRandomnessCheck.h" +#include "PredictableRandCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang::ast_matchers; -namespace clang::tidy::cert { +namespace clang::tidy::misc { -void LimitedRandomnessCheck::registerMatchers(MatchFinder *Finder) { +void PredictableRandCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(callExpr(callee(functionDecl(namedDecl(hasName("::rand")), parameterCountIs(0)))) .bind("randomGenerator"), this); } -void LimitedRandomnessCheck::check(const MatchFinder::MatchResult &Result) { +void PredictableRandCheck::check(const MatchFinder::MatchResult &Result) { std::string Msg; if (getLangOpts().CPlusPlus) Msg = "; use C++11 random library instead"; @@ -30,4 +30,4 @@ void LimitedRandomnessCheck::check(const MatchFinder::MatchResult &Result) { diag(MatchedDecl->getBeginLoc(), "rand() has limited randomness" + Msg); } -} // namespace clang::tidy::cert +} // namespace clang::tidy::misc diff --git a/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.h b/clang-tools-extra/clang-tidy/misc/PredictableRandCheck.h index a806cd3..2237e7e 100644 --- a/clang-tools-extra/clang-tidy/cert/LimitedRandomnessCheck.h +++ b/clang-tools-extra/clang-tidy/misc/PredictableRandCheck.h @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_LIMITEDRANDOMNESSCHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_LIMITEDRANDOMNESSCHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_PREDICTABLERANDCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_PREDICTABLERANDCHECK_H #include "../ClangTidyCheck.h" -namespace clang::tidy::cert { +namespace clang::tidy::misc { /// Pseudorandom number generators are not genuinely random. The result of the /// std::rand() function makes no guarantees as to the quality of the random @@ -19,15 +19,15 @@ namespace clang::tidy::cert { /// This check warns for the usage of std::rand() function. /// /// For the user-facing documentation see: -/// https://clang.llvm.org/extra/clang-tidy/checks/cert/msc50-cpp.html -class LimitedRandomnessCheck : public ClangTidyCheck { +/// https://clang.llvm.org/extra/clang-tidy/checks/misc/predictable-rand.html +class PredictableRandCheck : public ClangTidyCheck { public: - LimitedRandomnessCheck(StringRef Name, ClangTidyContext *Context) + PredictableRandCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; }; -} // namespace clang::tidy::cert +} // namespace clang::tidy::misc -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_LIMITEDRANDOMNESSCHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_PREDICTABLERANDCHECK_H diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index c8ae41c..2b63dab 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -890,7 +890,6 @@ static bool areStringsSameIgnoreSpaces(const llvm::StringRef Left, static bool areExprsSameMacroOrLiteral(const BinaryOperator *BinOp, const ASTContext *Context) { - if (!BinOp) return false; @@ -1147,16 +1146,18 @@ void RedundantExpressionCheck::checkArithmeticExpr( } } -static bool exprEvaluatesToZero(BinaryOperatorKind Opcode, APSInt Value) { +static bool exprEvaluatesToZero(BinaryOperatorKind Opcode, + const APSInt &Value) { return (Opcode == BO_And || Opcode == BO_AndAssign) && Value == 0; } static bool exprEvaluatesToBitwiseNegatedZero(BinaryOperatorKind Opcode, - APSInt Value) { + const APSInt &Value) { return (Opcode == BO_Or || Opcode == BO_OrAssign) && ~Value == 0; } -static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value) { +static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, + const APSInt &Value) { return ((Opcode == BO_Or || Opcode == BO_OrAssign) && Value == 0) || ((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0); } diff --git a/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp index ae08096..9c38bb1 100644 --- a/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/UnusedParametersCheck.cpp @@ -30,13 +30,10 @@ static bool isOverrideMethod(const FunctionDecl *Function) { static bool hasAttrAfterParam(const SourceManager *SourceManager, const ParmVarDecl *Param) { - for (const auto *Attr : Param->attrs()) { - if (SourceManager->isBeforeInTranslationUnit(Param->getLocation(), - Attr->getLocation())) { - return true; - } - } - return false; + return llvm::any_of(Param->attrs(), [&](const Attr *Attr) { + return SourceManager->isBeforeInTranslationUnit(Param->getLocation(), + Attr->getLocation()); + }); } void UnusedParametersCheck::registerMatchers(MatchFinder *Finder) { @@ -160,7 +157,6 @@ void UnusedParametersCheck::warnOnUnusedParameter( !Result.SourceManager->isInMainFile(Function->getLocation()) || !Indexer->getOtherRefs(Function).empty() || isOverrideMethod(Function) || isLambdaCallOperator(Function)) { - // It is illegal to omit parameter name here in C code, so early-out. if (!Result.Context->getLangOpts().CPlusPlus) return; diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp index 531311e..7663f37 100644 --- a/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/AvoidBindCheck.cpp @@ -259,7 +259,6 @@ buildBindArguments(const MatchFinder::MatchResult &Result, // Start at index 1 as first argument to bind is the function name. unsigned CaptureIndex = 0; for (size_t I = 1, ArgCount = BindCall->getNumArgs(); I < ArgCount; ++I) { - const Expr *E = BindCall->getArg(I); BindArgument &B = BindArguments.emplace_back(); @@ -327,7 +326,6 @@ static int findPositionOfPlaceholderUse(ArrayRef<BindArgument> Args, static void addPlaceholderArgs(const LambdaProperties &LP, llvm::raw_ostream &Stream, bool PermissiveParameterList) { - ArrayRef<BindArgument> Args = LP.BindArguments; const auto *MaxPlaceholderIt = llvm::max_element( @@ -465,7 +463,6 @@ static const FunctionDecl *getCallOperator(const CXXRecordDecl *Callable, static const FunctionDecl * getCallMethodDecl(const MatchFinder::MatchResult &Result, CallableType Type, CallableMaterializationKind Materialization) { - const Expr *Callee = Result.Nodes.getNodeAs<Expr>("ref"); const Expr *CallExpression = ignoreTemporariesAndPointers(Callee); diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidCStyleCastCheck.cpp index 3a5a9cd..7f9bf63 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/AvoidCStyleCastCheck.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "AvoidCStyleCastsCheck.h" +#include "AvoidCStyleCastCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -14,10 +14,9 @@ using namespace clang::ast_matchers; -namespace clang::tidy::google::readability { +namespace clang::tidy::modernize { -void AvoidCStyleCastsCheck::registerMatchers( - ast_matchers::MatchFinder *Finder) { +void AvoidCStyleCastCheck::registerMatchers(ast_matchers::MatchFinder *Finder) { Finder->addMatcher( cStyleCastExpr( // Filter out (EnumType)IntegerLiteral construct, which is generated @@ -113,7 +112,7 @@ static bool sameTypeAsWritten(QualType X, QualType Y) { } } -void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) { +void AvoidCStyleCastCheck::check(const MatchFinder::MatchResult &Result) { const auto *CastExpr = Result.Nodes.getNodeAs<ExplicitCastExpr>("cast"); // Ignore casts in macros. @@ -248,6 +247,12 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) { } break; } + if (DestType->isVoidPointerType() && SourceType->isPointerType() && + !SourceType->getPointeeType()->isPointerType()) { + ReplaceWithNamedCast("reinterpret_cast"); + return; + } + [[fallthrough]]; case clang::CK_IntegralCast: // Convert integral and no-op casts between builtin types and enums to @@ -269,6 +274,12 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) { return; } break; + case CK_BaseToDerived: + if (!needsConstCast(SourceType, DestType)) { + ReplaceWithNamedCast("static_cast"); + return; + } + break; default: break; } @@ -276,4 +287,4 @@ void AvoidCStyleCastsCheck::check(const MatchFinder::MatchResult &Result) { Diag << "static_cast/const_cast/reinterpret_cast"; } -} // namespace clang::tidy::google::readability +} // namespace clang::tidy::modernize diff --git a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h b/clang-tools-extra/clang-tidy/modernize/AvoidCStyleCastCheck.h index a305bd5..123d524 100644 --- a/clang-tools-extra/clang-tidy/google/AvoidCStyleCastsCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/AvoidCStyleCastCheck.h @@ -6,12 +6,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDCSTYLECASTSCHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDCSTYLECASTSCHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_AVOIDCSTYLECASTCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_AVOIDCSTYLECASTCHECK_H #include "../ClangTidyCheck.h" -namespace clang::tidy::google::readability { +namespace clang::tidy::modernize { /// Finds usages of C-style casts. /// @@ -24,10 +24,10 @@ namespace clang::tidy::google::readability { /// ones generated by `-Wold-style-cast`. /// /// For the user-facing documentation see: -/// https://clang.llvm.org/extra/clang-tidy/checks/google/readability-casting.html -class AvoidCStyleCastsCheck : public ClangTidyCheck { +/// https://clang.llvm.org/extra/clang-tidy/checks/modernize/avoid-c-style-cast.html +class AvoidCStyleCastCheck : public ClangTidyCheck { public: - AvoidCStyleCastsCheck(StringRef Name, ClangTidyContext *Context) + AvoidCStyleCastCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; @@ -36,6 +36,6 @@ public: } }; -} // namespace clang::tidy::google::readability +} // namespace clang::tidy::modernize -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_AVOIDCSTYLECASTSCHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_AVOIDCSTYLECASTCHECK_H diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 882f2dc..488c359 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS add_clang_library(clangTidyModernizeModule STATIC AvoidBindCheck.cpp AvoidCArraysCheck.cpp + AvoidCStyleCastCheck.cpp AvoidSetjmpLongjmpCheck.cpp AvoidVariadicFunctionsCheck.cpp ConcatNestedNamespacesCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp index 21eefab..eff7c2f 100644 --- a/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/DeprecatedHeadersCheck.cpp @@ -135,7 +135,6 @@ IncludeModernizePPCallbacks::IncludeModernizePPCallbacks( const LangOptions &LangOpts, const SourceManager &SM, bool CheckHeaderFile) : IncludesToBeProcessed(IncludesToBeProcessed), SM(SM), CheckHeaderFile(CheckHeaderFile) { - static constexpr std::pair<StringRef, StringRef> CXX98Headers[] = { {"assert.h", "cassert"}, {"complex.h", "complex"}, {"ctype.h", "cctype"}, {"errno.h", "cerrno"}, @@ -167,7 +166,6 @@ void IncludeModernizePPCallbacks::InclusionDirective( bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) { - // If we don't want to warn for non-main file reports and this is one, skip // it. if (!CheckHeaderFile && !SM.isInMainFile(HashLoc)) diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp index 30e2d4f..19b406f 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -92,7 +92,7 @@ static StatementMatcher incrementVarMatcher() { } static StatementMatcher -arrayConditionMatcher(internal::Matcher<Expr> LimitExpr) { +arrayConditionMatcher(const internal::Matcher<Expr> &LimitExpr) { return binaryOperator( anyOf(allOf(hasOperatorName("<"), hasLHS(integerComparisonMatcher()), hasRHS(LimitExpr)), @@ -156,7 +156,6 @@ static StatementMatcher makeArrayLoopMatcher() { /// Client code will need to make sure that: /// - The two containers on which 'begin' and 'end' are called are the same. static StatementMatcher makeIteratorLoopMatcher(bool IsReverse) { - auto BeginNameMatcher = IsReverse ? hasAnyName("rbegin", "crbegin") : hasAnyName("begin", "cbegin"); auto BeginNameMatcherStd = IsReverse @@ -511,27 +510,24 @@ static bool canBeModified(ASTContext *Context, const Expr *E) { /// Returns true when it can be guaranteed that the elements of the /// container are not being modified. static bool usagesAreConst(ASTContext *Context, const UsageResult &Usages) { - for (const Usage &U : Usages) { + return llvm::none_of(Usages, [&Context](const Usage &U) { // Lambda captures are just redeclarations (VarDecl) of the same variable, // not expressions. If we want to know if a variable that is captured by // reference can be modified in an usage inside the lambda's body, we need // to find the expression corresponding to that particular usage, later in // this loop. - if (U.Kind != Usage::UK_CaptureByCopy && U.Kind != Usage::UK_CaptureByRef && - canBeModified(Context, U.Expression)) - return false; - } - return true; + return U.Kind != Usage::UK_CaptureByCopy && + U.Kind != Usage::UK_CaptureByRef && + canBeModified(Context, U.Expression); + }); } /// Returns true if the elements of the container are never accessed /// by reference. static bool usagesReturnRValues(const UsageResult &Usages) { - for (const auto &U : Usages) { - if (U.Expression && !U.Expression->isPRValue()) - return false; - } - return true; + return llvm::all_of(Usages, [](const Usage &U) { + return !U.Expression || U.Expression->isPRValue(); + }); } /// Returns true if the container is const-qualified. @@ -563,7 +559,6 @@ LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context) UseCxx20IfAvailable(Options.get("UseCxx20ReverseRanges", true)), ReverseFunction(Options.get("MakeReverseRangeFunction", "")), ReverseHeader(Options.get("MakeReverseRangeHeader", "")) { - if (ReverseFunction.empty() && !ReverseHeader.empty()) { configurationDiag( "modernize-loop-convert: 'MakeReverseRangeHeader' is set but " diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp index 170a4f6..f6685dd 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertUtils.cpp @@ -89,13 +89,11 @@ bool DependencyFinderASTVisitor::VisitVarDecl(VarDecl *V) { // Next, check if the variable was removed from existence by an earlier // iteration. - for (const auto &I : *ReplacedVars) { - if (I.second == V) { - DependsOnInsideVariable = true; - return false; - } - } - return true; + if (llvm::none_of(*ReplacedVars, + [&](const auto &I) { return I.second == V; })) + return true; + DependsOnInsideVariable = true; + return false; } /// If we already created a variable for TheLoop, check to make sure @@ -234,11 +232,8 @@ static bool containsExpr(ASTContext *Context, const ContainerT *Container, const Expr *E) { llvm::FoldingSetNodeID ID; E->Profile(ID, *Context, true); - for (const auto &I : *Container) { - if (ID == I.second) - return true; - } - return false; + return llvm::any_of(*Container, + [&](const auto &I) { return ID == I.second; }); } /// Returns true when the index expression is a declaration reference to diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp index 7940939..39c5def 100644 --- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "MakeSmartPtrCheck.h" #include "../utils/TypeTraits.h" -#include "MakeSharedCheck.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/Preprocessor.h" diff --git a/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp index b5a985b..f459295 100644 --- a/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp @@ -243,7 +243,6 @@ void MinMaxUseInitializerListCheck::registerPPCallbacks( void MinMaxUseInitializerListCheck::check( const MatchFinder::MatchResult &Match) { - const auto *TopCall = Match.Nodes.getNodeAs<CallExpr>("topCall"); const FindArgsResult Result = findArgs(TopCall); diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index 360e2b8..a410f8d 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -11,6 +11,7 @@ #include "../ClangTidyModuleRegistry.h" #include "AvoidBindCheck.h" #include "AvoidCArraysCheck.h" +#include "AvoidCStyleCastCheck.h" #include "AvoidSetjmpLongjmpCheck.h" #include "AvoidVariadicFunctionsCheck.h" #include "ConcatNestedNamespacesCheck.h" @@ -65,6 +66,8 @@ public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { CheckFactories.registerCheck<AvoidBindCheck>("modernize-avoid-bind"); CheckFactories.registerCheck<AvoidCArraysCheck>("modernize-avoid-c-arrays"); + CheckFactories.registerCheck<AvoidCStyleCastCheck>( + "modernize-avoid-c-style-cast"); CheckFactories.registerCheck<AvoidSetjmpLongjmpCheck>( "modernize-avoid-setjmp-longjmp"); CheckFactories.registerCheck<AvoidVariadicFunctionsCheck>( diff --git a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp index a257f53..09d98ee 100644 --- a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp @@ -196,11 +196,7 @@ static bool hasRValueOverload(const CXXConstructorDecl *Ctor, return true; }; - for (const auto *Candidate : Record->ctors()) { - if (IsRValueOverload(Candidate)) - return true; - } - return false; + return llvm::any_of(Record->ctors(), IsRValueOverload); } /// Find all references to \p ParamDecl across all of the diff --git a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp index fdb088f..14874e3 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp @@ -70,7 +70,6 @@ matchEnableIfSpecializationImplTypename(TypeLoc TheType) { if (const auto SpecializationLoc = TheType.getAs<TemplateSpecializationTypeLoc>()) { - const auto *Specialization = dyn_cast<TemplateSpecializationType>(SpecializationLoc.getTypePtr()); if (!Specialization) @@ -101,7 +100,6 @@ static std::optional<TemplateSpecializationTypeLoc> matchEnableIfSpecializationImplTrait(TypeLoc TheType) { if (const auto SpecializationLoc = TheType.getAs<TemplateSpecializationTypeLoc>()) { - const auto *Specialization = dyn_cast<TemplateSpecializationType>(SpecializationLoc.getTypePtr()); if (!Specialization) @@ -182,7 +180,6 @@ matchTrailingTemplateParam(const FunctionTemplateDecl *FunctionTemplate) { TemplateParams->getParam(TemplateParams->size() - 1); if (const auto *LastTemplateParam = dyn_cast<NonTypeTemplateParmDecl>(LastParam)) { - if (!LastTemplateParam->hasDefaultArgument() || !LastTemplateParam->getName().empty()) return {}; diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp index 2cc3ce1..e798f6f 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp @@ -49,7 +49,6 @@ static unsigned getNumberOfDesignated(const InitListExpr *SyntacticInitList) { namespace { struct Designators { - Designators(const InitListExpr *InitList) : InitList(InitList) { assert(InitList->isSyntacticForm()); }; diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp index e585dd1..ca97b11 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp @@ -44,17 +44,12 @@ AST_MATCHER_P(NamedDecl, hasAnyNameIgnoringTemplates, std::vector<StringRef>, // clang/lib/ASTMatchers/ASTMatchersInternal.cpp and checks whether // FullNameTrimmed matches any of the given Names. const StringRef FullNameTrimmedRef = FullNameTrimmed; - for (const StringRef Pattern : Names) { - if (Pattern.starts_with("::")) { - if (FullNameTrimmed == Pattern) - return true; - } else if (FullNameTrimmedRef.ends_with(Pattern) && - FullNameTrimmedRef.drop_back(Pattern.size()).ends_with("::")) { - return true; - } - } - - return false; + return llvm::any_of(Names, [&](const StringRef Pattern) { + if (Pattern.starts_with("::")) + return FullNameTrimmed == Pattern; + return FullNameTrimmedRef.ends_with(Pattern) && + FullNameTrimmedRef.drop_back(Pattern.size()).ends_with("::"); + }); } // Checks if the given matcher is the last argument of the given CallExpr. diff --git a/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp index 62a2de2..e2e7bba 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp @@ -35,7 +35,6 @@ void UseOverrideCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { } void UseOverrideCheck::registerMatchers(MatchFinder *Finder) { - auto IgnoreDestructorMatcher = IgnoreDestructors ? cxxMethodDecl(unless(cxxDestructorDecl())) : cxxMethodDecl(); diff --git a/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp index 2e2f25f..529b5a43 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp @@ -135,7 +135,6 @@ class StdNumericReplacer : public StdReplacer { } // namespace utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const { - utils::UseRangesCheck::ReplacerMap Result; // template<typename Iter> Func(Iter first, Iter last,...). diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp index 47ff9ff..0315728 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseStdNumbersCheck.cpp @@ -81,16 +81,17 @@ AST_MATCHER_P(clang::Expr, anyOfExhaustive, std::vector<Matcher<clang::Stmt>>, // literals. struct MatchBuilder { auto - ignoreParenAndArithmeticCasting(const Matcher<clang::Expr> Matcher) const { + ignoreParenAndArithmeticCasting(const Matcher<clang::Expr> &Matcher) const { return expr(hasType(qualType(isArithmetic())), ignoringParenCasts(Matcher)); } - auto ignoreParenAndFloatingCasting(const Matcher<clang::Expr> Matcher) const { + auto + ignoreParenAndFloatingCasting(const Matcher<clang::Expr> &Matcher) const { return expr(hasType(qualType(isFloating())), ignoringParenCasts(Matcher)); } auto matchMathCall(const StringRef FunctionName, - const Matcher<clang::Expr> ArgumentMatcher) const { + const Matcher<clang::Expr> &ArgumentMatcher) const { auto HasAnyPrecisionName = hasAnyName( FunctionName, (FunctionName + "l").str(), (FunctionName + "f").str()); // Support long double(l) and float(f). @@ -100,7 +101,7 @@ struct MatchBuilder { hasArgument(0, ArgumentMatcher)))); } - auto matchSqrt(const Matcher<clang::Expr> ArgumentMatcher) const { + auto matchSqrt(const Matcher<clang::Expr> &ArgumentMatcher) const { return matchMathCall("sqrt", ArgumentMatcher); } @@ -148,7 +149,7 @@ struct MatchBuilder { return expr(anyOf(Int, Float, Dref)); } - auto match1Div(const Matcher<clang::Expr> Match) const { + auto match1Div(const Matcher<clang::Expr> &Match) const { return binaryOperator(hasOperatorName("/"), hasLHS(matchValue(1)), hasRHS(Match)); } diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp index 99ade04..1ab9576 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp @@ -36,7 +36,6 @@ UseStdPrintCheck::UseStdPrintCheck(StringRef Name, ClangTidyContext *Context) utils::IncludeSorter::IS_LLVM), areDiagsSelfContained()), MaybeHeaderToInclude(Options.get("PrintHeader")) { - if (PrintfLikeFunctions.empty() && FprintfLikeFunctions.empty()) { PrintfLikeFunctions.emplace_back("::printf"); PrintfLikeFunctions.emplace_back("absl::PrintF"); @@ -70,8 +69,8 @@ void UseStdPrintCheck::registerPPCallbacks(const SourceManager &SM, this->PP = PP; } -static clang::ast_matchers::StatementMatcher -unusedReturnValue(clang::ast_matchers::StatementMatcher MatchedCallExpr) { +static clang::ast_matchers::StatementMatcher unusedReturnValue( + const clang::ast_matchers::StatementMatcher &MatchedCallExpr) { auto UnusedInCompoundStmt = compoundStmt(forEach(MatchedCallExpr), // The checker can't currently differentiate between the diff --git a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h b/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h index 18cff9a..7d771c4 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.h @@ -36,7 +36,7 @@ public: } private: - Preprocessor *PP; + Preprocessor *PP = nullptr; bool StrictMode; std::vector<StringRef> PrintfLikeFunctions; std::vector<StringRef> FprintfLikeFunctions; diff --git a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp index 3c828c4..02865b6 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp @@ -55,13 +55,12 @@ public: bool visitUnqualName(StringRef UnqualName) { // Check for collisions with function arguments. - for (const ParmVarDecl *Param : F.parameters()) + Collision = llvm::any_of(F.parameters(), [&](const ParmVarDecl *Param) { if (const IdentifierInfo *Ident = Param->getIdentifier()) - if (Ident->getName() == UnqualName) { - Collision = true; - return true; - } - return false; + return Ident->getName() == UnqualName; + return false; + }); + return Collision; } bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) { @@ -305,7 +304,6 @@ static SourceRange findReturnTypeAndCVSourceRange(const FunctionDecl &F, const TypeLoc &ReturnLoc, const ASTContext &Ctx, const SourceManager &SM, const LangOptions &LangOpts, Preprocessor *PP) { - // We start with the range of the return type and expand to neighboring // qualifiers (const, volatile and restrict). SourceRange ReturnTypeRange = F.getReturnTypeSourceRange(); @@ -459,7 +457,6 @@ UseTrailingReturnTypeCheck::UseTrailingReturnTypeCheck( : ClangTidyCheck(Name, Context), TransformFunctions(Options.get("TransformFunctions", true)), TransformLambdas(Options.get("TransformLambdas", TransformLambda::All)) { - if (TransformFunctions == false && TransformLambdas == TransformLambda::None) this->configurationDiag( "The check 'modernize-use-trailing-return-type' will not perform any " @@ -604,7 +601,6 @@ void UseTrailingReturnTypeCheck::check(const MatchFinder::MatchResult &Result) { void UseTrailingReturnTypeCheck::diagOnLambda( const LambdaExpr *Lambda, const ast_matchers::MatchFinder::MatchResult &Result) { - const CXXMethodDecl *Method = Lambda->getCallOperator(); if (!Method || Lambda->hasExplicitResultType()) return; diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h index 60813cd..07d15fa 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h @@ -18,7 +18,6 @@ namespace clang::tidy::modernize { /// For the user-facing documentation see: /// https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-using.html class UseUsingCheck : public ClangTidyCheck { - const bool IgnoreMacros; const bool IgnoreExternC; SourceLocation LastReplacementEnd; diff --git a/clang-tools-extra/clang-tidy/objc/MissingHashCheck.cpp b/clang-tools-extra/clang-tidy/objc/MissingHashCheck.cpp index 7b48fd9..b8010e0 100644 --- a/clang-tools-extra/clang-tidy/objc/MissingHashCheck.cpp +++ b/clang-tools-extra/clang-tidy/objc/MissingHashCheck.cpp @@ -25,11 +25,9 @@ AST_MATCHER_P(ObjCImplementationDecl, hasInterface, AST_MATCHER_P(ObjCContainerDecl, hasInstanceMethod, ast_matchers::internal::Matcher<ObjCMethodDecl>, Base) { // Check each instance method against the provided matcher. - for (const auto *I : Node.instance_methods()) { - if (Base.matches(*I, Finder, Builder)) - return true; - } - return false; + return llvm::any_of(Node.instance_methods(), [&](const ObjCMethodDecl *I) { + return Base.matches(*I, Finder, Builder); + }); } } // namespace diff --git a/clang-tools-extra/clang-tidy/openmp/UseDefaultNoneCheck.cpp b/clang-tools-extra/clang-tidy/openmp/UseDefaultNoneCheck.cpp index d02ab72..5bd842b 100644 --- a/clang-tools-extra/clang-tidy/openmp/UseDefaultNoneCheck.cpp +++ b/clang-tools-extra/clang-tidy/openmp/UseDefaultNoneCheck.cpp @@ -37,8 +37,9 @@ void UseDefaultNoneCheck::check(const MatchFinder::MatchResult &Result) { "OpenMP directive '%0' specifies 'default(%1)' clause, consider using " "'default(none)' clause instead") << getOpenMPDirectiveName(Directive->getDirectiveKind()) - << getOpenMPSimpleClauseTypeName(Clause->getClauseKind(), - unsigned(Clause->getDefaultKind())); + << getOpenMPSimpleClauseTypeName( + Clause->getClauseKind(), + llvm::to_underlying(Clause->getDefaultKind())); diag(Clause->getBeginLoc(), "existing 'default' clause specified here", DiagnosticIDs::Note); return; diff --git a/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp index 29faf9f..9ab6608 100644 --- a/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/NoexceptSwapCheck.cpp @@ -17,7 +17,6 @@ using namespace clang::ast_matchers; namespace clang::tidy::performance { void NoexceptSwapCheck::registerMatchers(MatchFinder *Finder) { - // Match non-const method with single argument that is non-const reference to // a class type that owns method and return void. // Matches: void Class::swap(Class&) diff --git a/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp b/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp index 2f54b17..416c41d 100644 --- a/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp @@ -23,12 +23,9 @@ namespace { AST_MATCHER(Decl, isFirstDecl) { return Node.isFirstDecl(); } AST_MATCHER_P(CXXRecordDecl, hasBase, Matcher<QualType>, InnerMatcher) { - for (const CXXBaseSpecifier &BaseSpec : Node.bases()) { - const QualType BaseType = BaseSpec.getType(); - if (InnerMatcher.matches(BaseType, Finder, Builder)) - return true; - } - return false; + return llvm::any_of(Node.bases(), [&](const CXXBaseSpecifier &BaseSpec) { + return InnerMatcher.matches(BaseSpec.getType(), Finder, Builder); + }); } } // namespace diff --git a/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.h b/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.h index 0dd6402..d66149a 100644 --- a/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.h +++ b/clang-tools-extra/clang-tidy/portability/RestrictSystemIncludesCheck.h @@ -23,7 +23,7 @@ namespace clang::tidy::portability { class RestrictSystemIncludesCheck : public ClangTidyCheck { public: RestrictSystemIncludesCheck(StringRef Name, ClangTidyContext *Context, - std::string DefaultAllowedIncludes = "*") + StringRef DefaultAllowedIncludes = "*") : ClangTidyCheck(Name, Context), AllowedIncludes(Options.get("Includes", DefaultAllowedIncludes)), AllowedIncludesGlobList(AllowedIncludes) {} @@ -36,7 +36,7 @@ public: } private: - std::string AllowedIncludes; + StringRef AllowedIncludes; GlobList AllowedIncludesGlobList; }; diff --git a/clang-tools-extra/clang-tidy/readability/AmbiguousSmartptrResetCallCheck.cpp b/clang-tools-extra/clang-tidy/readability/AmbiguousSmartptrResetCallCheck.cpp index 22ff5ce..ef9263b 100644 --- a/clang-tools-extra/clang-tidy/readability/AmbiguousSmartptrResetCallCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/AmbiguousSmartptrResetCallCheck.cpp @@ -20,12 +20,9 @@ namespace clang::tidy::readability { namespace { AST_MATCHER(CXXMethodDecl, hasOnlyDefaultParameters) { - for (const auto *Param : Node.parameters()) { - if (!Param->hasDefaultArg()) - return false; - } - - return true; + return llvm::all_of(Node.parameters(), [](const ParmVarDecl *Param) { + return Param->hasDefaultArg(); + }); } const auto DefaultSmartPointers = "::std::shared_ptr;::std::unique_ptr;" diff --git a/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDeclsCheck.cpp b/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDeclsCheck.cpp index affcea4..506f8e2 100644 --- a/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDeclsCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/AvoidConstParamsInDeclsCheck.cpp @@ -26,7 +26,6 @@ static SourceRange getTypeRange(const ParmVarDecl &Param) { static std::optional<Token> findConstToRemove(const ParmVarDecl &Param, const MatchFinder::MatchResult &Result) { - const CharSourceRange FileRange = Lexer::makeFileCharRange( CharSourceRange::getTokenRange(getTypeRange(Param)), *Result.SourceManager, Result.Context->getLangOpts()); diff --git a/clang-tools-extra/clang-tidy/readability/AvoidUnconditionalPreprocessorIfCheck.cpp b/clang-tools-extra/clang-tidy/readability/AvoidUnconditionalPreprocessorIfCheck.cpp index 631bb14..9fc8185 100644 --- a/clang-tools-extra/clang-tidy/readability/AvoidUnconditionalPreprocessorIfCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/AvoidUnconditionalPreprocessorIfCheck.cpp @@ -17,7 +17,6 @@ namespace clang::tidy::readability { namespace { struct AvoidUnconditionalPreprocessorIfPPCallbacks : public PPCallbacks { - explicit AvoidUnconditionalPreprocessorIfPPCallbacks(ClangTidyCheck &Check, Preprocessor &PP) : Check(Check), PP(PP) {} diff --git a/clang-tools-extra/clang-tidy/readability/ContainerContainsCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerContainsCheck.cpp index a340552..efcf13d 100644 --- a/clang-tools-extra/clang-tidy/readability/ContainerContainsCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ContainerContainsCheck.cpp @@ -47,9 +47,8 @@ void ContainerContainsCheck::registerMatchers(MatchFinder *Finder) { const auto StringNpos = anyOf(declRefExpr(to(varDecl(hasName("npos")))), memberExpr(member(hasName("npos")))); - auto AddSimpleMatcher = [&](auto Matcher) { - Finder->addMatcher( - traverse(TK_IgnoreUnlessSpelledInSource, std::move(Matcher)), this); + auto AddSimpleMatcher = [&](const auto &Matcher) { + Finder->addMatcher(traverse(TK_IgnoreUnlessSpelledInSource, Matcher), this); }; // Find membership tests which use `count()`. diff --git a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp index a5a6e3c..e308aef 100644 --- a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp @@ -107,8 +107,11 @@ void ContainerDataPointerCheck::check(const MatchFinder::MatchResult &Result) { Lexer::getSourceText(CharSourceRange::getTokenRange(SrcRange), *Result.SourceManager, getLangOpts())}; - if (!isa<DeclRefExpr, ArraySubscriptExpr, CXXOperatorCallExpr, CallExpr, - MemberExpr>(CE)) + const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(CE); + const bool NeedsParens = + OpCall ? (OpCall->getOperator() != OO_Subscript) + : !isa<DeclRefExpr, MemberExpr, ArraySubscriptExpr, CallExpr>(CE); + if (NeedsParens) ReplacementText = "(" + ReplacementText + ")"; if (CE->getType()->isPointerType()) diff --git a/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp b/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp index cc9ae47..4842fe2 100644 --- a/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.cpp @@ -7,10 +7,12 @@ //===----------------------------------------------------------------------===// #include "DuplicateIncludeCheck.h" +#include "../utils/OptionsUtils.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Regex.h" #include <memory> namespace clang::tidy::readability { @@ -33,11 +35,8 @@ using FileList = SmallVector<StringRef>; class DuplicateIncludeCallbacks : public PPCallbacks { public: DuplicateIncludeCallbacks(DuplicateIncludeCheck &Check, - const SourceManager &SM) - : Check(Check), SM(SM) { - // The main file doesn't participate in the FileChanged notification. - Files.emplace_back(); - } + const SourceManager &SM, + llvm::ArrayRef<StringRef> IgnoredList); void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, @@ -62,10 +61,31 @@ private: SmallVector<FileList> Files; DuplicateIncludeCheck &Check; const SourceManager &SM; + SmallVector<llvm::Regex> AllowedRegexes; }; } // namespace +DuplicateIncludeCheck::DuplicateIncludeCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + IgnoredFilesList(utils::options::parseStringList( + Options.get("IgnoredFilesList", ""))) {} + +DuplicateIncludeCallbacks::DuplicateIncludeCallbacks( + DuplicateIncludeCheck &Check, const SourceManager &SM, + llvm::ArrayRef<StringRef> IgnoredList) + : Check(Check), SM(SM) { + // The main file doesn't participate in the FileChanged notification. + Files.emplace_back(); + + AllowedRegexes.reserve(IgnoredList.size()); + for (const StringRef &It : IgnoredList) { + if (!It.empty()) + AllowedRegexes.emplace_back(It); + } +} + void DuplicateIncludeCallbacks::FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, @@ -78,7 +98,7 @@ void DuplicateIncludeCallbacks::FileChanged(SourceLocation Loc, void DuplicateIncludeCallbacks::InclusionDirective( SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, - bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, + bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef /*File*/, StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, bool ModuleImported, SrcMgr::CharacteristicKind FileType) { // Skip includes behind macros @@ -86,6 +106,10 @@ void DuplicateIncludeCallbacks::InclusionDirective( FilenameRange.getEnd().isMacroID()) return; if (llvm::is_contained(Files.back(), FileName)) { + if (llvm::any_of(AllowedRegexes, [&FileName](const llvm::Regex &R) { + return R.match(FileName); + })) + return; // We want to delete the entire line, so make sure that [Start,End] covers // everything. const SourceLocation Start = @@ -111,7 +135,13 @@ void DuplicateIncludeCallbacks::MacroUndefined(const Token &MacroNameTok, void DuplicateIncludeCheck::registerPPCallbacks( const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) { - PP->addPPCallbacks(std::make_unique<DuplicateIncludeCallbacks>(*this, SM)); + PP->addPPCallbacks( + std::make_unique<DuplicateIncludeCallbacks>(*this, SM, IgnoredFilesList)); +} + +void DuplicateIncludeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IgnoredFilesList", + utils::options::serializeStringList(IgnoredFilesList)); } } // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.h b/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.h index ca36791..1ee5b1c 100644 --- a/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.h +++ b/clang-tools-extra/clang-tidy/readability/DuplicateIncludeCheck.h @@ -19,11 +19,16 @@ namespace clang::tidy::readability { /// directives between them are analyzed. class DuplicateIncludeCheck : public ClangTidyCheck { public: - DuplicateIncludeCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + DuplicateIncludeCheck(StringRef Name, ClangTidyContext *Context); void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + +private: + // Semicolon-separated list of regexes or file names to ignore from duplicate + // warnings. + const std::vector<StringRef> IgnoredFilesList; }; } // namespace clang::tidy::readability diff --git a/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp b/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp index a420c56..4ef28c8b 100644 --- a/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp @@ -185,7 +185,6 @@ void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) { static bool hasPreprocessorBranchEndBetweenLocations( const ElseAfterReturnCheck::ConditionalBranchMap &ConditionalBranchMap, const SourceManager &SM, SourceLocation StartLoc, SourceLocation EndLoc) { - const SourceLocation ExpandedStartLoc = SM.getExpansionLoc(StartLoc); const SourceLocation ExpandedEndLoc = SM.getExpansionLoc(EndLoc); if (!SM.isWrittenInSameFile(ExpandedStartLoc, ExpandedEndLoc)) diff --git a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp index ccac645..a966f1f 100644 --- a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp @@ -519,7 +519,6 @@ void FunctionCognitiveComplexityCheck::registerMatchers(MatchFinder *Finder) { void FunctionCognitiveComplexityCheck::check( const MatchFinder::MatchResult &Result) { - FunctionASTVisitor Visitor(IgnoreMacros); SourceLocation Loc; @@ -558,7 +557,7 @@ void FunctionCognitiveComplexityCheck::check( // Increase, on the other hand, can be 0. diag(Detail.Loc, Msgs[MsgId], DiagnosticIDs::Note) - << (unsigned)Increase << (unsigned)Detail.Nesting << 1 + Detail.Nesting; + << Increase << Detail.Nesting << 1 + Detail.Nesting; } } diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index 890ce40..79f8437 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -318,8 +318,8 @@ std::string IdentifierNamingCheck::HungarianNotation::getDeclTypeName( if (!EOL) EOL = Begin + strlen(Begin); - const char *PosList[] = {strchr(Begin, '='), strchr(Begin, ';'), - strchr(Begin, ','), strchr(Begin, ')'), EOL}; + const char *const PosList[] = {strchr(Begin, '='), strchr(Begin, ';'), + strchr(Begin, ','), strchr(Begin, ')'), EOL}; for (const auto &Pos : PosList) { if (Pos > Begin) EOL = std::min(EOL, Pos); @@ -408,7 +408,6 @@ IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, : RenamerClangTidyCheck(Name, Context), Context(Context), GetConfigPerFile(Options.get("GetConfigPerFile", true)), IgnoreFailedSplit(Options.get("IgnoreFailedSplit", false)) { - auto IterAndInserted = NamingStylesCache.try_emplace( llvm::sys::path::parent_path(Context->getCurrentFile()), getFileStyleFromOptions(Options)); @@ -447,7 +446,6 @@ bool IdentifierNamingCheck::HungarianNotation::isOptionEnabled( void IdentifierNamingCheck::HungarianNotation::loadFileConfig( const ClangTidyCheck::OptionsView &Options, IdentifierNamingCheck::HungarianNotationOption &HNOption) const { - static constexpr StringRef HNOpts[] = {"TreatStructAsClass"}; static constexpr StringRef HNDerivedTypes[] = {"Array", "Pointer", "FunctionPointer"}; @@ -643,7 +641,6 @@ std::string IdentifierNamingCheck::HungarianNotation::getDataTypePrefix( std::string IdentifierNamingCheck::HungarianNotation::getClassPrefix( const CXXRecordDecl *CRD, const IdentifierNamingCheck::HungarianNotationOption &HNOption) const { - if (CRD->isUnion()) return {}; @@ -723,7 +720,6 @@ size_t IdentifierNamingCheck::HungarianNotation::getAsteriskCount( void IdentifierNamingCheck::HungarianNotation::loadDefaultConfig( IdentifierNamingCheck::HungarianNotationOption &HNOption) const { - // Options static constexpr std::pair<StringRef, StringRef> General[] = { {"TreatStructAsClass", "false"}}; diff --git a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp index 77150fd..c135b42 100644 --- a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp @@ -362,7 +362,6 @@ void ImplicitBoolConversionCheck::registerMatchers(MatchFinder *Finder) { void ImplicitBoolConversionCheck::check( const MatchFinder::MatchResult &Result) { - if (const auto *CastToBool = Result.Nodes.getNodeAs<ImplicitCastExpr>("implicitCastToBool")) { const auto *Parent = Result.Nodes.getNodeAs<Stmt>("parentStmt"); @@ -416,7 +415,6 @@ void ImplicitBoolConversionCheck::handleCastFromBool( if (const auto *BoolLiteral = dyn_cast<CXXBoolLiteralExpr>(Cast->getSubExpr()->IgnoreParens())) { - const auto EquivalentForBoolLiteral = getEquivalentForBoolLiteral(BoolLiteral, DestType, Context); if (UseUpperCaseLiteralSuffix) diff --git a/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp b/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp index c496841..7b27ab9 100644 --- a/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/InconsistentDeclarationParameterNameCheck.cpp @@ -107,6 +107,10 @@ findDifferingParamsInDeclaration(const FunctionDecl *ParameterSourceDeclaration, while (SourceParamIt != ParameterSourceDeclaration->param_end() && OtherParamIt != OtherDeclaration->param_end()) { + if ((*SourceParamIt)->isParameterPack() != + (*OtherParamIt)->isParameterPack()) + break; + auto SourceParamName = (*SourceParamIt)->getName(); auto OtherParamName = (*OtherParamIt)->getName(); diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp index 01abf51..6ba1408 100644 --- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp @@ -25,7 +25,6 @@ namespace clang { static bool isUsedToInitializeAConstant(const MatchFinder::MatchResult &Result, const DynTypedNode &Node) { - const auto *AsDecl = Node.get<DeclaratorDecl>(); if (AsDecl) { if (AsDecl->getType().isConstQualified()) @@ -45,7 +44,6 @@ static bool isUsedToInitializeAConstant(const MatchFinder::MatchResult &Result, static bool isUsedToDefineATypeAlias(const MatchFinder::MatchResult &Result, const DynTypedNode &Node) { - if (Node.get<TypeAliasDecl>() || Node.get<TypedefNameDecl>()) return true; @@ -144,7 +142,6 @@ void MagicNumbersCheck::registerMatchers(MatchFinder *Finder) { } void MagicNumbersCheck::check(const MatchFinder::MatchResult &Result) { - const TraversalKindScope RAII(*Result.Context, TK_AsIs); checkBoundMatch<IntegerLiteral>(Result, "integer"); diff --git a/clang-tools-extra/clang-tidy/readability/OperatorsRepresentationCheck.cpp b/clang-tools-extra/clang-tidy/readability/OperatorsRepresentationCheck.cpp index 4260e0f..05f31c7 100644 --- a/clang-tools-extra/clang-tidy/readability/OperatorsRepresentationCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/OperatorsRepresentationCheck.cpp @@ -136,11 +136,9 @@ getRepresentation(const std::vector<llvm::StringRef> &Config, template <typename T> static bool isAnyOperatorEnabled(const std::vector<llvm::StringRef> &Config, const T &Operators) { - for (const auto &[traditional, alternative] : Operators) { - if (!getRepresentation(Config, traditional, alternative).empty()) - return true; - } - return false; + return llvm::any_of(Operators, [&](const auto &Op) { + return !getRepresentation(Config, Op.first, Op.second).empty(); + }); } OperatorsRepresentationCheck::OperatorsRepresentationCheck( @@ -275,7 +273,6 @@ void OperatorsRepresentationCheck::registerMatchers(MatchFinder *Finder) { void OperatorsRepresentationCheck::check( const MatchFinder::MatchResult &Result) { - SourceLocation Loc; if (const auto *Op = Result.Nodes.getNodeAs<BinaryOperator>("binary_op")) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantCastingCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantCastingCheck.cpp index d11c41c..21f481a 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantCastingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantCastingCheck.cpp @@ -9,6 +9,7 @@ #include "RedundantCastingCheck.h" #include "../utils/FixItHintUtils.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/TypeBase.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Lex/Lexer.h" @@ -29,7 +30,7 @@ static bool areTypesEqual(QualType S, QualType D) { const QualType PtrD = D->getPointeeType(); if (!PtrS.isNull() && !PtrD.isNull()) - return areTypesEqual(PtrS, PtrD); + return areTypesEqual(PtrS.IgnoreParens(), PtrD.IgnoreParens()); const DeducedType *DT = S->getContainedDeducedType(); if (DT && DT->isDeduced()) diff --git a/clang-tools-extra/clang-tidy/readability/RedundantInlineSpecifierCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantInlineSpecifierCheck.cpp index 76adaa8..7b6eb34 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantInlineSpecifierCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantInlineSpecifierCheck.cpp @@ -16,10 +16,9 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" #include "clang/Lex/Token.h" -#include "../utils/LexerUtils.h" - using namespace clang::ast_matchers; namespace clang::tidy::readability { diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp index 756fe43..5cbbbca 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp @@ -7,13 +7,11 @@ //===----------------------------------------------------------------------===// #include "RedundantStringInitCheck.h" -#include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/ASTMatchers/ASTMatchers.h" #include <optional> using namespace clang::ast_matchers; -using namespace clang::tidy::matchers; namespace clang::tidy::readability { diff --git a/clang-tools-extra/clang-tidy/readability/RedundantTypenameCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantTypenameCheck.cpp index a4edd2b..5f2519c 100644 --- a/clang-tools-extra/clang-tidy/readability/RedundantTypenameCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantTypenameCheck.cpp @@ -47,6 +47,9 @@ void RedundantTypenameCheck::check(const MatchFinder::MatchResult &Result) { const SourceLocation ElaboratedKeywordLoc = [&] { if (const auto *NonDependentTypeLoc = Result.Nodes.getNodeAs<TypeLoc>("nonDependentTypeLoc")) { + if (NonDependentTypeLoc->getType()->isDependentType()) + return SourceLocation(); + if (const auto TL = NonDependentTypeLoc->getAs<TypedefTypeLoc>()) return TL.getElaboratedKeywordLoc(); @@ -59,8 +62,7 @@ void RedundantTypenameCheck::check(const MatchFinder::MatchResult &Result) { if (const auto TL = NonDependentTypeLoc->getAs<TemplateSpecializationTypeLoc>()) - if (!TL.getType()->isDependentType()) - return TL.getElaboratedKeywordLoc(); + return TL.getElaboratedKeywordLoc(); } else { TypeLoc InnermostTypeLoc = *Result.Nodes.getNodeAs<TypeLoc>("dependentTypeLoc"); diff --git a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp index 19b4726..0b52a96 100644 --- a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp @@ -173,7 +173,6 @@ static bool applySuffixHeuristic(StringRef Arg, StringRef Param, static bool applySubstringHeuristic(StringRef Arg, StringRef Param, int8_t Threshold) { - std::size_t MaxLength = 0; SmallVector<std::size_t, SmallVectorSize> Current(Param.size()); SmallVector<std::size_t, SmallVectorSize> Previous(Param.size()); @@ -759,7 +758,7 @@ bool SuspiciousCallArgumentCheck::areParamAndArgComparable( bool SuspiciousCallArgumentCheck::areArgsSwapped(std::size_t Position1, std::size_t Position2) const { - for (const Heuristic H : AppliedHeuristics) { + return llvm::any_of(AppliedHeuristics, [&](Heuristic H) { const bool A1ToP2Similar = areNamesSimilar( ArgNames[Position2], ParamNames[Position1], H, BoundKind::SimilarAbove); const bool A2ToP1Similar = areNamesSimilar( @@ -772,11 +771,9 @@ bool SuspiciousCallArgumentCheck::areArgsSwapped(std::size_t Position1, !areNamesSimilar(ArgNames[Position2], ParamNames[Position2], H, BoundKind::DissimilarBelow); - if ((A1ToP2Similar || A2ToP1Similar) && A1ToP1Dissimilar && - A2ToP2Dissimilar) - return true; - } - return false; + return (A1ToP2Similar || A2ToP1Similar) && A1ToP1Dissimilar && + A2ToP2Dissimilar; + }); } bool SuspiciousCallArgumentCheck::areNamesSimilar(StringRef Arg, diff --git a/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp b/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp index c9d7041..1dff8089 100644 --- a/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UniqueptrDeleteReleaseCheck.cpp @@ -28,7 +28,6 @@ UniqueptrDeleteReleaseCheck::UniqueptrDeleteReleaseCheck( PreferResetCall(Options.get("PreferResetCall", false)) {} void UniqueptrDeleteReleaseCheck::registerMatchers(MatchFinder *Finder) { - auto UniquePtrWithDefaultDelete = classTemplateSpecializationDecl( hasName("::std::unique_ptr"), hasTemplateArgument(1, refersToType(hasDeclaration(cxxRecordDecl( diff --git a/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp index fe03f21..6364915 100644 --- a/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UseAnyOfAllOfCheck.cpp @@ -71,7 +71,6 @@ void UseAnyOfAllOfCheck::registerMatchers(MatchFinder *Finder) { } static bool isViableLoop(const CXXForRangeStmt &S, ASTContext &Context) { - ExprMutationAnalyzer Mutations(*S.getBody(), Context); if (Mutations.isMutated(S.getLoopVariable())) return false; @@ -86,7 +85,6 @@ static bool isViableLoop(const CXXForRangeStmt &S, ASTContext &Context) { } void UseAnyOfAllOfCheck::check(const MatchFinder::MatchResult &Result) { - if (const auto *S = Result.Nodes.getNodeAs<CXXForRangeStmt>("any_of_loop")) { if (!isViableLoop(*S, *Result.Context)) return; diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp index 5a7add8..ee0810b 100644 --- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp @@ -96,12 +96,11 @@ static QualType getReplacementCastType(const Expr *CondLhs, const Expr *CondRhs, return GlobalImplicitCastType; } -static std::string createReplacement(const Expr *CondLhs, const Expr *CondRhs, - const Expr *AssignLhs, - const SourceManager &Source, - const LangOptions &LO, - StringRef FunctionName, - const BinaryOperator *BO) { +static std::string +createReplacement(const Expr *CondLhs, const Expr *CondRhs, + const Expr *AssignLhs, const SourceManager &Source, + const LangOptions &LO, StringRef FunctionName, + const BinaryOperator *BO, StringRef Comment = "") { const llvm::StringRef CondLhsStr = Lexer::getSourceText( Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO); const llvm::StringRef CondRhsStr = Lexer::getSourceText( @@ -116,7 +115,8 @@ static std::string createReplacement(const Expr *CondLhs, const Expr *CondRhs, (!GlobalImplicitCastType.isNull() ? "<" + GlobalImplicitCastType.getAsString() + ">(" : "(") + - CondLhsStr + ", " + CondRhsStr + ");") + CondLhsStr + ", " + CondRhsStr + ");" + (Comment.empty() ? "" : " ") + + Comment) .str(); } @@ -172,13 +172,65 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) { auto ReplaceAndDiagnose = [&](const llvm::StringRef FunctionName) { const SourceManager &Source = *Result.SourceManager; + llvm::SmallString<64> Comment; + + const auto AppendNormalized = [&](llvm::StringRef Text) { + Text = Text.ltrim(); + if (!Text.empty()) { + if (!Comment.empty()) + Comment += " "; + Comment += Text; + } + }; + + const auto GetSourceText = [&](SourceLocation StartLoc, + SourceLocation EndLoc) { + return Lexer::getSourceText( + CharSourceRange::getCharRange( + Lexer::getLocForEndOfToken(StartLoc, 0, Source, LO), EndLoc), + Source, LO); + }; + + // Captures: + // if (cond) // Comment A + // if (cond) /* Comment A */ { ... } + // if (cond) /* Comment A */ x = y; + AppendNormalized( + GetSourceText(If->getRParenLoc(), If->getThen()->getBeginLoc())); + + if (const auto *CS = dyn_cast<CompoundStmt>(If->getThen())) { + const Stmt *Inner = CS->body_front(); + + // Captures: + // if (cond) { // Comment B + // ... + // } + // if (cond) { /* Comment B */ x = y; } + AppendNormalized(GetSourceText(CS->getBeginLoc(), Inner->getBeginLoc())); + + // Captures: + // if (cond) { x = y; // Comment C } + // if (cond) { x = y; /* Comment C */ } + llvm::StringRef PostInner = + GetSourceText(Inner->getEndLoc(), CS->getEndLoc()); + + // Strip the trailing semicolon to avoid fixes like: + // x = std::min(x, y);; // comment + const size_t Semi = PostInner.find(';'); + if (Semi != llvm::StringRef::npos && + PostInner.take_front(Semi).trim().empty()) { + PostInner = PostInner.drop_front(Semi + 1); + } + AppendNormalized(PostInner); + } + diag(IfLocation, "use `%0` instead of `%1`") << FunctionName << BinaryOp->getOpcodeStr() << FixItHint::CreateReplacement( SourceRange(IfLocation, Lexer::getLocForEndOfToken( ThenLocation, 0, Source, LO)), createReplacement(CondLhs, CondRhs, AssignLhs, Source, LO, - FunctionName, BinaryOp)) + FunctionName, BinaryOp, Comment)) << IncludeInserter.createIncludeInsertion( Source.getFileID(If->getBeginLoc()), AlgorithmHeader); }; diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp index f5e4bf0..6a1f61d 100644 --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -104,8 +104,7 @@ Configuration files: )"); const char DefaultChecks[] = // Enable these checks by default: - "clang-diagnostic-*," // * compiler diagnostics - "clang-analyzer-*"; // * Static Analyzer checks + "clang-diagnostic-*"; // * compiler diagnostics static cl::opt<std::string> Checks("checks", desc(R"( Comma-separated list of globs with optional '-' @@ -466,10 +465,9 @@ createOptionsProvider(llvm::IntrusiveRefCntPtr<vfs::FileSystem> FS) { } static llvm::IntrusiveRefCntPtr<vfs::FileSystem> -getVfsFromFile(const std::string &OverlayFile, - llvm::IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) { +getVfsFromFile(const std::string &OverlayFile, vfs::FileSystem &BaseFS) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer = - BaseFS->getBufferForFile(OverlayFile); + BaseFS.getBufferForFile(OverlayFile); if (!Buffer) { llvm::errs() << "Can't load virtual filesystem overlay file '" << OverlayFile << "': " << Buffer.getError().message() @@ -585,7 +583,7 @@ static llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> createBaseFS() { if (!VfsOverlay.empty()) { IntrusiveRefCntPtr<vfs::FileSystem> VfsFromFile = - getVfsFromFile(VfsOverlay, BaseFS); + getVfsFromFile(VfsOverlay, *BaseFS); if (!VfsFromFile) return nullptr; BaseFS->pushOverlay(std::move(VfsFromFile)); diff --git a/clang-tools-extra/clang-tidy/tool/check_alphabetical_order.py b/clang-tools-extra/clang-tidy/tool/check_alphabetical_order.py new file mode 100644 index 0000000..66819ab --- /dev/null +++ b/clang-tools-extra/clang-tidy/tool/check_alphabetical_order.py @@ -0,0 +1,421 @@ +#!/usr/bin/env python3 +# +# ===-----------------------------------------------------------------------===# +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ===-----------------------------------------------------------------------===# + +""" + +Clang-Tidy Alphabetical Order Checker +===================================== + +Normalize Clang-Tidy documentation with deterministic sorting for linting/tests. + +Behavior: +- Sort entries in docs/clang-tidy/checks/list.rst csv-table. +- Sort key sections in docs/ReleaseNotes.rst. +- Detect duplicated entries in 'Changes in existing checks'. + +Flags: + -o/--output Write normalized content to this path instead of updating docs. +""" + +import argparse +from collections import defaultdict +import io +from operator import itemgetter +import os +import re +import sys +from typing import ( + DefaultDict, + Final, + Iterable, + List, + NamedTuple, + Optional, + Sequence, + Tuple, +) + +# Matches a :doc:`label <path>` or :doc:`label` reference anywhere in text and +# captures the label. Used to sort bullet items alphabetically in ReleaseNotes +# items by their label. +DOC_LABEL_RN_RE: Final = re.compile(r":doc:`(?P<label>[^`<]+)\s*(?:<[^>]+>)?`") + +# Matches a single csv-table row line in list.rst that begins with a :doc: +# reference, capturing the label. Used to extract the sort key per row. +DOC_LINE_RE: Final = re.compile(r"^\s*:doc:`(?P<label>[^`<]+?)\s*<[^>]+>`.*$") + + +EXTRA_DIR: Final = os.path.join(os.path.dirname(__file__), "../..") +DOCS_DIR: Final = os.path.join(EXTRA_DIR, "docs") +CLANG_TIDY_DOCS_DIR: Final = os.path.join(DOCS_DIR, "clang-tidy") +CHECKS_DOCS_DIR: Final = os.path.join(CLANG_TIDY_DOCS_DIR, "checks") +LIST_DOC: Final = os.path.join(CHECKS_DOCS_DIR, "list.rst") +RELEASE_NOTES_DOC: Final = os.path.join(DOCS_DIR, "ReleaseNotes.rst") + + +# Label extracted from :doc:`...`. +CheckLabel = str +Lines = List[str] +BulletBlock = List[str] + +# Pair of the extracted label and its block +BulletItem = Tuple[CheckLabel, BulletBlock] + +# Index of the first line of a bullet block within the full lines list. +BulletStart = int + +# All occurrences for a given label. +DuplicateOccurrences = List[Tuple[BulletStart, BulletBlock]] + + +class BulletBlocks(NamedTuple): + """Structured result of parsing a bullet-list section. + + - prefix: lines before the first bullet within the section range. + - blocks: list of (label, block-lines) pairs for each bullet block. + - suffix: lines after the last bullet within the section range. + """ + + prefix: Lines + blocks: List[BulletItem] + suffix: Lines + + +class ScannedBlocks(NamedTuple): + """Result of scanning bullet blocks within a section range. + + - blocks_with_pos: list of (start_index, block_lines) for each bullet block. + - next_index: index where scanning stopped; start of the suffix region. + """ + + blocks_with_pos: List[Tuple[BulletStart, BulletBlock]] + next_index: int + + +def _scan_bullet_blocks(lines: Sequence[str], start: int, end: int) -> ScannedBlocks: + """Scan consecutive bullet blocks and return (blocks_with_pos, next_index). + + Each entry in blocks_with_pos is a tuple of (start_index, block_lines). + next_index is the index where scanning stopped (start of suffix). + """ + i = start + n = end + blocks_with_pos: List[Tuple[BulletStart, BulletBlock]] = [] + while i < n: + if not _is_bullet_start(lines[i]): + break + bstart = i + i += 1 + while i < n and not _is_bullet_start(lines[i]): + if ( + i + 1 < n + and set(lines[i + 1].rstrip("\n")) == {"^"} + and lines[i].strip() + ): + break + i += 1 + block: BulletBlock = list(lines[bstart:i]) + blocks_with_pos.append((bstart, block)) + return ScannedBlocks(blocks_with_pos, i) + + +def read_text(path: str) -> str: + with io.open(path, "r", encoding="utf-8") as f: + return f.read() + + +def write_text(path: str, content: str) -> None: + with io.open(path, "w", encoding="utf-8", newline="") as f: + f.write(content) + + +def _normalize_list_rst_lines(lines: Sequence[str]) -> List[str]: + """Return normalized content of checks list.rst as a list of lines.""" + out: List[str] = [] + i = 0 + n = len(lines) + + def check_name(line: str) -> Tuple[int, CheckLabel]: + if m := DOC_LINE_RE.match(line): + return (0, m.group("label")) + return (1, "") + + while i < n: + line = lines[i] + if line.lstrip().startswith(".. csv-table::"): + out.append(line) + i += 1 + + while i < n and (lines[i].startswith(" ") or lines[i].strip() == ""): + if DOC_LINE_RE.match(lines[i]): + break + out.append(lines[i]) + i += 1 + + entries: List[str] = [] + while i < n and lines[i].startswith(" "): + entries.append(lines[i]) + i += 1 + + entries_sorted = sorted(entries, key=check_name) + out.extend(entries_sorted) + continue + + out.append(line) + i += 1 + + return out + + +def normalize_list_rst(data: str) -> str: + """Normalize list.rst content and return a string.""" + lines = data.splitlines(True) + return "".join(_normalize_list_rst_lines(lines)) + + +def find_heading(lines: Sequence[str], title: str) -> Optional[int]: + """Find heading start index for a section underlined with ^ characters. + + The function looks for a line equal to `title` followed by a line that + consists solely of ^, which matches the ReleaseNotes style for subsection + headings used here. + + Returns index of the title line, or None if not found. + """ + for i in range(len(lines) - 1): + if lines[i].rstrip("\n") == title: + if ( + (underline := lines[i + 1].rstrip("\n")) + and set(underline) == {"^"} + and len(underline) == len(title) + ): + return i + return None + + +def extract_label(text: str) -> str: + if m := DOC_LABEL_RN_RE.search(text): + return m.group("label") + return text + + +def _is_bullet_start(line: str) -> bool: + return line.startswith("- ") + + +def _parse_bullet_blocks(lines: Sequence[str], start: int, end: int) -> BulletBlocks: + i = start + n = end + first_bullet = i + while first_bullet < n and not _is_bullet_start(lines[first_bullet]): + first_bullet += 1 + prefix: Lines = list(lines[i:first_bullet]) + + blocks: List[BulletItem] = [] + res = _scan_bullet_blocks(lines, first_bullet, n) + for _, block in res.blocks_with_pos: + key: CheckLabel = extract_label(block[0]) + blocks.append((key, block)) + + suffix: Lines = list(lines[res.next_index : n]) + return BulletBlocks(prefix, blocks, suffix) + + +def sort_blocks(blocks: Iterable[BulletItem]) -> List[BulletBlock]: + """Return blocks sorted deterministically by their extracted label. + + Duplicates are preserved; merging is left to authors to handle manually. + """ + return list(map(itemgetter(1), sorted(blocks, key=itemgetter(0)))) + + +def find_duplicate_entries( + lines: Sequence[str], title: str +) -> List[Tuple[CheckLabel, DuplicateOccurrences]]: + """Return detailed duplicate info as (key, [(start_idx, block_lines), ...]). + + start_idx is the 0-based index of the first line of the bullet block in + the original lines list. Only keys with more than one occurrence are + returned, and occurrences are listed in the order they appear. + """ + bounds = _find_section_bounds(lines, title, None) + if bounds is None: + return [] + _, sec_start, sec_end = bounds + + i = sec_start + n = sec_end + + while i < n and not _is_bullet_start(lines[i]): + i += 1 + + blocks_with_pos: List[Tuple[CheckLabel, BulletStart, BulletBlock]] = [] + res = _scan_bullet_blocks(lines, i, n) + for bstart, block in res.blocks_with_pos: + key = extract_label(block[0]) + blocks_with_pos.append((key, bstart, block)) + + grouped: DefaultDict[CheckLabel, DuplicateOccurrences] = defaultdict(list) + for key, start, block in blocks_with_pos: + grouped[key].append((start, block)) + + result: List[Tuple[CheckLabel, DuplicateOccurrences]] = [] + for key, occs in grouped.items(): + if len(occs) > 1: + result.append((key, occs)) + + result.sort(key=itemgetter(0)) + return result + + +def _find_section_bounds( + lines: Sequence[str], title: str, next_title: Optional[str] +) -> Optional[Tuple[int, int, int]]: + """Return (h_start, sec_start, sec_end) for section `title`. + + - h_start: index of the section title line + - sec_start: index of the first content line after underline + - sec_end: index of the first line of the next section title (or end) + """ + if (h_start := find_heading(lines, title)) is None: + return None + + sec_start = h_start + 2 + + # Determine end of section either from next_title or by scanning. + if next_title is not None: + if (h_end := find_heading(lines, next_title)) is None: + # Scan forward to the next heading-like underline. + h_end = sec_start + while h_end + 1 < len(lines): + if lines[h_end].strip() and set(lines[h_end + 1].rstrip("\n")) == {"^"}: + break + h_end += 1 + sec_end = h_end + else: + # Scan to end or until a heading underline is found. + h_end = sec_start + while h_end + 1 < len(lines): + if lines[h_end].strip() and set(lines[h_end + 1].rstrip("\n")) == {"^"}: + break + h_end += 1 + sec_end = h_end + + return h_start, sec_start, sec_end + + +def _normalize_release_notes_section( + lines: Sequence[str], title: str, next_title: Optional[str] +) -> List[str]: + """Normalize a single release-notes section and return updated lines.""" + if (bounds := _find_section_bounds(lines, title, next_title)) is None: + return list(lines) + _, sec_start, sec_end = bounds + + prefix, blocks, suffix = _parse_bullet_blocks(lines, sec_start, sec_end) + sorted_blocks = sort_blocks(blocks) + + new_section: List[str] = [] + new_section.extend(prefix) + for i_b, b in enumerate(sorted_blocks): + if i_b > 0 and ( + not new_section or (new_section and new_section[-1].strip() != "") + ): + new_section.append("\n") + new_section.extend(b) + new_section.extend(suffix) + + return list(lines[:sec_start]) + new_section + list(lines[sec_end:]) + + +def normalize_release_notes(lines: Sequence[str]) -> str: + sections = ["New checks", "New check aliases", "Changes in existing checks"] + + out = list(lines) + + for idx in range(len(sections) - 1, -1, -1): + title = sections[idx] + next_title = sections[idx + 1] if idx + 1 < len(sections) else None + out = _normalize_release_notes_section(out, title, next_title) + + return "".join(out) + + +def _emit_duplicate_report(lines: Sequence[str], title: str) -> Optional[str]: + if not (dups_detail := find_duplicate_entries(lines, title)): + return None + out: List[str] = [] + out.append(f"Error: Duplicate entries in '{title}':\n") + for key, occs in dups_detail: + out.append(f"\n-- Duplicate: {key}\n") + for start_idx, block in occs: + out.append(f"- At line {start_idx + 1}:\n") + out.append("".join(block)) + if not (block and block[-1].endswith("\n")): + out.append("\n") + return "".join(out) + + +def process_release_notes(out_path: str, rn_doc: str) -> int: + text = read_text(rn_doc) + lines = text.splitlines(True) + normalized = normalize_release_notes(lines) + write_text(out_path, normalized) + + # Prefer reporting ordering issues first; let diff fail the test. + if text != normalized: + sys.stderr.write( + "\nEntries in 'clang-tools-extra/docs/ReleaseNotes.rst' are not alphabetically sorted.\n" + "Fix the ordering by applying diff printed below.\n\n" + ) + return 0 + + # Ordering is clean then enforce duplicates. + if report := _emit_duplicate_report(lines, "Changes in existing checks"): + sys.stderr.write(report) + return 3 + return 0 + + +def process_checks_list(out_path: str, list_doc: str) -> int: + text = read_text(list_doc) + normalized = normalize_list_rst(text) + + if text != normalized: + sys.stderr.write( + "\nChecks in 'clang-tools-extra/docs/clang-tidy/checks/list.rst' csv-table are not alphabetically sorted.\n" + "Fix the ordering by applying diff printed below.\n\n" + ) + + write_text(out_path, normalized) + return 0 + + +def main(argv: Sequence[str]) -> int: + ap = argparse.ArgumentParser() + ap.add_argument("-o", "--output", dest="out", default=None) + args = ap.parse_args(argv) + + list_doc, rn_doc = (os.path.normpath(LIST_DOC), os.path.normpath(RELEASE_NOTES_DOC)) + + if args.out: + out_path = args.out + out_lower = os.path.basename(out_path).lower() + if "release" in out_lower: + return process_release_notes(out_path, rn_doc) + else: + return process_checks_list(out_path, list_doc) + + process_checks_list(list_doc, list_doc) + return process_release_notes(rn_doc, rn_doc) + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/clang-tools-extra/clang-tidy/tool/check_alphabetical_order_test.py b/clang-tools-extra/clang-tidy/tool/check_alphabetical_order_test.py new file mode 100644 index 0000000..48a3c76 --- /dev/null +++ b/clang-tools-extra/clang-tidy/tool/check_alphabetical_order_test.py @@ -0,0 +1,401 @@ +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# To run these tests: +# python3 check_alphabetical_order_test.py -v + +import check_alphabetical_order as _mod +from contextlib import redirect_stderr +import io +import os +import tempfile +import textwrap +from typing import cast +import unittest + + +class TestAlphabeticalOrderCheck(unittest.TestCase): + def test_normalize_list_rst_sorts_rows(self) -> None: + input_text = textwrap.dedent( + """\ + .. csv-table:: Clang-Tidy checks + :header: "Name", "Offers fixes" + + :doc:`bugprone-virtual-near-miss <bugprone/virtual-near-miss>`, "Yes" + :doc:`cert-flp30-c <cert/flp30-c>`, + :doc:`abseil-cleanup-ctad <abseil/cleanup-ctad>`, "Yes" + A non-doc row that should stay after docs + """ + ) + + expected_text = textwrap.dedent( + """\ + .. csv-table:: Clang-Tidy checks + :header: "Name", "Offers fixes" + + :doc:`abseil-cleanup-ctad <abseil/cleanup-ctad>`, "Yes" + :doc:`bugprone-virtual-near-miss <bugprone/virtual-near-miss>`, "Yes" + :doc:`cert-flp30-c <cert/flp30-c>`, + A non-doc row that should stay after docs + """ + ) + + out_str = _mod.normalize_list_rst(input_text) + self.assertEqual(out_str, expected_text) + + def test_find_heading(self) -> None: + text = textwrap.dedent( + """\ + - Deprecated the :program:`clang-tidy` ``zircon`` module. All checks have been + moved to the ``fuchsia`` module instead. The ``zircon`` module will be removed + in the 24th release. + + New checks + ^^^^^^^^^^ + - New :doc:`bugprone-derived-method-shadowing-base-method + <clang-tidy/checks/bugprone/derived-method-shadowing-base-method>` check. + """ + ) + lines = text.splitlines(True) + idx = _mod.find_heading(lines, "New checks") + self.assertEqual(idx, 4) + + def test_duplicate_detection_and_report(self) -> None: + # Ensure duplicate detection works properly when sorting is incorrect. + text = textwrap.dedent( + """\ + Changes in existing checks + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - Improved :doc:`bugprone-exception-escape + <clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas: + exceptions from captures are now diagnosed, exceptions in the bodies of + lambdas that aren't actually invoked are not. + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + """ + ) + lines = text.splitlines(True) + report = _mod._emit_duplicate_report(lines, "Changes in existing checks") + self.assertIsNotNone(report) + report_str = cast(str, report) + + expected_report = textwrap.dedent( + """\ + Error: Duplicate entries in 'Changes in existing checks': + + -- Duplicate: - Improved :doc:`bugprone-easily-swappable-parameters + + - At line 4: + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - At line 14: + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + """ + ) + self.assertEqual(report_str, expected_report) + + def test_process_release_notes_with_unsorted_content(self) -> None: + # When content is not normalized, the function writes normalized text and returns 0. + rn_text = textwrap.dedent( + """\ + New checks + ^^^^^^^^^^ + + - New :doc:`readability-redundant-parentheses + <clang-tidy/checks/readability/redundant-parentheses>` check. + + Detect redundant parentheses. + + - New :doc:`bugprone-derived-method-shadowing-base-method + <clang-tidy/checks/bugprone/derived-method-shadowing-base-method>` check. + + Finds derived class methods that shadow a (non-virtual) base class method. + + """ + ) + with tempfile.TemporaryDirectory() as td: + rn_doc = os.path.join(td, "ReleaseNotes.rst") + out_path = os.path.join(td, "out.rst") + with open(rn_doc, "w", encoding="utf-8") as f: + f.write(rn_text) + + buf = io.StringIO() + with redirect_stderr(buf): + rc = _mod.process_release_notes(out_path, rn_doc) + + self.assertEqual(rc, 0) + with open(out_path, "r", encoding="utf-8") as f: + out = f.read() + + expected_out = textwrap.dedent( + """\ + New checks + ^^^^^^^^^^ + + - New :doc:`bugprone-derived-method-shadowing-base-method + <clang-tidy/checks/bugprone/derived-method-shadowing-base-method>` check. + + Finds derived class methods that shadow a (non-virtual) base class method. + + - New :doc:`readability-redundant-parentheses + <clang-tidy/checks/readability/redundant-parentheses>` check. + + Detect redundant parentheses. + + + """ + ) + + self.assertEqual(out, expected_out) + self.assertIn("not alphabetically sorted", buf.getvalue()) + + def test_process_release_notes_prioritizes_sorting_over_duplicates(self) -> None: + # Sorting is incorrect and duplicates exist, should report ordering issues first. + rn_text = textwrap.dedent( + """\ + Changes in existing checks + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - Improved :doc:`bugprone-exception-escape + <clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas: + exceptions from captures are now diagnosed, exceptions in the bodies of + lambdas that aren't actually invoked are not. + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + """ + ) + with tempfile.TemporaryDirectory() as td: + rn_doc = os.path.join(td, "ReleaseNotes.rst") + out_path = os.path.join(td, "out.rst") + with open(rn_doc, "w", encoding="utf-8") as f: + f.write(rn_text) + + buf = io.StringIO() + with redirect_stderr(buf): + rc = _mod.process_release_notes(out_path, rn_doc) + self.assertEqual(rc, 0) + self.assertIn( + "Entries in 'clang-tools-extra/docs/ReleaseNotes.rst' are not alphabetically sorted.", + buf.getvalue(), + ) + + with open(out_path, "r", encoding="utf-8") as f: + out = f.read() + expected_out = textwrap.dedent( + """\ + Changes in existing checks + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - Improved :doc:`bugprone-exception-escape + <clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas: + exceptions from captures are now diagnosed, exceptions in the bodies of + lambdas that aren't actually invoked are not. + + + """ + ) + self.assertEqual(out, expected_out) + + def test_process_release_notes_with_duplicates_fails(self) -> None: + # Sorting is already correct but duplicates exist, should return 3 and report. + rn_text = textwrap.dedent( + """\ + Changes in existing checks + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - Improved :doc:`bugprone-exception-escape + <clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas: + exceptions from captures are now diagnosed, exceptions in the bodies of + lambdas that aren't actually invoked are not. + + """ + ) + with tempfile.TemporaryDirectory() as td: + rn_doc = os.path.join(td, "ReleaseNotes.rst") + out_path = os.path.join(td, "out.rst") + with open(rn_doc, "w", encoding="utf-8") as f: + f.write(rn_text) + + buf = io.StringIO() + with redirect_stderr(buf): + rc = _mod.process_release_notes(out_path, rn_doc) + + self.assertEqual(rc, 3) + expected_report = textwrap.dedent( + """\ + Error: Duplicate entries in 'Changes in existing checks': + + -- Duplicate: - Improved :doc:`bugprone-easily-swappable-parameters + + - At line 4: + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - At line 9: + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + """ + ) + self.assertEqual(buf.getvalue(), expected_report) + + with open(out_path, "r", encoding="utf-8") as f: + out = f.read() + self.assertEqual(out, rn_text) + + def test_release_notes_handles_nested_sub_bullets(self) -> None: + rn_text = textwrap.dedent( + """\ + Changes in existing checks + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - Improved :doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals + <clang-tidy/checks/llvm/prefer-isa-or-dyn-cast-in-conditionals>` check: + + - Fix-it handles callees with nested-name-specifier correctly. + + - ``if`` statements with init-statement (``if (auto X = ...; ...)``) are + handled correctly. + + - ``for`` loops are supported. + + - Improved :doc:`bugprone-exception-escape + <clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas: + exceptions from captures are now diagnosed, exceptions in the bodies of + lambdas that aren't actually invoked are not. + + """ + ) + + out = _mod.normalize_release_notes(rn_text.splitlines(True)) + + expected_out = textwrap.dedent( + """\ + Changes in existing checks + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + + - Improved :doc:`bugprone-easily-swappable-parameters + <clang-tidy/checks/bugprone/easily-swappable-parameters>` check by + correcting a spelling mistake on its option + ``NamePrefixSuffixSilenceDissimilarityTreshold``. + + - Improved :doc:`bugprone-exception-escape + <clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas: + exceptions from captures are now diagnosed, exceptions in the bodies of + lambdas that aren't actually invoked are not. + + - Improved :doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals + <clang-tidy/checks/llvm/prefer-isa-or-dyn-cast-in-conditionals>` check: + + - Fix-it handles callees with nested-name-specifier correctly. + + - ``if`` statements with init-statement (``if (auto X = ...; ...)``) are + handled correctly. + + - ``for`` loops are supported. + + + """ + ) + self.assertEqual(out, expected_out) + + def test_process_checks_list_normalizes_output(self) -> None: + list_text = textwrap.dedent( + """\ + .. csv-table:: List + :header: "Name", "Redirect", "Offers fixes" + + :doc:`cert-dcl16-c <cert/dcl16-c>`, :doc:`readability-uppercase-literal-suffix <readability/uppercase-literal-suffix>`, "Yes" + :doc:`cert-con36-c <cert/con36-c>`, :doc:`bugprone-spuriously-wake-up-functions <bugprone/spuriously-wake-up-functions>`, + :doc:`cert-dcl37-c <cert/dcl37-c>`, :doc:`bugprone-reserved-identifier <bugprone/reserved-identifier>`, "Yes" + :doc:`cert-arr39-c <cert/arr39-c>`, :doc:`bugprone-sizeof-expression <bugprone/sizeof-expression>`, + """ + ) + with tempfile.TemporaryDirectory() as td: + in_doc = os.path.join(td, "list.rst") + out_doc = os.path.join(td, "out.rst") + with open(in_doc, "w", encoding="utf-8") as f: + f.write(list_text) + buf = io.StringIO() + with redirect_stderr(buf): + rc = _mod.process_checks_list(out_doc, in_doc) + self.assertEqual(rc, 0) + self.assertIn( + "Checks in 'clang-tools-extra/docs/clang-tidy/checks/list.rst' csv-table are not alphabetically sorted.", + buf.getvalue(), + ) + self.assertEqual(rc, 0) + with open(out_doc, "r", encoding="utf-8") as f: + out = f.read() + + expected_out = textwrap.dedent( + """\ + .. csv-table:: List + :header: "Name", "Redirect", "Offers fixes" + + :doc:`cert-arr39-c <cert/arr39-c>`, :doc:`bugprone-sizeof-expression <bugprone/sizeof-expression>`, + :doc:`cert-con36-c <cert/con36-c>`, :doc:`bugprone-spuriously-wake-up-functions <bugprone/spuriously-wake-up-functions>`, + :doc:`cert-dcl16-c <cert/dcl16-c>`, :doc:`readability-uppercase-literal-suffix <readability/uppercase-literal-suffix>`, "Yes" + :doc:`cert-dcl37-c <cert/dcl37-c>`, :doc:`bugprone-reserved-identifier <bugprone/reserved-identifier>`, "Yes" + """ + ) + self.assertEqual(out, expected_out) + + +if __name__ == "__main__": + unittest.main() diff --git a/clang-tools-extra/clang-tidy/utils/Aliasing.cpp b/clang-tools-extra/clang-tidy/utils/Aliasing.cpp index a22d235..1b12859 100644 --- a/clang-tools-extra/clang-tidy/utils/Aliasing.cpp +++ b/clang-tools-extra/clang-tidy/utils/Aliasing.cpp @@ -65,15 +65,9 @@ static bool hasPtrOrReferenceInStmt(const Stmt *S, const ValueDecl *Var) { if (isPtrOrReferenceForVar(S, Var)) return true; - for (const Stmt *Child : S->children()) { - if (!Child) - continue; - - if (hasPtrOrReferenceInStmt(Child, Var)) - return true; - } - - return false; + return llvm::any_of(S->children(), [&](const Stmt *Child) { + return Child && hasPtrOrReferenceInStmt(Child, Var); + }); } static bool refersToEnclosingLambdaCaptureByRef(const Decl *Func, diff --git a/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.cpp b/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.cpp index aacb4e3..d0659ad 100644 --- a/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.cpp +++ b/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.cpp @@ -141,7 +141,7 @@ BraceInsertionHints getBraceInsertionsHints(const Stmt *const S, // StartLoc points at the location of the opening brace to be inserted. SourceLocation EndLoc; - std::string ClosingInsertion; + StringRef ClosingInsertion; if (EndLocHint.isValid()) { EndLoc = EndLocHint; ClosingInsertion = "} "; diff --git a/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.h b/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.h index 879c84d..2b2d71f 100644 --- a/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.h +++ b/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.h @@ -39,7 +39,7 @@ struct BraceInsertionHints { /// Constructor for a hint offering fix-its for brace insertion. Both /// positions must be valid. BraceInsertionHints(SourceLocation OpeningBracePos, - SourceLocation ClosingBracePos, std::string ClosingBrace) + SourceLocation ClosingBracePos, StringRef ClosingBrace) : DiagnosticPos(OpeningBracePos), OpeningBracePos(OpeningBracePos), ClosingBracePos(ClosingBracePos), ClosingBrace(ClosingBrace) { assert(offersFixIts()); @@ -64,7 +64,7 @@ struct BraceInsertionHints { private: SourceLocation OpeningBracePos; SourceLocation ClosingBracePos; - std::string ClosingBrace; + StringRef ClosingBrace; }; /// Create fix-it hints for braces that wrap the given statement when applied. diff --git a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp index 75a6daf..a807c95 100644 --- a/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp @@ -21,10 +21,7 @@ using llvm::SmallPtrSet; template <typename S> static bool isSetDifferenceEmpty(const S &S1, const S &S2) { - for (auto E : S1) - if (S2.count(E) == 0) - return false; - return true; + return llvm::none_of(S1, [&S2](const auto &E) { return !S2.contains(E); }); } // Extracts all Nodes keyed by ID from Matches and inserts them into Nodes. diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index 8ead264..f766a1bc 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -192,8 +192,7 @@ static bool isFunctionPointerConvertible(QualType From, QualType To) { // // The function should only be called in C++ mode. static bool isQualificationConvertiblePointer(QualType From, QualType To, - LangOptions LangOpts) { - + const LangOptions &LangOpts) { // [N4659 7.5 (1)] // A cv-decomposition of a type T is a sequence of cv_i and P_i such that T is // cv_0 P_0 cv_1 P_1 ... cv_n−1 P_n−1 cv_n U” for n > 0, @@ -601,13 +600,14 @@ ExceptionAnalyzer::throwsException(const Stmt *St, // whether the call itself throws. if (const auto *Call = dyn_cast<CallExpr>(St)) { if (const FunctionDecl *Func = Call->getDirectCallee()) { - ExceptionInfo Excs = + const ExceptionInfo Excs = throwsException(Func, Caught, CallStack, Call->getBeginLoc()); Results.merge(Excs); } } else if (const auto *Construct = dyn_cast<CXXConstructExpr>(St)) { - ExceptionInfo Excs = throwsException(Construct->getConstructor(), Caught, - CallStack, Construct->getBeginLoc()); + const ExceptionInfo Excs = + throwsException(Construct->getConstructor(), Caught, CallStack, + Construct->getBeginLoc()); Results.merge(Excs); } } diff --git a/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp b/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp index 0375d0f..45fcacf 100644 --- a/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExprSequence.cpp @@ -148,12 +148,9 @@ bool ExprSequence::inSequence(const Stmt *Before, const Stmt *After) const { // If 'After' is a parent of 'Before' or is sequenced after one of these // parents, we know that it is sequenced after 'Before'. - for (const Stmt *Parent : BeforeParents) { - if (Parent == After || inSequence(Parent, After)) - return true; - } - - return false; + return llvm::any_of(BeforeParents, [&](const Stmt *Parent) { + return Parent == After || inSequence(Parent, After); + }); } bool ExprSequence::potentiallyAfter(const Stmt *After, diff --git a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp index 127de30..d210b00 100644 --- a/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp +++ b/clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp @@ -624,7 +624,6 @@ bool FormatStringConverter::HandlePrintfSpecifier(const PrintfSpecifier &FS, const char *StartSpecifier, unsigned SpecifierLen, const TargetInfo &Target) { - const size_t StartSpecifierPos = StartSpecifier - PrintfFormatString.data(); assert(StartSpecifierPos + SpecifierLen <= PrintfFormatString.size()); @@ -701,6 +700,7 @@ void FormatStringConverter::finalizeFormatText() { /// Append literal parts of the format text, reinstating escapes as required. void FormatStringConverter::appendFormatText(const StringRef Text) { for (const char Ch : Text) { + const auto UCh = static_cast<unsigned char>(Ch); if (Ch == '\a') StandardFormatString += "\\a"; else if (Ch == '\b') @@ -725,10 +725,10 @@ void FormatStringConverter::appendFormatText(const StringRef Text) { } else if (Ch == '}') { StandardFormatString += "}}"; FormatStringNeededRewriting = true; - } else if (Ch < 32) { + } else if (UCh < 32) { StandardFormatString += "\\x"; - StandardFormatString += llvm::hexdigit(Ch >> 4, true); - StandardFormatString += llvm::hexdigit(Ch & 0xf, true); + StandardFormatString += llvm::hexdigit(UCh >> 4, true); + StandardFormatString += llvm::hexdigit(UCh & 0xf, true); } else StandardFormatString += Ch; } diff --git a/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp b/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp index 0f20fde..06d6caa 100644 --- a/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "LexerUtils.h" -#include "clang/AST/AST.h" #include "clang/Basic/SourceManager.h" #include <optional> #include <utility> @@ -170,7 +169,6 @@ static bool breakAndReturnEndPlus1Token(const Stmt &S) { static SourceLocation getSemicolonAfterStmtEndLoc(const SourceLocation &EndLoc, const SourceManager &SM, const LangOptions &LangOpts) { - if (EndLoc.isMacroID()) { // Assuming EndLoc points to a function call foo within macro F. // This method is supposed to return location of the semicolon within @@ -206,7 +204,6 @@ static SourceLocation getSemicolonAfterStmtEndLoc(const SourceLocation &EndLoc, SourceLocation getUnifiedEndLoc(const Stmt &S, const SourceManager &SM, const LangOptions &LangOpts) { - const Stmt *LastChild = &S; while (!LastChild->children().empty() && !breakAndReturnEnd(*LastChild) && !breakAndReturnEndPlus1Token(*LastChild)) { diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.cpp b/clang-tools-extra/clang-tidy/utils/Matchers.cpp index 4382745..b1591fb 100644 --- a/clang-tools-extra/clang-tidy/utils/Matchers.cpp +++ b/clang-tools-extra/clang-tidy/utils/Matchers.cpp @@ -27,7 +27,6 @@ MatchesAnyListedTypeNameMatcher::~MatchesAnyListedTypeNameMatcher() = default; bool MatchesAnyListedTypeNameMatcher::matches( const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder, ast_matchers::internal::BoundNodesTreeBuilder *Builder) const { - if (NameMatchers.empty()) return false; diff --git a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp index d7dad62..6fa62302 100644 --- a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp @@ -9,7 +9,6 @@ #include "TransformerClangTidyCheck.h" #include "clang/Basic/DiagnosticIDs.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/STLExtras.h" #include <optional> namespace clang::tidy::utils { @@ -66,7 +65,7 @@ TransformerClangTidyCheck::TransformerClangTidyCheck(StringRef Name, // we would be accessing `getLangOpts` and `Options` before the underlying // `ClangTidyCheck` instance was properly initialized. TransformerClangTidyCheck::TransformerClangTidyCheck( - std::function<std::optional<RewriteRuleWith<std::string>>( + llvm::function_ref<std::optional<RewriteRuleWith<std::string>>( const LangOptions &, const OptionsView &)> MakeRule, StringRef Name, ClangTidyContext *Context) diff --git a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.h b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.h index e77f84b..da8606f 100644 --- a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.h +++ b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.h @@ -48,8 +48,9 @@ public: /// /// See \c setRule for constraints on the rule. TransformerClangTidyCheck( - std::function<std::optional<transformer::RewriteRuleWith<std::string>>( - const LangOptions &, const OptionsView &)> + llvm::function_ref< + std::optional<transformer::RewriteRuleWith<std::string>>( + const LangOptions &, const OptionsView &)> MakeRule, StringRef Name, ClangTidyContext *Context); diff --git a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp index 98a5d40..dde6e9a 100644 --- a/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp +++ b/clang-tools-extra/clang-tidy/utils/TypeTraits.cpp @@ -24,11 +24,9 @@ static bool hasDeletedCopyConstructor(QualType Type) { auto *Record = Type->getAsCXXRecordDecl(); if (!Record || !Record->hasDefinition()) return false; - for (const auto *Constructor : Record->ctors()) { - if (Constructor->isCopyConstructor() && Constructor->isDeleted()) - return true; - } - return false; + return llvm::any_of(Record->ctors(), [](const auto *Constructor) { + return Constructor->isCopyConstructor() && Constructor->isDeleted(); + }); } std::optional<bool> isExpensiveToCopy(QualType Type, @@ -70,14 +68,10 @@ bool recordIsTriviallyDefaultConstructible(const RecordDecl &RecordDecl, return false; } // If all its direct bases are trivially constructible. - for (const CXXBaseSpecifier &Base : ClassDecl->bases()) { - if (!isTriviallyDefaultConstructible(Base.getType(), Context)) - return false; - if (Base.isVirtual()) - return false; - } - - return true; + return llvm::all_of(ClassDecl->bases(), [&](const CXXBaseSpecifier &Base) { + return isTriviallyDefaultConstructible(Base.getType(), Context) && + !Base.isVirtual(); + }); } // Based on QualType::isTrivial. diff --git a/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp index 8b7019b..ab584cb 100644 --- a/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp @@ -55,7 +55,7 @@ AST_MATCHER(Expr, hasSideEffects) { } // namespace static auto -makeExprMatcher(ast_matchers::internal::Matcher<Expr> ArgumentMatcher, +makeExprMatcher(const ast_matchers::internal::Matcher<Expr> &ArgumentMatcher, ArrayRef<StringRef> MethodNames, ArrayRef<StringRef> FreeNames) { return expr( @@ -199,7 +199,7 @@ void UseRangesCheck::check(const MatchFinder::MatchResult &Result) { if (!NodeStr.consume_front(FuncDecl)) continue; Function = Value.get<FunctionDecl>(); - size_t Index; + size_t Index = 0; if (NodeStr.getAsInteger(10, Index)) { llvm_unreachable("Unable to extract replacer index"); } diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt index fb3f053..d7ec853 100644 --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -165,6 +165,7 @@ clang_target_link_libraries(clangDaemon clangBasic clangDependencyScanning clangDriver + clangOptions clangFormat clangFrontend clangIndex diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index f8e6da7..1518f17 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -554,6 +554,8 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, if (const auto &Dir = Params.initializationOptions.compilationDatabasePath) CDBOpts.CompileCommandsDir = Dir; CDBOpts.ContextProvider = Opts.ContextProvider; + if (Opts.StrongWorkspaceMode) + CDBOpts.applyFallbackWorkingDirectory(Opts.WorkspaceRoot); BaseCDB = std::make_unique<DirectoryBasedGlobalCompilationDatabase>(CDBOpts); } diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h index 4a1eae1..d45d13f 100644 --- a/clang-tools-extra/clangd/ClangdServer.h +++ b/clang-tools-extra/clangd/ClangdServer.h @@ -152,6 +152,11 @@ public: /// FIXME: If not set, should use the current working directory. std::optional<std::string> WorkspaceRoot; + /// Sets an alternate mode of operation. Current effects are: + /// - Using the current working directory as the working directory for + /// fallback commands + bool StrongWorkspaceMode; + /// The resource directory is used to find internal headers, overriding /// defaults and -resource-dir compiler flag). /// If std::nullopt, ClangdServer calls diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index c1be937..4eda330 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -11,8 +11,8 @@ #include "support/Logger.h" #include "support/Trace.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Options/Options.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/ArrayRef.h" @@ -132,8 +132,7 @@ std::optional<std::string> detectSysroot() { std::string detectStandardResourceDir() { static int StaticForMainAddr; // Just an address in this process. - return CompilerInvocation::GetResourcesPath("clangd", - (void *)&StaticForMainAddr); + return GetResourcesPath("clangd", (void *)&StaticForMainAddr); } // The path passed to argv[0] is important: @@ -206,7 +205,7 @@ void CommandMangler::operator()(tooling::CompileCommand &Command, if (Cmd.empty()) return; - auto &OptTable = clang::driver::getDriverOptTable(); + auto &OptTable = getDriverOptTable(); // OriginalArgs needs to outlive ArgList. llvm::SmallVector<const char *, 16> OriginalArgs; OriginalArgs.reserve(Cmd.size()); @@ -222,8 +221,8 @@ void CommandMangler::operator()(tooling::CompileCommand &Command, llvm::opt::InputArgList ArgList; ArgList = OptTable.ParseArgs( llvm::ArrayRef(OriginalArgs).drop_front(), IgnoredCount, IgnoredCount, - llvm::opt::Visibility(IsCLMode ? driver::options::CLOption - : driver::options::ClangOption)); + llvm::opt::Visibility(IsCLMode ? options::CLOption + : options::ClangOption)); llvm::SmallVector<unsigned, 1> IndicesToDrop; // Having multiple architecture options (e.g. when building fat binaries) @@ -232,7 +231,7 @@ void CommandMangler::operator()(tooling::CompileCommand &Command, // As there are no signals to figure out which one user actually wants. They // can explicitly specify one through `CompileFlags.Add` if need be. unsigned ArchOptCount = 0; - for (auto *Input : ArgList.filtered(driver::options::OPT_arch)) { + for (auto *Input : ArgList.filtered(options::OPT_arch)) { ++ArchOptCount; for (auto I = 0U; I <= Input->getNumValues(); ++I) IndicesToDrop.push_back(Input->getIndex() + I); @@ -262,13 +261,12 @@ void CommandMangler::operator()(tooling::CompileCommand &Command, // explicitly at the end of the flags. This ensures modifications done in the // following steps apply in more cases (like setting -x, which only affects // inputs that come after it). - for (auto *Input : ArgList.filtered(driver::options::OPT_INPUT)) { + for (auto *Input : ArgList.filtered(options::OPT_INPUT)) { SawInput(Input->getValue(0)); IndicesToDrop.push_back(Input->getIndex()); } // Anything after `--` is also treated as input, drop them as well. - if (auto *DashDash = - ArgList.getLastArgNoClaim(driver::options::OPT__DASH_DASH)) { + if (auto *DashDash = ArgList.getLastArgNoClaim(options::OPT__DASH_DASH)) { auto DashDashIndex = DashDash->getIndex() + 1; // +1 accounts for Cmd[0] // Another +1 so we don't treat the `--` itself as an input. for (unsigned I = DashDashIndex + 1; I < Cmd.size(); ++I) @@ -424,11 +422,11 @@ DriverMode getDriverMode(const std::vector<std::string> &Args) { // Returns the set of DriverModes where an option may be used. unsigned char getModes(const llvm::opt::Option &Opt) { unsigned char Result = DM_None; - if (Opt.hasVisibilityFlag(driver::options::ClangOption)) + if (Opt.hasVisibilityFlag(options::ClangOption)) Result |= DM_GCC; - if (Opt.hasVisibilityFlag(driver::options::CC1Option)) + if (Opt.hasVisibilityFlag(options::CC1Option)) Result |= DM_CC1; - if (Opt.hasVisibilityFlag(driver::options::CLOption)) + if (Opt.hasVisibilityFlag(options::CLOption)) Result |= DM_CL; return Result; } @@ -442,8 +440,8 @@ llvm::ArrayRef<ArgStripper::Rule> ArgStripper::rulesFor(llvm::StringRef Arg) { using TableTy = llvm::StringMap<llvm::SmallVector<Rule, 4>, llvm::BumpPtrAllocator>; static TableTy *Table = [] { - auto &DriverTable = driver::getDriverOptTable(); - using DriverID = clang::driver::options::ID; + auto &DriverTable = getDriverOptTable(); + using DriverID = clang::options::ID; // Collect sets of aliases, so we can treat -foo and -foo= as synonyms. // Conceptually a double-linked list: PrevAlias[I] -> I -> NextAlias[I]. @@ -468,7 +466,7 @@ llvm::ArrayRef<ArgStripper::Rule> ArgStripper::rulesFor(llvm::StringRef Arg) { FLAGS, VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, \ METAVAR, VALUES, SUBCOMMANDIDS_OFFSET) \ {DriverID::OPT_##ID, DriverID::OPT_##ALIAS, ALIASARGS}, -#include "clang/Driver/Options.inc" +#include "clang/Options/Options.inc" #undef OPTION }; for (auto &E : AliasTable) diff --git a/clang-tools-extra/clangd/Compiler.cpp b/clang-tools-extra/clangd/Compiler.cpp index 6ebc2ea..9ea7df13 100644 --- a/clang-tools-extra/clangd/Compiler.cpp +++ b/clang-tools-extra/clangd/Compiler.cpp @@ -9,6 +9,7 @@ #include "Compiler.h" #include "support/Logger.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Driver/CreateInvocationFromArgs.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Serialization/PCHContainerOperations.h" diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index c6afd0b..d229a71 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -64,7 +64,9 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File) const { if (FileExtension.empty() || FileExtension == ".h") Argv.push_back("-xobjective-c++-header"); Argv.push_back(std::string(File)); - tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File), + tooling::CompileCommand Cmd(FallbackWorkingDirectory + ? *FallbackWorkingDirectory + : llvm::sys::path::parent_path(File), llvm::sys::path::filename(File), std::move(Argv), /*Output=*/""); Cmd.Heuristic = "clangd fallback"; @@ -349,7 +351,8 @@ bool DirectoryBasedGlobalCompilationDatabase::DirectoryCache::load( DirectoryBasedGlobalCompilationDatabase:: DirectoryBasedGlobalCompilationDatabase(const Options &Opts) - : Opts(Opts), Broadcaster(std::make_unique<BroadcastThread>(*this)) { + : GlobalCompilationDatabase(Opts.FallbackWorkingDirectory), Opts(Opts), + Broadcaster(std::make_unique<BroadcastThread>(*this)) { if (!this->Opts.ContextProvider) this->Opts.ContextProvider = [](llvm::StringRef) { return Context::current().clone(); @@ -460,6 +463,21 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB( return Result; } +void DirectoryBasedGlobalCompilationDatabase::Options:: + applyFallbackWorkingDirectory( + std::optional<std::string> FallbackWorkingDirectory) { + if (FallbackWorkingDirectory) + this->FallbackWorkingDirectory = *FallbackWorkingDirectory; + else { + // Clangd is running in strong workspace mode but the client didn't + // specify a workspace path in the `initialize` request. + // Fallback to current working directory. + SmallString<256> CWD; + llvm::sys::fs::current_path(CWD); + this->FallbackWorkingDirectory = std::string(CWD); + } +} + // The broadcast thread announces files with new compile commands to the world. // Primarily this is used to enqueue them for background indexing. // @@ -759,9 +777,10 @@ DirectoryBasedGlobalCompilationDatabase::getProjectModules(PathRef File) const { OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base, std::vector<std::string> FallbackFlags, - CommandMangler Mangler) - : DelegatingCDB(Base), Mangler(std::move(Mangler)), - FallbackFlags(std::move(FallbackFlags)) {} + CommandMangler Mangler, + std::optional<std::string> FallbackWorkingDirectory) + : DelegatingCDB(Base, FallbackWorkingDirectory), + Mangler(std::move(Mangler)), FallbackFlags(std::move(FallbackFlags)) {} std::optional<tooling::CompileCommand> OverlayCDB::getCompileCommand(PathRef File) const { @@ -844,16 +863,20 @@ OverlayCDB::getProjectModules(PathRef File) const { return MDB; } -DelegatingCDB::DelegatingCDB(const GlobalCompilationDatabase *Base) - : Base(Base) { +DelegatingCDB::DelegatingCDB( + const GlobalCompilationDatabase *Base, + std::optional<std::string> FallbackWorkingDirectory) + : GlobalCompilationDatabase(FallbackWorkingDirectory), Base(Base) { if (Base) BaseChanged = Base->watch([this](const std::vector<std::string> Changes) { OnCommandChanged.broadcast(Changes); }); } -DelegatingCDB::DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base) - : DelegatingCDB(Base.get()) { +DelegatingCDB::DelegatingCDB( + std::unique_ptr<GlobalCompilationDatabase> Base, + std::optional<std::string> FallbackWorkingDirectory) + : DelegatingCDB(Base.get(), FallbackWorkingDirectory) { BaseOwner = std::move(Base); } diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h b/clang-tools-extra/clangd/GlobalCompilationDatabase.h index 1d636d7..415c7f5 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h @@ -35,6 +35,9 @@ struct ProjectInfo { /// Provides compilation arguments used for parsing C and C++ files. class GlobalCompilationDatabase { public: + GlobalCompilationDatabase( + std::optional<std::string> FallbackWorkingDirectory = std::nullopt) + : FallbackWorkingDirectory(FallbackWorkingDirectory) {} virtual ~GlobalCompilationDatabase() = default; /// If there are any known-good commands for building this file, returns one. @@ -69,14 +72,19 @@ public: } protected: + std::optional<std::string> FallbackWorkingDirectory; mutable CommandChanged OnCommandChanged; }; // Helper class for implementing GlobalCompilationDatabases that wrap others. class DelegatingCDB : public GlobalCompilationDatabase { public: - DelegatingCDB(const GlobalCompilationDatabase *Base); - DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base); + DelegatingCDB( + const GlobalCompilationDatabase *Base, + std::optional<std::string> FallbackWorkingDirectory = std::nullopt); + DelegatingCDB( + std::unique_ptr<GlobalCompilationDatabase> Base, + std::optional<std::string> FallbackWorkingDirectory = std::nullopt); std::optional<tooling::CompileCommand> getCompileCommand(PathRef File) const override; @@ -117,6 +125,12 @@ public: // Only look for a compilation database in this one fixed directory. // FIXME: fold this into config/context mechanism. std::optional<Path> CompileCommandsDir; + // Working directory for fallback commands + // If unset, parent directory of file should be used + std::optional<std::string> FallbackWorkingDirectory; + + void applyFallbackWorkingDirectory( + std::optional<std::string> FallbackWorkingDirectory); }; DirectoryBasedGlobalCompilationDatabase(const Options &Opts); @@ -194,9 +208,11 @@ public: // Base may be null, in which case no entries are inherited. // FallbackFlags are added to the fallback compile command. // Adjuster is applied to all commands, fallback or not. - OverlayCDB(const GlobalCompilationDatabase *Base, - std::vector<std::string> FallbackFlags = {}, - CommandMangler Mangler = nullptr); + OverlayCDB( + const GlobalCompilationDatabase *Base, + std::vector<std::string> FallbackFlags = {}, + CommandMangler Mangler = nullptr, + std::optional<std::string> FallbackWorkingDirectory = std::nullopt); std::optional<tooling::CompileCommand> getCompileCommand(PathRef File) const override; diff --git a/clang-tools-extra/clangd/ScanningProjectModules.cpp b/clang-tools-extra/clangd/ScanningProjectModules.cpp index 672e996..e1b6cbe1 100644 --- a/clang-tools-extra/clangd/ScanningProjectModules.cpp +++ b/clang-tools-extra/clangd/ScanningProjectModules.cpp @@ -8,8 +8,8 @@ #include "ProjectModules.h" #include "support/Logger.h" -#include "clang/Tooling/DependencyScanning/DependencyScanningService.h" -#include "clang/Tooling/DependencyScanning/DependencyScanningTool.h" +#include "clang/DependencyScanning/DependencyScanningService.h" +#include "clang/Tooling/DependencyScanningTool.h" namespace clang::clangd { namespace { @@ -36,8 +36,8 @@ public: std::shared_ptr<const clang::tooling::CompilationDatabase> CDB, const ThreadsafeFS &TFS) : CDB(CDB), TFS(TFS), - Service(tooling::dependencies::ScanningMode::CanonicalPreprocessing, - tooling::dependencies::ScanningOutputFormat::P1689) {} + Service(dependencies::ScanningMode::CanonicalPreprocessing, + dependencies::ScanningOutputFormat::P1689) {} /// The scanned modules dependency information for a specific source file. struct ModuleDependencyInfo { @@ -81,7 +81,7 @@ private: // Whether the scanner has scanned the project globally. bool GlobalScanned = false; - clang::tooling::dependencies::DependencyScanningService Service; + clang::dependencies::DependencyScanningService Service; // TODO: Add a scanning cache. @@ -104,7 +104,7 @@ ModuleDependencyScanner::scan(PathRef FilePath, if (Mangler) Mangler(Cmd, FilePath); - using namespace clang::tooling::dependencies; + using namespace clang::tooling; llvm::SmallString<128> FilePathDir(FilePath); llvm::sys::path::remove_filename(FilePathDir); diff --git a/clang-tools-extra/clangd/SemanticSelection.cpp b/clang-tools-extra/clangd/SemanticSelection.cpp index 3353121..71ebf00 100644 --- a/clang-tools-extra/clangd/SemanticSelection.cpp +++ b/clang-tools-extra/clangd/SemanticSelection.cpp @@ -11,9 +11,13 @@ #include "Protocol.h" #include "Selection.h" #include "SourceCode.h" +#include "support/Bracket.h" +#include "support/DirectiveTree.h" +#include "support/Token.h" #include "clang/AST/DeclBase.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Tooling/Syntax/BuildTree.h" #include "clang/Tooling/Syntax/Nodes.h" #include "clang/Tooling/Syntax/TokenBufferTokenManager.h" @@ -22,9 +26,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" -#include "support/Bracket.h" -#include "support/DirectiveTree.h" -#include "support/Token.h" #include <optional> #include <queue> #include <vector> @@ -41,72 +42,6 @@ void addIfDistinct(const Range &R, std::vector<Range> &Result) { } } -std::optional<FoldingRange> toFoldingRange(SourceRange SR, - const SourceManager &SM) { - const auto Begin = SM.getDecomposedLoc(SR.getBegin()), - End = SM.getDecomposedLoc(SR.getEnd()); - // Do not produce folding ranges if either range ends is not within the main - // file. Macros have their own FileID so this also checks if locations are not - // within the macros. - if ((Begin.first != SM.getMainFileID()) || (End.first != SM.getMainFileID())) - return std::nullopt; - FoldingRange Range; - Range.startCharacter = SM.getColumnNumber(Begin.first, Begin.second) - 1; - Range.startLine = SM.getLineNumber(Begin.first, Begin.second) - 1; - Range.endCharacter = SM.getColumnNumber(End.first, End.second) - 1; - Range.endLine = SM.getLineNumber(End.first, End.second) - 1; - return Range; -} - -std::optional<FoldingRange> -extractFoldingRange(const syntax::Node *Node, - const syntax::TokenBufferTokenManager &TM) { - if (const auto *Stmt = dyn_cast<syntax::CompoundStatement>(Node)) { - const auto *LBrace = cast_or_null<syntax::Leaf>( - Stmt->findChild(syntax::NodeRole::OpenParen)); - // FIXME(kirillbobyrev): This should find the last child. Compound - // statements have only one pair of braces so this is valid but for other - // node kinds it might not be correct. - const auto *RBrace = cast_or_null<syntax::Leaf>( - Stmt->findChild(syntax::NodeRole::CloseParen)); - if (!LBrace || !RBrace) - return std::nullopt; - // Fold the entire range within braces, including whitespace. - const SourceLocation LBraceLocInfo = - TM.getToken(LBrace->getTokenKey())->endLocation(), - RBraceLocInfo = - TM.getToken(RBrace->getTokenKey())->location(); - auto Range = toFoldingRange(SourceRange(LBraceLocInfo, RBraceLocInfo), - TM.sourceManager()); - // Do not generate folding range for compound statements without any - // nodes and newlines. - if (Range && Range->startLine != Range->endLine) - return Range; - } - return std::nullopt; -} - -// Traverse the tree and collect folding ranges along the way. -std::vector<FoldingRange> -collectFoldingRanges(const syntax::Node *Root, - const syntax::TokenBufferTokenManager &TM) { - std::queue<const syntax::Node *> Nodes; - Nodes.push(Root); - std::vector<FoldingRange> Result; - while (!Nodes.empty()) { - const syntax::Node *Node = Nodes.front(); - Nodes.pop(); - const auto Range = extractFoldingRange(Node, TM); - if (Range) - Result.push_back(*Range); - if (const auto *T = dyn_cast<syntax::Tree>(Node)) - for (const auto *NextNode = T->getFirstChild(); NextNode; - NextNode = NextNode->getNextSibling()) - Nodes.push(NextNode); - } - return Result; -} - } // namespace llvm::Expected<SelectionRange> getSemanticRanges(ParsedAST &AST, Position Pos) { @@ -163,17 +98,71 @@ llvm::Expected<SelectionRange> getSemanticRanges(ParsedAST &AST, Position Pos) { return std::move(Head); } -// FIXME(kirillbobyrev): Collect comments, PP conditional regions, includes and -// other code regions (e.g. public/private/protected sections of classes, -// control flow statement bodies). -// Related issue: https://github.com/clangd/clangd/issues/310 -llvm::Expected<std::vector<FoldingRange>> getFoldingRanges(ParsedAST &AST) { - syntax::Arena A; - syntax::TokenBufferTokenManager TM(AST.getTokens(), AST.getLangOpts(), - AST.getSourceManager()); - const auto *SyntaxTree = syntax::buildSyntaxTree(A, TM, AST.getASTContext()); - return collectFoldingRanges(SyntaxTree, TM); -} +class PragmaRegionFinder { + // Record the token range of a region: + // + // #pragma region name[[ + // ... + // ]]#pragma endregion + std::vector<Token::Range> &Ranges; + const TokenStream &Code; + // Stack of starting token (the name of the region) indices for nested #pragma + // region. + std::vector<unsigned> Stack; + +public: + PragmaRegionFinder(std::vector<Token::Range> &Ranges, const TokenStream &Code) + : Ranges(Ranges), Code(Code) {} + + void walk(const DirectiveTree &T) { + for (const auto &C : T.Chunks) + std::visit(*this, C); + } + + void operator()(const DirectiveTree::Code &C) {} + + void operator()(const DirectiveTree::Directive &D) { + // Get the tokens that make up this directive. + auto Tokens = Code.tokens(D.Tokens); + if (Tokens.empty()) + return; + const Token &HashToken = Tokens.front(); + assert(HashToken.Kind == tok::hash); + const Token &Pragma = HashToken.nextNC(); + if (Pragma.text() != "pragma") + return; + const Token &Value = Pragma.nextNC(); + + // Handle "#pragma region name" + if (Value.text() == "region") { + // Find the last token at the same line. + const Token *T = &Value.next(); + while (T < Tokens.end() && T->Line == Pragma.Line) + T = &T->next(); + --T; + Stack.push_back(T->OriginalIndex); + return; + } + + // Handle "#pragma endregion" + if (Value.text() == "endregion") { + if (Stack.empty()) + return; // unmatched end region; ignore. + + unsigned StartIdx = Stack.back(); + Stack.pop_back(); + Ranges.push_back(Token::Range{StartIdx, HashToken.OriginalIndex}); + } + } + + void operator()(const DirectiveTree::Conditional &C) { + // C.Branches needs to see the DirectiveTree definition, otherwise build + // fails in C++20. + [[maybe_unused]] DirectiveTree Dummy; + for (const auto &[_, SubTree] : C.Branches) + walk(SubTree); + } +}; // FIXME( usaxena95): Collect includes and other code regions (e.g. // public/private/protected sections of classes, control flow statement bodies). @@ -286,6 +275,17 @@ getFoldingRanges(const std::string &Code, bool LineFoldingOnly) { } AddFoldingRange(Start, End, FoldingRange::COMMENT_KIND); } + + // #pragma region + std::vector<Token::Range> Ranges; + PragmaRegionFinder(Ranges, OrigStream).walk(DirectiveStructure); + auto Ts = OrigStream.tokens(); + for (const auto &R : Ranges) { + auto End = StartPosition(Ts[R.End]); + if (LineFoldingOnly) + End.line--; + AddFoldingRange(EndPosition(Ts[R.Begin]), End, FoldingRange::REGION_KIND); + } return Result; } diff --git a/clang-tools-extra/clangd/SemanticSelection.h b/clang-tools-extra/clangd/SemanticSelection.h index dd9d3ea..4e19397 100644 --- a/clang-tools-extra/clangd/SemanticSelection.h +++ b/clang-tools-extra/clangd/SemanticSelection.h @@ -27,10 +27,6 @@ namespace clangd { llvm::Expected<SelectionRange> getSemanticRanges(ParsedAST &AST, Position Pos); /// Returns a list of ranges whose contents might be collapsible in an editor. -/// This should include large scopes, preprocessor blocks etc. -llvm::Expected<std::vector<FoldingRange>> getFoldingRanges(ParsedAST &AST); - -/// Returns a list of ranges whose contents might be collapsible in an editor. /// This version uses the pseudoparser which does not require the AST. llvm::Expected<std::vector<FoldingRange>> getFoldingRanges(const std::string &Code, bool LineFoldingOnly); diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp index 1e1f7c6..21c078f 100644 --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -1217,6 +1217,26 @@ EligibleRegion getEligiblePoints(llvm::StringRef Code, return ER; } +std::string getNamespaceAtPosition(StringRef Code, const Position &Pos, + const LangOptions &LangOpts) { + std::vector<std::string> Enclosing = {""}; + parseNamespaceEvents(Code, LangOpts, [&](NamespaceEvent Event) { + if (Pos < Event.Pos) + return; + if (Event.Trigger == NamespaceEvent::UsingDirective) + return; + if (!Event.Payload.empty()) + Event.Payload.append("::"); + if (Event.Trigger == NamespaceEvent::BeginNamespace) { + Enclosing.emplace_back(std::move(Event.Payload)); + } else { + Enclosing.pop_back(); + assert(Enclosing.back() == Event.Payload); + } + }); + return Enclosing.back(); +} + bool isHeaderFile(llvm::StringRef FileName, std::optional<LangOptions> LangOpts) { // Respect the langOpts, for non-file-extension cases, e.g. standard library diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h index 028549f..274099f 100644 --- a/clang-tools-extra/clangd/SourceCode.h +++ b/clang-tools-extra/clangd/SourceCode.h @@ -309,6 +309,11 @@ EligibleRegion getEligiblePoints(llvm::StringRef Code, llvm::StringRef FullyQualifiedName, const LangOptions &LangOpts); +/// Returns the fully qualified name of the namespace at \p Pos in the \p Code. +/// Employs pseudo-parsing to determine the start and end of namespaces. +std::string getNamespaceAtPosition(llvm::StringRef Code, const Position &Pos, + const LangOptions &LangOpts); + struct DefinedMacro { llvm::StringRef Name; const MacroInfo *Info; diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp index e4eef22..45e7ade 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "AST.h" +#include "FindSymbols.h" #include "FindTarget.h" #include "HeaderSourceSwitch.h" #include "ParsedAST.h" @@ -34,6 +35,7 @@ #include <cstddef> #include <optional> #include <string> +#include <tuple> namespace clang { namespace clangd { @@ -362,6 +364,12 @@ struct InsertionPoint { size_t Offset; }; +enum class RelativeInsertPos { Before, After }; +struct InsertionAnchor { + Location Loc; + RelativeInsertPos RelInsertPos = RelativeInsertPos::Before; +}; + // Returns the range that should be deleted from declaration, which always // contains function body. In addition to that it might contain constructor // initializers. @@ -489,8 +497,14 @@ public: Expected<Effect> apply(const Selection &Sel) override { const SourceManager &SM = Sel.AST->getSourceManager(); - auto CCFile = SameFile ? Sel.AST->tuPath().str() - : getSourceFile(Sel.AST->tuPath(), Sel); + std::optional<Path> CCFile; + auto Anchor = getDefinitionOfAdjacentDecl(Sel); + if (Anchor) { + CCFile = Anchor->Loc.uri.file(); + } else { + CCFile = SameFile ? Sel.AST->tuPath().str() + : getSourceFile(Sel.AST->tuPath(), Sel); + } if (!CCFile) return error("Couldn't find a suitable implementation file."); assert(Sel.FS && "FS Must be set in apply"); @@ -499,21 +513,62 @@ public: // doesn't exist? if (!Buffer) return llvm::errorCodeToError(Buffer.getError()); + auto Contents = Buffer->get()->getBuffer(); - auto InsertionPoint = getInsertionPoint(Contents, Sel); - if (!InsertionPoint) - return InsertionPoint.takeError(); + SourceManagerForFile SMFF(*CCFile, Contents); + + std::optional<Position> InsertionPos; + if (Anchor) { + if (auto P = getInsertionPointFromExistingDefinition( + SMFF, **Buffer, Anchor->Loc, Anchor->RelInsertPos, Sel.AST)) { + InsertionPos = *P; + } + } + + std::optional<std::size_t> Offset; + const DeclContext *EnclosingNamespace = nullptr; + std::string EnclosingNamespaceName; + + if (InsertionPos) { + EnclosingNamespaceName = getNamespaceAtPosition(Contents, *InsertionPos, + Sel.AST->getLangOpts()); + } else if (SameFile) { + auto P = getInsertionPointInMainFile(Sel.AST); + if (!P) + return P.takeError(); + Offset = P->Offset; + EnclosingNamespace = P->EnclosingNamespace; + } else { + auto Region = getEligiblePoints( + Contents, Source->getQualifiedNameAsString(), Sel.AST->getLangOpts()); + assert(!Region.EligiblePoints.empty()); + EnclosingNamespaceName = Region.EnclosingNamespace; + InsertionPos = Region.EligiblePoints.back(); + } + + if (InsertionPos) { + auto O = positionToOffset(Contents, *InsertionPos); + if (!O) + return O.takeError(); + Offset = *O; + auto TargetContext = + findContextForNS(EnclosingNamespaceName, Source->getDeclContext()); + if (!TargetContext) + return error("define outline: couldn't find a context for target"); + EnclosingNamespace = *TargetContext; + } + + assert(Offset); + assert(EnclosingNamespace); auto FuncDef = getFunctionSourceCode( - Source, InsertionPoint->EnclosingNamespace, Sel.AST->getTokens(), + Source, EnclosingNamespace, Sel.AST->getTokens(), Sel.AST->getHeuristicResolver(), SameFile && isHeaderFile(Sel.AST->tuPath(), Sel.AST->getLangOpts())); if (!FuncDef) return FuncDef.takeError(); - SourceManagerForFile SMFF(*CCFile, Contents); - const tooling::Replacement InsertFunctionDef( - *CCFile, InsertionPoint->Offset, 0, *FuncDef); + const tooling::Replacement InsertFunctionDef(*CCFile, *Offset, 0, *FuncDef); auto Effect = Effect::mainFileEdit( SMFF.get(), tooling::Replacements(InsertFunctionDef)); if (!Effect) @@ -548,59 +603,188 @@ public: return std::move(*Effect); } - // Returns the most natural insertion point for \p QualifiedName in \p - // Contents. This currently cares about only the namespace proximity, but in - // feature it should also try to follow ordering of declarations. For example, - // if decls come in order `foo, bar, baz` then this function should return - // some point between foo and baz for inserting bar. - // FIXME: The selection can be made smarter by looking at the definition - // locations for adjacent decls to Source. Unfortunately pseudo parsing in - // getEligibleRegions only knows about namespace begin/end events so we - // can't match function start/end positions yet. - llvm::Expected<InsertionPoint> getInsertionPoint(llvm::StringRef Contents, - const Selection &Sel) { - // If the definition goes to the same file and there is a namespace, - // we should (and, in the case of anonymous namespaces, need to) - // put the definition into the original namespace block. - if (SameFile) { - auto *Klass = Source->getDeclContext()->getOuterLexicalRecordContext(); - if (!Klass) - return error("moving to same file not supported for free functions"); - const SourceLocation EndLoc = Klass->getBraceRange().getEnd(); - const auto &TokBuf = Sel.AST->getTokens(); - auto Tokens = TokBuf.expandedTokens(); - auto It = llvm::lower_bound( - Tokens, EndLoc, [](const syntax::Token &Tok, SourceLocation EndLoc) { - return Tok.location() < EndLoc; - }); - while (It != Tokens.end()) { - if (It->kind() != tok::semi) { - ++It; - continue; + std::optional<InsertionAnchor> + getDefinitionOfAdjacentDecl(const Selection &Sel) { + if (!Sel.Index) + return {}; + std::optional<Location> Anchor; + std::string TuURI = URI::createFile(Sel.AST->tuPath()).toString(); + auto CheckCandidate = [&](Decl *Candidate) { + assert(Candidate != Source); + if (auto Func = llvm::dyn_cast_or_null<FunctionDecl>(Candidate); + !Func || Func->isThisDeclarationADefinition()) { + return; + } + std::optional<Location> CandidateLoc; + Sel.Index->lookup({{getSymbolID(Candidate)}}, [&](const Symbol &S) { + if (S.Definition) { + if (auto Loc = indexToLSPLocation(S.Definition, Sel.AST->tuPath())) + CandidateLoc = *Loc; + else + log("getDefinitionOfAdjacentDecl: {0}", Loc.takeError()); } - unsigned Offset = Sel.AST->getSourceManager() - .getDecomposedLoc(It->endLocation()) - .second; - return InsertionPoint{Klass->getEnclosingNamespaceContext(), Offset}; + }); + if (!CandidateLoc) + return; + + // If our definition is constrained to the same file, ignore + // definitions that are not located there. + // If our definition is not constrained to the same file, but + // our anchor definition is in the same file, then we also put our + // definition there, because that appears to be the user preference. + // Exception: If the existing definition is a template, then the + // location is likely due to technical necessity rather than preference, + // so ignore that definition. + bool CandidateSameFile = TuURI == CandidateLoc->uri.uri(); + if (SameFile && !CandidateSameFile) + return; + if (!SameFile && CandidateSameFile) { + if (Candidate->isTemplateDecl()) + return; + SameFile = true; } - return error( - "failed to determine insertion location: no end of class found"); + Anchor = *CandidateLoc; + }; + + // Try to find adjacent function declarations. + // Determine the closest one by alternatingly going "up" and "down" + // from our function in increasing steps. + const DeclContext *ParentContext = Source->getParent(); + const auto SourceIt = llvm::find_if( + ParentContext->decls(), [this](const Decl *D) { return D == Source; }); + if (SourceIt == ParentContext->decls_end()) + return {}; + const int Preceding = std::distance(ParentContext->decls_begin(), SourceIt); + const int Following = + std::distance(SourceIt, ParentContext->decls_end()) - 1; + for (int Offset = 1; Offset <= Preceding || Offset <= Following; ++Offset) { + if (Offset <= Preceding) + CheckCandidate( + *std::next(ParentContext->decls_begin(), Preceding - Offset)); + if (Anchor) + return InsertionAnchor{*Anchor, RelativeInsertPos::After}; + if (Offset <= Following) + CheckCandidate(*std::next(SourceIt, Offset)); + if (Anchor) + return InsertionAnchor{*Anchor, RelativeInsertPos::Before}; } + return {}; + } - auto Region = getEligiblePoints( - Contents, Source->getQualifiedNameAsString(), Sel.AST->getLangOpts()); + // We don't know the actual start or end of the definition, only the position + // of the name. Therefore, we heuristically try to locate the last token + // before or in this function, respectively. Adapt as required by user code. + std::optional<Position> getInsertionPointFromExistingDefinition( + SourceManagerForFile &SMFF, const llvm::MemoryBuffer &Buffer, + const Location &Loc, RelativeInsertPos RelInsertPos, ParsedAST *AST) { + auto StartOffset = positionToOffset(Buffer.getBuffer(), Loc.range.start); + if (!StartOffset) + return {}; + SourceLocation InsertionLoc; + SourceManager &SM = SMFF.get(); + + auto InsertBefore = [&] { + // Go backwards until we encounter one of the following: + // - An opening brace (of a namespace). + // - A closing brace (of a function definition). + // - A semicolon (of a declaration). + // If no such token was found, then the first token in the file starts the + // definition. + auto Tokens = syntax::tokenize( + syntax::FileRange(SM.getMainFileID(), 0, *StartOffset), SM, + AST->getLangOpts()); + if (Tokens.empty()) + return; + for (auto I = std::rbegin(Tokens); + InsertionLoc.isInvalid() && I != std::rend(Tokens); ++I) { + switch (I->kind()) { + case tok::l_brace: + case tok::r_brace: + case tok::semi: + if (I != std::rbegin(Tokens)) + InsertionLoc = std::prev(I)->location(); + else + InsertionLoc = I->endLocation(); + break; + default: + break; + } + } + if (InsertionLoc.isInvalid()) + InsertionLoc = Tokens.front().location(); + }; - assert(!Region.EligiblePoints.empty()); - auto Offset = positionToOffset(Contents, Region.EligiblePoints.back()); - if (!Offset) - return Offset.takeError(); + if (RelInsertPos == RelativeInsertPos::Before) { + InsertBefore(); + } else { + // Skip over one top-level pair of parentheses (for the parameter list) + // and one pair of curly braces (for the code block). + // If that fails, insert before the function instead. + auto Tokens = + syntax::tokenize(syntax::FileRange(SM.getMainFileID(), *StartOffset, + Buffer.getBuffer().size()), + SM, AST->getLangOpts()); + bool SkippedParams = false; + int OpenParens = 0; + int OpenBraces = 0; + std::optional<syntax::Token> Tok; + for (const auto &T : Tokens) { + tok::TokenKind StartKind = SkippedParams ? tok::l_brace : tok::l_paren; + tok::TokenKind EndKind = SkippedParams ? tok::r_brace : tok::r_paren; + int &Count = SkippedParams ? OpenBraces : OpenParens; + if (T.kind() == StartKind) { + ++Count; + } else if (T.kind() == EndKind) { + if (--Count == 0) { + if (SkippedParams) { + Tok = T; + break; + } + SkippedParams = true; + } else if (Count < 0) { + break; + } + } + } + if (Tok) + InsertionLoc = Tok->endLocation(); + else + InsertBefore(); + } - auto TargetContext = - findContextForNS(Region.EnclosingNamespace, Source->getDeclContext()); - if (!TargetContext) - return error("define outline: couldn't find a context for target"); + if (!InsertionLoc.isValid()) + return {}; + return sourceLocToPosition(SM, InsertionLoc); + } - return InsertionPoint{*TargetContext, *Offset}; + // Returns the most natural insertion point in this file. + // This is a fallback for when we failed to find an existing definition to + // place the new one next to. It only considers namespace proximity. + llvm::Expected<InsertionPoint> getInsertionPointInMainFile(ParsedAST *AST) { + // If the definition goes to the same file and there is a namespace, + // we should (and, in the case of anonymous namespaces, need to) + // put the definition into the original namespace block. + auto *Klass = Source->getDeclContext()->getOuterLexicalRecordContext(); + if (!Klass) + return error("moving to same file not supported for free functions"); + const SourceLocation EndLoc = Klass->getBraceRange().getEnd(); + const auto &TokBuf = AST->getTokens(); + auto Tokens = TokBuf.expandedTokens(); + auto It = llvm::lower_bound( + Tokens, EndLoc, [](const syntax::Token &Tok, SourceLocation EndLoc) { + return Tok.location() < EndLoc; + }); + while (It != Tokens.end()) { + if (It->kind() != tok::semi) { + ++It; + continue; + } + unsigned Offset = + AST->getSourceManager().getDecomposedLoc(It->endLocation()).second; + return InsertionPoint{Klass->getEnclosingNamespaceContext(), Offset}; + } + return error( + "failed to determine insertion location: no end of class found"); } private: diff --git a/clang-tools-extra/clangd/test/CMakeLists.txt b/clang-tools-extra/clangd/test/CMakeLists.txt index 42fc350..eef8f52 100644 --- a/clang-tools-extra/clangd/test/CMakeLists.txt +++ b/clang-tools-extra/clangd/test/CMakeLists.txt @@ -5,6 +5,10 @@ set(CLANGD_TEST_DEPS split-file ) +if (LLVM_INCLUDE_BENCHMARKS) + list(APPEND CLANGD_TEST_DEPS IndexBenchmark) +endif() + if(CLANGD_BUILD_XPC) list(APPEND CLANGD_TEST_DEPS clangd-xpc-test-client) list(APPEND CLANGD_TEST_DEPS ClangdXpcUnitTests) diff --git a/clang-tools-extra/clangd/test/include-cleaner-batch-fix.test b/clang-tools-extra/clangd/test/include-cleaner-batch-fix.test index 07ebe10..5a87a87 100644 --- a/clang-tools-extra/clangd/test/include-cleaner-batch-fix.test +++ b/clang-tools-extra/clangd/test/include-cleaner-batch-fix.test @@ -7,7 +7,9 @@ # RUN: cp -r %S/Inputs/include-cleaner %t/include # RUN: echo '-I%t/include' > %t/compile_flags.txt # Create a config file enabling include-cleaner features. -# RUN: echo $'Diagnostics:\n UnusedIncludes: Strict\n MissingIncludes: Strict' >> %t/clangd/config.yaml +# RUN: echo 'Diagnostics:' > %t/clangd/config.yaml +# RUN: echo ' UnusedIncludes: Strict' >> %t/clangd/config.yaml +# RUN: echo ' MissingIncludes: Strict' >> %t/clangd/config.yaml # RUN: env XDG_CONFIG_HOME=%t clangd -lit-test -enable-config --compile-commands-dir=%t < %s | FileCheck -strict-whitespace %s {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"workspace":{"workspaceEdit":{"documentChanges":true, "changeAnnotationSupport":{"groupsOnLabel":true}}}},"trace":"off"}} diff --git a/clang-tools-extra/clangd/test/index-tools.test b/clang-tools-extra/clangd/test/index-tools.test index 93cf56f..cc01e19 100644 --- a/clang-tools-extra/clangd/test/index-tools.test +++ b/clang-tools-extra/clangd/test/index-tools.test @@ -1,6 +1,7 @@ +# Paths are not constructed correctly for the test to run on Windows. +# UNSUPPORTED: system-windows +# REQUIRES: have-benchmarks # RUN: clangd-indexer %p/Inputs/BenchmarkSource.cpp -- -I%p/Inputs > %t.index -# FIXME: By default, benchmarks are excluded from the list of default targets hence not built. Find a way to depend on benchmarks to run the next command. -# REQUIRES: shell -# RUN: if [ -f %clangd-benchmark-dir/IndexBenchmark ]; then %clangd-benchmark-dir/IndexBenchmark %t.index %p/Inputs/requests.json --benchmark_min_time=0.01 ; fi +# RUN: %clangd-benchmark-dir/IndexBenchmark %t.index %p/Inputs/requests.json --benchmark_min_time=0.01 # Pass invalid JSON file and check that IndexBenchmark fails to parse it. -# RUN: if [ -f %clangd-benchmark-dir/IndexBenchmark ]; then not %clangd-benchmark-dir/IndexBenchmark %t.index %t --benchmark_min_time=0.01 ; fi +# RUN: not %clangd-benchmark-dir/IndexBenchmark %t.index %t --benchmark_min_time=0.01 diff --git a/clang-tools-extra/clangd/test/lit.cfg.py b/clang-tools-extra/clangd/test/lit.cfg.py index 8ab4309..bd721c4 100644 --- a/clang-tools-extra/clangd/test/lit.cfg.py +++ b/clang-tools-extra/clangd/test/lit.cfg.py @@ -1,13 +1,27 @@ +import os + import lit.llvm +import lit.util lit.llvm.initialize(lit_config, config) lit.llvm.llvm_config.clang_setup() lit.llvm.llvm_config.use_default_substitutions() +# TODO: Consolidate the logic for turning on the internal shell by default for all LLVM test suites. +# See https://github.com/llvm/llvm-project/issues/106636 for more details. +# +# We prefer the lit internal shell which provides a better user experience on failures +# and is faster unless the user explicitly disables it with LIT_USE_INTERNAL_SHELL=0 +# env var. +use_lit_shell = True +lit_shell_env = os.environ.get("LIT_USE_INTERNAL_SHELL") +if lit_shell_env: + use_lit_shell = lit.util.pythonize_bool(lit_shell_env) + config.name = "Clangd" config.suffixes = [".test"] config.excludes = ["Inputs"] -config.test_format = lit.formats.ShTest(not lit.llvm.llvm_config.use_lit_shell) +config.test_format = lit.formats.ShTest(not use_lit_shell) config.test_source_root = config.clangd_source_dir + "/test" config.test_exec_root = config.clangd_binary_dir + "/test" @@ -37,6 +51,9 @@ if config.clangd_tidy_checks: if config.have_zlib: config.available_features.add("zlib") +if lit.util.pythonize_bool(config.have_benchmarks): + config.available_features.add("have-benchmarks") + # It is not realistically possible to account for all options that could # possibly be present in system and user configuration files, so disable # default configs for the test runs. diff --git a/clang-tools-extra/clangd/test/lit.site.cfg.py.in b/clang-tools-extra/clangd/test/lit.site.cfg.py.in index a0bb356..f5ae3eb 100644 --- a/clang-tools-extra/clangd/test/lit.site.cfg.py.in +++ b/clang-tools-extra/clangd/test/lit.site.cfg.py.in @@ -19,6 +19,7 @@ config.clangd_build_dexp = @CLANGD_BUILD_DEXP@ config.clangd_enable_remote = @CLANGD_ENABLE_REMOTE@ config.clangd_tidy_checks = @CLANGD_TIDY_CHECKS@ config.have_zlib = @LLVM_ENABLE_ZLIB@ +config.have_benchmarks = "@LLVM_INCLUDE_BENCHMARKS@" # Delegate logic to lit.cfg.py. lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg.py") diff --git a/clang-tools-extra/clangd/test/system-include-extractor.test b/clang-tools-extra/clangd/test/system-include-extractor.test index 83a8c28bf..861d2e1 100644 --- a/clang-tools-extra/clangd/test/system-include-extractor.test +++ b/clang-tools-extra/clangd/test/system-include-extractor.test @@ -5,7 +5,8 @@ # Create a bin directory to store the mock-driver and add it to the path # RUN: mkdir -p %t.dir/bin -# RUN: export PATH=%t.dir/bin:$PATH +# RUN: %python -c "print(__import__('os').environ['PATH'])" | tr -d '\n' > %t.path +# RUN: export PATH=%t.dir/bin:%{readfile:%t.path} # Generate a mock-driver that will print %temp_dir%/my/dir and # %temp_dir%/my/dir2 as include search paths. # RUN: echo '#!/bin/sh' >> %t.dir/bin/my_driver.sh diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp index df8d075..9c6de40 100644 --- a/clang-tools-extra/clangd/tool/Check.cpp +++ b/clang-tools-extra/clangd/tool/Check.cpp @@ -169,6 +169,8 @@ public: bool buildCommand(const ThreadsafeFS &TFS) { log("Loading compilation database..."); DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS); + if (Opts.StrongWorkspaceMode) + CDBOpts.applyFallbackWorkingDirectory(Opts.WorkspaceRoot); CDBOpts.CompileCommandsDir = Config::current().CompileFlags.CDBSearch.FixedCDBPath; BaseCDB = @@ -178,8 +180,10 @@ public: getSystemIncludeExtractor(llvm::ArrayRef(Opts.QueryDriverGlobs)); if (Opts.ResourceDir) Mangler.ResourceDir = *Opts.ResourceDir; + CDB = std::make_unique<OverlayCDB>( - BaseCDB.get(), std::vector<std::string>{}, std::move(Mangler)); + BaseCDB.get(), std::vector<std::string>{}, std::move(Mangler), + CDBOpts.FallbackWorkingDirectory); if (auto TrueCmd = CDB->getCompileCommand(File)) { Cmd = std::move(*TrueCmd); @@ -502,7 +506,7 @@ bool check(llvm::StringRef File, const ThreadsafeFS &TFS, config::DiagnosticCallback Diag) const override { config::Fragment F; // If we're timing clang-tidy checks, implicitly disabling the slow ones - // is counterproductive! + // is counterproductive! if (CheckTidyTime.getNumOccurrences()) F.Diagnostics.ClangTidy.FastCheckFilter.emplace("None"); return {std::move(F).compile(Diag)}; diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index 4a990f8..54af366 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -500,6 +500,17 @@ opt<bool> EnableConfig{ init(true), }; +opt<bool> StrongWorkspaceMode{ + "strong-workspace-mode", + cat(Features), + desc("An alternate mode of operation for clangd, where the clangd instance " + "is used to edit a single workspace.\n" + "When enabled, fallback commands use the workspace directory as their " + "working directory instead of the parent folder."), + init(false), + Hidden, +}; + opt<bool> UseDirtyHeaders{"use-dirty-headers", cat(Misc), desc("Use files open in the editor when parsing " "headers instead of reading from the disk"), @@ -907,6 +918,7 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var } if (!ResourceDir.empty()) Opts.ResourceDir = ResourceDir; + Opts.StrongWorkspaceMode = StrongWorkspaceMode; Opts.BuildDynamicSymbolIndex = true; #if CLANGD_ENABLE_REMOTE if (RemoteIndexAddress.empty() != ProjectRoot.empty()) { diff --git a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp index c9e01e5..39ab144 100644 --- a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp +++ b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp @@ -55,6 +55,20 @@ TEST(GlobalCompilationDatabaseTest, FallbackCommand) { testPath("foo/bar"))); } +TEST(GlobalCompilationDatabaseTest, FallbackWorkingDirectory) { + MockFS TFS; + DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS); + CDBOpts.applyFallbackWorkingDirectory(testPath("foo")); + EXPECT_EQ(CDBOpts.FallbackWorkingDirectory, testPath("foo")); + + DirectoryBasedGlobalCompilationDatabase DB(CDBOpts); + auto Cmd = DB.getFallbackCommand(testPath("foo/src/bar.cc")); + EXPECT_EQ(Cmd.Directory, testPath("foo")); + EXPECT_THAT(Cmd.CommandLine, + ElementsAre("clang", testPath("foo/src/bar.cc"))); + EXPECT_EQ(Cmd.Output, ""); +} + static tooling::CompileCommand cmd(llvm::StringRef File, llvm::StringRef Arg) { return tooling::CompileCommand( testRoot(), File, {"clang", std::string(Arg), std::string(File)}, ""); diff --git a/clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp b/clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp index 4efae25..31bb794 100644 --- a/clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp @@ -196,76 +196,6 @@ TEST(SemanticSelection, RunViaClangdServer) { ElementsAre(SourceAnnotations.range("empty"))); } -TEST(FoldingRanges, ASTAll) { - const char *Tests[] = { - R"cpp( - #define FOO int foo() {\ - int Variable = 42; \ - return 0; \ - } - - // Do not generate folding range for braces within macro expansion. - FOO - - // Do not generate folding range within macro arguments. - #define FUNCTOR(functor) functor - void func() {[[ - FUNCTOR([](){}); - ]]} - - // Do not generate folding range with a brace coming from macro. - #define LBRACE { - void bar() LBRACE - int X = 42; - } - )cpp", - R"cpp( - void func() {[[ - int Variable = 100; - - if (Variable > 5) {[[ - Variable += 42; - ]]} else if (Variable++) - ++Variable; - else {[[ - Variable--; - ]]} - - // Do not generate FoldingRange for empty CompoundStmts. - for (;;) {} - - // If there are newlines between {}, we should generate one. - for (;;) {[[ - - ]]} - ]]} - )cpp", - R"cpp( - class Foo { - public: - Foo() {[[ - int X = 1; - ]]} - - private: - int getBar() {[[ - return 42; - ]]} - - // Braces are located at the same line: no folding range here. - void getFooBar() { } - }; - )cpp", - }; - for (const char *Test : Tests) { - auto T = Annotations(Test); - auto AST = TestTU::withCode(T.code()).build(); - EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(AST))), - UnorderedElementsAreArray(T.ranges())) - << Test; - } -} - TEST(FoldingRanges, PseudoParserWithoutLineFoldings) { const char *Tests[] = { R"cpp( @@ -410,6 +340,22 @@ TEST(FoldingRanges, PseudoParserWithoutLineFoldings) { Variable = 3; # )cpp", + R"cpp( + #pragma region R1[[ + + #pragma region R2[[ + constexpr int a = 2; + ]]#pragma endregion + + ]]#pragma endregion + )cpp", + R"cpp( + #pragma region[[ + ]]#pragma endregion + + #pragma /*comment1*/ region /*comment2*/name[[ + ]]#pragma endregion + )cpp", }; for (const char *Test : Tests) { auto T = Annotations(Test); @@ -470,6 +416,12 @@ TEST(FoldingRanges, PseudoParserLineFoldingsOnly) { //[[ foo /* bar */]] )cpp", + R"cpp( + #pragma region abc[[ + constexpr int a = 2; + ]] + #pragma endregion + )cpp", // FIXME: Support folding template arguments. // R"cpp( // template <[[typename foo, class bar]]> struct baz {}; diff --git a/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp index 02133ec..7689bf3 100644 --- a/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp +++ b/clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp @@ -448,7 +448,6 @@ inline T Foo<T>::bar(const T& t, const U& u) { return {}; } TEST_F(DefineOutlineTest, InCppFile) { FileName = "Test.cpp"; - struct { llvm::StringRef Test; llvm::StringRef ExpectedSource; @@ -773,8 +772,8 @@ class A { )cpp"; std::string SourceAfter = R"cpp( #include "a.hpp" -void A::bar(){} -void A::foo(){} +void A::bar(){}void A::foo(){} + )cpp"; Workspace.addSource("a.hpp", HeaderBefore.code()); Workspace.addMainFile("a.cpp", SourceBefore); @@ -786,6 +785,195 @@ void A::foo(){} FileWithContents(testPath("a.cpp"), SourceAfter))))); } +// Test that the definition is inserted in a sensible location +// under various circumstances. +// Note that the formatting looks a little off here and there, +// which is because in contrast to the actual tweak, the test procedure +// does not run clang-format on the resulting code. +TEST_F(DefineOutlineWorkspaceTest, SensibleInsertionLocations) { + const struct { + llvm::StringRef HeaderBefore; + llvm::StringRef SourceBefore; + llvm::StringRef HeaderAfter; + llvm::StringRef SourceAfter; + } Cases[] = { + // Criterion 1: Distance + { + R"cpp( +struct Foo { + void ignored1(); // Too far away + void ignored2(); // No definition + void ignored3() {} // Defined inline + void fo^o() {} + void neighbor(); +}; +)cpp", + R"cpp( +#include "a.hpp" +void Foo::ignored1() {} +void Foo::neighbor() {} +)cpp", + R"cpp( +struct Foo { + void ignored1(); // Too far away + void ignored2(); // No definition + void ignored3() {} // Defined inline + void foo() ; + void neighbor(); +}; +)cpp", + R"cpp( +#include "a.hpp" +void Foo::ignored1() {} +void Foo::foo() {} +void Foo::neighbor() {} +)cpp"}, + + // Criterion 2: Prefer preceding + { + R"cpp( +struct Foo { + void neighbor(); + void fo^o() {} + void ignored(); +}; +)cpp", + R"cpp( +#include "a.hpp" +void Foo::neighbor() {} +void Foo::ignored() {} +)cpp", + R"cpp( +struct Foo { + void neighbor(); + void foo() ; + void ignored(); +}; +)cpp", + R"cpp( +#include "a.hpp" +void Foo::neighbor() {}void Foo::foo() {} + +void Foo::ignored() {} +)cpp"}, + + // Like above, but with a namespace + { + R"cpp( +namespace NS { +struct Foo { + void neighbor(); + void fo^o() {} + void ignored(); +}; +} +)cpp", + R"cpp( +#include "a.hpp" +namespace NS { +void Foo::neighbor() {} +void Foo::ignored() {} +} +)cpp", + R"cpp( +namespace NS { +struct Foo { + void neighbor(); + void foo() ; + void ignored(); +}; +} +)cpp", + R"cpp( +#include "a.hpp" +namespace NS { +void Foo::neighbor() {}void Foo::foo() {} + +void Foo::ignored() {} +} +)cpp"}, + + // Like above, but there is no namespace at the definition site + { + R"cpp( +namespace NS { +struct Foo { + void neighbor(); + void fo^o() {} + void ignored(); +}; +} +)cpp", + R"cpp( +#include "a.hpp" +void NS::Foo::neighbor() {} +void NS::Foo::ignored() {} +)cpp", + R"cpp( +namespace NS { +struct Foo { + void neighbor(); + void foo() ; + void ignored(); +}; +} +)cpp", + R"cpp( +#include "a.hpp" +void NS::Foo::neighbor() {}void NS::Foo::foo() {} + +void NS::Foo::ignored() {} +)cpp"}, + + // Neighbor's definition is in header + { + R"cpp( +struct Foo { + void fo^o() {} + void neighbor(); + void ignored(); +}; +inline void Foo::neighbor() {} +)cpp", + R"cpp( +#include "a.hpp" +void Foo::ignored() {} +)cpp", + R"cpp( +struct Foo { + void foo() ; + void neighbor(); + void ignored(); +}; +inline void Foo::foo() {} +inline void Foo::neighbor() {} +)cpp", + {}}, + + }; + + for (const auto &Case : Cases) { + Workspace = {}; + llvm::Annotations Hdr(Case.HeaderBefore); + Workspace.addSource("a.hpp", Hdr.code()); + Workspace.addMainFile("a.cpp", Case.SourceBefore); + auto Result = apply("a.hpp", {Hdr.point(), Hdr.point()}); + if (Case.SourceAfter.empty()) { + EXPECT_THAT(Result, + AllOf(withStatus("success"), + editedFiles(UnorderedElementsAre(FileWithContents( + testPath("a.hpp"), Case.HeaderAfter))))); + + } else { + EXPECT_THAT( + Result, + AllOf(withStatus("success"), + editedFiles(UnorderedElementsAre( + FileWithContents(testPath("a.hpp"), Case.HeaderAfter), + FileWithContents(testPath("a.cpp"), Case.SourceAfter))))); + } + } +} } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 666865c..6d3da61 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -58,6 +58,10 @@ Potentially Breaking Changes :program:`clang-tidy-20`. Users should use the check-specific options of the same name instead. +- Removed `clang-analyzer-*` checks from default checks in :program:`clang-tidy`. + From now on, users should specify explicitly that they want CSA checks to run + in :program:`clang-tidy` via `clang-analyzer-*`. + - Renamed a few :program:`clang-tidy` check options, as they were misspelled: @@ -70,6 +74,13 @@ Potentially Breaking Changes :doc:`bugprone-signed-char-misuse <clang-tidy/checks/bugprone/signed-char-misuse>` +- Modified the custom message format of :doc:`bugprone-unsafe-functions + <clang-tidy/checks/bugprone/unsafe-functions>` by assigning a special meaning + to the character ``>`` at the start of the value of the option + ``CustomFunctions``. If the option value starts with ``>``, then the + replacement suggestion part of the message (which would be included by + default) is omitted. (This does not change the warning locations.) + - :program:`clang-tidy` now displays warnings from all non-system headers by default. Previously, users had to explicitly opt-in to header warnings using `-header-filter='.*'`. To disable warnings from non-system, set `-header-filter` @@ -177,6 +188,10 @@ Improvements to clang-tidy scripts by adding the `-hide-progress` option to suppress progress and informational messages. +- Removed `clang-analyzer-*` check from default checks in :program:`clang-tidy`. + From now on, users should specify explicitly that they want CSA checks to run + in :program:`clang-tidy`. + - Deprecated the :program:`clang-tidy` ``zircon`` module. All checks have been moved to the ``fuchsia`` module instead. The ``zircon`` module will be removed in the 24th release. @@ -269,6 +284,10 @@ New check aliases <clang-tidy/checks/bugprone/throwing-static-initialization>` keeping initial check as an alias to the new one. +- Renamed :doc:`cert-err60-cpp <clang-tidy/checks/cert/err60-cpp>` to + :doc:`bugprone-exception-copy-constructor-throws + <clang-tidy/checks/bugprone/exception-copy-constructor-throws>` + - Renamed :doc:`cert-flp30-c <clang-tidy/checks/cert/flp30-c>` to :doc:`bugprone-float-loop-counter <clang-tidy/checks/bugprone/float-loop-counter>` @@ -279,6 +298,26 @@ New check aliases <clang-tidy/checks/bugprone/default-operator-new-on-overaligned-type>` keeping initial check as an alias to the new one. +- Renamed :doc:`cert-msc30-c <clang-tidy/checks/cert/msc30-c>` to + :doc:`misc-predictable-rand + <clang-tidy/checks/misc/predictable-rand>` + keeping initial check as an alias to the new one. + +- Renamed :doc:`cert-msc32-c <clang-tidy/checks/cert/msc32-c>` to + :doc:`bugprone-random-generator-seed + <clang-tidy/checks/bugprone/random-generator-seed>` + keeping initial check as an alias to the new one. + +- Renamed :doc:`cert-msc50-cpp <clang-tidy/checks/cert/msc50-cpp>` to + :doc:`misc-predictable-rand + <clang-tidy/checks/misc/predictable-rand>` + keeping initial check as an alias to the new one. + +- Renamed :doc:`cert-msc51-cpp <clang-tidy/checks/cert/msc51-cpp>` to + :doc:`bugprone-random-generator-seed + <clang-tidy/checks/bugprone/random-generator-seed>` + keeping initial check as an alias to the new one. + - Renamed :doc:`cert-oop57-cpp <clang-tidy/checks/cert/oop57-cpp>` to :doc:`bugprone-raw-memory-call-on-non-trivial-type <clang-tidy/checks/bugprone/raw-memory-call-on-non-trivial-type>` @@ -289,6 +328,11 @@ New check aliases <clang-tidy/checks/bugprone/copy-constructor-mutates-argument>` keeping initial check as an alias to the new one. +- Renamed :doc:`google-readability-casting <clang-tidy/checks/google/readability-casting>` to + :doc:`modernize-avoid-c-style-cast + <clang-tidy/checks/modernize/avoid-c-style-cast>` + keeping initial check as an alias to the new one. + Changes in existing checks ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -302,7 +346,9 @@ Changes in existing checks exceptions from captures are now diagnosed, exceptions in the bodies of lambdas that aren't actually invoked are not. Additionally, fixed an issue where the check wouldn't diagnose throws in arguments to functions or - constructors. + constructors. Added fine-grained configuration via options + `CheckDestructors`, `CheckMoveMemberFunctions`, `CheckMain`, + `CheckedSwapFunctions`, and `CheckNothrowFunctions`. - Improved :doc:`bugprone-infinite-loop <clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for @@ -351,13 +397,26 @@ Changes in existing checks - Improved :doc:`bugprone-unchecked-optional-access <clang-tidy/checks/bugprone/unchecked-optional-access>` check by supporting ``NullableValue::makeValue`` and ``NullableValue::makeValueInplace`` to - prevent false-positives for ``BloombergLP::bdlb::NullableValue`` type. + prevent false-positives for ``BloombergLP::bdlb::NullableValue`` type, and by + adding the `IgnoreValueCalls` option to suppress diagnostics for + ``optional::value()`` and the `IgnoreSmartPointerDereference` option to + ignore optionals reached via smart-pointer-like dereference, while still + diagnosing UB-prone dereferences via ``operator*`` and ``operator->``. - Improved :doc:`bugprone-unhandled-self-assignment <clang-tidy/checks/bugprone/unhandled-self-assignment>` check by adding an additional matcher that generalizes the copy-and-swap idiom pattern detection. +- Improved :doc:`bugprone-unsafe-functions + <clang-tidy/checks/bugprone/unsafe-functions>` check by hiding the default + suffix when the reason starts with the character `>` in the `CustomFunctions` + option. + +- Improved :doc:`bugprone-use-after-move + <clang-tidy/checks/bugprone/use-after-move>` check by adding + `InvalidationFunctions` option to support custom invalidation functions. + - Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables <clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables>` check by adding a new option `AllowThreadLocal` that suppresses warnings on @@ -382,6 +441,25 @@ Changes in existing checks adding an option to allow pointer arithmetic via prefix/postfix increment or decrement operators. +- Improved :doc:`cppcoreguidelines-pro-type-member-init + <clang-tidy/checks/cppcoreguidelines/pro-type-member-init>` check to + correctly ignore ``std::array`` and other array-like containers when + `IgnoreArrays` option is set to `true`. + +- Improved :doc:`fuchsia-multiple-inheritance + <clang-tidy/checks/fuchsia/multiple-inheritance>` + by fixing an issue where the check would only analyze the first class with + a given name in the program, missing any subsequent classes with that same + name (declared in a different scope). + +- Improved :doc:`google-readability-casting + <clang-tidy/checks/google/readability-casting>` check by adding fix-it + notes for downcasts and casts to void pointer. + +- Improved :doc:`google-readability-todo + <clang-tidy/checks/google/readability-todo>` check to accept the new TODO + format from the Google Style Guide. + - Improved :doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals <clang-tidy/checks/llvm/prefer-isa-or-dyn-cast-in-conditionals>` check: @@ -397,7 +475,13 @@ Changes in existing checks positives when pointers is transferred to non-const references and avoid false positives of function pointer and fix false positives on return of non-const pointer and fix false positives on - pointer-to-member operator. + pointer-to-member operator and avoid false positives when the address + of a variable is taken to be passed to a function. + +- Improved :doc:`misc-coroutine-hostile-raii + <clang-tidy/checks/misc/coroutine-hostile-raii>` check by adding the option + `AllowedCallees`, that allows exempting safely awaitable callees from the + check. - Improved :doc:`misc-header-include-cycle <clang-tidy/checks/misc/header-include-cycle>` check performance. @@ -442,7 +526,8 @@ Changes in existing checks - Improved :doc:`modernize-use-std-print <clang-tidy/checks/modernize/use-std-print>` check to correctly match when the format string is converted to a different type by an implicit - constructor call. + constructor call, and fixed a crash when handling format strings + containing non-ASCII characters. - Improved :doc:`performance-unnecessary-copy-initialization <clang-tidy/checks/performance/unnecessary-copy-initialization>` by printing @@ -462,12 +547,21 @@ Changes in existing checks comparisons to ``npos``. Internal changes may cause new rare false positives in non-standard containers. +- Improved :doc:`readability-container-data-pointer + <clang-tidy/checks/readability/container-data-pointer>` check by correctly + adding parentheses when the container expression is a dereference. + - Improved :doc:`readability-container-size-empty <clang-tidy/checks/readability/container-size-empty>` check by correctly generating fix-it hints when size method is called from implicit ``this``, ignoring default constructors with user provided arguments and adding detection in container's method except ``empty``. +- Improved :doc:`readability-duplicate-include + <clang-tidy/checks/readability/duplicate-include>` check by adding + the ``IgnoredFilesList`` option (semicolon-separated list of regexes or + filenames) to allow intentional duplicates. + - Improved :doc:`readability-identifier-naming <clang-tidy/checks/readability/identifier-naming>` check by ignoring declarations and macros in system headers. The documentation is also improved @@ -479,10 +573,19 @@ Changes in existing checks adding parentheses when the inner expression are implicitly converted multiple times. +- Improved :doc:`readability-inconsistent-declaration-parameter-name + <clang-tidy/checks/readability/inconsistent-declaration-parameter-name>` check + by not enforcing parameter name consistency between a variadic parameter pack + in the primary template and specific parameters in its specializations. + - Improved :doc:`readability-qualified-auto <clang-tidy/checks/readability/qualified-auto>` check by adding the option `IgnoreAliasing`, that allows not looking at underlying types of type aliases. +- Improved :doc:`readability-redundant-casting + <clang-tidy/checks/readability/redundant-casting>` check by fixing false + negatives when explicitly cast from function pointer. + - Improved :doc:`readability-uppercase-literal-suffix <clang-tidy/checks/readability/uppercase-literal-suffix>` check to recognize literal suffixes added in C++23 and C23. @@ -491,6 +594,11 @@ Changes in existing checks <clang-tidy/checks/readability/use-concise-preprocessor-directives>` check to generate correct fix-its for forms without a space after the directive. +- Improved :doc:`readability-use-std-min-max + <clang-tidy/checks/readability/use-std-min-max>` check by ensuring that + comments between the ``if`` condition and the ``then`` block are preserved + when applying the fix. + Removed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/abseil/duration-addition.rst b/clang-tools-extra/docs/clang-tidy/checks/abseil/duration-addition.rst index ce2eefd..e8e3da0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/abseil/duration-addition.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/abseil/duration-addition.rst @@ -3,10 +3,10 @@ abseil-duration-addition ======================== -Check for cases where addition should be performed in the ``absl::Time`` domain. -When adding two values, and one is known to be an ``absl::Time``, we can infer -that the other should be interpreted as an ``absl::Duration`` of a similar -scale, and make that inference explicit. +Checks for cases where addition should be performed in the ``absl::Time`` +domain. When adding two values, and one is known to be an ``absl::Time``, +we can infer that the other should be interpreted as an ``absl::Duration`` +of a similar scale, and make that inference explicit. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/abseil/duration-division.rst b/clang-tools-extra/docs/clang-tidy/checks/abseil/duration-division.rst index b7c8635..40c12d4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/abseil/duration-division.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/abseil/duration-division.rst @@ -4,8 +4,10 @@ abseil-duration-division ======================== ``absl::Duration`` arithmetic works like it does with integers. That means that -division of two ``absl::Duration`` objects returns an ``int64`` with any fractional -component truncated toward 0. See `this link <https://github.com/abseil/abseil-cpp/blob/29ff6d4860070bf8fcbd39c8805d0c32d56628a3/absl/time/time.h#L137>`_ for more information on arithmetic with ``absl::Duration``. +division of two ``absl::Duration`` objects returns an ``int64`` with any +fractional component truncated toward 0. +See `this link <https://github.com/abseil/abseil-cpp/blob/29ff6d4860070bf8fcbd39c8805d0c32d56628a3/absl/time/time.h#L137>`_ +for more information on arithmetic with ``absl::Duration``. For example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/abseil/faster-strsplit-delimiter.rst b/clang-tools-extra/docs/clang-tidy/checks/abseil/faster-strsplit-delimiter.rst index fe91156..b5b79d4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/abseil/faster-strsplit-delimiter.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/abseil/faster-strsplit-delimiter.rst @@ -5,9 +5,9 @@ abseil-faster-strsplit-delimiter Finds instances of ``absl::StrSplit()`` or ``absl::MaxSplits()`` where the delimiter is a single character string literal and replaces with a character. -The check will offer a suggestion to change the string literal into a character. -It will also catch code using ``absl::ByAnyChar()`` for just a single character -and will transform that into a single character as well. +The check will offer a suggestion to change the string literal into a +character. It will also catch code using ``absl::ByAnyChar()`` for just a +single character and will transform that into a single character as well. These changes will give the same result, but using characters rather than single character string literals is more efficient and readable. diff --git a/clang-tools-extra/docs/clang-tidy/checks/abseil/string-find-str-contains.rst b/clang-tools-extra/docs/clang-tidy/checks/abseil/string-find-str-contains.rst index 042fbdb..418df19 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/abseil/string-find-str-contains.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/abseil/string-find-str-contains.rst @@ -3,8 +3,8 @@ abseil-string-find-str-contains =============================== -Finds ``s.find(...) == string::npos`` comparisons (for various string-like types) -and suggests replacing with ``absl::StrContains()``. +Finds ``s.find(...) == string::npos`` comparisons (for various string-like +types) and suggests replacing with ``absl::StrContains()``. This improves readability and reduces the likelihood of accidentally mixing ``find()`` and ``npos`` from different string-like types. diff --git a/clang-tools-extra/docs/clang-tidy/checks/abseil/upgrade-duration-conversions.rst b/clang-tools-extra/docs/clang-tidy/checks/abseil/upgrade-duration-conversions.rst index 24e557d..3abdd40b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/abseil/upgrade-duration-conversions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/abseil/upgrade-duration-conversions.rst @@ -8,17 +8,17 @@ argument needs an explicit cast to continue compiling after upcoming API changes. The operators ``*=``, ``/=``, ``*``, and ``/`` for ``absl::Duration`` currently -accept an argument of class type that is convertible to an arithmetic type. Such -a call currently converts the value to an ``int64_t``, even in a case such as -``std::atomic<float>`` that would result in lossy conversion. +accept an argument of class type that is convertible to an arithmetic type. +Such a call currently converts the value to an ``int64_t``, even in a case such +as ``std::atomic<float>`` that would result in lossy conversion. Additionally, the ``absl::Duration`` factory functions (``absl::Hours``, ``absl::Minutes``, etc) currently accept an ``int64_t`` or a floating-point type. Similar to the arithmetic operators, calls with an argument of class type that is convertible to an arithmetic type go through the ``int64_t`` path. -These operators and factories will be changed to only accept arithmetic types to -prevent unintended behavior. After these changes are released, passing an +These operators and factories will be changed to only accept arithmetic types +to prevent unintended behavior. After these changes are released, passing an argument of class type will no longer compile, even if the type is implicitly convertible to an arithmetic type. diff --git a/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-inotify-init1.rst b/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-inotify-init1.rst index 827598c..7411589 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-inotify-init1.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-inotify-init1.rst @@ -3,9 +3,10 @@ android-cloexec-inotify-init1 ============================= -``inotify_init1()`` should include ``IN_CLOEXEC`` in its type argument to avoid the -file descriptor leakage. Without this flag, an opened sensitive file would -remain open across a fork+exec to a lower-privileged SELinux domain. +``inotify_init1()`` should include ``IN_CLOEXEC`` in its type argument +to avoid the file descriptor leakage. Without this flag, an opened +sensitive file would remain open across a fork+exec to a +lower-privileged SELinux domain. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-pipe.rst b/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-pipe.rst index b0504e9..c19e07f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-pipe.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-pipe.rst @@ -3,9 +3,10 @@ android-cloexec-pipe ==================== -This check detects usage of ``pipe()``. Using ``pipe()`` is not recommended, ``pipe2()`` is the -suggested replacement. The check also adds the O_CLOEXEC flag that marks the file descriptor to -be closed in child processes. Without this flag a sensitive file descriptor can be leaked to a +This check detects usage of ``pipe()``. Using ``pipe()`` is not recommended, +``pipe2()`` is the suggested replacement. The check also adds the ``O_CLOEXEC`` +flag that marks the file descriptor to be closed in child processes. +Without this flag a sensitive file descriptor can be leaked to a child process, potentially into a lower-privileged SELinux domain. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-pipe2.rst b/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-pipe2.rst index 9fb54be..dc9c6fc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-pipe2.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/android/cloexec-pipe2.rst @@ -3,8 +3,9 @@ android-cloexec-pipe2 ===================== -This check ensures that pipe2() is called with the O_CLOEXEC flag. The check also -adds the O_CLOEXEC flag that marks the file descriptor to be closed in child processes. +This check ensures that ``pipe2()`` is called with the ``O_CLOEXEC`` flag. +The check also adds the ``O_CLOEXEC`` flag that marks the file descriptor +to be closed in child processes. Without this flag a sensitive file descriptor can be leaked to a child process, potentially into a lower-privileged SELinux domain. diff --git a/clang-tools-extra/docs/clang-tidy/checks/android/comparison-in-temp-failure-retry.rst b/clang-tools-extra/docs/clang-tidy/checks/android/comparison-in-temp-failure-retry.rst index 31cc72b..42e8dd9 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/android/comparison-in-temp-failure-retry.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/android/comparison-in-temp-failure-retry.rst @@ -22,8 +22,8 @@ Example buggy usage looks like: // Do something with cs. } -Because TEMP_FAILURE_RETRY will check for whether the result *of the comparison* -is ``-1``, and retry if so. +Because ``TEMP_FAILURE_RETRY`` will check for whether the result +*of the comparison* is ``-1``, and retry if so. If you encounter this, the fix is simple: lift the comparison out of the ``TEMP_FAILURE_RETRY`` argument, like so: diff --git a/clang-tools-extra/docs/clang-tidy/checks/boost/use-to-string.rst b/clang-tools-extra/docs/clang-tidy/checks/boost/use-to-string.rst index 8365e80..9a5bb88 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/boost/use-to-string.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/boost/use-to-string.rst @@ -3,9 +3,9 @@ boost-use-to-string =================== -This check finds conversion from integer type like ``int`` to ``std::string`` or -``std::wstring`` using ``boost::lexical_cast``, and replace it with calls to -``std::to_string`` and ``std::to_wstring``. +This check finds conversion from integer type like ``int`` to +``std::string`` or ``std::wstring`` using ``boost::lexical_cast``, +and replace it with calls to ``std::to_string`` and ``std::to_wstring``. It doesn't replace conversion from floating points despite the ``to_string`` overloads, because it would change the behavior. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/assignment-in-if-condition.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/assignment-in-if-condition.rst index 691b6e4..980e814 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/assignment-in-if-condition.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/assignment-in-if-condition.rst @@ -4,11 +4,13 @@ bugprone-assignment-in-if-condition =================================== Finds assignments within conditions of `if` statements. -Such assignments are bug-prone because they may have been intended as equality tests. +Such assignments are bug-prone because they may have been intended as +equality tests. -This check finds all assignments within `if` conditions, including ones that are not flagged -by `-Wparentheses` due to an extra set of parentheses, and including assignments that call -an overloaded `operator=()`. The identified assignments violate +This check finds all assignments within `if` conditions, including ones that +are not flagged by `-Wparentheses` due to an extra set of parentheses, and +including assignments that call an overloaded ``operator=()``. The identified +assignments violate `BARR group "Rule 8.2.c" <https://barrgroup.com/embedded-systems/books/embedded-c-coding-standard/statement-rules/if-else-statements>`_. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/bitwise-pointer-cast.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/bitwise-pointer-cast.rst index ac58654..171e6e6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/bitwise-pointer-cast.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/bitwise-pointer-cast.rst @@ -31,9 +31,9 @@ not on pointer types: int x{}; float y = std::bit_cast<float>(x); -This way, the bytes of the input object are copied into the output object, which -is much safer. Do note that Undefined Behavior can still occur, if there is no -value of type ``To`` corresponding to the value representation produced. +This way, the bytes of the input object are copied into the output object, +which is much safer. Do note that Undefined Behavior can still occur, if there +is no value of type ``To`` corresponding to the value representation produced. Compilers may be able to optimize this copy and generate identical assembly to the original ``reinterpret_cast`` version. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/capturing-this-in-member-variable.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/capturing-this-in-member-variable.rst index 1017462..6a6ad73 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/capturing-this-in-member-variable.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/capturing-this-in-member-variable.rst @@ -6,11 +6,11 @@ bugprone-capturing-this-in-member-variable Finds lambda captures that capture the ``this`` pointer and store it as class members without handle the copy and move constructors and the assignments. -Capture this in a lambda and store it as a class member is dangerous because the -lambda can outlive the object it captures. Especially when the object is copied -or moved, the captured ``this`` pointer will be implicitly propagated to the -new object. Most of the time, people will believe that the captured ``this`` -pointer points to the new object, which will lead to bugs. +Capture this in a lambda and store it as a class member is dangerous because +the lambda can outlive the object it captures. Especially when the object is +copied or moved, the captured ``this`` pointer will be implicitly propagated +to the new object. Most of the time, people will believe that the captured +``this`` pointer points to the new object, which will lead to bugs. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst index 21efda4..3c0b52a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/casting-through-void.rst @@ -13,16 +13,19 @@ Two-step type conversions via ``void*`` are discouraged for several reasons. - These conversions bypass valuable compiler support, erasing warnings related to pointer alignment. It may violate strict aliasing rule and leading to undefined behavior. -- In scenarios involving multiple inheritance, ambiguity and unexpected outcomes - can arise due to the loss of type information, posing runtime issues. +- In scenarios involving multiple inheritance, ambiguity and unexpected + outcomes can arise due to the loss of type information, posing runtime + issues. -In summary, avoiding two-step type conversions through ``void*`` ensures clearer code, -maintains essential compiler warnings, and prevents ambiguity and potential runtime -errors, particularly in complex inheritance scenarios. If such a cast is wanted, -it shall be done via ``reinterpret_cast``, to express the intent more clearly. +In summary, avoiding two-step type conversions through ``void*`` ensures +clearer code, maintains essential compiler warnings, and prevents ambiguity +and potential runtime errors, particularly in complex inheritance scenarios. +If such a cast is wanted, it shall be done via ``reinterpret_cast``, +to express the intent more clearly. Note: it is expected that, after applying the suggested fix and using -``reinterpret_cast``, the check :doc:`cppcoreguidelines-pro-type-reinterpret-cast +``reinterpret_cast``, the check +:doc:`cppcoreguidelines-pro-type-reinterpret-cast <../cppcoreguidelines/pro-type-reinterpret-cast>` will emit a warning. This is intentional: ``reinterpret_cast`` is a dangerous operation that can easily break the strict aliasing rules when dereferencing the casted pointer, diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst index cc711d6..6b2a82f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/compare-pointer-to-member-virtual-function.rst @@ -3,8 +3,8 @@ bugprone-compare-pointer-to-member-virtual-function =================================================== -Detects unspecified behavior about equality comparison between pointer to member -virtual function and anything other than null-pointer-constant. +Detects unspecified behavior about equality comparison between pointer to +member virtual function and anything other than null-pointer-constant. .. code-block:: c++ @@ -47,11 +47,11 @@ becomes particularly challenging when dealing with pointers to pure virtual functions, as they may not even have a valid address, further complicating comparisons. -Instead, it is recommended to utilize the ``typeid`` operator or other appropriate -mechanisms for comparing objects to ensure robust and predictable behavior in -your codebase. By heeding this detection and adopting a more reliable comparison -method, you can mitigate potential issues related to unspecified behavior, -especially when dealing with pointers to member virtual functions or pure +Instead, it is recommended to utilize the ``typeid`` operator or other +appropriate mechanisms for comparing objects to ensure robust and predictable +behavior in your codebase. By heeding this detection and adopting a more reliable +comparison method, you can mitigate potential issues related to unspecified +behavior, especially when dealing with pointers to member virtual functions or pure virtual functions, thereby improving the overall stability and maintainability of your code. In scenarios involving pointers to member virtual functions, it's only advisable to employ ``nullptr`` for comparisons. @@ -60,6 +60,6 @@ only advisable to employ ``nullptr`` for comparisons. Limitations ----------- -Does not analyze values stored in a variable. For variable, only analyze all virtual -methods in the same ``class`` or ``struct`` and diagnose when assigning a pointer -to member virtual function to this variable is possible. +Does not analyze values stored in a variable. For variable, only analyze all +virtual methods in the same ``class`` or ``struct`` and diagnose when assigning +a pointer to member virtual function to this variable is possible. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/copy-constructor-mutates-argument.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/copy-constructor-mutates-argument.rst index 28e5015..e45a94a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/copy-constructor-mutates-argument.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/copy-constructor-mutates-argument.rst @@ -8,4 +8,4 @@ in copy constructors and copy assignment operators. This check corresponds to the CERT C Coding Standard rule `OOP58-CPP. Copy operations must not mutate the source object -<https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP58-CPP.+Copy+operations+must+not+mutate+the+source+object>`_.
\ No newline at end of file +<https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP58-CPP.+Copy+operations+must+not+mutate+the+source+object>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/dangling-handle.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/dangling-handle.rst index 752b711..c25f8c4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/dangling-handle.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/dangling-handle.rst @@ -4,8 +4,9 @@ bugprone-dangling-handle ======================== Detect dangling references in value handles like ``std::string_view``. -These dangling references can be a result of constructing handles from temporary -values, where the temporary is destroyed soon after the handle is created. +These dangling references can be a result of constructing handles from +temporary values, where the temporary is destroyed soon after the handle +is created. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/derived-method-shadowing-base-method.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/derived-method-shadowing-base-method.rst index aff3e1e6..4906b50 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/derived-method-shadowing-base-method.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/derived-method-shadowing-base-method.rst @@ -10,11 +10,12 @@ In order to be considered "shadowing", methods must have the same signature Only checks public, non-templated methods. The below example is bugprone because consumers of the ``Derived`` class will -expect the ``reset`` method to do the work of ``Base::reset()`` in addition to extra -work required to reset the ``Derived`` class. Common fixes include: +expect the ``reset`` method to do the work of ``Base::reset()`` in addition to +extra work required to reset the ``Derived`` class. Common fixes include: - Making the ``reset`` method polymorphic -- Re-naming ``Derived::reset`` if it's not meant to intersect with ``Base::reset`` +- Re-naming ``Derived::reset`` if it's not meant to intersect with + ``Base::reset`` - Using ``using Base::reset`` to change the access specifier This is also a violation of the Liskov Substitution Principle. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/dynamic-static-initializers.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/dynamic-static-initializers.rst index b4d5f750..93d403c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/dynamic-static-initializers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/dynamic-static-initializers.rst @@ -8,12 +8,12 @@ in header files. This can pose problems in certain multithreaded contexts. For example, when disabling compiler generated synchronization instructions for -static variables initialized at runtime (e.g. by ``-fno-threadsafe-statics``), even if a particular project -takes the necessary precautions to prevent race conditions during -initialization by providing their own synchronization, header files included from other projects may -not. Therefore, such a check is helpful for ensuring that disabling -compiler generated synchronization for static variable initialization will not cause -problems. +static variables initialized at runtime (e.g. by ``-fno-threadsafe-statics``), +even if a particular project takes the necessary precautions to prevent race +conditions during initialization by providing their own synchronization, header +files included from other projects may not. Therefore, such a check is helpful +for ensuring that disabling compiler generated synchronization for static +variable initialization will not cause problems. Consider the following code: @@ -24,4 +24,6 @@ Consider the following code: return k; } -When synchronization of static initialization is disabled, if two threads both call `foo` for the first time, there is the possibility that `k` will be double initialized, creating a race condition. +When synchronization of static initialization is disabled, if two threads both +call `foo` for the first time, there is the possibility that `k` will be double +initialized, creating a race condition. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/easily-swappable-parameters.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/easily-swappable-parameters.rst index a96d7f60..59ccab4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/easily-swappable-parameters.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/easily-swappable-parameters.rst @@ -12,9 +12,9 @@ swapped (or badly ordered) arguments. void drawPoint(int X, int Y) { /* ... */ } FILE *open(const char *Dir, const char *Name, Flags Mode) { /* ... */ } -A potential call like ``drawPoint(-2, 5)`` or ``openPath("a.txt", "tmp", Read)`` -is perfectly legal from the language's perspective, but might not be what the -developer of the function intended. +A potential call like ``drawPoint(-2, 5)`` or +``openPath("a.txt", "tmp", Read)`` is perfectly legal from the language's +perspective, but might not be what the developer of the function intended. More elaborate and type-safe constructs, such as opaque typedefs or strong types should be used instead, to prevent a mistaken order of arguments. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/empty-catch.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/empty-catch.rst index fd1db59..87c7edc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/empty-catch.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/empty-catch.rst @@ -118,10 +118,10 @@ Here is an example: it->second.callFunction(); } -In conclusion, empty catch statements are a bad practice that can lead to hidden -bugs, security issues, poor code quality, and unreliable code. By handling -exceptions properly, developers can ensure that their code is robust, secure, -and maintainable. +In conclusion, empty catch statements are a bad practice that can lead to +hidden bugs, security issues, poor code quality, and unreliable code. By +handling exceptions properly, developers can ensure that their code is +robust, secure, and maintainable. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst new file mode 100644 index 0000000..7170501 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-copy-constructor-throws.rst @@ -0,0 +1,31 @@ +.. title:: clang-tidy - bugprone-exception-copy-constructor-throws + +bugprone-exception-copy-constructor-throws +========================================== + +Checks whether a thrown object's copy constructor can throw. + +Exception objects are required to be copy constructible in C++. However, an +exception's copy constructor should not throw to avoid potential issues when +unwinding the stack. If an exception is thrown during stack unwinding (such +as from a copy constructor of an exception object), the program will +terminate via ``std::terminate``. + +.. code-block:: c++ + + class SomeException { + public: + SomeException() = default; + SomeException(const SomeException&) { /* may throw */ } + }; + + void f() { + throw SomeException(); // warning: thrown exception type's copy constructor can throw + } + +References +---------- + +This check corresponds to the CERT C++ Coding Standard rule +`ERR60-CPP. Exception objects must be nothrow copy constructible +<https://wiki.sei.cmu.edu/confluence/display/cplusplus/ERR60-CPP.+Exception+objects+must+be+nothrow+copy+constructible>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst index 182fade..7d724a4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/exception-escape.rst @@ -26,15 +26,40 @@ function also results in unexpected termination. Functions declared explicitly with ``noexcept(false)`` or ``throw(exception)`` will be excluded from the analysis, as even though it is not recommended for -functions like ``swap()``, ``main()``, move constructors, move assignment operators -and destructors, it is a clear indication of the developer's intention and -should be respected. +functions like ``swap()``, ``main()``, move constructors, move assignment +operators and destructors, it is a clear indication of the developer's +intention and should be respected. WARNING! This check may be expensive on large source files. Options ------- +.. option:: CheckDestructors + + When `true`, destructors are analyzed to not throw exceptions. + Default value is `true`. + +.. option:: CheckMoveMemberFunctions + + When `true`, move constructors and move assignment operators are analyzed + to not throw exceptions. Default value is `true`. + +.. option:: CheckMain + + When `true`, the ``main()`` function is analyzed to not throw exceptions. + Default value is `true`. + +.. option:: CheckNothrowFunctions + + When `true`, functions marked with ``noexcept`` or ``throw()`` exception + specifications are analyzed to not throw exceptions. Default value is `true`. + +.. option:: CheckedSwapFunctions + + Comma-separated list of swap function names which should not throw exceptions. + Default value is `swap,iter_swap,iter_move`. + .. option:: FunctionsThatShouldNotThrow Comma separated list containing function names which should not throw. An diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/fold-init-type.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/fold-init-type.rst index 8c6872d..fefad9f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/fold-init-type.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/fold-init-type.rst @@ -6,13 +6,14 @@ bugprone-fold-init-type The check flags type mismatches in `folds <https://en.wikipedia.org/wiki/Fold_(higher-order_function)>`_ like ``std::accumulate`` that might result in loss of precision. -``std::accumulate`` folds an input range into an initial value using the type of -the latter, with ``operator+`` by default. This can cause loss of precision -through: +``std::accumulate`` folds an input range into an initial value using +the type of the latter, with ``operator+`` by default. This can cause +loss of precision through: - Truncation: The following code uses a floating point range and an int - initial value, so truncation will happen at every application of ``operator+`` - and the result will be `0`, which might not be what the user expected. + initial value, so truncation will happen at every application of + ``operator+`` and the result will be `0`, which might not be what the + user expected. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/forward-declaration-namespace.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/forward-declaration-namespace.rst index 99ecb63..5e04f66 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/forward-declaration-namespace.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/forward-declaration-namespace.rst @@ -17,4 +17,5 @@ the forward declaration is in a potentially wrong namespace. // warning : no definition found for 'A', but a definition with the same name // 'A' found in another namespace 'nb::' -This check can only generate warnings, but it can't suggest a fix at this point. +This check can only generate warnings, but it can't suggest a fix at this +point. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst index 6d70a50..cd079a3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst @@ -6,8 +6,8 @@ bugprone-forwarding-reference-overload The check looks for perfect forwarding constructors that can hide copy or move constructors. If a non const lvalue reference is passed to the constructor, the forwarding reference parameter will be a better match than the const reference -parameter of the copy constructor, so the perfect forwarding constructor will be -called, which can be confusing. +parameter of the copy constructor, so the perfect forwarding constructor will +be called, which can be confusing. For detailed description of this issue see: Scott Meyers, Effective Modern C++, Item 26. @@ -47,12 +47,12 @@ Consider the following example: Person(const Person& rhs); }; -The check warns for constructors C1 and C2, because those can hide copy and move -constructors. We suppress warnings if the copy and the move constructors are both -disabled (deleted or private), because there is nothing the perfect forwarding -constructor could hide in this case. We also suppress warnings for constructors -like C3-C6 that are guarded with an ``enable_if`` or a concept, assuming the -programmer was aware of the possible hiding. +The check warns for constructors C1 and C2, because those can hide copy and +move constructors. We suppress warnings if the copy and the move constructors +are both disabled (deleted or private), because there is nothing the perfect +forwarding constructor could hide in this case. We also suppress warnings for +constructors like C3-C6 that are guarded with an ``enable_if`` or a concept, +assuming the programmer was aware of the possible hiding. Background ---------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/inc-dec-in-conditions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/inc-dec-in-conditions.rst index 380033f..f3f0331 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/inc-dec-in-conditions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/inc-dec-in-conditions.rst @@ -7,9 +7,9 @@ Detects when a variable is both incremented/decremented and referenced inside a complex condition and suggests moving them outside to avoid ambiguity in the variable's value. -When a variable is modified and also used in a complex condition, it can lead to -unexpected behavior. The side-effect of changing the variable's value within the -condition can make the code difficult to reason about. Additionally, the +When a variable is modified and also used in a complex condition, it can lead +to unexpected behavior. The side-effect of changing the variable's value within +the condition can make the code difficult to reason about. Additionally, the developer's intended timing for the modification of the variable may not be clear, leading to misunderstandings and errors. This can be particularly problematic when the condition involves logical operators like ``&&`` and @@ -44,8 +44,8 @@ throughout the code. // do something } -Another common issue occurs when multiple increments or decrements are performed -on the same variable inside a complex condition. For example: +Another common issue occurs when multiple increments or decrements are +performed on the same variable inside a complex condition. For example: .. code-block:: c++ @@ -55,13 +55,14 @@ on the same variable inside a complex condition. For example: // do something } -There is a potential issue with this code due to the order of evaluation in C++. -The ``||`` operator used in the condition statement guarantees that if the first -operand evaluates to ``true``, the second operand will not be evaluated. This -means that if ``i`` were initially ``4``, the first operand ``i < 5`` would -evaluate to ``true`` and the second operand ``i > 2`` would not be evaluated. -As a result, the decrement operation ``--i`` would not be executed and ``i`` -would hold value ``5``, which may not be the intended behavior for the developer. +There is a potential issue with this code due to the order of evaluation in +C++. The ``||`` operator used in the condition statement guarantees that if +the first operand evaluates to ``true``, the second operand will not be +evaluated. This means that if ``i`` were initially ``4``, the first operand +``i < 5`` would evaluate to ``true`` and the second operand ``i > 2`` would +not be evaluated. As a result, the decrement operation ``--i`` would not be +executed and ``i`` would hold value ``5``, which may not be the intended +behavior for the developer. To avoid this potential issue, the both increment and decrement operation on ``i`` should be moved outside the condition statement. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/infinite-loop.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/infinite-loop.rst index 89502c1..bbbc877 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/infinite-loop.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/infinite-loop.rst @@ -11,15 +11,15 @@ However, it is possible to detect some obvious infinite loops, for example, if the loop condition is not changed. This check detects such loops. A loop is considered infinite if it does not have any loop exit statement (``break``, ``continue``, ``goto``, ``return``, ``throw`` or a call to a function called as -``[[noreturn]]``) and all of the following conditions hold for every variable in -the condition: +``[[noreturn]]``) and all of the following conditions hold for every variable +in the condition: - It is a local variable. - It has no reference or pointer aliases. - It is not a structure or class member. -Furthermore, the condition must not contain a function call to consider the loop -infinite since functions may return different values for different calls. +Furthermore, the condition must not contain a function call to consider the +loop infinite since functions may return different values for different calls. For example, the following loop is considered infinite `i` is not changed in the body: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst index 45cb878..fcbfce7 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/invalid-enum-default-initialization.rst @@ -19,8 +19,8 @@ The check emits a warning only if an ``enum`` variable is default-initialized value of 0. The type can be a scoped or non-scoped ``enum``. Unions are not handled by the check (if it contains a member of enumeration type). -Note that the ``enum`` ``std::errc`` is always ignored because it is expected to -be default initialized, despite not defining an enumerator with the value 0. +Note that the ``enum`` ``std::errc`` is always ignored because it is expected +to be default initialized, despite not defining an enumerator with the value 0. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/misplaced-operator-in-strlen-in-alloc.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/misplaced-operator-in-strlen-in-alloc.rst index 38df480..c9a2a648 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/misplaced-operator-in-strlen-in-alloc.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/misplaced-operator-in-strlen-in-alloc.rst @@ -4,14 +4,14 @@ bugprone-misplaced-operator-in-strlen-in-alloc ============================================== Finds cases where ``1`` is added to the string in the argument to ``strlen()``, -``strnlen()``, ``strnlen_s()``, ``wcslen()``, ``wcsnlen()``, and ``wcsnlen_s()`` -instead of the result and the value is used as an argument to a memory -allocation function (``malloc()``, ``calloc()``, ``realloc()``, ``alloca()``) or -the ``new[]`` operator in `C++`. The check detects error cases even if one of -these functions (except the ``new[]`` operator) is called by a constant function -pointer. Cases where ``1`` is added both to the parameter and the result of the -``strlen()``-like function are ignored, as are cases where the whole addition is -surrounded by extra parentheses. +``strnlen()``, ``strnlen_s()``, ``wcslen()``, ``wcsnlen()``, and +``wcsnlen_s()`` instead of the result and the value is used as an argument to a +memory allocation function (``malloc()``, ``calloc()``, ``realloc()``, +``alloca()``) or the ``new[]`` operator in `C++`. The check detects error cases +even if one of these functions (except the ``new[]`` operator) is called by a +constant function pointer. Cases where ``1`` is added both to the parameter and +the result of the ``strlen()``-like function are ignored, as are cases where +the whole addition is surrounded by extra parentheses. `C` example code: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/multiple-new-in-one-expression.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/multiple-new-in-one-expression.rst index b9b8984..154013d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/multiple-new-in-one-expression.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/multiple-new-in-one-expression.rst @@ -10,11 +10,11 @@ and throws exception. C++ does often not specify the exact order of evaluation of the operands of an operator or arguments of a function. Therefore if a first allocation succeeds and a second fails, in an exception handler it is not possible to tell which -allocation has failed and free the memory. Even if the order is fixed the result -of a first ``new`` may be stored in a temporary location that is not reachable -at the time when a second allocation fails. It is best to avoid any expression -that contains more than one ``operator new`` call, if exception handling is -used to check for allocation errors. +allocation has failed and free the memory. Even if the order is fixed the +result of a first ``new`` may be stored in a temporary location that is not +reachable at the time when a second allocation fails. It is best to avoid any +expression that contains more than one ``operator new`` call, if exception +handling is used to check for allocation errors. Different rules apply for are the short-circuit operators ``||`` and ``&&`` and the ``,`` operator, where evaluation of one side must be completed before the @@ -31,9 +31,9 @@ For any warning to be emitted the ``new`` calls should be in a code block where exception handling is used with catch for ``std::bad_alloc`` or ``std::exception``. At ``||``, ``&&``, ``,``, ``?`` (condition and one branch) operators no warning is emitted. No warning is emitted if both of the memory -allocations are not assigned to a variable or not passed directly to a function. -The reason is that in this case the memory may be intentionally not freed or the -allocated objects can be self-destructing objects. +allocations are not assigned to a variable or not passed directly to a +function. The reason is that in this case the memory may be intentionally not +freed or the allocated objects can be self-destructing objects. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/narrowing-conversions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/narrowing-conversions.rst index 1a1217e..4327bc0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/narrowing-conversions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/narrowing-conversions.rst @@ -3,7 +3,8 @@ bugprone-narrowing-conversions ============================== -`cppcoreguidelines-narrowing-conversions` redirects here as an alias for this check. +`cppcoreguidelines-narrowing-conversions` redirects here as an alias for +this check. Checks for silent narrowing conversions, e.g: ``int i = 0; i += 0.1;``. While the issue is obvious in this former example, it might not be so in the @@ -19,8 +20,8 @@ We flag narrowing conversions from: if WarnOnFloatingPointNarrowingConversion Option is set. This check will flag: - - All narrowing conversions that are not marked by an explicit cast (c-style or - ``static_cast``). For example: ``int i = 0; i += 0.1;``, + - All narrowing conversions that are not marked by an explicit cast (c-style + or ``static_cast``). For example: ``int i = 0; i += 0.1;``, ``void f(int); f(0.1);``, - All applications of binary operators with a narrowing conversions. For example: ``int i; i+= 0.1;``. @@ -110,17 +111,17 @@ FAQ - What does "narrowing conversion from 'int' to 'float'" mean? An IEEE754 Floating Point number can represent all integer values in the range -[-2^PrecisionBits, 2^PrecisionBits] where PrecisionBits is the number of bits in -the mantissa. +[-2^PrecisionBits, 2^PrecisionBits] where PrecisionBits is the number of bits +in the mantissa. -For ``float`` this would be [-2^23, 2^23], where ``int`` can represent values in -the range [-2^31, 2^31-1]. +For ``float`` this would be [-2^23, 2^23], where ``int`` can represent values +in the range [-2^31, 2^31-1]. - What does "implementation-defined" mean? -You may have encountered messages like "narrowing conversion from 'unsigned int' -to signed type 'int' is implementation-defined". -The C/C++ standard does not mandate two's complement for signed integers, and so -the compiler is free to define what the semantics are for converting an unsigned -integer to signed integer. Clang's implementation uses the two's complement -format. +You may have encountered messages like "narrowing conversion from 'unsigned +int' to signed type 'int' is implementation-defined". +The C/C++ standard does not mandate two's complement for signed integers, and +so the compiler is free to define what the semantics are for converting an +unsigned integer to signed integer. Clang's implementation uses the two's +complement format. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/no-escape.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/no-escape.rst index 770a71c..850b01c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/no-escape.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/no-escape.rst @@ -5,8 +5,8 @@ bugprone-no-escape Finds pointers with the ``noescape`` attribute that are captured by an asynchronously-executed block. The block arguments in ``dispatch_async()`` and -``dispatch_after()`` are guaranteed to escape, so it is an error if a pointer with the -``noescape`` attribute is captured by one of these blocks. +``dispatch_after()`` are guaranteed to escape, so it is an error if a pointer +with the ``noescape`` attribute is captured by one of these blocks. The following is an example of an invalid use of the ``noescape`` attribute. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/non-zero-enum-to-bool-conversion.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/non-zero-enum-to-bool-conversion.rst index 168ed71..0ae950d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/non-zero-enum-to-bool-conversion.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/non-zero-enum-to-bool-conversion.rst @@ -3,24 +3,24 @@ bugprone-non-zero-enum-to-bool-conversion ========================================= -Detect implicit and explicit casts of ``enum`` type into ``bool`` where ``enum`` -type doesn't have a zero-value enumerator. If the ``enum`` is used only to hold -values equal to its enumerators, then conversion to ``bool`` will always result -in ``true`` value. This can lead to unnecessary code that reduces readability -and maintainability and can result in bugs. +Detect implicit and explicit casts of ``enum`` type into ``bool`` where +``enum`` type doesn't have a zero-value enumerator. If the ``enum`` is used +only to hold values equal to its enumerators, then conversion to ``bool`` will +always result in ``true`` value. This can lead to unnecessary code that reduces +readability and maintainability and can result in bugs. May produce false positives if the ``enum`` is used to store other values (used as a bit-mask or zero-initialized on purpose). To deal with them, -``// NOLINT`` or casting first to the underlying type before casting to ``bool`` -can be used. +``// NOLINT`` or casting first to the underlying type before casting to +``bool`` can be used. It is important to note that this check will not generate warnings if the definition of the enumeration type is not available. Additionally, C++11 enumeration classes are supported by this check. -Overall, this check serves to improve code quality and readability by identifying -and flagging instances where implicit or explicit casts from enumeration types to -boolean could cause potential issues. +Overall, this check serves to improve code quality and readability by +identifying and flagging instances where implicit or explicit casts from +enumeration types to boolean could cause potential issues. Example ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/not-null-terminated-result.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/not-null-terminated-result.rst index ed7d65c..db86e94 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/not-null-terminated-result.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/not-null-terminated-result.rst @@ -3,10 +3,11 @@ bugprone-not-null-terminated-result =================================== -Finds function calls where it is possible to cause a not null-terminated result. -Usually the proper length of a string is ``strlen(src) + 1`` or equal length of -this expression, because the null terminator needs an extra space. Without the -null terminator it can result in undefined behavior when the string is read. +Finds function calls where it is possible to cause a not null-terminated +result. Usually the proper length of a string is ``strlen(src) + 1`` or equal +length of this expression, because the null terminator needs an extra space. +Without the null terminator it can result in undefined behavior when the +string is read. The following and their respective ``wchar_t`` based functions are checked: @@ -25,8 +26,8 @@ of the allocated memory is not enough to hold the null terminator. return result; } -In addition to issuing warnings, fix-it rewrites all the necessary code. It also -tries to adjust the capacity of the destination array: +In addition to issuing warnings, fix-it rewrites all the necessary code. +It also tries to adjust the capacity of the destination array: .. code-block:: c @@ -62,8 +63,8 @@ Rewrite based on the destination array the safe version (ending with ``cpy_s``). - If the new function is could be safe version and C++ files are analyzed and - the destination array is plain ``char``/``wchar_t`` without ``un/signed`` then - the length of the destination array can be omitted. + the destination array is plain ``char``/``wchar_t`` without ``un/signed`` + then the length of the destination array can be omitted. - If the new function is could be safe version and the destination array is ``un/signed`` it needs to be casted to plain ``char *``/``wchar_t *``. @@ -76,8 +77,9 @@ Rewrite based on the length of the source string ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - If the given length is ``strlen(source)`` or equal length of this expression - then the new function should be the older copy function (ending with ``cpy``), - as it is more efficient than the safe version (ending with ``cpy_s``). + then the new function should be the older copy function (ending with + ``cpy``), as it is more efficient than the safe version (ending with + ``cpy_s``). - Otherwise we assume that the programmer wanted to copy 'N' characters, so the new function is ``ncpy``-like which copies 'N' characters. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/posix-return.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/posix-return.rst index a5c4ccb..1a4a3ed 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/posix-return.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/posix-return.rst @@ -13,7 +13,8 @@ Example buggy usage looks like: if (posix_fadvise(...) < 0) { -This will never happen as the return value is always non-negative. A simple fix could be: +This will never happen as the return value is always non-negative. +A simple fix could be: .. code-block:: c diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/random-generator-seed.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/random-generator-seed.rst new file mode 100644 index 0000000..2568099 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/random-generator-seed.rst @@ -0,0 +1,44 @@ +.. title:: clang-tidy - bugprone-random-generator-seed + +bugprone-random-generator-seed +============================== + +Flags all pseudo-random number engines, engine adaptor +instantiations and ``srand()`` when initialized or seeded with default +argument, constant expression or any user-configurable type. Pseudo-random +number engines seeded with a predictable value may cause vulnerabilities +e.g. in security protocols. + +Examples: + +.. code-block:: c++ + + void foo() { + std::mt19937 engine1; // Diagnose, always generate the same sequence + std::mt19937 engine2(1); // Diagnose + engine1.seed(); // Diagnose + engine2.seed(1); // Diagnose + + std::time_t t; + engine1.seed(std::time(&t)); // Diagnose, system time might be controlled by user + + int x = atoi(argv[1]); + std::mt19937 engine3(x); // Will not warn + } + +Options +------- + +.. option:: DisallowedSeedTypes + + A comma-separated list of the type names which are disallowed. + Default value is `time_t,std::time_t`. + +References +---------- + +This check corresponds to the CERT C++ Coding Standard rules +`MSC51-CPP. Ensure your random number generator is properly seeded +<https://wiki.sei.cmu.edu/confluence/display/cplusplus/MSC51-CPP.+Ensure+your+random+number+generator+is+properly+seeded>`_ and +`MSC32-C. Properly seed pseudorandom number generators +<https://wiki.sei.cmu.edu/confluence/display/c/MSC32-C.+Properly+seed+pseudorandom+number+generators>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/redundant-branch-condition.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/redundant-branch-condition.rst index c2efff8..7a321bd 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/redundant-branch-condition.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/redundant-branch-condition.rst @@ -16,9 +16,9 @@ Simple example: scream(); } -Here `onFire` is checked both in the outer ``if`` and the inner ``if`` statement -without a possible change between the two checks. The check warns for this code -and suggests removal of the second checking of variable `onFire`. +Here `onFire` is checked both in the outer ``if`` and the inner ``if`` +statement without a possible change between the two checks. The check warns for +this code and suggests removal of the second checking of variable `onFire`. The checker also detects redundant condition checks if the condition variable is an operand of a logical "and" (``&&``) or a logical "or" (``||``) operator: @@ -44,8 +44,8 @@ condition variable and keep the other side of the ``&&``. In the second case (logical "or") the whole ``if`` is removed similarly to the simple case on the top. -The condition of the outer ``if`` statement may also be a logical "and" (``&&``) -expression: +The condition of the outer ``if`` statement may also be a logical "and" +(``&&``) expression: .. code-block:: c @@ -62,8 +62,8 @@ The error is also detected if both the outer statement is a logical "and" The inner ``if`` statement does not have to be a direct descendant of the outer one. -No error is detected if the condition variable may have been changed between the -two checks: +No error is detected if the condition variable may have been changed between +the two checks: .. code-block:: c diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/return-const-ref-from-parameter.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/return-const-ref-from-parameter.rst index 00759a2..663e214 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/return-const-ref-from-parameter.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/return-const-ref-from-parameter.rst @@ -3,14 +3,14 @@ bugprone-return-const-ref-from-parameter ======================================== -Detects return statements that return a constant reference parameter as constant -reference. This may cause use-after-free errors if the caller uses xvalues as -arguments. - -In C++, constant reference parameters can accept xvalues which will be destructed -after the call. When the function returns such a parameter also as constant reference, -then the returned reference can be used after the object it refers to has been -destroyed. +Detects return statements that return a constant reference parameter as +constant reference. This may cause use-after-free errors if the caller +uses xvalues as arguments. + +In C++, constant reference parameters can accept xvalues which will be +destructed after the call. When the function returns such a parameter also +as constant reference, then the returned reference can be used after the +object it refers to has been destroyed. Example ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/signal-handler.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/signal-handler.rst index 848fb66..42cfdf0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/signal-handler.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/signal-handler.rst @@ -20,10 +20,10 @@ Checked signal handler rules for up to and including C++14: The check is disabled on C++17 and later. -Asynchronous-safety is determined by comparing the function's name against a set -of known functions. In addition, the function must come from a system header -include and in a global namespace. The (possible) arguments passed to the -function are not checked. Any function that cannot be determined to be +Asynchronous-safety is determined by comparing the function's name against a +set of known functions. In addition, the function must come from a system +header include and in a global namespace. The (possible) arguments passed to +the function are not checked. Any function that cannot be determined to be asynchronous-safe is assumed to be non-asynchronous-safe by the check, including user functions for which only the declaration is visible. Calls to user-defined functions with visible definitions are checked @@ -45,11 +45,11 @@ Options Selects which set of functions is considered as asynchronous-safe (and therefore allowed in signal handlers). It can be set to the following values: - ``minimal`` + - `minimal` Selects a minimal set that is defined in the CERT SIG30-C rule. and includes functions ``abort()``, ``_Exit()``, ``quick_exit()`` and ``signal()``. - ``POSIX`` + - `POSIX` Selects a larger set of functions that is listed in POSIX.1-2017 (see `this link <https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03>`_ @@ -94,4 +94,4 @@ Options The function ``quick_exit`` is not included in the POSIX list but it is included here in the set of safe functions. - The default value is ``POSIX``. + The default value is `POSIX`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/signed-char-misuse.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/signed-char-misuse.rst index 3e06e11..4b98c36 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/signed-char-misuse.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/signed-char-misuse.rst @@ -17,30 +17,34 @@ human programmer probably expects that the converted value matches with the character code (a value from [0..255]), however, the actual value is in [-128..127] interval. To avoid this kind of misinterpretation, the desired way of converting from a ``signed char`` to an integer value is converting to -``unsigned char`` first, which stores all the characters in the positive [0..255] -interval which matches the known character codes. +``unsigned char`` first, which stores all the characters in the positive +[0..255] interval which matches the known character codes. In case of implicit conversion, the programmer might not actually be aware that a conversion happened and char value is used as an integer. There are -some use cases when this unawareness might lead to a functionally imperfect code. -For example, checking the equality of a ``signed char`` and an ``unsigned char`` -variable is something we should avoid in C++ code. During this comparison, -the two variables are converted to integers which have different value ranges. -For ``signed char``, the non-ASCII characters are stored as a value in [-128..-1] -interval, while the same characters are stored in the [128..255] interval for -an ``unsigned char``. - -It depends on the actual platform whether plain ``char`` is handled as ``signed char`` -by default and so it is caught by this check or not. To change the default behavior -you can use ``-funsigned-char`` and ``-fsigned-char`` compilation options. +some use cases when this unawareness might lead to a functionally imperfect +code. For example, checking the equality of a ``signed char`` and an +``unsigned char`` variable is something we should avoid in C++ code. During +this comparison, the two variables are converted to integers which have +different value ranges. For ``signed char``, the non-ASCII characters are +stored as a value in [-128..-1] interval, while the same characters are +stored in the [128..255] interval for an ``unsigned char``. + +It depends on the actual platform whether plain ``char`` is handled as +``signed char`` by default and so it is caught by this check or not. +To change the default behavior you can use ``-funsigned-char`` and +``-fsigned-char`` compilation options. Currently, this check warns in the following cases: + - ``signed char`` is assigned to an integer variable -- ``signed char`` and ``unsigned char`` are compared with equality/inequality operator +- ``signed char`` and ``unsigned char`` are compared with + equality/inequality operator - ``signed char`` is converted to an integer in the array subscript See also: -`STR34-C. Cast characters to unsigned char before converting to larger integer sizes +`STR34-C. Cast characters to unsigned char before converting to larger +integer sizes <https://wiki.sei.cmu.edu/confluence/display/c/STR34-C.+Cast+characters+to+unsigned+char+before+converting+to+larger+integer+sizes>`_ A good example from the CERT description when a ``char`` variable is used to diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/sizeof-container.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/sizeof-container.rst index fb2f0b2..5d70d45 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/sizeof-container.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/sizeof-container.rst @@ -3,12 +3,12 @@ bugprone-sizeof-container ========================= -The check finds usages of ``sizeof`` on expressions of STL container types. Most -likely the user wanted to use ``.size()`` instead. +The check finds usages of ``sizeof`` on expressions of STL container types. +Most likely the user wanted to use ``.size()`` instead. -All class/struct types declared in namespace ``std::`` having a const ``size()`` -method are considered containers, with the exception of ``std::bitset`` and -``std::array``. +All class/struct types declared in namespace ``std::`` having a const +``size()`` method are considered containers, with the exception of +``std::bitset`` and ``std::array``. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/sizeof-expression.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/sizeof-expression.rst index 09be75c..aa2e529 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/sizeof-expression.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/sizeof-expression.rst @@ -73,9 +73,9 @@ Suspicious usage of 'sizeof(char*)' There is a subtle difference between declaring a string literal with ``char* A = ""`` and ``char A[] = ""``. The first case has the type ``char*`` -instead of the aggregate type ``char[]``. Using ``sizeof`` on an object declared -with ``char*`` type is returning the size of a pointer instead of the number of -characters (bytes) in the string literal. +instead of the aggregate type ``char[]``. Using ``sizeof`` on an object +declared with ``char*`` type is returning the size of a pointer instead of +the number of characters (bytes) in the string literal. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/std-namespace-modification.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/std-namespace-modification.rst index c6e5608..56d2559 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/std-namespace-modification.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/std-namespace-modification.rst @@ -10,13 +10,18 @@ The ``std`` (or ``posix``) namespace is allowed to be extended with (class or function) template specializations that depend on an user-defined type (a type that is not defined in the standard system headers). -The check detects the following (user provided) declarations in namespace ``std`` or ``posix``: +The check detects the following (user provided) declarations in namespace +``std`` or ``posix``: - Anything that is not a template specialization. -- Explicit specializations of any standard library function template or class template, if it does not have any user-defined type as template argument. -- Explicit specializations of any member function of a standard library class template. -- Explicit specializations of any member function template of a standard library class or class template. -- Explicit or partial specialization of any member class template of a standard library class or class template. +- Explicit specializations of any standard library function template or class + template, if it does not have any user-defined type as template argument. +- Explicit specializations of any member function of a standard library class + template. +- Explicit specializations of any member function template of a standard + library class or class template. +- Explicit or partial specialization of any member class template of a standard + library class or class template. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/string-literal-with-embedded-nul.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/string-literal-with-embedded-nul.rst index c1c4d32..bc5f2ce 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/string-literal-with-embedded-nul.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/string-literal-with-embedded-nul.rst @@ -21,9 +21,9 @@ like this ``\0x42`` where the ``\0`` stands for the NUL character. Truncated literal ----------------- -String-like classes can manipulate strings with embedded NUL as they are keeping -track of the bytes and the length. This is not the case for a ``char*`` -(NUL-terminated) string. +String-like classes can manipulate strings with embedded NUL as they are +keeping track of the bytes and the length. This is not the case for a +``char*`` (NUL-terminated) string. A common mistake is to pass a string-literal with embedded NUL to a string constructor expecting a NUL-terminated string. The bytes after the first NUL diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-enum-usage.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-enum-usage.rst index 94f29ee..94e3db9 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-enum-usage.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-enum-usage.rst @@ -3,11 +3,11 @@ bugprone-suspicious-enum-usage ============================== -The checker detects various cases when an enum is probably misused (as a bitmask -). +The checker detects various cases when an enum is probably misused +(as a bitmask). -1. When "ADD" or "bitwise OR" is used between two enum which come from different - types and these types value ranges are not disjoint. +1. When "ADD" or "bitwise OR" is used between two enum which come + from different types and these types value ranges are not disjoint. The following cases will be investigated only using :option:`StrictMode`. We regard the enum as a (suspicious) @@ -17,17 +17,17 @@ bitmask if the three conditions below are true at the same time: short enumerations) * there is another non pow-of-2 number than the enum constant representing all choices (the result "bitwise OR" operation of all enum elements) -* enum type variable/enumconstant is used as an argument of a `+` or "bitwise OR - " operator +* enum type variable/enumconstant is used as an argument of a `+` or "bitwise + OR" operator So whenever the non pow-of-2 element is used as a bitmask element we diagnose a misuse and give a warning. -2. Investigating the right hand side of `+=` and `|=` operator. -3. Check only the enum value side of a `|` and `+` operator if one of them is not - enum val. -4. Check both side of `|` or `+` operator where the enum values are from the - same enum type. +2. Investigating the right hand side of ``+=`` and ``|=`` operator. +3. Check only the enum value side of a ``|`` and ``+`` operator if one of + them is not enum val. +4. Check both side of ``|`` or ``+`` operator where the enum values are from + the same enum type. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-memory-comparison.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-memory-comparison.rst index f82863f..317f8e1 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-memory-comparison.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-memory-comparison.rst @@ -24,10 +24,12 @@ and <https://wiki.sei.cmu.edu/confluence/display/c/FLP37-C.+Do+not+use+object+representations+to+compare+floating-point+values>`_ This check is also related to and partially overlaps the CERT C++ Coding Standard rules -`OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions +`OOP57-CPP. Prefer special member functions and overloaded operators to +C Standard Library functions <https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP57-CPP.+Prefer+special+member+functions+and+overloaded+operators+to+C+Standard+Library+functions>`_ and -`EXP62-CPP. Do not access the bits of an object representation that are not part of the object's value representation +`EXP62-CPP. Do not access the bits of an object representation that are not +part of the object's value representation <https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP62-CPP.+Do+not+access+the+bits+of+an+object+representation+that+are+not+part+of+the+object%27s+value+representation>`_ `cert-exp42-c` redirects here as an alias of this check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-realloc-usage.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-realloc-usage.rst index 25a0d88..9885d9c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-realloc-usage.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-realloc-usage.rst @@ -3,8 +3,8 @@ bugprone-suspicious-realloc-usage ================================= -This check finds usages of ``realloc`` where the return value is assigned to the -same expression as passed to the first argument: +This check finds usages of ``realloc`` where the return value is assigned to +the same expression as passed to the first argument: ``p = realloc(p, size);`` The problem with this construct is that if ``realloc`` fails it returns a null pointer but does not deallocate the original memory. If no other variable @@ -12,8 +12,9 @@ is pointing to it, the original memory block is not available any more for the program to use or free. In either case ``p = realloc(p, size);`` indicates bad coding style and can be replaced by ``q = realloc(p, size);``. -The pointer expression (used at ``realloc``) can be a variable or a field member -of a data structure, but can not contain function calls or unresolved types. +The pointer expression (used at ``realloc``) can be a variable or a field +member of a data structure, but can not contain function calls or unresolved +types. In obvious cases when the pointer used at realloc is assigned to another variable before the ``realloc`` call, no warning is emitted. This happens only diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-semicolon.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-semicolon.rst index 76c891f..56e23d77 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-semicolon.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-semicolon.rst @@ -5,9 +5,9 @@ bugprone-suspicious-semicolon Finds most instances of stray semicolons that unexpectedly alter the meaning of the code. More specifically, it looks for ``if``, ``while``, ``for`` and -``for-range`` statements whose body is a single semicolon, and then analyzes the -context of the code (e.g. indentation) in an attempt to determine whether that -is intentional. +``for-range`` statements whose body is a single semicolon, and then analyzes +the context of the code (e.g. indentation) in an attempt to determine whether +that is intentional. .. code-block:: c++ @@ -26,8 +26,8 @@ of the first line, and `x` will be incremented regardless of the condition. processLine(line); As a result of this code, `processLine()` will only be called once, when the -``while`` loop with the empty body exits with `line == NULL`. The indentation of -the code indicates the intention of the programmer. +``while`` loop with the empty body exits with ``line == NULL``. The indentation +of the code indicates the intention of the programmer. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-string-compare.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-string-compare.rst index 85e1796..973b703 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-string-compare.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-string-compare.rst @@ -30,8 +30,8 @@ A common mistake is to compare the result to `1` or `-1`. if (strcmp(...) == -1) // Incorrect usage of the returned value. Additionally, the check warns if the results value is implicitly cast to a -*suspicious* non-integer type. It's happening when the returned value is used in -a wrong context. +*suspicious* non-integer type. It's happening when the returned value is +used in a wrong context. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/swapped-arguments.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/swapped-arguments.rst index 674108f..e798b67 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/swapped-arguments.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/swapped-arguments.rst @@ -34,8 +34,8 @@ dealing with floating-point arguments, implicit casts between different floating-point types are considered acceptable. To avoid confusion, swaps where both swapped arguments are of integral types or -both are of floating-point types do not trigger the warning. In such cases, it's -assumed that the developer intentionally used different integral or +both are of floating-point types do not trigger the warning. In such cases, +it's assumed that the developer intentionally used different integral or floating-point types and does not raise a warning. This approach prevents false -positives and provides flexibility in handling situations where varying integral -or floating-point types are intentionally utilized. +positives and provides flexibility in handling situations where varying +integral or floating-point types are intentionally utilized. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/switch-missing-default-case.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/switch-missing-default-case.rst index 3ce862f..0f0e549 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/switch-missing-default-case.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/switch-missing-default-case.rst @@ -51,6 +51,6 @@ Example: on non-enum types where the compiler warnings may not be present. .. seealso:: - The `CppCoreGuideline ES.79 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-default>`_ + The `CppCoreGuideline ES.79 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#res-default>`_ provide guidelines on switch statements, including the recommendation to always provide a default case. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/tagged-union-member-count.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/tagged-union-member-count.rst index a3469dc..5ac5e32 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/tagged-union-member-count.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/tagged-union-member-count.rst @@ -53,10 +53,10 @@ How enum constants are counted ------------------------------ The main complicating factor when counting the number of enum constants is that -some of them might be auxiliary values that purposefully don't have a corresponding union -data member and are used for something else. For example the last enum constant -sometimes explicitly "points to" the last declared valid enum constant or -tracks how many enum constants have been declared. +some of them might be auxiliary values that purposefully don't have a +corresponding union data member and are used for something else. For example +the last enum constant sometimes explicitly "points to" the last declared valid +enum constant or tracks how many enum constants have been declared. For an illustration: @@ -76,23 +76,24 @@ For an illustration: TagCount, // is 3 }; -The check counts the number of distinct values among the enum constants and not the enum -constants themselves. This way the enum constants that are essentially just aliases of other -enum constants are not included in the final count. +The check counts the number of distinct values among the enum constants and not +the enum constants themselves. This way the enum constants that are essentially +just aliases of other enum constants are not included in the final count. -Handling of counting enum constants (ones like :code:`TagCount` in the previous code example) -is done by decreasing the number of enum values by one if the name of the last enum constant -starts with a prefix or ends with a suffix specified in :option:`CountingEnumPrefixes`, -:option:`CountingEnumSuffixes` and it's value is one less than the total number of distinct -values in the enum. +Handling of counting enum constants (ones like :code:`TagCount` in the previous +code example) is done by decreasing the number of enum values by one if the name +of the last enum constant starts with a prefix or ends with a suffix specified in +:option:`CountingEnumPrefixes`, :option:`CountingEnumSuffixes` and it's value is +one less than the total number of distinct values in the enum. -When the final count is adjusted based on this heuristic then a diagnostic note is emitted -that shows which enum constant matched the criteria. +When the final count is adjusted based on this heuristic then a diagnostic note +is emitted that shows which enum constant matched the criteria. -The heuristic can be disabled entirely (:option:`EnableCountingEnumHeuristic`) or -configured to follow your naming convention (:option:`CountingEnumPrefixes`, :option:`CountingEnumSuffixes`). -The strings specified in :option:`CountingEnumPrefixes`, :option:`CountingEnumSuffixes` are matched -case insensitively. +The heuristic can be disabled entirely (:option:`EnableCountingEnumHeuristic`) +or configured to follow your naming convention (:option:`CountingEnumPrefixes`, +:option:`CountingEnumSuffixes`). +The strings specified in :option:`CountingEnumPrefixes`, +:option:`CountingEnumSuffixes` are matched case insensitively. Example counts: @@ -184,8 +185,8 @@ If :option:`EnableCountingEnumHeuristic` is `false` then these options do nothin The default value of :option:`CountingEnumSuffixes` is `count` and of :option:`CountingEnumPrefixes` is the empty string. -When :option:`EnableCountingEnumHeuristic` is `true` and :option:`CountingEnumSuffixes` -is `count;size`: +When :option:`EnableCountingEnumHeuristic` is `true` and +:option:`CountingEnumSuffixes` is `count;size`: .. code-block:: c++ @@ -223,7 +224,8 @@ is `count;size`: } Data; }; -When :option:`EnableCountingEnumHeuristic` is `true` and :option:`CountingEnumPrefixes` is `maxsize;last_` +When :option:`EnableCountingEnumHeuristic` is `true` and +:option:`CountingEnumPrefixes` is `maxsize;last_` .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/throw-keyword-missing.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/throw-keyword-missing.rst index 240a62e..be80fc8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/throw-keyword-missing.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/throw-keyword-missing.rst @@ -3,9 +3,10 @@ bugprone-throw-keyword-missing ============================== -Warns about a potentially missing ``throw`` keyword. If a temporary object is created, but the -object's type derives from (or is the same as) a class that has 'EXCEPTION', 'Exception' or -'exception' in its name, we can assume that the programmer's intention was to throw that object. +Warns about a potentially missing ``throw`` keyword. If a temporary object +is created, but the object's type derives from (or is the same as) a class +that has 'EXCEPTION', 'Exception' or 'exception' in its name, we can assume +that the programmer's intention was to throw that object. Example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/throwing-static-initialization.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/throwing-static-initialization.rst index 5e320a1..4f88719 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/throwing-static-initialization.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/throwing-static-initialization.rst @@ -11,4 +11,4 @@ References This check corresponds to the CERT C++ Coding Standard rule `ERR58-CPP. Handle all exceptions thrown before main() begins executing -<https://www.securecoding.cert.org/confluence/display/cplusplus/ERR58-CPP.+Handle+all+exceptions+thrown+before+main%28%29+begins+executing>`_.
\ No newline at end of file +<https://www.securecoding.cert.org/confluence/display/cplusplus/ERR58-CPP.+Handle+all+exceptions+thrown+before+main%28%29+begins+executing>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/too-small-loop-variable.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/too-small-loop-variable.rst index 077abf0..efba0cc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/too-small-loop-variable.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/too-small-loop-variable.rst @@ -14,10 +14,11 @@ iteration range. for (short i = 0; i < size; ++i) {} } -This ``for`` loop is an infinite loop because the ``short`` type can't represent -all values in the ``[0..size]`` interval. +This ``for`` loop is an infinite loop because the ``short`` type can't +represent all values in the ``[0..size]`` interval. -In a real use case size means a container's size which depends on the user input. +In a real use case size means a container's size which depends on the +user input. .. code-block:: c++ @@ -29,8 +30,9 @@ This algorithm works for a small amount of objects, but will lead to freeze for a larger user input. It's recommended to enable the compiler warning -`-Wtautological-constant-out-of-range-compare` as well, since check does not -inspect compile-time constant loop boundaries to avoid overlaps with the warning. +`-Wtautological-constant-out-of-range-compare` as well, since check does +not inspect compile-time constant loop boundaries to avoid overlaps with +the warning. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst index 552e6db..3423eaa 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-optional-access.rst @@ -15,9 +15,10 @@ types collectively as ``optional<T>``. An access to the value of an ``optional<T>`` occurs when one of its ``value``, ``operator*``, or ``operator->`` member functions is invoked. To align with -common misconceptions, the check considers these member functions as equivalent, -even though there are subtle differences related to exceptions versus undefined -behavior. See *Additional notes*, below, for more information on this topic. +common misconceptions, the check considers these member functions as +equivalent, even though there are subtle differences related to exceptions +versus undefined behavior. See *Additional notes*, below, for more information +on this topic. An access to the value of an ``optional<T>`` is considered safe if and only if code in the local scope (for example, a function body) ensures that the @@ -208,8 +209,8 @@ local variable and use that variable to access the value. For example: Do not rely on uncommon-API invariants ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -When uncommon APIs guarantee that an optional has contents, do not rely on it -- -instead, check explicitly that the optional object has a value. For example: +When uncommon APIs guarantee that an optional has contents, do not rely on it +-- instead, check explicitly that the optional object has a value. For example: .. code-block:: c++ @@ -293,8 +294,8 @@ or terminating the program), why treat it the same as ``operator*()`` which causes undefined behavior (UB)? That is, why is it considered unsafe to access an optional with ``value()``, if it's not provably populated with a value? For that matter, why is ``CHECK()`` followed by ``operator*()`` any better than -``value()``, given that they are semantically equivalent (on configurations that -disable exceptions)? +``value()``, given that they are semantically equivalent (on configurations +that disable exceptions)? The answer is that we assume most users do not realize the difference between ``value()`` and ``operator*()``. Shifting to ``operator*()`` and some form of @@ -308,3 +309,22 @@ advantages: * Performance. A single check can cover many or even all accesses within scope. This gives the user the best of both worlds -- the safety of a dynamic check, but without incurring redundant costs. + +Options +------- + +.. option:: IgnoreSmartPointerDereference + + If set to `true`, the check ignores optionals that + are reached through overloaded smart-pointer-like dereference (``operator*``, + ``operator->``) on classes other than the optional type itself. This helps + avoid false positives where the analysis cannot equate results across such + calls. This does not cover access through ``operator[]``. Default is `false`. + +.. option:: IgnoreValueCalls + + If set to `true`, the check does not diagnose calls + to ``optional::value()``. Diagnostics for ``operator*()`` and + ``operator->()`` remain enabled. This is useful for codebases that + intentionally rely on ``value()`` for defined, guarded access while still + flagging UB-prone operator dereferences. Default is `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-string-to-number-conversion.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-string-to-number-conversion.rst index c3ea196..e38b298 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-string-to-number-conversion.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unchecked-string-to-number-conversion.rst @@ -5,8 +5,8 @@ bugprone-unchecked-string-to-number-conversion This check flags calls to string-to-number conversion functions that do not verify the validity of the conversion, such as ``atoi()`` or ``scanf()``. It -does not flag calls to ``strtol()``, or other, related conversion functions that -do perform better error checking. +does not flag calls to ``strtol()``, or other, related conversion functions +that do perform better error checking. .. code-block:: c diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unhandled-self-assignment.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unhandled-self-assignment.rst index 3a6245d..07c4b33 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unhandled-self-assignment.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unhandled-self-assignment.rst @@ -10,9 +10,10 @@ Finds user-defined copy assignment operators which do not protect the code against self-assignment either by checking self-assignment explicitly or using the copy-and-swap or the copy-and-move method. -By default, this check searches only those classes which have any pointer or C array field -to avoid false positives. In case of a pointer or a C array, it's likely that self-copy -assignment breaks the object if the copy assignment operator was not written with care. +By default, this check searches only those classes which have any pointer or C +array field to avoid false positives. In case of a pointer or a C array, it's +likely that self-copy assignment breaks the object if the copy assignment +operator was not written with care. See also: `OOP54-CPP. Gracefully handle self-copy assignment @@ -90,9 +91,9 @@ The second one is the copy-and-swap method when we create a temporary copy } }; -There is a third pattern which is less common. Let's call it the copy-and-move method -when we create a temporary copy (using the copy constructor) and then move this -temporary object into ``this`` (needs a move assignment operator): +There is a third pattern which is less common. Let's call it the copy-and-move +method when we create a temporary copy (using the copy constructor) and then move +this temporary object into ``this`` (needs a move assignment operator): .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unintended-char-ostream-output.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unintended-char-ostream-output.rst index 29254c4..da510c4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unintended-char-ostream-output.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unintended-char-ostream-output.rst @@ -3,14 +3,14 @@ bugprone-unintended-char-ostream-output ======================================= -Finds unintended character output from ``unsigned char`` and ``signed char`` to an -``ostream``. +Finds unintended character output from ``unsigned char`` and ``signed char`` to +an ``ostream``. -Normally, when ``unsigned char (uint8_t)`` or ``signed char (int8_t)`` is used, it -is more likely a number than a character. However, when it is passed directly to -``std::ostream``'s ``operator<<``, the result is the character output instead -of the numeric value. This often contradicts the developer's intent to print -integer values. +Normally, when ``unsigned char (uint8_t)`` or ``signed char (int8_t)`` is used, +it is more likely a number than a character. However, when it is passed +directly to ``std::ostream``'s ``operator<<``, the result is the character +output instead of the numeric value. This often contradicts the developer's +intent to print integer values. .. code-block:: c++ @@ -26,8 +26,9 @@ intent, by default, it will cast to ``unsigned int`` for ``unsigned char`` and std::cout << static_cast<unsigned int>(v); // when v is unsigned char std::cout << static_cast<int>(v); // when v is signed char -To avoid lengthy cast statements, add prefix ``+`` to the variable can also -suppress warnings because unary expression will promote the value to an ``int``. +To avoid lengthy cast statements, add prefix ``+`` to the variable can +also suppress warnings because unary expression will promote the value +to an ``int``. .. code-block:: c++ @@ -44,11 +45,11 @@ Options .. option:: AllowedTypes - A semicolon-separated list of type names that will be treated like the ``char``
- type: the check will not report variables declared with with these types or
- explicit cast expressions to these types. Note that this distinguishes type
- aliases from the original type, so specifying e.g. ``unsigned char`` here
- will not suppress reports about ``uint8_t`` even if it is defined as a
+ A semicolon-separated list of type names that will be treated like the ``char`` + type: the check will not report variables declared with with these types or + explicit cast expressions to these types. Note that this distinguishes type + aliases from the original type, so specifying e.g. ``unsigned char`` here + will not suppress reports about ``uint8_t`` even if it is defined as a ``typedef`` alias for ``unsigned char``. Default is `unsigned char;signed char`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst index 6937c517..cb7ea41 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unsafe-functions.rst @@ -19,7 +19,8 @@ The check implements the following rules from the CERT C Coding Standard: Unsafe functions ---------------- -The following functions are reported if :option:`ReportDefaultFunctions` is enabled. +The following functions are reported if :option:`ReportDefaultFunctions` +is enabled. If *Annex K.* is available, a replacement from *Annex K.* is suggested for the following functions: @@ -42,7 +43,8 @@ following functions from the previous list: - ``asctime``, ``asctime_r``, suggested replacement: ``strftime`` - ``gets``, suggested replacement: ``fgets`` -The following functions are always checked, regardless of *Annex K* availability: +The following functions are always checked, regardless of *Annex K* +availability: - ``rewind``, suggested replacement: ``fseek`` - ``setbuf``, suggested replacement: ``setvbuf`` @@ -80,8 +82,8 @@ including any system headers. Custom functions ---------------- -The option :option:`CustomFunctions` allows the user to define custom functions to be -checked. The format is the following, without newlines: +The option :option:`CustomFunctions` allows the user to define custom functions +to be checked. The format is the following, without newlines: .. code:: @@ -94,36 +96,62 @@ checked. The format is the following, without newlines: The functions are matched using POSIX extended regular expressions. *(Note: The regular expressions do not support negative* ``(?!)`` *matches.)* -The `reason` is optional and is used to provide additional information about the -reasoning behind the replacement. The default reason is `is marked as unsafe`. +The ``reason`` is optional and is used to provide additional information about the +reasoning behind the replacement. The default reason is ``is marked as unsafe``. -If `replacement` is empty, the text `it should not be used` will be shown -instead of the suggestion for a replacement. +If ``replacement`` is empty, the default text ``it should not be used`` will be +shown instead of the suggestion for a replacement. -As an example, the configuration `^original$, replacement, is deprecated;` -will produce the following diagnostic message. +If the ``reason`` starts with the character ``>``, the reason becomes fully custom. +The default suffix is disabled even if a ``replacement`` is present, and only the +reason message is shown after the matched function, to allow better control over +the suggestions. (The starting ``>`` and whitespace directly after it are +trimmed from the message.) + +As an example, the following configuration matches only the function ``original`` +in the default namespace. A similar diagnostic can also be printed using a fully +custom reason. .. code:: c + // bugprone-unsafe-functions.CustomFunctions: + // ^original$, replacement, is deprecated; + // Using the fully custom message syntax: + // ^suspicious$,,> should be avoided if possible. original(); // warning: function 'original' is deprecated; 'replacement' should be used instead. + suspicious(); // warning: function 'suspicious' should be avoided if possible. ::std::original(); // no-warning original_function(); // no-warning -If the regular expression contains the character `:`, it is matched against the -qualified name (i.e. ``std::original``), otherwise the regex is matched against the unqualified name (``original``). -If the regular expression starts with `::` (or `^::`), it is matched against the -fully qualified name (``::std::original``). +If the regular expression contains the character ``:``, it is matched against the +qualified name (i.e. ``std::original``), otherwise the regex is matched against +the unqualified name (``original``). If the regular expression starts with ``::`` +(or ``^::``), it is matched against the fully qualified name +(``::std::original``). + +One of the use cases for fully custom messages is suggesting compiler options +and warning flags: + +.. code:: c + + // bugprone-unsafe-functions.CustomFunctions: + // ^memcpy$,,>is recommended to have compiler hardening using '_FORTIFY_SOURCE'; + // ^printf$,,>is recommended to have the '-Werror=format-security' compiler warning flag; + + memcpy(dest, src, 999'999); // warning: function 'memcpy' is recommended to have compiler hardening using '_FORTIFY_SOURCE' + printf(raw_str); // warning: function 'printf' is recommended to have the '-Werror=format-security' compiler warning flag .. note:: - Fully qualified names can contain template parameters on certain C++ classes, but not on C++ functions. - Type aliases are resolved before matching. + Fully qualified names can contain template parameters on certain C++ classes, + but not on C++ functions. Type aliases are resolved before matching. As an example, the member function ``open`` in the class ``std::ifstream`` has a fully qualified name of ``::std::basic_ifstream<char>::open``. - The example could also be matched with the regex ``::std::basic_ifstream<[^>]*>::open``, which matches all potential - template parameters, but does not match nested template classes. + The example could also be matched with the regex + ``::std::basic_ifstream<[^>]*>::open``, which matches all potential template + parameters, but does not match nested template classes. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst index 10ae0fe..725403a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-return-value.rst @@ -3,7 +3,8 @@ bugprone-unused-return-value ============================ -Warns on unused function return values. The checked functions can be configured. +Warns on unused function return values. The checked functions can be +configured. Operator overloading with assignment semantics are ignored. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst index 965fc2d..77424d3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst @@ -83,9 +83,9 @@ move: std::cout << str; } -If you want to avoid the overhead of actually reinitializing the object, you can -create a dummy function that causes the check to assume the object was -reinitialized: +If you want to avoid the overhead of actually reinitializing the object, +you can create a dummy function that causes the check to assume the object +was reinitialized: .. code-block:: c++ @@ -104,9 +104,9 @@ You can use this as follows: std::cout << str; } -The check will not output a warning in this case because passing the object to a -function as a non-const pointer or reference counts as a reinitialization (see section -`Reinitialization`_ below). +The check will not output a warning in this case because passing the object +to a function as a non-const pointer or reference counts as a reinitialization +(see section `Reinitialization`_ below). Unsequenced moves, uses, and reinitializations ---------------------------------------------- @@ -143,10 +143,10 @@ reference parameter. This means that the check will flag a use-after-move even on a type that does not define a move constructor or move assignment operator. This is intentional. -Developers may use ``std::move`` on such a type in the expectation that the type -will add move semantics in the future. If such a ``std::move`` has the potential -to cause a use-after-move, we want to warn about it even if the type does not -implement move semantics yet. +Developers may use ``std::move`` on such a type in the expectation that the +type will add move semantics in the future. If such a ``std::move`` has the +potential to cause a use-after-move, we want to warn about it even if the type +does not implement move semantics yet. Furthermore, if the result of ``std::move`` *is* passed to an rvalue reference parameter, this will always be considered to cause a move, even if the function @@ -169,9 +169,9 @@ that a move always takes place: The check will assume that the last line causes a move, even though, in this particular case, it does not. Again, this is intentional. -There is one special case: A call to ``std::move`` inside a ``try_emplace`` call -is conservatively assumed not to move. This is to avoid spurious warnings, as -the check has no way to reason about the ``bool`` returned by ``try_emplace``. +There is one special case: A call to ``std::move`` inside a ``try_emplace`` +call is conservatively assumed not to move. This is to avoid spurious warnings, +as the check has no way to reason about the ``bool`` returned by ``try_emplace``. When analyzing the order in which moves, uses and reinitializations happen (see section `Unsequenced moves, uses, and reinitializations`_), the move is assumed @@ -198,8 +198,8 @@ is considered to be a use. An exception to this are objects of type ``std::unique_ptr``, ``std::shared_ptr``, ``std::weak_ptr``, ``std::optional``, and ``std::any``. An exception to this are objects of type ``std::unique_ptr``, -``std::shared_ptr``, ``std::weak_ptr``, ``std::optional``, and ``std::any``, which -can be reinitialized via ``reset``. For smart pointers specifically, the +``std::shared_ptr``, ``std::weak_ptr``, ``std::optional``, and ``std::any``, +which can be reinitialized via ``reset``. For smart pointers specifically, the moved-from objects have a well-defined state of being ``nullptr``s, and only ``operator*``, ``operator->`` and ``operator[]`` are considered bad accesses as they would be dereferencing a ``nullptr``. @@ -217,10 +217,10 @@ The check considers a variable to be reinitialized in the following cases: lvalue reference. (It is assumed that the variable may be an out-parameter for the function.) - - ``clear()`` or ``assign()`` is called on the variable and the variable is of - one of the standard container types ``basic_string``, ``vector``, ``deque``, - ``forward_list``, ``list``, ``set``, ``map``, ``multiset``, ``multimap``, - ``unordered_set``, ``unordered_map``, ``unordered_multiset``, + - ``clear()`` or ``assign()`` is called on the variable and the variable is + of one of the standard container types ``basic_string``, ``vector``, + ``deque``, ``forward_list``, ``list``, ``set``, ``map``, ``multiset``, + ``multimap``, ``unordered_set``, ``unordered_map``, ``unordered_multiset``, ``unordered_multimap``. - ``reset()`` is called on the variable and the variable is of type @@ -253,3 +253,13 @@ For example, if an additional member variable is added to ``S``, it is easy to forget to add the reinitialization for this additional member. Instead, it is safer to assign to the entire struct in one go, and this will also avoid the use-after-move warning. + +Options +------- + +.. option:: InvalidationFunctions + + A semicolon-separated list of names of functions that cause their first + arguments to be invalidated (e.g., closing a handle). + For member functions, the first argument is considered to be the implicit + object argument (``this``). Default value is an empty string. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/virtual-near-miss.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/virtual-near-miss.rst index b3f02b8..d422684 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/virtual-near-miss.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/virtual-near-miss.rst @@ -3,8 +3,9 @@ bugprone-virtual-near-miss ========================== -Warn if a function is a near miss (i.e. the name is very similar and the function -signature is the same) to a virtual function from a base class. +Warn if a function is a near miss (i.e. the name is very similar and +the function signature is the same) to a virtual function from a base +class. Example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/con36-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/con36-c.rst index 2a1d517..95f70d8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/con36-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/con36-c.rst @@ -6,5 +6,6 @@ cert-con36-c ============ The `cert-con36-c` check is an alias, please see -:doc:`bugprone-spuriously-wake-up-functions <../bugprone/spuriously-wake-up-functions>` +:doc:`bugprone-spuriously-wake-up-functions +<../bugprone/spuriously-wake-up-functions>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/con54-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/con54-cpp.rst index 3b4039d..c8cc8bd 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/con54-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/con54-cpp.rst @@ -6,5 +6,6 @@ cert-con54-cpp ============== The `cert-con54-cpp` check is an alias, please see -:doc:`bugprone-spuriously-wake-up-functions <../bugprone/spuriously-wake-up-functions>` +:doc:`bugprone-spuriously-wake-up-functions +<../bugprone/spuriously-wake-up-functions>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/ctr56-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/ctr56-cpp.rst index e42acbe..78afc2f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/ctr56-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/ctr56-cpp.rst @@ -7,4 +7,4 @@ cert-ctr56-cpp The `cert-ctr56-cpp` check is an alias, please see :doc:`bugprone-pointer-arithmetic-on-polymorphic-object -<../bugprone/pointer-arithmetic-on-polymorphic-object>` for more information.
\ No newline at end of file +<../bugprone/pointer-arithmetic-on-polymorphic-object>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/dcl16-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/dcl16-c.rst index 7a5b63d..977a0a5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/dcl16-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/dcl16-c.rst @@ -6,4 +6,5 @@ cert-dcl16-c ============ The `cert-dcl16-c` check is an alias, please see -:doc:`readability-uppercase-literal-suffix <../readability/uppercase-literal-suffix>` for more information. +:doc:`readability-uppercase-literal-suffix +<../readability/uppercase-literal-suffix>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/dcl50-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/dcl50-cpp.rst index 719e03d..dd4bd30 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/dcl50-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/dcl50-cpp.rst @@ -6,7 +6,8 @@ cert-dcl50-cpp ============== The `cert-dcl50-cpp` check is an alias, please see -`modernize-avoid-variadic-functions <../modernize/avoid-variadic-functions.html>`_ +:doc:`modernize-avoid-variadic-functions +<../modernize/avoid-variadic-functions>` for more information. This check corresponds to the CERT C++ Coding Standard rule diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/dcl58-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/dcl58-cpp.rst index 1b8c2c4f9..f584e88 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/dcl58-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/dcl58-cpp.rst @@ -3,8 +3,9 @@ cert-dcl58-cpp ============== -The `cert-dcl58-cpp` is an aliaes, please see -`bugprone-std-namespace-modification <../bugprone/std-namespace-modification.html>`_ +The `cert-dcl58-cpp` is an alias, please see +:doc:`bugprone-std-namespace-modification +<../bugprone/std-namespace-modification>` for more information. This check corresponds to the CERT C++ Coding Standard rule diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/dcl59-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/dcl59-cpp.rst index 9aeed14..027d2ec 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/dcl59-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/dcl59-cpp.rst @@ -6,4 +6,5 @@ cert-dcl59-cpp ============== The `cert-dcl59-cpp` check is an alias, please see -:doc:`google-build-namespaces <../google/build-namespaces>` for more information. +:doc:`google-build-namespaces <../google/build-namespaces>` +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/env33-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/env33-c.rst index 751bccf..33fa7f1 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/env33-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/env33-c.rst @@ -4,7 +4,7 @@ cert-env33-c ============ The `cert-env33-c` check is an alias, please see -`bugprone-command-processor <../bugprone/command-processor.html>`_ +:doc:`bugprone-command-processor <../bugprone/command-processor>` for more information. This check corresponds to the CERT C Coding Standard rule diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/err09-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/err09-cpp.rst index 1a9c0f9..65d3a60 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/err09-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/err09-cpp.rst @@ -6,10 +6,12 @@ cert-err09-cpp ============== The `cert-err09-cpp` check is an alias, please see -:doc:`misc-throw-by-value-catch-by-reference <../misc/throw-by-value-catch-by-reference>` +:doc:`misc-throw-by-value-catch-by-reference +<../misc/throw-by-value-catch-by-reference>` for more information. This check corresponds to the CERT C++ Coding Standard recommendation -ERR09-CPP. Throw anonymous temporaries. However, all of the CERT recommendations -have been removed from public view, and so their justification for the behavior -of this check requires an account on their wiki to view. +ERR09-CPP. Throw anonymous temporaries. However, all of the CERT +recommendations have been removed from public view, and so their +justification for the behavior of this check requires an account on +their wiki to view. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/err33-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/err33-c.rst index 9bcc5f9..75da669 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/err33-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/err33-c.rst @@ -186,8 +186,8 @@ functions are checked: * wscanf() * wscanf_s() -This check is an alias of check :doc:`bugprone-unused-return-value <../bugprone/unused-return-value>` -with a fixed set of functions. +This check is an alias of check :doc:`bugprone-unused-return-value +<../bugprone/unused-return-value>` with a fixed set of functions. Suppressing issues by casting to ``void`` is enabled by default and can be disabled by setting `AllowCastToVoid` option to `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/err34-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/err34-c.rst index dc3f632..5f0dc80 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/err34-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/err34-c.rst @@ -6,5 +6,6 @@ cert-err34-c ============ The cert-err34-c check is an alias, please see -`bugprone-unchecked-string-to-number-conversion <../bugprone/unchecked-string-to-number-conversion.html>`_ +:doc:`bugprone-unchecked-string-to-number-conversion +<../bugprone/unchecked-string-to-number-conversion>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/err52-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/err52-cpp.rst index 144d209b..4b726d81 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/err52-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/err52-cpp.rst @@ -4,7 +4,7 @@ cert-err52-cpp ============== The `cert-err52-cpp` check is an alias, please see -`modernize-avoid-setjmp-longjmp <../modernize/avoid-setjmp-longjmp.html>`_ +:doc:`modernize-avoid-setjmp-longjmp <../modernize/avoid-setjmp-longjmp>` for more information. This check corresponds to the CERT C++ Coding Standard rule diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/err58-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/err58-cpp.rst index 4db0727..c5e2850 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/err58-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/err58-cpp.rst @@ -6,7 +6,8 @@ cert-err58-cpp ============== The `cert-err58-cpp` check is an alias, please see -`bugprone-throwing-static-initialization <../bugprone/throwing-static-initialization.html>`_ +:doc:`bugprone-throwing-static-initialization +<../bugprone/throwing-static-initialization>` for more information. This check corresponds to the CERT C++ Coding Standard rule diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/err60-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/err60-cpp.rst index 9fcb840..f5ed313 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/err60-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/err60-cpp.rst @@ -1,11 +1,15 @@ .. title:: clang-tidy - cert-err60-cpp +.. meta:: + :http-equiv=refresh: 5;URL=../bugprone/exception-copy-constructor-throws.html cert-err60-cpp ============== -This check flags all throw expressions where the exception object is not nothrow -copy constructible. +The `cert-err60-cpp` check is an alias, please see +:doc:`bugprone-exception-copy-constructor-throws +<../bugprone/exception-copy-constructor-throws>` +for more information. This check corresponds to the CERT C++ Coding Standard rule `ERR60-CPP. Exception objects must be nothrow copy constructible -<https://www.securecoding.cert.org/confluence/display/cplusplus/ERR60-CPP.+Exception+objects+must+be+nothrow+copy+constructible>`_. +<https://wiki.sei.cmu.edu/confluence/display/cplusplus/ERR60-CPP.+Exception+objects+must+be+nothrow+copy+constructible>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/err61-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/err61-cpp.rst index 9600795..2cf7813 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/err61-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/err61-cpp.rst @@ -6,5 +6,6 @@ cert-err61-cpp ============== The `cert-err61-cpp` check is an alias, please see -:doc:`misc-throw-by-value-catch-by-reference <../misc/throw-by-value-catch-by-reference>` +:doc:`misc-throw-by-value-catch-by-reference +<../misc/throw-by-value-catch-by-reference>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/exp42-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/exp42-c.rst index 03a3679..69f9c7a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/exp42-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/exp42-c.rst @@ -5,4 +5,5 @@ cert-exp42-c ============ The `cert-exp42-c` check is an alias, please see -:doc:`bugprone-suspicious-memory-comparison <../bugprone/suspicious-memory-comparison>` for more information. +:doc:`bugprone-suspicious-memory-comparison +<../bugprone/suspicious-memory-comparison>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/flp30-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/flp30-c.rst index 5f6eff44..8bd23f6c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/flp30-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/flp30-c.rst @@ -4,7 +4,7 @@ cert-flp30-c ============ The `cert-flp30-c` check is an alias, please see -`bugprone-float-loop-counter <../bugprone/float-loop-counter.html>`_ +:doc:`bugprone-float-loop-counter <../bugprone/float-loop-counter>` for more information This check corresponds to the CERT C Coding Standard rule diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/flp37-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/flp37-c.rst index 05277ef..01c3544 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/flp37-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/flp37-c.rst @@ -5,4 +5,5 @@ cert-flp37-c ============ The `cert-flp37-c` check is an alias, please see -:doc:`bugprone-suspicious-memory-comparison <../bugprone/suspicious-memory-comparison>` for more information. +:doc:`bugprone-suspicious-memory-comparison +<../bugprone/suspicious-memory-comparison>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/mem57-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/mem57-cpp.rst index b359d85a..aeeffec 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/mem57-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/mem57-cpp.rst @@ -3,8 +3,9 @@ cert-mem57-cpp ============== -The `cert-mem57-cpp` is an aliaes, please see -`bugprone-default-operator-new-on-overaligned-type <../bugprone/default-operator-new-on-overaligned-type.html>`_ +The `cert-mem57-cpp` is an alias, please see +:doc:`bugprone-default-operator-new-on-overaligned-type +<../bugprone/default-operator-new-on-overaligned-type>` for more information. This check corresponds to the CERT C++ Coding Standard rule diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/msc30-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/msc30-c.rst index a2898f1..27f92a8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/msc30-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/msc30-c.rst @@ -1,9 +1,13 @@ .. title:: clang-tidy - cert-msc30-c .. meta:: - :http-equiv=refresh: 5;URL=../cert/msc50-cpp.html + :http-equiv=refresh: 5;URL=../misc/predictable-rand.html cert-msc30-c ============ The `cert-msc30-c` check is an alias, please see -:doc:`cert-msc50-cpp <../cert/msc50-cpp>` for more information. +:doc:`misc-predictable-rand <../misc/predictable-rand>` for more information. + +This check corresponds to the CERT C Coding Standard rule +`MSC30-C. Do not use the rand() function for generating pseudorandom numbers +<https://wiki.sei.cmu.edu/confluence/display/c/MSC30-C.+Do+not+use+the+rand%28%29+function+for+generating+pseudorandom+numbers>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/msc32-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/msc32-c.rst index 6e453ed..e0ed807 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/msc32-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/msc32-c.rst @@ -1,9 +1,14 @@ .. title:: clang-tidy - cert-msc32-c .. meta:: - :http-equiv=refresh: 5;URL=../cert/msc51-cpp.html + :http-equiv=refresh: 5;URL=../bugprone/random-generator-seed.html cert-msc32-c ============ The `cert-msc32-c` check is an alias, please see -:doc:`cert-msc51-cpp <../cert/msc51-cpp>` for more information. +:doc:`bugprone-random-generator-seed <../bugprone/random-generator-seed>` +for more information. + +This check corresponds to the CERT C Coding Standard rule +`MSC32-C. Properly seed pseudorandom number generators +<https://wiki.sei.cmu.edu/confluence/display/c/MSC32-C.+Properly+seed+pseudorandom+number+generators>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/msc50-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/msc50-cpp.rst index debf01c..59738f5b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/msc50-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/msc50-cpp.rst @@ -1,11 +1,13 @@ .. title:: clang-tidy - cert-msc50-cpp +.. meta:: + :http-equiv=refresh: 5;URL=../misc/predictable-rand.html cert-msc50-cpp ============== -Pseudorandom number generators use mathematical algorithms to produce a sequence -of numbers with good statistical properties, but the numbers produced are not -genuinely random. The ``std::rand()`` function takes a seed (number), runs a -mathematical operation on it and returns the result. By manipulating the seed -the result can be predictable. This check warns for the usage of -``std::rand()``. +The `cert-msc50-cpp` check is an alias, please see +:doc:`misc-predictable-rand <../misc/predictable-rand>` for more information. + +This check corresponds to the CERT C Coding Standard rule +`MSC50-CPP. Do not use std::rand() for generating pseudorandom numbers +<https://wiki.sei.cmu.edu/confluence/display/cplusplus/MSC50-CPP.+Do+not+use+std%3A%3Arand%28%29+for+generating+pseudorandom+numbers>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/msc51-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/msc51-cpp.rst index 99e550a..dbaed1d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/msc51-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/msc51-cpp.rst @@ -1,40 +1,15 @@ .. title:: clang-tidy - cert-msc51-cpp +.. meta:: + :http-equiv=refresh: 5;URL=../bugprone/random-generator-seed.html cert-msc51-cpp ============== -This check flags all pseudo-random number engines, engine adaptor -instantiations and ``srand()`` when initialized or seeded with default argument, -constant expression or any user-configurable type. Pseudo-random number -engines seeded with a predictable value may cause vulnerabilities e.g. in -security protocols. -This is a CERT security rule, see -`MSC51-CPP. Ensure your random number generator is properly seeded -<https://wiki.sei.cmu.edu/confluence/display/cplusplus/MSC51-CPP.+Ensure+your+random+number+generator+is+properly+seeded>`_ and -`MSC32-C. Properly seed pseudorandom number generators -<https://wiki.sei.cmu.edu/confluence/display/c/MSC32-C.+Properly+seed+pseudorandom+number+generators>`_. - -Examples: - -.. code-block:: c++ - - void foo() { - std::mt19937 engine1; // Diagnose, always generate the same sequence - std::mt19937 engine2(1); // Diagnose - engine1.seed(); // Diagnose - engine2.seed(1); // Diagnose - - std::time_t t; - engine1.seed(std::time(&t)); // Diagnose, system time might be controlled by user +The `cert-msc51-cpp` check is an alias, please see +:doc:`bugprone-random-generator-seed +<../bugprone/random-generator-seed>` +for more information. - int x = atoi(argv[1]); - std::mt19937 engine3(x); // Will not warn - } - -Options -------- - -.. option:: DisallowedSeedTypes - - A comma-separated list of the type names which are disallowed. - Default value is `time_t,std::time_t`. +This check corresponds to the CERT C++ Coding Standard rule +`MSC51-CPP. Ensure your random number generator is properly seeded +<https://wiki.sei.cmu.edu/confluence/display/cplusplus/MSC51-CPP.+Ensure+your+random+number+generator+is+properly+seeded>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/oop54-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/oop54-cpp.rst index e7c9574..1e8b7bb 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/oop54-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/oop54-cpp.rst @@ -6,5 +6,6 @@ cert-oop54-cpp ============== The `cert-oop54-cpp` check is an alias, please see -:doc:`bugprone-unhandled-self-assignment <../bugprone/unhandled-self-assignment>` +:doc:`bugprone-unhandled-self-assignment +<../bugprone/unhandled-self-assignment>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/oop57-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/oop57-cpp.rst index 414f788..9a0f38b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/oop57-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/oop57-cpp.rst @@ -6,7 +6,8 @@ cert-oop57-cpp ============== The `cert-oop57-cpp` check is an alias, please see -`bugprone-raw-memory-call-on-non-trivial-type <../bugprone/raw-memory-call-on-non-trivial-type.html>`_ +:doc:`bugprone-raw-memory-call-on-non-trivial-type +<../bugprone/raw-memory-call-on-non-trivial-type>` for more information. This check corresponds to the CERT C++ Coding Standard rule diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/oop58-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/oop58-cpp.rst index e435490..2efa68f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/oop58-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/oop58-cpp.rst @@ -6,5 +6,6 @@ cert-oop58-cpp ============== The `cert-oop58-cpp` check is an alias, please see -:doc:`bugprone-copy-constructor-mutates-argument <../bugprone/copy-constructor-mutates-argument>` -for more information.
\ No newline at end of file +:doc:`bugprone-copy-constructor-mutates-argument +<../bugprone/copy-constructor-mutates-argument>` +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/pos44-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/pos44-c.rst index 2fd6c5c..c5141b9 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/pos44-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/pos44-c.rst @@ -6,4 +6,5 @@ cert-pos44-c ============ The `cert-pos44-c` check is an alias, please see -:doc:`bugprone-bad-signal-to-kill-thread <../bugprone/bad-signal-to-kill-thread>` for more information. +:doc:`bugprone-bad-signal-to-kill-thread +<../bugprone/bad-signal-to-kill-thread>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert/pos47-c.rst b/clang-tools-extra/docs/clang-tidy/checks/cert/pos47-c.rst index 9b62a3a..ad5570ab 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert/pos47-c.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert/pos47-c.rst @@ -6,4 +6,5 @@ cert-pos47-c ============ The `cert-pos47-c` check is an alias, please see -:doc:`concurrency-thread-canceltype-asynchronous <../concurrency/thread-canceltype-asynchronous>` for more information. +:doc:`concurrency-thread-canceltype-asynchronous +<../concurrency/thread-canceltype-asynchronous>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.SetgidSetuidOrder.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.SetgidSetuidOrder.rst index b3ba785..bb1f5d7 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.SetgidSetuidOrder.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.SetgidSetuidOrder.rst @@ -5,12 +5,13 @@ clang-analyzer-security.SetgidSetuidOrder ========================================= -The checker checks for sequences of ``setuid(getuid())`` and ``setgid(getgid())`` -calls (in this order). If such a sequence is found and there is no other -privilege-changing function call (``seteuid``, ``setreuid``, ``setresuid`` and -the GID versions of these) in between, a warning is generated. The checker finds -only exactly ``setuid(getuid())`` calls (and the GID versions), not for example -if the result of ``getuid()`` is stored in a variable. +The checker checks for sequences of ``setuid(getuid())`` and +``setgid(getgid())`` calls (in this order). If such a sequence is found and +there is no other privilege-changing function call (``seteuid``, ``setreuid``, +``setresuid`` and the GID versions of these) in between, a warning is +generated. The checker finds only exactly ``setuid(getuid())`` calls (and the +GID versions), not for example if the result of ``getuid()`` is stored in +a variable. The `clang-analyzer-security.SetgidSetuidOrder` check is an alias, please see `Clang Static Analyzer Available Checkers diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.decodeValueOfObjCType.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.decodeValueOfObjCType.rst index 4405f721..6b926f3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.decodeValueOfObjCType.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.decodeValueOfObjCType.rst @@ -1,9 +1,13 @@ .. title:: clang-tidy - clang-analyzer-security.insecureAPI.decodeValueOfObjCType +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-decodevalueofobjctype clang-analyzer-security.insecureAPI.decodeValueOfObjCType ========================================================= Warn on uses of the '-decodeValueOfObjCType:at:' method. -The clang-analyzer-security.insecureAPI.decodeValueOfObjCType check is an alias of -Clang Static Analyzer security.insecureAPI.decodeValueOfObjCType. +The `clang-analyzer-security.insecureAPI.decodeValueOfObjCType` check is an alias, please see +`Clang Static Analyzer security.insecureAPI.decodeValueOfObjCType +<https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-decodevalueofobjctype>`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.StdCLibraryFunctions.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.StdCLibraryFunctions.rst index 1790673..0415dab 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.StdCLibraryFunctions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.StdCLibraryFunctions.rst @@ -5,8 +5,8 @@ clang-analyzer-unix.StdCLibraryFunctions ======================================== -Check for invalid arguments of C standard library functions, and apply relations -between arguments and return value. +Check for invalid arguments of C standard library functions, and apply +relations between arguments and return value. The `clang-analyzer-unix.StdCLibraryFunctions` check is an alias, please see `Clang Static Analyzer Available Checkers diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-c-arrays.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-c-arrays.rst index f3fba94..be9b80a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-c-arrays.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-c-arrays.rst @@ -5,6 +5,6 @@ cppcoreguidelines-avoid-c-arrays ================================ -The cppcoreguidelines-avoid-c-arrays check is an alias, please see +The `cppcoreguidelines-avoid-c-arrays` check is an alias, please see :doc:`modernize-avoid-c-arrays <../modernize/avoid-c-arrays>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-capturing-lambda-coroutines.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-capturing-lambda-coroutines.rst index 74ec504..58bfc35 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-capturing-lambda-coroutines.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-capturing-lambda-coroutines.rst @@ -8,7 +8,7 @@ use-after-free errors and suggests avoiding captures or ensuring the lambda closure object has a guaranteed lifetime. This check implements `CP.51 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rcoro-capture>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rcoro-capture>`_ from the C++ Core Guidelines. Using coroutine lambdas with non-empty capture lists can be risky, as capturing @@ -17,9 +17,9 @@ This issue can occur even with refcounted smart pointers and copyable types. When a lambda expression creates a coroutine, it results in a closure object with storage, which is often on the stack and will eventually go out of scope. When the closure object goes out of scope, its captures also go out of scope. -While normal lambdas finish executing before this happens, coroutine lambdas may -resume from suspension after the closure object has been destructed, resulting -in use-after-free memory access for all captures. +While normal lambdas finish executing before this happens, coroutine lambdas +may resume from suspension after the closure object has been destructed, +resulting in use-after-free memory access for all captures. Consider the following example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-const-or-ref-data-members.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-const-or-ref-data-members.rst index 57c4829..82bd337 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-const-or-ref-data-members.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-const-or-ref-data-members.rst @@ -44,7 +44,7 @@ Examples: }; This check implements `C.12 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-constref>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rc-constref>`_ from the C++ Core Guidelines. Further reading: diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-do-while.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-do-while.rst index 4b195c9..8b0ee30 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-do-while.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-do-while.rst @@ -3,12 +3,13 @@ cppcoreguidelines-avoid-do-while ================================ -Warns when using ``do-while`` loops. They are less readable than plain ``while`` -loops, since the termination condition is at the end and the condition is not -checked prior to the first iteration. This can lead to subtle bugs. +Warns when using ``do-while`` loops. They are less readable than plain +``while`` loops, since the termination condition is at the end and the +condition is not checked prior to the first iteration. +This can lead to subtle bugs. This check implements `ES.75 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-do>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#res-do>`_ from the C++ Core Guidelines. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-magic-numbers.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-magic-numbers.rst index 119b1fd..22e4b95 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-magic-numbers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-magic-numbers.rst @@ -5,6 +5,6 @@ cppcoreguidelines-avoid-magic-numbers ===================================== -The cppcoreguidelines-avoid-magic-numbers check is an alias, please see +The `cppcoreguidelines-avoid-magic-numbers` check is an alias, please see :doc:`readability-magic-numbers <../readability/magic-numbers>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst index 3d5fef3..b7d2dc8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.rst @@ -6,7 +6,7 @@ cppcoreguidelines-avoid-non-const-global-variables Finds non-const global variables as described in `I.2 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#i2-avoid-non-const-global-variables>`_ of C++ Core Guidelines. -As `R.6 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-global>`_ +As `R.6 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rr-global>`_ of C++ Core Guidelines is a duplicate of rule `I.2 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#i2-avoid-non-const-global-variables>`_ it also covers that rule. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-reference-coroutine-parameters.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-reference-coroutine-parameters.rst index b44430a1..887bdc6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-reference-coroutine-parameters.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-reference-coroutine-parameters.rst @@ -3,8 +3,9 @@ cppcoreguidelines-avoid-reference-coroutine-parameters ====================================================== -Warns when a coroutine accepts reference parameters. After a coroutine suspend point, -references could be dangling and no longer valid. Instead, pass parameters as values. +Warns when a coroutine accepts reference parameters. After a coroutine suspend +point, references could be dangling and no longer valid. Instead, pass +parameters as values. Examples: @@ -17,5 +18,5 @@ Examples: } This check implements `CP.53 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rcoro-reference-parameters>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rcoro-reference-parameters>`_ from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/c-copy-assignment-signature.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/c-copy-assignment-signature.rst index 986b63b..4631198 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/c-copy-assignment-signature.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/c-copy-assignment-signature.rst @@ -5,6 +5,6 @@ cppcoreguidelines-c-copy-assignment-signature ============================================= -The `cppcoreguidelines-c-copy-assignment-signature` check is an alias, please see -:doc:`misc-unconventional-assign-operator <../misc/unconventional-assign-operator>` -for more information. +The `cppcoreguidelines-c-copy-assignment-signature` check is an alias, +please see :doc:`misc-unconventional-assign-operator +<../misc/unconventional-assign-operator>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/explicit-virtual-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/explicit-virtual-functions.rst index e9a703c..a7069d2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/explicit-virtual-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/explicit-virtual-functions.rst @@ -5,6 +5,6 @@ cppcoreguidelines-explicit-virtual-functions ============================================ -The `cppcoreguidelines-explicit-virtual-functions` check is an alias, please see -:doc:`modernize-use-override <../modernize/use-override>` +The `cppcoreguidelines-explicit-virtual-functions` check is an alias, +please see :doc:`modernize-use-override <../modernize/use-override>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/init-variables.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/init-variables.rst index 0465436..e8ca823 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/init-variables.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/init-variables.rst @@ -8,8 +8,8 @@ value. These may lead to unexpected behavior if there is a code path that reads the variable before assigning to it. This rule is part of the `Type safety (Type.5) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-type-init>`_ -profile and `ES.20 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-always>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-type-init>`_ +profile and `ES.20 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#res-always>`_ from the C++ Core Guidelines. Only integers, booleans, floats, doubles and pointers are checked. The fix diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/interfaces-global-init.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/interfaces-global-init.rst index f8e9da9..65ff1db 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/interfaces-global-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/interfaces-global-init.rst @@ -7,7 +7,7 @@ This check flags initializers of globals that access extern objects, and therefore can lead to order-of-initialization problems. This check implements `I.22 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ri-global-init>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#ri-global-init>`_ from the C++ Core Guidelines. Note that currently this does not flag calls to non-constexpr functions, and diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/macro-to-enum.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/macro-to-enum.rst index e64f030..5686624 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/macro-to-enum.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/macro-to-enum.rst @@ -5,5 +5,6 @@ cppcoreguidelines-macro-to-enum =============================== -The cppcoreguidelines-macro-to-enum check is an alias, please see -:doc:`modernize-macro-to-enum <../modernize/macro-to-enum>` for more information. +The `cppcoreguidelines-macro-to-enum` check is an alias, please see +:doc:`modernize-macro-to-enum <../modernize/macro-to-enum>` +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst index 62e38fc..c2af123 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst @@ -43,5 +43,5 @@ Options Specify the function used for forwarding. Default is `::std::forward`. This check implements `F.19 -<http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-forward>`_ +<http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rf-forward>`_ from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst index ea24e87..b1d3e40 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/narrowing-conversions.rst @@ -9,6 +9,6 @@ This check implements part of `ES.46 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es46-avoid-lossy-narrowing-truncating-arithmetic-conversions>`_ from the C++ Core Guidelines. -The cppcoreguidelines-narrowing-conversions check is an alias, please see +The `cppcoreguidelines-narrowing-conversions` check is an alias, please see :doc:`bugprone-narrowing-conversions <../bugprone/narrowing-conversions>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-malloc.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-malloc.rst index e3a1620..6b95604 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-malloc.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-malloc.rst @@ -4,13 +4,13 @@ cppcoreguidelines-no-malloc =========================== This check handles C-Style memory management using ``malloc()``, ``realloc()``, -``calloc()`` and ``free()``. It warns about its use and tries to suggest the use -of an appropriate RAII object. -Furthermore, it can be configured to check against a user-specified list of functions -that are used for memory management (e.g. ``posix_memalign()``). +``calloc()`` and ``free()``. It warns about its use and tries to suggest the +use of an appropriate RAII object. +Furthermore, it can be configured to check against a user-specified list of +functions that are used for memory management (e.g. ``posix_memalign()``). This check implements `R.10 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-mallocfree>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rr-mallocfree>`_ from the C++ Core Guidelines. There is no attempt made to provide fix-it hints, since manual resource diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst index 59981f2..81b88e3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst @@ -36,5 +36,5 @@ Examples: } This check implements `CP.52 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rcoro-locks>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rcoro-locks>`_ from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/noexcept-move-operations.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/noexcept-move-operations.rst index a4b0f7d..ca6b92c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/noexcept-move-operations.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/noexcept-move-operations.rst @@ -9,5 +9,5 @@ This check implements `C.66 <https://isocpp.github.io/CppCoreGuidelines/CppCoreG from the C++ Core Guidelines. The `cppcoreguidelines-noexcept-move-operations` check is an alias, please see -:doc:`performance-noexcept-move-constructor <../performance/noexcept-move-constructor>` -for more information. +:doc:`performance-noexcept-move-constructor +<../performance/noexcept-move-constructor>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/non-private-member-variables-in-classes.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/non-private-member-variables-in-classes.rst index 7f18c17..a08bb5c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/non-private-member-variables-in-classes.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/non-private-member-variables-in-classes.rst @@ -5,7 +5,6 @@ cppcoreguidelines-non-private-member-variables-in-classes ========================================================= -The cppcoreguidelines-non-private-member-variables-in-classes check is an alias, -please see -:doc:`misc-non-private-member-variables-in-classes <../misc/non-private-member-variables-in-classes>` -for more information. +The `cppcoreguidelines-non-private-member-variables-in-classes` check is +an alias, please see :doc:`misc-non-private-member-variables-in-classes +<../misc/non-private-member-variables-in-classes>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/owning-memory.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/owning-memory.rst index 4fc49f8..218de55 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/owning-memory.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/owning-memory.rst @@ -3,9 +3,9 @@ cppcoreguidelines-owning-memory =============================== -This check implements the type-based semantics of ``gsl::owner<T*>``, which allows -static analysis on code, that uses raw pointers to handle resources like -dynamic memory, but won't introduce RAII concepts. +This check implements the type-based semantics of ``gsl::owner<T*>``, which +allows static analysis on code, that uses raw pointers to handle resources +like dynamic memory, but won't introduce RAII concepts. This check implements `I.11 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#i11-never-transfer-ownership-by-a-raw-pointer-t-or-reference-t>`_, @@ -14,7 +14,7 @@ This check implements `I.11 `R.3 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#r3-a-raw-pointer-a-t-is-non-owning>`_ and `GSL.Views -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-views>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#ss-views>`_ from the C++ Core Guidelines. The definition of a ``gsl::owner<T*>`` is straight forward @@ -23,13 +23,14 @@ The definition of a ``gsl::owner<T*>`` is straight forward namespace gsl { template <typename T> owner = T; } It is therefore simple to introduce the owner even without using an implementation of -the `Guideline Support Library <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-gsl>`_. +the `Guideline Support Library <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#s-gsl>`_. All checks are purely type based and not (yet) flow sensitive. -The following examples will demonstrate the correct and incorrect initializations -of owners, assignment is handled the same way. Note that both ``new`` and -``malloc()``-like resource functions are considered to produce resources. +The following examples will demonstrate the correct and incorrect +initializations of owners, assignment is handled the same way. +Note that both ``new`` and ``malloc()``-like resource functions are +considered to produce resources. .. code-block:: c++ @@ -62,8 +63,9 @@ to be deleted. gsl::owner<int*> Owner = new int(42); // Good delete Owner; // Good as well, statically enforced, that only owners get deleted -The check will furthermore ensure, that functions, that expect a ``gsl::owner<T*>`` as -argument get called with either a ``gsl::owner<T*>`` or a newly created resource. +The check will furthermore ensure, that functions, that expect a +``gsl::owner<T*>`` as argument get called with either a ``gsl::owner<T*>`` or +a newly created resource. .. code-block:: c++ @@ -164,8 +166,8 @@ Known code constructs that do not get diagnosed correctly are: // False positive, getValue returns int* and not gsl::owner<int*> gsl::owner<int*> OwnedInt = Owner.getValue(); -Another limitation of the current implementation is only the type based checking. -Suppose you have code like the following: +Another limitation of the current implementation is only the type based +checking. Suppose you have code like the following: .. code-block:: c++ @@ -176,9 +178,9 @@ Suppose you have code like the following: Owner2 = Owner1; // Conceptual Leak of initial resource of Owner2! Owner1 = nullptr; -The semantic of a ``gsl::owner<T*>`` is mostly like a ``std::unique_ptr<T>``, therefore -assignment of two ``gsl::owner<T*>`` is considered a move, which requires that the -resource ``Owner2`` must have been released before the assignment. -This kind of condition could be caught in later improvements of this check with -flowsensitive analysis. Currently, the `Clang Static Analyzer` catches this bug -for dynamic memory, but not for general types of resources. +The semantic of a ``gsl::owner<T*>`` is mostly like a ``std::unique_ptr<T>``, +therefore assignment of two ``gsl::owner<T*>`` is considered a move, which +requires that the resource ``Owner2`` must have been released before the +assignment. This kind of condition could be caught in later improvements of +this check with flowsensitive analysis. Currently, the `Clang Static Analyzer` +catches this bug for dynamic memory, but not for general types of resources. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-member-initializer.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-member-initializer.rst index 6d1bdb93..12aeaa8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-member-initializer.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/prefer-member-initializer.rst @@ -16,7 +16,8 @@ from the C++ Core Guidelines. Please note, that this check does not enforce rule `C.48 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c48-prefer-in-class-initializers-to-member-initializers-in-constructors-for-constant-initializers>`_ from the C++ Core Guidelines. For that purpose -see check :doc:`modernize-use-default-member-init <../modernize/use-default-member-init>`. +see check :doc:`modernize-use-default-member-init +<../modernize/use-default-member-init>`. Example 1 --------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-array-to-pointer-decay.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-array-to-pointer-decay.rst index c890e16..06de6fc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-array-to-pointer-decay.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-array-to-pointer-decay.rst @@ -9,5 +9,5 @@ Pointers should not be used as arrays. ``span<T>`` is a bounds-checked, safe alternative to using pointers to access arrays. This rule is part of the `Bounds safety (Bounds 3) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-decay>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-bounds-decay>`_ profile from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst index f45bca6..38143c9 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-avoid-unchecked-container-access.rst @@ -25,13 +25,13 @@ and will generate a warning. -STL containers for which ``operator[]`` is well-defined for all inputs are excluded -from this check (e.g.: ``std::map::operator[]``). +STL containers for which ``operator[]`` is well-defined for all inputs are +excluded from this check (e.g.: ``std::map::operator[]``). This check enforces part of the `SL.con.3 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>` +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon3-avoid-bounds-errors>`_ guideline and is part of the `Bounds Safety (Bounds 4) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-arrayindex>` +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-bounds-arrayindex>`_ profile from the C++ Core Guidelines. Options diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-constant-array-index.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-constant-array-index.rst index 9b82e0c..4eddeb4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-constant-array-index.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-constant-array-index.rst @@ -9,7 +9,7 @@ are out of bounds (for ``std::array``). For out-of-bounds checking of static arrays, see the `-Warray-bounds` Clang diagnostic. This rule is part of the `Bounds safety (Bounds 2) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-arrayindex>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-bounds-arrayindex>`_ profile from the C++ Core Guidelines. Optionally, this check can generate fixes using ``gsl::at`` for indexing. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.rst index a3f1371..3f02009 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.rst @@ -11,7 +11,7 @@ and easy to get wrong. ``span<T>`` is a bounds-checked, safe type for accessing arrays of data. This rule is part of the `Bounds safety (Bounds 1) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-arithmetic>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-bounds-arithmetic>`_ profile from the C++ Core Guidelines. Options diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-const-cast.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-const-cast.rst index 961a591..b5cc486 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-const-cast.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-const-cast.rst @@ -16,13 +16,13 @@ attempts to change the value of that variable. Removing the ``volatile`` qualifier in C++ can have serious consequences. This qualifier indicates that a variable's value can change unpredictably, and -removing it may lead to undefined behavior, optimization problems, and debugging -challenges. It's essential to retain the ``volatile`` qualifier in situations -where the variable's volatility is a crucial aspect of program correctness and -reliability. +removing it may lead to undefined behavior, optimization problems, and +debugging challenges. It's essential to retain the ``volatile`` qualifier in +situations where the variable's volatility is a crucial aspect of program +correctness and reliability. This rule is part of the `Type safety (Type 3) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-type-constcast>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-type-constcast>`_ profile and `ES.50: Don’t cast away const <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es50-dont-cast-away-const>`_ rule from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-cstyle-cast.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-cstyle-cast.rst index daa93c6..a94115e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-cstyle-cast.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-cstyle-cast.rst @@ -7,13 +7,13 @@ This check flags all use of C-style casts that perform a ``static_cast`` downcast, ``const_cast``, or ``reinterpret_cast``. Use of these casts can violate type safety and cause the program to access a -variable that is actually of type X to be accessed as if it were of an unrelated -type Z. Note that a C-style ``(T)expression`` cast means to perform the first of -the following that is possible: a ``const_cast``, a ``static_cast``, a -``static_cast`` followed by a ``const_cast``, a ``reinterpret_cast``, or a -``reinterpret_cast`` followed by a ``const_cast``. This rule bans -``(T)expression`` only when used to perform an unsafe cast. +variable that is actually of type X to be accessed as if it were of an +unrelated type Z. Note that a C-style ``(T)expression`` cast means to perform +the first of the following that is possible: a ``const_cast``, a +``static_cast``, a ``static_cast`` followed by a ``const_cast``, a +``reinterpret_cast``, or a ``reinterpret_cast`` followed by a ``const_cast``. +This rule bans ``(T)expression`` only when used to perform an unsafe cast. This rule is part of the `Type safety (Type.4) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-type-cstylecast>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-type-cstylecast>`_ profile from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-member-init.rst index 3c6797b..b86083f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-member-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-member-init.rst @@ -20,9 +20,9 @@ account but generates false positives for fields initialized in methods invoked in the constructor body. The check also flags variables with automatic storage duration that have record -types without a user-provided constructor and are not initialized. The suggested -fix is to zero initialize the variable via ``{}`` for C++11 and beyond or ``= -{}`` for older language versions. +types without a user-provided constructor and are not initialized. The +suggested fix is to zero initialize the variable via ``{}`` for C++11 and +beyond or ``= {}`` for older language versions. Options ------- @@ -40,5 +40,5 @@ Options Default is `false`. This rule is part of the `Type safety (Type.6) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-type-memberinit>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-type-memberinit>`_ profile from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-reinterpret-cast.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-reinterpret-cast.rst index a094682..c2e4170 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-reinterpret-cast.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-reinterpret-cast.rst @@ -10,5 +10,5 @@ variable that is actually of type ``X`` to be accessed as if it were of an unrelated type ``Z``. This rule is part of the `Type safety (Type.1.1) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-type-reinterpretcast>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-type-reinterpretcast>`_ profile from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-static-cast-downcast.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-static-cast-downcast.rst index 333e6db..21c0145 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-static-cast-downcast.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-static-cast-downcast.rst @@ -12,7 +12,7 @@ variable that is actually of type ``X`` to be accessed as if it were of an unrelated type ``Z``. This rule is part of the `Type safety (Type.2) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-type-downcast>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-type-downcast>`_ profile from the C++ Core Guidelines. Options diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-union-access.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-union-access.rst index 3a5af53..db726a2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-union-access.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-union-access.rst @@ -13,5 +13,5 @@ enforced to be safe in the language and so relies on programmer discipline to get it right. This rule is part of the `Type safety (Type.7) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-type-unions>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-type-unions>`_ profile from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-vararg.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-vararg.rst index e74b006..09809c2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-vararg.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-vararg.rst @@ -11,9 +11,9 @@ To allow for SFINAE use of vararg functions, a call is not flagged if a literal context. Passing to varargs assumes the correct type will be read. This is fragile -because it cannot generally be enforced to be safe in the language and so relies -on programmer discipline to get it right. +because it cannot generally be enforced to be safe in the language and so +relies on programmer discipline to get it right. This rule is part of the `Type safety (Type.8) -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-type-varargs>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#pro-type-varargs>`_ profile from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst index 982d16fc..1b050a5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/special-member-functions.rst @@ -16,7 +16,7 @@ Note that defining a function with ``= delete`` is considered to be a definition. This check implements `C.21 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-five>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rc-five>`_ from the C++ Core Guidelines. Options diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/use-default-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/use-default-member-init.rst index e785f31..55661c0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/use-default-member-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/use-default-member-init.rst @@ -5,7 +5,7 @@ cppcoreguidelines-use-default-member-init ========================================= -This check implements `C.48 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-in-class-initializer>`_ +This check implements `C.48 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rc-in-class-initializer>`_ from the C++ Core Guidelines. The `cppcoreguidelines-use-default-member-init` check is an alias, please see diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/use-enum-class.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/use-enum-class.rst index 9e9f4c9..9358996a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/use-enum-class.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/use-enum-class.rst @@ -7,7 +7,7 @@ Finds unscoped (non-class) ``enum`` declarations and suggests using ``enum class`` instead. This check implements `Enum.3 -<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Renum-class>`_ +<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#renum-class>`_ from the C++ Core Guidelines." Example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/virtual-class-destructor.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/virtual-class-destructor.rst index 752fd81..80932c4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/virtual-class-destructor.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/virtual-class-destructor.rst @@ -8,7 +8,7 @@ nor protected and non-virtual. A virtual class's destructor should be specified in one of these ways to prevent undefined behavior. This check implements -`C.35 <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-dtor-virtual>`_ +`C.35 <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rc-dtor-virtual>`_ from the C++ Core Guidelines. Note that this check will diagnose a class with a virtual method regardless of diff --git a/clang-tools-extra/docs/clang-tidy/checks/fuchsia/statically-constructed-objects.rst b/clang-tools-extra/docs/clang-tidy/checks/fuchsia/statically-constructed-objects.rst index bed9e5a..ad87283 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/fuchsia/statically-constructed-objects.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/fuchsia/statically-constructed-objects.rst @@ -3,9 +3,9 @@ fuchsia-statically-constructed-objects ====================================== -Warns if global, non-trivial objects with static storage are constructed, unless -the object is statically initialized with a ``constexpr`` constructor or has no -explicit constructor. +Warns if global, non-trivial objects with static storage are constructed, +unless the object is statically initialized with a ``constexpr`` constructor +or has no explicit constructor. For example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/google/explicit-constructor.rst b/clang-tools-extra/docs/clang-tidy/checks/google/explicit-constructor.rst index acafc1a..1bef268 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/google/explicit-constructor.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/google/explicit-constructor.rst @@ -23,8 +23,8 @@ Consider this example: return a == b; } -The function will return ``true``, since the objects are implicitly converted to -``bool`` before comparison, which is unlikely to be the intent. +The function will return ``true``, since the objects are implicitly converted +to ``bool`` before comparison, which is unlikely to be the intent. The check will suggest inserting ``explicit`` before the constructor or conversion operator declaration. However, copy and move constructors should not diff --git a/clang-tools-extra/docs/clang-tidy/checks/google/objc-avoid-throwing-exception.rst b/clang-tools-extra/docs/clang-tidy/checks/google/objc-avoid-throwing-exception.rst index 50441f7..bd099c4 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/google/objc-avoid-throwing-exception.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/google/objc-avoid-throwing-exception.rst @@ -11,7 +11,8 @@ exceptions from Objective-C code. The corresponding C++ style guide rule: https://google.github.io/styleguide/cppguide.html#Exceptions -Instead, prefer passing in ``NSError **`` and return ``BOOL`` to indicate success or failure. +Instead, prefer passing in ``NSError **`` and return ``BOOL`` to indicate +success or failure. A counterexample: diff --git a/clang-tools-extra/docs/clang-tidy/checks/google/objc-global-variable-declaration.rst b/clang-tools-extra/docs/clang-tidy/checks/google/objc-global-variable-declaration.rst index 84c9776..105b4ff 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/google/objc-global-variable-declaration.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/google/objc-global-variable-declaration.rst @@ -9,9 +9,9 @@ pattern of variable names in Google's Objective-C Style Guide. The corresponding style guide rule: https://google.github.io/styleguide/objcguide.html#variable-names -All the global variables should follow the pattern of ``g[A-Z].*`` (variables) or -``k[A-Z].*`` (constants). The check will suggest a variable name that follows the -pattern if it can be inferred from the original name. +All the global variables should follow the pattern of ``g[A-Z].*`` (variables) +or ``k[A-Z].*`` (constants). The check will suggest a variable name that +follows the pattern if it can be inferred from the original name. For code: @@ -43,5 +43,5 @@ However for code that prefixed with non-alphabetical characters like: static NSString* __anotherString = @"world"; -The check will give a warning message but will not be able to suggest a fix. The -user needs to fix it on their own. +The check will give a warning message but will not be able to suggest +a fix. The user needs to fix it on their own. diff --git a/clang-tools-extra/docs/clang-tidy/checks/google/readability-avoid-underscore-in-googletest-name.rst b/clang-tools-extra/docs/clang-tidy/checks/google/readability-avoid-underscore-in-googletest-name.rst index e667fd1..a1da79d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/google/readability-avoid-underscore-in-googletest-name.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/google/readability-avoid-underscore-in-googletest-name.rst @@ -25,8 +25,8 @@ would trigger the check. `Underscores are not allowed`_ in test suite name nor test names. The ``DISABLED_`` prefix, which may be used to -`disable test suites and individual tests`_, is removed from the test suite name -and test name before checking for underscores. +`disable test suites and individual tests`_, is removed from the test suite +name and test name before checking for underscores. This check does not propose any fixes. diff --git a/clang-tools-extra/docs/clang-tidy/checks/google/readability-braces-around-statements.rst b/clang-tools-extra/docs/clang-tidy/checks/google/readability-braces-around-statements.rst index 6130609..764694e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/google/readability-braces-around-statements.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/google/readability-braces-around-statements.rst @@ -6,5 +6,6 @@ google-readability-braces-around-statements =========================================== The `google-readability-braces-around-statements` check is an alias, please see -:doc:`readability-braces-around-statements <../readability/braces-around-statements>` +:doc:`readability-braces-around-statements +<../readability/braces-around-statements>` for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/google/readability-casting.rst b/clang-tools-extra/docs/clang-tidy/checks/google/readability-casting.rst index d927e1c..31ee3bd 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/google/readability-casting.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/google/readability-casting.rst @@ -3,12 +3,12 @@ google-readability-casting ========================== +The `google-readability-casting` check is an alias, please see +:doc:`modernize-avoid-c-style-cast <../modernize/avoid-c-style-cast>` +for more information. + Finds usages of C-style casts. https://google.github.io/styleguide/cppguide.html#Casting Corresponding cpplint.py check name: `readability/casting`. - -This check is similar to ``-Wold-style-cast``, but it suggests automated fixes -in some cases. The reported locations should not be different from the -ones generated by ``-Wold-style-cast``. diff --git a/clang-tools-extra/docs/clang-tidy/checks/google/readability-todo.rst b/clang-tools-extra/docs/clang-tidy/checks/google/readability-todo.rst index 159d2b4..fccfa81 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/google/readability-todo.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/google/readability-todo.rst @@ -9,3 +9,14 @@ The relevant style guide section is https://google.github.io/styleguide/cppguide.html#TODO_Comments. Corresponding cpplint.py check: `readability/todo` + +Options +------- + +.. option:: Style + + A string specifying the TODO style for fix-it hints. Accepted values are + `Hyphen` and `Parentheses`. Default is `Hyphen`. + + * `Hyphen` will format the fix-it as: ``// TODO: username - details``. + * `Parentheses` will format the fix-it as: ``// TODO(username): details``. diff --git a/clang-tools-extra/docs/clang-tidy/checks/google/upgrade-googletest-case.rst b/clang-tools-extra/docs/clang-tidy/checks/google/upgrade-googletest-case.rst index 8759283..df98369 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/google/upgrade-googletest-case.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/google/upgrade-googletest-case.rst @@ -17,8 +17,8 @@ check to remove deprecated names. The affected APIs are: - Member functions of ``testing::Test``, ``testing::TestInfo``, - ``testing::TestEventListener``, ``testing::UnitTest``, and any type inheriting - from these types + ``testing::TestEventListener``, ``testing::UnitTest``, and any type + inheriting from these types - The macros ``TYPED_TEST_CASE``, ``TYPED_TEST_CASE_P``, ``REGISTER_TYPED_TEST_CASE_P``, and ``INSTANTIATE_TYPED_TEST_CASE_P`` - The type alias ``testing::TestCase`` diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/braces-around-statements.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/braces-around-statements.rst index 15a410e..aef9975 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/braces-around-statements.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/braces-around-statements.rst @@ -6,6 +6,8 @@ hicpp-braces-around-statements ============================== The `hicpp-braces-around-statements` check is an alias, please see -:doc:`readability-braces-around-statements <../readability/braces-around-statements>` +:doc:`readability-braces-around-statements +<../readability/braces-around-statements>` for more information. -It enforces the `rule 6.1.1 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/statements>`_. +It enforces the `rule 6.1.1 +<https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/statements>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/explicit-conversions.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/explicit-conversions.rst index d8c6939..6072527b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/explicit-conversions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/explicit-conversions.rst @@ -5,13 +5,21 @@ hicpp-explicit-conversions ========================== -This check is an alias for :doc:`google-explicit-constructor <../google/explicit-constructor>`. -Used to enforce parts of `rule 5.4.1 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard-expressions>`_. -This check will enforce that constructors and conversion operators are marked `explicit`. -Other forms of casting checks are implemented in other places. -The following checks can be used to check for more forms of casting: +This check is an alias for +:doc:`google-explicit-constructor <../google/explicit-constructor>`. -- :doc:`cppcoreguidelines-pro-type-static-cast-downcast <../cppcoreguidelines/pro-type-static-cast-downcast>` -- :doc:`cppcoreguidelines-pro-type-reinterpret-cast <../cppcoreguidelines/pro-type-reinterpret-cast>` -- :doc:`cppcoreguidelines-pro-type-const-cast <../cppcoreguidelines/pro-type-const-cast>` -- :doc:`cppcoreguidelines-pro-type-cstyle-cast <../cppcoreguidelines/pro-type-cstyle-cast>` +Used to enforce parts of `rule 5.4.1 +<https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard-expressions>`_. +This check will enforce that constructors and conversion operators are +marked ``explicit``. Other forms of casting checks are implemented in +other places. The following checks can be used to check for more forms +of casting: + +- :doc:`cppcoreguidelines-pro-type-static-cast-downcast + <../cppcoreguidelines/pro-type-static-cast-downcast>` +- :doc:`cppcoreguidelines-pro-type-reinterpret-cast + <../cppcoreguidelines/pro-type-reinterpret-cast>` +- :doc:`cppcoreguidelines-pro-type-const-cast + <../cppcoreguidelines/pro-type-const-cast>` +- :doc:`cppcoreguidelines-pro-type-cstyle-cast + <../cppcoreguidelines/pro-type-cstyle-cast>` diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/function-size.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/function-size.rst index 5ccf670..ad91c25 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/function-size.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/function-size.rst @@ -5,7 +5,8 @@ hicpp-function-size =================== -This check is an alias for :doc:`readability-function-size <../readability/function-size>`. +This check is an alias for +:doc:`readability-function-size <../readability/function-size>`. Useful to enforce multiple sections on function complexity. - `rule 8.2.2 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/definitions>`_ diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst index 6ca704a..4a89949c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/ignored-remove-result.rst @@ -13,7 +13,8 @@ operating over. On completion, they return an iterator to the last valid element. In the majority of cases the correct behavior is to use this result as the first operand in a call to ``std::erase``. -This check is a subset of :doc:`bugprone-unused-return-value <../bugprone/unused-return-value>` +This check is a subset of :doc:`bugprone-unused-return-value +<../bugprone/unused-return-value>` and depending on used options it can be superfluous to enable both checks. Options diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/invalid-access-moved.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/invalid-access-moved.rst index 13184d4..fd2e04a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/invalid-access-moved.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/invalid-access-moved.rst @@ -5,6 +5,7 @@ hicpp-invalid-access-moved ========================== -This check is an alias for :doc:`bugprone-use-after-move <../bugprone/use-after-move>`. +This check is an alias for +:doc:`bugprone-use-after-move <../bugprone/use-after-move>`. Implements parts of the `rule 8.4.1 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/definitions>`_ to check if moved-from objects are accessed. diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/move-const-arg.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/move-const-arg.rst index b43c233..7af8401 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/move-const-arg.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/move-const-arg.rst @@ -6,5 +6,6 @@ hicpp-move-const-arg ==================== The `hicpp-move-const-arg` check is an alias, please see -:doc:`performance-move-const-arg <../performance/move-const-arg>` for more information. +:doc:`performance-move-const-arg <../performance/move-const-arg>` +for more information. It enforces the `rule 17.3.1 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/standard-library>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/multiway-paths-covered.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/multiway-paths-covered.rst index 983de34..f164f4c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/multiway-paths-covered.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/multiway-paths-covered.rst @@ -4,15 +4,16 @@ hicpp-multiway-paths-covered ============================ This check discovers situations where code paths are not fully-covered. -It furthermore suggests using ``if`` instead of ``switch`` if the code will be more clear. +It furthermore suggests using ``if`` instead of ``switch`` if the code +will be more clear. The `rule 6.1.2 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/statements>`_ and `rule 6.1.4 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/statements>`_ of the High Integrity C++ Coding Standard are enforced. -``if-else if`` chains that miss a final ``else`` branch might lead to unexpected -program execution and be the result of a logical error. -If the missing ``else`` branch is intended you can leave it empty with a clarifying -comment. +``if-else if`` chains that miss a final ``else`` branch might lead to +unexpected program execution and be the result of a logical error. +If the missing ``else`` branch is intended you can leave it empty with +a clarifying comment. This warning can be noisy on some code bases, so it is disabled by default. .. code-block:: c++ @@ -28,7 +29,8 @@ This warning can be noisy on some code bases, so it is disabled by default. // ... } -Similar arguments hold for ``switch`` statements which do not cover all possible code paths. +Similar arguments hold for ``switch`` statements which do not cover all +possible code paths. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/named-parameter.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/named-parameter.rst index 7f894b1..4506596 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/named-parameter.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/named-parameter.rst @@ -5,6 +5,7 @@ hicpp-named-parameter ===================== -This check is an alias for :doc:`readability-named-parameter <../readability/named-parameter>`. +This check is an alias for :doc:`readability-named-parameter +<../readability/named-parameter>`. Implements `rule 8.2.1 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/definitions>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/no-array-decay.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/no-array-decay.rst index 85b93cb..715a1b7 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/no-array-decay.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/no-array-decay.rst @@ -6,6 +6,7 @@ hicpp-no-array-decay ==================== The `hicpp-no-array-decay` check is an alias, please see -:doc:`cppcoreguidelines-pro-bounds-array-to-pointer-decay <../cppcoreguidelines/pro-bounds-array-to-pointer-decay>` +:doc:`cppcoreguidelines-pro-bounds-array-to-pointer-decay +<../cppcoreguidelines/pro-bounds-array-to-pointer-decay>` for more information. It enforces the `rule 4.1.1 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/standard-conversions>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/hicpp/uppercase-literal-suffix.rst b/clang-tools-extra/docs/clang-tidy/checks/hicpp/uppercase-literal-suffix.rst index 994363a..34b9f25 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/hicpp/uppercase-literal-suffix.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/hicpp/uppercase-literal-suffix.rst @@ -6,7 +6,8 @@ hicpp-uppercase-literal-suffix ============================== The hicpp-uppercase-literal-suffix check is an alias, please see -:doc:`readability-uppercase-literal-suffix <../readability/uppercase-literal-suffix>` for more information. +:doc:`readability-uppercase-literal-suffix +<../readability/uppercase-literal-suffix>` for more information. Partially implements `rule 4.2.1 <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard/standard-conversions>`_ to ensure that the ``U`` suffix is writeln properly. diff --git a/clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-check-errs.rst b/clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-check-errs.rst index cef5a70..6a4b743 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-check-errs.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/linuxkernel/must-check-errs.rst @@ -4,8 +4,8 @@ linuxkernel-must-check-errs =========================== Checks Linux kernel code to see if it uses the results from the functions in -``linux/err.h``. Also checks to see if code uses the results from functions that -directly return a value from one of these error functions. +``linux/err.h``. Also checks to see if code uses the results from functions +that directly return a value from one of these error functions. This is important in the Linux kernel because ``ERR_PTR``, ``PTR_ERR``, ``IS_ERR``, ``IS_ERR_OR_NULL``, ``ERR_CAST``, and ``PTR_ERR_OR_ZERO`` return diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index e287560..865a2d3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -98,6 +98,7 @@ Clang-Tidy Checks :doc:`bugprone-dynamic-static-initializers <bugprone/dynamic-static-initializers>`, :doc:`bugprone-easily-swappable-parameters <bugprone/easily-swappable-parameters>`, :doc:`bugprone-empty-catch <bugprone/empty-catch>`, + :doc:`bugprone-exception-copy-constructor-throws <bugprone/exception-copy-constructor-throws>`, :doc:`bugprone-exception-escape <bugprone/exception-escape>`, :doc:`bugprone-float-loop-counter <bugprone/float-loop-counter>`, :doc:`bugprone-fold-init-type <bugprone/fold-init-type>`, @@ -132,6 +133,7 @@ Clang-Tidy Checks :doc:`bugprone-parent-virtual-call <bugprone/parent-virtual-call>`, "Yes" :doc:`bugprone-pointer-arithmetic-on-polymorphic-object <bugprone/pointer-arithmetic-on-polymorphic-object>`, :doc:`bugprone-posix-return <bugprone/posix-return>`, "Yes" + :doc:`bugprone-random-generator-seed <bugprone/random-generator-seed>`, :doc:`bugprone-raw-memory-call-on-non-trivial-type <bugprone/raw-memory-call-on-non-trivial-type>`, :doc:`bugprone-redundant-branch-condition <bugprone/redundant-branch-condition>`, "Yes" :doc:`bugprone-reserved-identifier <bugprone/reserved-identifier>`, "Yes" @@ -180,8 +182,8 @@ Clang-Tidy Checks :doc:`bugprone-virtual-near-miss <bugprone/virtual-near-miss>`, "Yes" :doc:`cert-err33-c <cert/err33-c>`, :doc:`cert-err60-cpp <cert/err60-cpp>`, + :doc:`cert-flp30-c <cert/flp30-c>`, :doc:`cert-msc50-cpp <cert/msc50-cpp>`, - :doc:`cert-msc51-cpp <cert/msc51-cpp>`, :doc:`cert-oop58-cpp <cert/oop58-cpp>`, :doc:`concurrency-mt-unsafe <concurrency/mt-unsafe>`, :doc:`concurrency-thread-canceltype-asynchronous <concurrency/thread-canceltype-asynchronous>`, @@ -237,7 +239,6 @@ Clang-Tidy Checks :doc:`google-objc-function-naming <google/objc-function-naming>`, :doc:`google-objc-global-variable-declaration <google/objc-global-variable-declaration>`, :doc:`google-readability-avoid-underscore-in-googletest-name <google/readability-avoid-underscore-in-googletest-name>`, - :doc:`google-readability-casting <google/readability-casting>`, :doc:`google-readability-todo <google/readability-todo>`, :doc:`google-runtime-float <google/runtime-float>`, :doc:`google-runtime-int <google/runtime-int>`, @@ -276,6 +277,7 @@ Clang-Tidy Checks :doc:`misc-non-copyable-objects <misc/non-copyable-objects>`, :doc:`misc-non-private-member-variables-in-classes <misc/non-private-member-variables-in-classes>`, :doc:`misc-override-with-different-visibility <misc/override-with-different-visibility>`, + :doc:`misc-predictable-rand <misc/predictable-rand>`, :doc:`misc-redundant-expression <misc/redundant-expression>`, "Yes" :doc:`misc-static-assert <misc/static-assert>`, "Yes" :doc:`misc-throw-by-value-catch-by-reference <misc/throw-by-value-catch-by-reference>`, @@ -288,6 +290,7 @@ Clang-Tidy Checks :doc:`misc-use-internal-linkage <misc/use-internal-linkage>`, "Yes" :doc:`modernize-avoid-bind <modernize/avoid-bind>`, "Yes" :doc:`modernize-avoid-c-arrays <modernize/avoid-c-arrays>`, + :doc:`modernize-avoid-c-style-cast <modernize/avoid-c-style-cast>`, :doc:`modernize-avoid-setjmp-longjmp <modernize/avoid-setjmp-longjmp>`, :doc:`modernize-avoid-variadic-functions <modernize/avoid-variadic-functions>`, :doc:`modernize-concat-nested-namespaces <modernize/concat-nested-namespaces>`, "Yes" @@ -449,6 +452,7 @@ Check aliases :doc:`cert-err34-c <cert/err34-c>`, :doc:`bugprone-unchecked-string-to-number-conversion <bugprone/unchecked-string-to-number-conversion>`, :doc:`cert-err52-cpp <cert/err52-cpp>`, :doc:`modernize-avoid-setjmp-longjmp <modernize/avoid-setjmp-longjmp>`, :doc:`cert-err58-cpp <cert/err58-cpp>`, :doc:`bugprone-throwing-static-initialization <bugprone/throwing-static-initialization>`, + :doc:`cert-err60-cpp <cert/err60-cpp>`, :doc:`bugprone-exception-copy-constructor-throws <bugprone/exception-copy-constructor-throws>`, :doc:`cert-err61-cpp <cert/err61-cpp>`, :doc:`misc-throw-by-value-catch-by-reference <misc/throw-by-value-catch-by-reference>`, :doc:`cert-exp42-c <cert/exp42-c>`, :doc:`bugprone-suspicious-memory-comparison <bugprone/suspicious-memory-comparison>`, :doc:`cert-fio38-c <cert/fio38-c>`, :doc:`misc-non-copyable-objects <misc/non-copyable-objects>`, @@ -457,9 +461,11 @@ Check aliases :doc:`cert-int09-c <cert/int09-c>`, :doc:`readability-enum-initial-value <readability/enum-initial-value>`, "Yes" :doc:`cert-mem57-cpp <cert/mem57-cpp>`, :doc:`bugprone-default-operator-new-on-overaligned-type <bugprone/default-operator-new-on-overaligned-type>`, :doc:`cert-msc24-c <cert/msc24-c>`, :doc:`bugprone-unsafe-functions <bugprone/unsafe-functions>`, - :doc:`cert-msc30-c <cert/msc30-c>`, :doc:`cert-msc50-cpp <cert/msc50-cpp>`, - :doc:`cert-msc32-c <cert/msc32-c>`, :doc:`cert-msc51-cpp <cert/msc51-cpp>`, + :doc:`cert-msc30-c <cert/msc30-c>`, :doc:`misc-predictable-rand <misc/predictable-rand>`, + :doc:`cert-msc32-c <cert/msc32-c>`, :doc:`bugprone-random-generator-seed <bugprone/random-generator-seed>`, :doc:`cert-msc33-c <cert/msc33-c>`, :doc:`bugprone-unsafe-functions <bugprone/unsafe-functions>`, + :doc:`cert-msc50-cpp <cert/msc50-cpp>`, :doc:`misc-predictable-rand <misc/predictable-rand>`, + :doc:`cert-msc51-cpp <cert/msc51-cpp>`, :doc:`bugprone-random-generator-seed <bugprone/random-generator-seed>`, :doc:`cert-msc54-cpp <cert/msc54-cpp>`, :doc:`bugprone-signal-handler <bugprone/signal-handler>`, :doc:`cert-oop11-cpp <cert/oop11-cpp>`, :doc:`performance-move-constructor-init <performance/move-constructor-init>`, :doc:`cert-oop54-cpp <cert/oop54-cpp>`, :doc:`bugprone-unhandled-self-assignment <bugprone/unhandled-self-assignment>`, @@ -544,7 +550,7 @@ Check aliases :doc:`clang-analyzer-security.insecureAPI.bcmp <clang-analyzer/security.insecureAPI.bcmp>`, `Clang Static Analyzer security.insecureAPI.bcmp <https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-bcmp>`_, :doc:`clang-analyzer-security.insecureAPI.bcopy <clang-analyzer/security.insecureAPI.bcopy>`, `Clang Static Analyzer security.insecureAPI.bcopy <https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-bcopy>`_, :doc:`clang-analyzer-security.insecureAPI.bzero <clang-analyzer/security.insecureAPI.bzero>`, `Clang Static Analyzer security.insecureAPI.bzero <https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-bzero>`_, - :doc:`clang-analyzer-security.insecureAPI.decodeValueOfObjCType <clang-analyzer/security.insecureAPI.decodeValueOfObjCType>`, Clang Static Analyzer security.insecureAPI.decodeValueOfObjCType, + :doc:`clang-analyzer-security.insecureAPI.decodeValueOfObjCType <clang-analyzer/security.insecureAPI.decodeValueOfObjCType>`, `Clang Static Analyzer security.insecureAPI.decodeValueOfObjCType <https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-decodevalueofobjctype>`_, :doc:`clang-analyzer-security.insecureAPI.getpw <clang-analyzer/security.insecureAPI.getpw>`, `Clang Static Analyzer security.insecureAPI.getpw <https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-getpw>`_, :doc:`clang-analyzer-security.insecureAPI.gets <clang-analyzer/security.insecureAPI.gets>`, `Clang Static Analyzer security.insecureAPI.gets <https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-gets>`_, :doc:`clang-analyzer-security.insecureAPI.mkstemp <clang-analyzer/security.insecureAPI.mkstemp>`, `Clang Static Analyzer security.insecureAPI.mkstemp <https://clang.llvm.org/docs/analyzer/checkers.html#security-insecureapi-mkstemp>`_, @@ -579,6 +585,7 @@ Check aliases :doc:`cppcoreguidelines-use-default-member-init <cppcoreguidelines/use-default-member-init>`, :doc:`modernize-use-default-member-init <modernize/use-default-member-init>`, "Yes" :doc:`fuchsia-header-anon-namespaces <fuchsia/header-anon-namespaces>`, :doc:`google-build-namespaces <google/build-namespaces>`, :doc:`google-readability-braces-around-statements <google/readability-braces-around-statements>`, :doc:`readability-braces-around-statements <readability/braces-around-statements>`, "Yes" + :doc:`google-readability-casting <google/readability-casting>`, :doc:`modernize-avoid-c-style-cast <modernize/avoid-c-style-cast>`, :doc:`google-readability-function-size <google/readability-function-size>`, :doc:`readability-function-size <readability/function-size>`, :doc:`google-readability-namespace-comments <google/readability-namespace-comments>`, :doc:`llvm-namespace-comment <llvm/namespace-comment>`, :doc:`hicpp-avoid-c-arrays <hicpp/avoid-c-arrays>`, :doc:`modernize-avoid-c-arrays <modernize/avoid-c-arrays>`, diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst index 18ec10b..01f3b75 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/const-correctness.rst @@ -4,14 +4,14 @@ misc-const-correctness ====================== This check implements detection of local variables which could be declared as -``const`` but are not. Declaring variables as ``const`` is required or recommended by many -coding guidelines, such as: +``const`` but are not. Declaring variables as ``const`` is required or +recommended by many coding guidelines, such as: `ES.25 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es25-declare-an-object-const-or-constexpr-unless-you-want-to-modify-its-value-later-on>`_ from the C++ Core Guidelines. -Please note that this check's analysis is type-based only. Variables that are not modified -but used to create a non-const handle that might escape the scope are not diagnosed -as potential ``const``. +Please note that this check's analysis is type-based only. Variables that are +not modified but used to create a non-const handle that might escape the scope +are not diagnosed as potential ``const``. .. code-block:: c++ @@ -44,8 +44,8 @@ The check can analyze values, pointers and references and pointees: int const*const pointer_variable = &potential_const_int; // After transformation, both pointer itself and pointee are supported. int last_copy = *pointer_variable; -The automatic code transformation is only applied to variables that are declared in single -declarations. You may want to prepare your code base with +The automatic code transformation is only applied to variables that are +declared in single declarations. You may want to prepare your code base with :doc:`readability-isolate-declaration <../readability/isolate-declaration>` first. Note that there is the check @@ -58,10 +58,11 @@ Limitations The check does not run on `C` code. -The check will not analyze templated variables or variables that are instantiation dependent. -Different instantiations can result in different ``const`` correctness properties and in general it -is not possible to find all instantiations of a template. The template might be used differently in -an independent translation unit. +The check will not analyze templated variables or variables that are +instantiation dependent. Different instantiations can result in +different ``const`` correctness properties and in general it is not +possible to find all instantiations of a template. The template might +be used differently in an independent translation unit. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/coroutine-hostile-raii.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/coroutine-hostile-raii.rst index 0b054e4..fc67634 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/coroutine-hostile-raii.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/coroutine-hostile-raii.rst @@ -7,21 +7,23 @@ Detects when objects of certain hostile RAII types persists across suspension points in a coroutine. Such hostile types include scoped-lockable types and types belonging to a configurable denylist. -Some objects require that they be destroyed on the same thread that created them. -Traditionally this requirement was often phrased as "must be a local variable", -under the assumption that local variables always work this way. However this is -incorrect with C++20 coroutines, since an intervening ``co_await`` may cause the -coroutine to suspend and later be resumed on another thread. - -The lifetime of an object that requires being destroyed on the same thread must -not encompass a ``co_await`` or ``co_yield`` point. If you create/destroy an object, -you must do so without allowing the coroutine to suspend in the meantime. +Some objects require that they be destroyed on the same thread that created +them. Traditionally this requirement was often phrased as "must be a local +variable", under the assumption that local variables always work this way. +However this is incorrect with C++20 coroutines, since an intervening +``co_await`` may cause the coroutine to suspend and later be resumed on +another thread. + +The lifetime of an object that requires being destroyed on the same thread +must not encompass a ``co_await`` or ``co_yield`` point. If you create/destroy +an object, you must do so without allowing the coroutine to suspend in the +meantime. Following types are considered as hostile: - - Scoped-lockable types: A scoped-lockable object persisting across a suspension - point is problematic as the lock held by this object could be unlocked by a - different thread. This would be undefined behaviour. + - Scoped-lockable types: A scoped-lockable object persisting across a + suspension point is problematic as the lock held by this object could + be unlocked by a different thread. This would be undefined behaviour. This includes all types annotated with the ``scoped_lockable`` attribute. - Types belonging to a configurable denylist. @@ -81,3 +83,23 @@ Options Eg: `my::safe::awaitable;other::awaitable` Default is an empty string. +.. option:: AllowedCallees + + A semicolon-separated list of callee function names which can + be safely awaited while having hostile RAII objects in scope. + Example usage: + + .. code-block:: c++ + + // Consider option AllowedCallees = "noop" + task noop() { co_return; } + + task coro() { + // This persists across the co_await but is not flagged + // because the awaitable is considered safe to await on. + const std::lock_guard l(&mu_); + co_await noop(); + } + + Eg: `my::safe::await;other::await` + Default is an empty string. diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/header-include-cycle.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/header-include-cycle.rst index de08f0d..d0ae0ea 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/header-include-cycle.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/header-include-cycle.rst @@ -47,18 +47,18 @@ quality, and a more maintainable codebase overall. Additionally, by ensuring that header files are organized in a way that avoids cyclic dependencies, developers can make their code easier to understand and modify over time. -It's worth noting that only user-defined headers their dependencies are analyzed, -System includes such as standard library headers and third-party library headers -are excluded. System includes are usually well-designed and free of include -cycles, and ignoring them helps to focus on potential issues within the -project's own codebase. This limitation doesn't diminish the ability to detect -``#include`` cycles within the analyzed code. +It's worth noting that only user-defined headers their dependencies are +analyzed, system includes such as standard library headers and third-party +library headers are excluded. System includes are usually well-designed and +free of include cycles, and ignoring them helps to focus on potential issues +within the project's own codebase. This limitation doesn't diminish the +ability to detect ``#include`` cycles within the analyzed code. Developers should carefully review any warnings or feedback provided by this solution. While the analysis aims to identify and prevent include cycles, there may be situations where exceptions or modifications are necessary. It's -important to exercise judgment and consider the specific context of the codebase -when making adjustments. +important to exercise judgment and consider the specific context of the +codebase when making adjustments. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/misleading-identifier.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/misleading-identifier.rst index 1e2b61a..5941d1c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/misleading-identifier.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/misleading-identifier.rst @@ -4,8 +4,8 @@ misc-misleading-identifier ========================== Finds identifiers that contain Unicode characters with right-to-left direction, -which can be confusing as they may change the understanding of a whole statement -line, as described in `Trojan Source <https://trojansource.codes>`_. +which can be confusing as they may change the understanding of a whole +statement line, as described in `Trojan Source <https://trojansource.codes>`_. An example of such misleading code follows: diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/no-recursion.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/no-recursion.rst index 1c04dbf..53753f1 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/no-recursion.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/no-recursion.rst @@ -11,7 +11,8 @@ and displays one example of a possible call graph loop (recursion). References: * CERT C++ Coding Standard rule `DCL56-CPP. Avoid cycles during initialization of static objects <https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL56-CPP.+Avoid+cycles+during+initialization+of+static+objects>`_. -* JPL Institutional Coding Standard for the C Programming Language (JPL DOCID D-60411) rule `2.4 Do not use direct or indirect recursion`. +* JPL Institutional Coding Standard for the C Programming Language + (JPL DOCID D-60411) rule `2.4 Do not use direct or indirect recursion`. * OpenCL Specification, Version 1.2 rule `6.9 Restrictions: i. Recursion is not supported. <https://www.khronos.org/registry/OpenCL/specs/opencl-1.2.pdf>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/override-with-different-visibility.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/override-with-different-visibility.rst index 24be51b..9958df5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/override-with-different-visibility.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/override-with-different-visibility.rst @@ -5,11 +5,12 @@ misc-override-with-different-visibility Finds virtual function overrides with different visibility than the function in the base class. This includes for example if a virtual function declared as -``private`` is overridden and declared as ``public`` in a subclass. The detected -change is the modification of visibility resulting from keywords ``public``, -``protected``, ``private`` at overridden virtual functions. The check applies to -any normal virtual function and optionally to destructors or operators. Use of -the ``using`` keyword is not considered as visibility change by this check. +``private`` is overridden and declared as ``public`` in a subclass. The +detected change is the modification of visibility resulting from keywords +``public``, ``protected``, ``private`` at overridden virtual functions. The +check applies to any normal virtual function and optionally to destructors or +operators. Use of the ``using`` keyword is not considered as visibility +change by this check. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/predictable-rand.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/predictable-rand.rst new file mode 100644 index 0000000..0015664 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/predictable-rand.rst @@ -0,0 +1,20 @@ +.. title:: clang-tidy - misc-predictable-rand + +misc-predictable-rand +===================== + +Warns for the usage of ``std::rand()``. Pseudorandom number generators use +mathematical algorithms to produce a sequence of numbers with good +statistical properties, but the numbers produced are not genuinely random. +The ``std::rand()`` function takes a seed (number), runs a mathematical +operation on it and returns the result. By manipulating the seed the result +can be predictable. + +References +---------- + +This check corresponds to the CERT C Coding Standard rules +`MSC30-C. Do not use the rand() function for generating pseudorandom numbers +<https://wiki.sei.cmu.edu/confluence/display/c/MSC30-C.+Do+not+use+the+rand%28%29+function+for+generating+pseudorandom+numbers>`_. +`MSC50-CPP. Do not use std::rand() for generating pseudorandom numbers +<https://wiki.sei.cmu.edu/confluence/display/cplusplus/MSC50-CPP.+Do+not+use+std%3A%3Arand%28%29+for+generating+pseudorandom+numbers>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/throw-by-value-catch-by-reference.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/throw-by-value-catch-by-reference.rst index b89fbe8..cfea1c8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/throw-by-value-catch-by-reference.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/throw-by-value-catch-by-reference.rst @@ -7,16 +7,16 @@ misc-throw-by-value-catch-by-reference Finds violations of the rule "Throw by value, catch by reference" presented for example in "C++ Coding Standards" by H. Sutter and A. Alexandrescu, as well as -the CERT C++ Coding Standard rule `ERR61-CPP. Catch exceptions by lvalue reference -<https://wiki.sei.cmu.edu/confluence/display/cplusplus/ERR61-CPP.+Catch+exceptions+by+lvalue+reference>`_. +the CERT C++ Coding Standard rule `ERR61-CPP. Catch exceptions by lvalue +reference <https://wiki.sei.cmu.edu/confluence/display/cplusplus/ERR61-CPP.+Catch+exceptions+by+lvalue+reference>`_. Exceptions: * Throwing string literals will not be flagged despite being a pointer. They are not susceptible to slicing and the usage of string literals is idiomatic. - * Catching character pointers (``char``, ``wchar_t``, unicode character types) - will not be flagged to allow catching string literals. + * Catching character pointers (``char``, ``wchar_t``, unicode character + types) will not be flagged to allow catching string literals. * Moved named values will not be flagged as not throwing an anonymous temporary. In this case we can be sure that the user knows that the object can't be accessed outside catch blocks handling the error. diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/unused-parameters.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/unused-parameters.rst index 9321f65..3d90245 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/unused-parameters.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/unused-parameters.rst @@ -8,9 +8,9 @@ code (e.g. when a different parameter is used instead). The suggested fixes either comment parameter name out or remove the parameter completely, if all callers of the function are in the same translation unit and can be updated. -The check is similar to the ``-Wunused-parameter`` compiler diagnostic and can be -used to prepare a codebase to enabling of that diagnostic. By default the check -is more permissive (see :option:`StrictMode`). +The check is similar to the `-Wunused-parameter` compiler diagnostic and +can be used to prepare a codebase to enabling of that diagnostic. By default +the check is more permissive (see :option:`StrictMode`). .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/unused-using-decls.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/unused-using-decls.rst index 29cd5a23..1754465 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/unused-using-decls.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/unused-using-decls.rst @@ -5,9 +5,10 @@ misc-unused-using-decls Finds unused ``using`` declarations. -Unused ``using``` declarations in header files will not be diagnosed since these -using declarations are part of the header's public API. Allowed header file -extensions can be configured via the global option `HeaderFileExtensions`. +Unused ``using`` declarations in header files will not be diagnosed +since these using declarations are part of the header's public API. +Allowed header file extensions can be configured via the global +option `HeaderFileExtensions`. Example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/use-anonymous-namespace.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/use-anonymous-namespace.rst index 0950127..102052d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/use-anonymous-namespace.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/use-anonymous-namespace.rst @@ -8,16 +8,16 @@ that could instead be moved into an anonymous namespace. Anonymous namespaces are the "superior alternative" according to the C++ Standard. ``static`` was proposed for deprecation, but later un-deprecated to -keep C compatibility [1]. ``static`` is an overloaded term with different meanings in -different contexts, so it can create confusion. +keep C compatibility [1]. ``static`` is an overloaded term with different +meanings in different contexts, so it can create confusion. The following uses of ``static`` will *not* be diagnosed: * Functions or variables in header files, since anonymous namespaces in headers - is considered an antipattern. Allowed header file extensions can be configured - via the global option `HeaderFileExtensions`. -* ``const`` or ``constexpr`` variables, since they already have implicit internal - linkage in C++. + is considered an antipattern. Allowed header file extensions can be + configured via the global option `HeaderFileExtensions`. +* ``const`` or ``constexpr`` variables, since they already have implicit + internal linkage in C++. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc/use-internal-linkage.rst b/clang-tools-extra/docs/clang-tidy/checks/misc/use-internal-linkage.rst index 508b0ca..224ad21 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc/use-internal-linkage.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc/use-internal-linkage.rst @@ -41,8 +41,8 @@ Options Selects what kind of a fix the check should provide. The default is `UseStatic`. - ``None`` + - `None` Don't fix automatically. - ``UseStatic`` + - `UseStatic` Add ``static`` for internal linkage variable and function. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-style-cast.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-style-cast.rst new file mode 100644 index 0000000..c43fb00 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-style-cast.rst @@ -0,0 +1,36 @@ +.. title:: clang-tidy - modernize-avoid-c-style-cast + +modernize-avoid-c-style-cast +============================ + +Finds usages of C-style casts. + +C-style casts can perform a variety of different conversions (``const_cast``, +``static_cast``, ``reinterpret_cast``, or a combination). This makes them +dangerous as the intent is not clear, and they can silently perform unsafe +conversions between incompatible types. + +This check is similar to `-Wold-style-cast`, but it suggests automated fixes +in some cases. The reported locations should not be different from the ones +generated by `-Wold-style-cast`. + +Examples +-------- + +.. code-block:: c++ + + class A { + public: + std::string v; + }; + + A a; + double *num = (double*)(&a); // Compiles! Hides danger + // num = static_cast<double*>(&a); // Won't compile (good!) + num = reinterpret_cast<double*>(&a); // Compiles, danger is explicit + + +References +---------- + +Corresponding cpplint.py check name: `readability/casting`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-setjmp-longjmp.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-setjmp-longjmp.rst index ae45619..744a12c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-setjmp-longjmp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-setjmp-longjmp.rst @@ -3,7 +3,8 @@ modernize-avoid-setjmp-longjmp ============================== -Flags all call expressions involving ``setjmp()`` and ``longjmp()`` in C++ code. +Flags all call expressions involving ``setjmp()`` and +``longjmp()`` in C++ code. Exception handling with ``throw`` and ``catch`` should be used instead. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-variadic-functions.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-variadic-functions.rst index 1c93c6b3..5b1da41 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-variadic-functions.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-variadic-functions.rst @@ -15,4 +15,4 @@ References This check corresponds to the CERT C++ Coding Standard rule `DCL50-CPP. Do not define a C-style variadic function -<https://www.securecoding.cert.org/confluence/display/cplusplus/DCL50-CPP.+Do+not+define+a+C-style+variadic+function>`_.
\ No newline at end of file +<https://www.securecoding.cert.org/confluence/display/cplusplus/DCL50-CPP.+Do+not+define+a+C-style+variadic+function>`_. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/concat-nested-namespaces.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/concat-nested-namespaces.rst index af2378e..6e1f505 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/concat-nested-namespaces.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/concat-nested-namespaces.rst @@ -3,8 +3,10 @@ modernize-concat-nested-namespaces ================================== -Checks for use of nested namespaces such as ``namespace a { namespace b { ... } }`` -and suggests changing to the more concise syntax introduced in C++17: ``namespace a::b { ... }``. +Checks for use of nested namespaces such as +``namespace a { namespace b { ... } }`` +and suggests changing to the more concise syntax introduced +in C++17: ``namespace a::b { ... }``. Inline namespaces are not modified. For example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst index 58d61d1..e11ced7 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/loop-convert.rst @@ -107,7 +107,8 @@ Original: for (int i = 0; i < size(v); ++i) cout << v[i]; -After applying the check with minimum confidence level set to `reasonable` (default): +After applying the check with minimum confidence level set to +`reasonable` (default): .. code-block:: c++ @@ -320,6 +321,6 @@ not be used on code with a compatibility requirement of OpenMP prior to version 5. It is **intentional** that this check does not make any attempts to exclude incorrect diagnostics on OpenMP for loops prior to OpenMP 5. -To prevent this check to be applied (and to break) OpenMP for loops but still be -applied to non-OpenMP for loops the usage of ``NOLINT`` (see -:ref:`clang-tidy-nolint`) on the specific for loops is recommended. +To prevent this check to be applied (and to break) OpenMP for loops +but still be applied to non-OpenMP for loops the usage of ``NOLINT`` +(see :ref:`clang-tidy-nolint`) on the specific for loops is recommended. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/replace-disallow-copy-and-assign-macro.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/replace-disallow-copy-and-assign-macro.rst index 5ef6ae7..485abca 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/replace-disallow-copy-and-assign-macro.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/replace-disallow-copy-and-assign-macro.rst @@ -38,9 +38,9 @@ Limitations ----------- * Notice that the migration example above leaves the ``private`` access - specification untouched. You might want to run the check :doc:`modernize-use-equals-delete - <../modernize/use-equals-delete>` to get warnings for deleted functions in - private sections. + specification untouched. You might want to run the check + :doc:`modernize-use-equals-delete <../modernize/use-equals-delete>` + to get warnings for deleted functions in private sections. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/replace-random-shuffle.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/replace-random-shuffle.rst index 546de84..c6dcd72 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/replace-random-shuffle.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/replace-random-shuffle.rst @@ -3,9 +3,12 @@ modernize-replace-random-shuffle ================================ -This check will find occurrences of ``std::random_shuffle`` and replace it with ``std::shuffle``. In C++17 ``std::random_shuffle`` will no longer be available and thus we need to replace it. +This check will find occurrences of ``std::random_shuffle`` and replace it with +``std::shuffle``. In C++17 ``std::random_shuffle`` will no longer be available +and thus we need to replace it. -Below are two examples of what kind of occurrences will be found and two examples of what it will be replaced with. +Below are two examples of what kind of occurrences will be found and two +examples of what it will be replaced with. .. code-block:: c++ @@ -23,10 +26,18 @@ Both of these examples will be replaced with: std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()())); -The second example will also receive a warning that ``randomFunc`` is no longer supported in the same way as before so if the user wants the same functionality, the user will need to change the implementation of the ``randomFunc``. +The second example will also receive a warning that ``randomFunc`` is no longer +supported in the same way as before so if the user wants the same +functionality, the user will need to change the implementation of the +``randomFunc``. -One thing to be aware of here is that ``std::random_device`` is quite expensive to initialize. So if you are using the code in a performance critical place, you probably want to initialize it elsewhere. -Another thing is that the seeding quality of the suggested fix is quite poor: ``std::mt19937`` has an internal state of 624 32-bit integers, but is only seeded with a single integer. So if you require +One thing to be aware of here is that ``std::random_device`` is quite expensive +to initialize. So if you are using the code in a performance critical place, +you probably want to initialize it elsewhere. + +Another thing is that the seeding quality of the suggested fix is quite poor: +``std::mt19937`` has an internal state of 624 32-bit integers, but is only +seeded with a single integer. So if you require higher quality randomness, you should consider seeding better, for example: .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst index c0cffde..fbe2b85 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst @@ -4,7 +4,8 @@ modernize-type-traits ===================== Converts standard library type traits of the form ``traits<...>::type`` and -``traits<...>::value`` into ``traits_t<...>`` and ``traits_v<...>`` respectively. +``traits<...>::value`` into ``traits_t<...>`` and +``traits_v<...>`` respectively. For example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/unary-static-assert.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/unary-static-assert.rst index 31ece10..9a0de6c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/unary-static-assert.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/unary-static-assert.rst @@ -3,8 +3,9 @@ modernize-unary-static-assert ============================= -The check diagnoses any ``static_assert`` declaration with an empty string literal -and provides a fix-it to replace the declaration with a single-argument ``static_assert`` declaration. +The check diagnoses any ``static_assert`` declaration with an +empty string literal and provides a fix-it note to replace the +declaration with a single-argument ``static_assert`` declaration. The check is only applicable for C++17 and later code. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-auto.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-auto.rst index 6753617..3cd37e0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-auto.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-auto.rst @@ -163,8 +163,8 @@ The check handles ``static_cast``, ``dynamic_cast``, ``const_cast``, ``reinterpret_cast``, functional casts, C-style casts and function templates that behave as casts, such as ``llvm::dyn_cast``, ``boost::lexical_cast`` and ``gsl::narrow_cast``. Calls to function templates are considered to behave as -casts if the first template argument is explicit and is a type, and the function -returns that type, or a pointer or reference to it. +casts if the first template argument is explicit and is a type, and the +function returns that type, or a pointer or reference to it. Limitations diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-constraints.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-constraints.rst index a8b31b8..232cd01 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-constraints.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-constraints.rst @@ -6,8 +6,8 @@ modernize-use-constraints Replace ``std::enable_if`` with C++20 requires clauses. ``std::enable_if`` is a SFINAE mechanism for selecting the desired function or -class template based on type traits or other requirements. ``enable_if`` changes -the meta-arity of the template, and has other +class template based on type traits or other requirements. ``enable_if`` +changes the meta-arity of the template, and has other `adverse side effects <https://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0225r0.html>`_ in the code. C++20 introduces concepts and constraints as a cleaner language diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst index 62ea906..1b8c9c3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst @@ -3,8 +3,8 @@ modernize-use-designated-initializers ===================================== -Finds initializer lists for aggregate types which could be written as designated -initializers instead. +Finds initializer lists for aggregate types which could be written as +designated initializers instead. With plain initializer lists, it is very easy to introduce bugs when adding new fields in the middle of a struct or class type. The same confusion might arise @@ -38,9 +38,9 @@ declaration of ``S``. Even when compiling in a language version older than C++20, depending on your compiler, designated initializers are potentially supported. Therefore, the check is by default restricted to C99/C++20 and above. Check out the options -``-Wc99-designator`` to get support for mixed designators in initializer list in -C and ``-Wc++20-designator`` for support of designated initializers in older C++ -language modes. +`-Wc99-designator` to get support for mixed designators in initializer list +in C and `-Wc++20-designator` for support of designated initializers in older +C++ language modes. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-emplace.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-emplace.rst index e020ece..f1031f6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-emplace.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-emplace.rst @@ -17,19 +17,22 @@ The :option:`ContainersWithPushBack`, :option:`ContainersWithPush`, and types that support the ``push_back``, ``push``, and ``push_front`` operations respectively. The default values for these options are as follows: -* :option:`ContainersWithPushBack`: ``std::vector``, ``std::deque``, and ``std::list``. -* :option:`ContainersWithPush`: ``std::stack``, ``std::queue``, and ``std::priority_queue``. -* :option:`ContainersWithPushFront`: ``std::forward_list``, ``std::list``, and ``std::deque``. +* :option:`ContainersWithPushBack`: ``std::vector``, ``std::deque``, + and ``std::list``. +* :option:`ContainersWithPush`: ``std::stack``, ``std::queue``, + and ``std::priority_queue``. +* :option:`ContainersWithPushFront`: ``std::forward_list``, + ``std::list``, and ``std::deque``. This check also reports when an ``emplace``-like method is improperly used, for example using ``emplace_back`` while also calling a constructor. This -creates a temporary that requires at best a move and at worst a copy. Almost all -``emplace``-like functions in the STL are covered by this, with ``try_emplace`` -on ``std::map`` and ``std::unordered_map`` being the exception as it behaves -slightly differently than all the others. More containers can be added with the -:option:`EmplacyFunctions` option, so long as the container defines a -``value_type`` type, and the ``emplace``-like functions construct a -``value_type`` object. +creates a temporary that requires at best a move and at worst a copy. Almost +all ``emplace``-like functions in the STL are covered by this, with +``try_emplace`` on ``std::map`` and ``std::unordered_map`` being the +exception as it behaves slightly differently than all the others. More +containers can be added with the :option:`EmplacyFunctions` option, so long +as the container defines a ``value_type`` type, and the ``emplace``-like +functions construct a ``value_type`` object. Before: diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-equals-delete.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-equals-delete.rst index d354fcc..f632c81 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-equals-delete.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-equals-delete.rst @@ -13,9 +13,9 @@ definition. This approach would result in either a compiler error (when attempting to call a private function) or a linker error (due to an undefined reference). -However, subsequent to the advent of C++11, a more conventional approach emerged -for achieving this purpose. It involves flagging functions as ``= delete`` and -keeping them in the ``public`` section of the class. +However, subsequent to the advent of C++11, a more conventional approach +emerged for achieving this purpose. It involves flagging functions as +``= delete`` and keeping them in the ``public`` section of the class. To prevent false positives, this check is only active within a translation unit where all other member functions have been implemented. The check will diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst index 21bb254..e87825f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-format.rst @@ -22,7 +22,7 @@ into: return std::format("The {} is {:3}", description, value); The check uses the same format-string-conversion algorithm as -`modernize-use-std-print <../modernize/use-std-print.html>`_ and its +:doc:`modernize-use-std-print <../modernize/use-std-print>` and its shortcomings and behaviour in combination with macros are described in the documentation for that check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst index 3005708..4641975 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst @@ -7,9 +7,11 @@ Converts calls to ``printf``, ``fprintf``, ``absl::PrintF`` and ``absl::FPrintf`` to equivalent calls to C++23's ``std::print`` or ``std::println`` as appropriate, modifying the format string appropriately. The replaced and replacement functions can be customised by configuration -options. Each argument that is the result of a call to ``std::string::c_str()`` and -``std::string::data()`` will have that now-unnecessary call removed in a -similar manner to the `readability-redundant-string-cstr` check. +options. Each argument that is the result of a call to +``std::string::c_str()`` and ``std::string::data()`` will have that +now-unnecessary call removed in a similar manner to the +:doc:`readability-redundant-string-cstr +<../readability/redundant-string-cstr>` check. In other words, it turns lines like: diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst index 63b8885..f74158b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst @@ -37,9 +37,12 @@ The following categories of return types cannot be rewritten currently: * member function pointers * member pointers -Unqualified names in the return type might erroneously refer to different entities after the rewrite. -Preventing such errors requires a full lookup of all unqualified names present in the return type in the scope of the trailing return type location. -This location includes e.g. function parameter names and members of the enclosing class (including all inherited classes). +Unqualified names in the return type might erroneously refer to different +entities after the rewrite. +Preventing such errors requires a full lookup of all unqualified names +present in the return type in the scope of the trailing return type location. +This location includes e.g. function parameter names and members of the +enclosing class (including all inherited classes). Such a lookup is currently not implemented. Given the following piece of code @@ -66,7 +69,8 @@ a careless rewrite would produce the following output: }; auto CC::m() -> S { return {0}; } // error -This code fails to compile because the S in the context of f refers to the equally named function parameter. +This code fails to compile because the S in the context of f refers to the +equally named function parameter. Similarly, the S in the context of m refers to the equally named class member. The check can currently only detect and avoid a clash with a function parameter name. diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-using.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-using.rst index 32272a0..9eedf20 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-using.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-using.rst @@ -48,5 +48,5 @@ Options .. option:: IgnoreExternC - If set to `true`, the check will not give warning inside `extern "C"`scope. - Default is `false`
\ No newline at end of file + If set to `true`, the check will not give warning inside ``extern "C"`` + scope. Default is `false` diff --git a/clang-tools-extra/docs/clang-tidy/checks/mpi/buffer-deref.rst b/clang-tools-extra/docs/clang-tidy/checks/mpi/buffer-deref.rst index ef9f391..9658246 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/mpi/buffer-deref.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/mpi/buffer-deref.rst @@ -5,9 +5,10 @@ mpi-buffer-deref This check verifies if a buffer passed to an MPI (Message Passing Interface) function is sufficiently dereferenced. Buffers should be passed as a single -pointer or array. As MPI function signatures specify ``void *`` for their buffer -types, insufficiently dereferenced buffers can be passed, like for example as -double pointers or multidimensional arrays, without a compiler warning emitted. +pointer or array. As MPI function signatures specify ``void *`` for their +buffer types, insufficiently dereferenced buffers can be passed, like for +example as double pointers or multidimensional arrays, without a compiler +warning emitted. Examples: diff --git a/clang-tools-extra/docs/clang-tidy/checks/mpi/type-mismatch.rst b/clang-tools-extra/docs/clang-tidy/checks/mpi/type-mismatch.rst index 10752ef..e5d174c3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/mpi/type-mismatch.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/mpi/type-mismatch.rst @@ -3,10 +3,11 @@ mpi-type-mismatch ================= -This check verifies if buffer type and MPI (Message Passing Interface) datatype -pairs match for used MPI functions. All MPI datatypes defined by the MPI -standard (3.1) are verified by this check. User defined typedefs, custom MPI -datatypes and null pointer constants are skipped, in the course of verification. +This check verifies if buffer type and MPI (Message Passing Interface) +datatype pairs match for used MPI functions. All MPI datatypes defined +by the MPI standard (3.1) are verified by this check. User defined typedefs, +custom MPI datatypes and null pointer constants are skipped, in the course +of verification. Example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/objc/forbidden-subclassing.rst b/clang-tools-extra/docs/clang-tidy/checks/objc/forbidden-subclassing.rst index 4bb023c..3894094 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/objc/forbidden-subclassing.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/objc/forbidden-subclassing.rst @@ -3,11 +3,11 @@ objc-forbidden-subclassing ========================== -Finds Objective-C classes which are subclasses of classes which are not designed -to be subclassed. +Finds Objective-C classes which are subclasses of classes which are +not designed to be subclassed. -By default, includes a list of Objective-C classes which are publicly documented -as not supporting subclassing. +By default, includes a list of Objective-C classes which are publicly +documented as not supporting subclassing. .. note:: diff --git a/clang-tools-extra/docs/clang-tidy/checks/objc/nsdate-formatter.rst b/clang-tools-extra/docs/clang-tidy/checks/objc/nsdate-formatter.rst index b5a1386..ea54a05 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/objc/nsdate-formatter.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/objc/nsdate-formatter.rst @@ -3,71 +3,93 @@ objc-nsdate-formatter ===================== -When ``NSDateFormatter`` is used to convert an ``NSDate`` type to a ``String`` type, the user -can specify a custom format string. Certain format specifiers are undesirable -despite being legal. See http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns for all legal date patterns. +When ``NSDateFormatter`` is used to convert an ``NSDate`` type to a ``String`` +type, the user can specify a custom format string. Certain format specifiers +are undesirable despite being legal. +See http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns +for all legal date patterns. -This checker reports as warnings the following string patterns in a date format specifier: +This checker reports as warnings the following string patterns in a date +format specifier: -#. yyyy + ww : Calendar year specified with week of a week year (unless YYYY is also specified). +#. yyyy + ww : Calendar year specified with week of a week year + (unless YYYY is also specified). - * | **Example 1:** Input Date: `29 December 2014` ; Format String: `yyyy-ww`; + * | **Example 1:** Input Date: `29 December 2014` ; + | Format String: `yyyy-ww`; | Output string: `2014-01` (Wrong because it’s not the first week of 2014) - * | **Example 2:** Input Date: `29 December 2014` ; Format String: `dd-MM-yyyy (ww-YYYY)`; + * | **Example 2:** Input Date: `29 December 2014` ; + | Format String: `dd-MM-yyyy (ww-YYYY)`; | Output string: `29-12-2014 (01-2015)` (This is correct) #. F without ee/EE : Numeric day of week in a month without actual day. * | **Example:** Input Date: `29 December 2014` ; Format String: `F-MM`; - | Output string: `5-12` (Wrong because it reads as *5th ___ of Dec* in English) + | Output string: `5-12` (Wrong because it reads as *5th ___ of Dec* in + | English) #. F without MM : Numeric day of week in a month without month. * | **Example:** Input Date: `29 December 2014` ; Format String: `F-EE` - | Output string: `5-Mon` (Wrong because it reads as *5th Mon of ___* in English) + | Output string: `5-Mon` (Wrong because it reads as *5th Mon of ___* in + | English) #. WW without MM : Week of the month without the month. * | **Example:** Input Date: `29 December 2014` ; Format String: `WW-yyyy` - | Output string: `05-2014` (Wrong because it reads as *5th Week of ___* in English) + | Output string: `05-2014` (Wrong because it reads as *5th Week of ___* in + | English) -#. YYYY + QQ : Week year specified with quarter of normal year (unless yyyy is also specified). +#. YYYY + QQ : Week year specified with quarter of normal year + (unless yyyy is also specified). * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-QQ` - | Output string: `2015-04` (Wrong because it’s not the 4th quarter of 2015) + | Output string: `2015-04` (Wrong because it’s not the 4th quarter of + | 2015) - * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (QQ-yyyy)` + * | **Example 2:** Input Date: `29 December 2014` ; + | Format String: `ww-YYYY (QQ-yyyy)` | Output string: `01-2015 (04-2014)` (This is correct) -#. YYYY + MM : Week year specified with Month of a calendar year (unless yyyy is also specified). +#. YYYY + MM : Week year specified with Month of a calendar year + (unless yyyy is also specified). * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-MM` | Output string: `2015-12` (Wrong because it’s not the 12th month of 2015) - * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (MM-yyyy)` + * | **Example 2:** Input Date: `29 December 2014` ; + | Format String: `ww-YYYY (MM-yyyy)` | Output string: `01-2015 (12-2014)` (This is correct) -#. YYYY + DD : Week year with day of a calendar year (unless yyyy is also specified). +#. YYYY + DD : Week year with day of a calendar year + (unless yyyy is also specified). * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-DD` | Output string: `2015-363` (Wrong because it’s not the 363rd day of 2015) - * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (DD-yyyy)` + * | **Example 2:** Input Date: `29 December 2014` ; + | Format String: `ww-YYYY (DD-yyyy)` | Output string: `01-2015 (363-2014)` (This is correct) -#. YYYY + WW : Week year with week of a calendar year (unless yyyy is also specified). +#. YYYY + WW : Week year with week of a calendar year + (unless yyyy is also specified). * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-WW` | Output string: `2015-05` (Wrong because it’s not the 5th week of 2015) - * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (WW-MM-yyyy)` + * | **Example 2:** Input Date: `29 December 2014` ; + | Format String: `ww-YYYY (WW-MM-yyyy)` | Output string: `01-2015 (05-12-2014)` (This is correct) -#. YYYY + F : Week year with day of week in a calendar month (unless yyyy is also specified). +#. YYYY + F : Week year with day of week in a calendar month + (unless yyyy is also specified). - * | **Example 1:** Input Date: `29 December 2014` ; Format String: `YYYY-ww-F-EE` - | Output string: `2015-01-5-Mon` (Wrong because it’s not the 5th Monday of January in 2015) + * | **Example 1:** Input Date: `29 December 2014` ; + | Format String: `YYYY-ww-F-EE` + | Output string: `2015-01-5-Mon` (Wrong because it’s not the 5th Monday of + | January in 2015) - * | **Example 2:** Input Date: `29 December 2014` ; Format String: `ww-YYYY (F-EE-MM-yyyy)` + * | **Example 2:** Input Date: `29 December 2014` ; + | Format String: `ww-YYYY (F-EE-MM-yyyy)` | Output string: `01-2015 (5-Mon-12-2014)` (This is correct) diff --git a/clang-tools-extra/docs/clang-tidy/checks/objc/property-declaration.rst b/clang-tools-extra/docs/clang-tidy/checks/objc/property-declaration.rst index 60b9c82..53f9453 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/objc/property-declaration.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/objc/property-declaration.rst @@ -23,8 +23,8 @@ The check will only fix 'CamelCase' to 'camelCase'. In some other cases we will only provide warning messages since the property name could be complicated. Users will need to come up with a proper name by their own. -This check also accepts special acronyms as prefixes or suffixes. Such prefixes or suffixes -will suppress the Lower Camel Case check according to the guide: +This check also accepts special acronyms as prefixes or suffixes. Such prefixes +or suffixes will suppress the Lower Camel Case check according to the guide: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingBasics.html#//apple_ref/doc/uid/20001281-1002931-BBCFHEAB For a full list of well-known acronyms: diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/no-int-to-ptr.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/no-int-to-ptr.rst index 8233ea1..dc69f20 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/performance/no-int-to-ptr.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/performance/no-int-to-ptr.rst @@ -7,8 +7,8 @@ Diagnoses every integer to pointer cast. While casting an (integral) pointer to an integer is obvious - you just get the integral value of the pointer, casting an integer to an (integral) pointer -is deceivingly different. While you will get a pointer with that integral value, -if you got that integral value via a pointer-to-integer cast originally, +is deceivingly different. While you will get a pointer with that integral +value, if you got that integral value via a pointer-to-integer cast originally, the new pointer will lack the provenance information from the original pointer. So while (integral) pointer to integer casts are effectively no-ops, diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/noexcept-swap.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/noexcept-swap.rst index 2901d72..e6d25d9 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/performance/noexcept-swap.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/performance/noexcept-swap.rst @@ -3,11 +3,11 @@ performance-noexcept-swap ========================= -The check flags user-defined swap and iter_swap functions not marked with ``noexcept`` or -marked with ``noexcept(expr)`` where ``expr`` evaluates to ``false`` -(but is not a ``false`` literal itself). +The check flags user-defined swap and iter_swap functions not marked with +``noexcept`` or marked with ``noexcept(expr)`` where ``expr`` evaluates to +``false`` (but is not a ``false`` literal itself). -When a swap or iter_swap function is marked as ``noexcept``, it assures the compiler that -no exceptions will be thrown during the swapping of two objects, which allows -the compiler to perform certain optimizations such as omitting exception -handling code. +When a swap or iter_swap function is marked as ``noexcept``, it assures the +compiler that no exceptions will be thrown during the swapping of two objects, +which allows the compiler to perform certain optimizations such as omitting +exception handling code. diff --git a/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-copy-initialization.rst b/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-copy-initialization.rst index 0e9d547..00581b1 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-copy-initialization.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/performance/unnecessary-copy-initialization.rst @@ -9,8 +9,8 @@ const reference. The check is only applied if it is safe to replace the copy by a const reference. This is the case when the variable is const qualified or when it is -only used as a const, i.e. only const methods or operators are invoked on it, or -it is used as const reference or value argument in constructors or function +only used as a const, i.e. only const methods or operators are invoked on it, +or it is used as const reference or value argument in constructors or function calls. Example: diff --git a/clang-tools-extra/docs/clang-tidy/checks/portability/simd-intrinsics.rst b/clang-tools-extra/docs/clang-tidy/checks/portability/simd-intrinsics.rst index ab43c2f..7ba3a1d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/portability/simd-intrinsics.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/portability/simd-intrinsics.rst @@ -19,18 +19,18 @@ objects. Otherwise, it just complains the intrinsics are non-portable (and there are `P0214`_ alternatives). -Many architectures provide SIMD operations (e.g. x86 SSE/AVX, Power AltiVec/VSX, -ARM NEON). It is common that SIMD code implementing the same algorithm, is -written in multiple target-dispatching pieces to optimize for different -architectures or micro-architectures. +Many architectures provide SIMD operations (e.g. x86 SSE/AVX, Power +AltiVec/VSX, ARM NEON). It is common that SIMD code implementing the same +algorithm, is written in multiple target-dispatching pieces to optimize for +different architectures or micro-architectures. The C++ standard proposal `P0214`_ and its extensions cover many common SIMD operations. By migrating from target-dependent intrinsics to `P0214`_ -operations, the SIMD code can be simplified and pieces for different targets can -be unified. +operations, the SIMD code can be simplified and pieces for different targets +can be unified. -Refer to `P0214`_ for introduction and motivation for the data-parallel standard -library. +Refer to `P0214`_ for introduction and motivation for the data-parallel +standard library. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/portability/std-allocator-const.rst b/clang-tools-extra/docs/clang-tidy/checks/portability/std-allocator-const.rst index 31463c2..fdde552 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/portability/std-allocator-const.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/portability/std-allocator-const.rst @@ -9,11 +9,11 @@ elements). These are not allowed in standard C++, and should usually be Per C++ ``[allocator.requirements.general]``: "T is any cv-unqualified object type", ``std::allocator<const T>`` is undefined. Many standard containers use -``std::allocator`` by default and therefore their ``const T`` instantiations are -undefined. +``std::allocator`` by default and therefore their ``const T`` instantiations +are undefined. -libc++ defines ``std::allocator<const T>`` as an extension which will be removed -in the future. +libc++ defines ``std::allocator<const T>`` as an extension which will be +removed in the future. libstdc++ and MSVC do not support ``std::allocator<const T>``: diff --git a/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst b/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst index 913b20f..e21dedf 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/portability/template-virtual-member-function.rst @@ -3,16 +3,17 @@ portability-template-virtual-member-function ============================================ -Finds cases when an uninstantiated virtual member function in a template class causes -cross-compiler incompatibility. +Finds cases when an uninstantiated virtual member function in a template class +causes cross-compiler incompatibility. -Upon instantiating a template class, non-virtual member functions don't have to be -instantiated unless they are used. Virtual member function instantiation on the other hand -is unspecified and depends on the implementation of the compiler. +Upon instantiating a template class, non-virtual member functions don't have +to be instantiated unless they are used. Virtual member function instantiation +on the other hand is unspecified and depends on the implementation of the +compiler. -In the following snippets the virtual member function is not instantiated by GCC and Clang, -but it is instantiated by MSVC, so while the snippet is accepted by the former compilers, -it is rejected by the latter. +In the following snippets the virtual member function is not instantiated by +GCC and Clang, but it is instantiated by MSVC, so while the snippet is accepted +by the former compilers, it is rejected by the latter. .. code:: c++ @@ -32,6 +33,7 @@ it is rejected by the latter. return 0; } -Cross-platform projects that need to support MSVC on Windows might see compiler errors -because certain virtual member functions are instantiated, which are not instantiated -by other compilers on other platforms. This check highlights such virtual member functions. +Cross-platform projects that need to support MSVC on Windows might see compiler +errors because certain virtual member functions are instantiated, which are not +instantiated by other compilers on other platforms. This check highlights such +virtual member functions. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/container-contains.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/container-contains.rst index 9f5b263f..120d360 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/container-contains.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/container-contains.rst @@ -30,5 +30,5 @@ Initial expression Result This check will apply to any class that has a ``contains`` method, notably including ``std::set``, ``std::unordered_set``, ``std::map``, and -``std::unordered_map`` as of C++20, and ``std::string`` and ``std::string_view`` -as of C++23. +``std::unordered_map`` as of C++20, and ``std::string`` and +``std::string_view`` as of C++23. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst index a4eff16..4b2ef6e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst @@ -6,11 +6,11 @@ readability-container-data-pointer Finds cases where code could use ``data()`` rather than the address of the element at index 0 in a container. This pattern is commonly used to materialize a pointer to the backing data of a container. ``std::vector`` and -``std::string`` provide a ``data()`` accessor to retrieve the data pointer which -should be preferred. +``std::string`` provide a ``data()`` accessor to retrieve the data pointer +which should be preferred. -This also ensures that in the case that the container is empty, the data pointer -access does not perform an errant memory access. +This also ensures that in the case that the container is empty, the data +pointer access does not perform an errant memory access. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/convert-member-functions-to-static.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/convert-member-functions-to-static.rst index 641cb83..59f4632 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/convert-member-functions-to-static.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/convert-member-functions-to-static.rst @@ -10,5 +10,6 @@ After applying modifications as suggested by the check, running the check again might find more opportunities to mark member functions ``static``. After making a member function ``static``, you might want to run the check -:doc:`readability-static-accessed-through-instance <../readability/static-accessed-through-instance>` to replace calls like +:doc:`readability-static-accessed-through-instance +<../readability/static-accessed-through-instance>` to replace calls like ``Instance.method()`` by ``Class::method()``. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/delete-null-pointer.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/delete-null-pointer.rst index 21c91b4..0877915 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/delete-null-pointer.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/delete-null-pointer.rst @@ -3,7 +3,8 @@ readability-delete-null-pointer =============================== -Checks the ``if`` statements where a pointer's existence is checked and then deletes the pointer. +Checks the ``if`` statements where a pointer's existence is checked and +then deletes the pointer. The check is unnecessary as deleting a null pointer has no effect. .. code:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/duplicate-include.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/duplicate-include.rst index 45df7e1..28a4991a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/duplicate-include.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/duplicate-include.rst @@ -33,3 +33,12 @@ Because of the intervening macro definitions, this code remains unchanged: #define NDEBUG #include "assertion.h" // ...code with assertions disabled + +Options +------- + +.. option:: IgnoredFilesList + + A semicolon-separated list of regular expressions or filenames that are + allowed to be included multiple times without diagnostics. Matching is + performed against the textual include name. Default is an empty string. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/else-after-return.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/else-after-return.rst index 25fb408..569fa24 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/else-after-return.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/else-after-return.rst @@ -9,7 +9,8 @@ Early exit is one of the suggested enforcements of that. Please do not use ``else`` or ``else if`` after something that interrupts control flow - like ``return``, ``break``, ``continue``, ``throw``. -The following piece of code illustrates how the check works. This piece of code: +The following piece of code illustrates how the check works. +This piece of code: .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/function-cognitive-complexity.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/function-cognitive-complexity.rst index 3710917..430006e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/function-cognitive-complexity.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/function-cognitive-complexity.rst @@ -68,8 +68,8 @@ Nesting level ^^^^^^^^^^^^^ While by itself the nesting level does not change the function's Cognitive -Complexity metric, it is tracked, and is used by the next, third building block. -The following structures increase the nesting level (by `1`): +Complexity metric, it is tracked, and is used by the next, third building +block. The following structures increase the nesting level (by `1`): * Conditional operators: diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst index 271970c2..c4d39a2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst @@ -16,7 +16,8 @@ The following options are described below: - :option:`MinimumVariableNameLength`, :option:`IgnoredVariableNames` - :option:`MinimumParameterNameLength`, :option:`IgnoredParameterNames` - :option:`MinimumLoopCounterNameLength`, :option:`IgnoredLoopCounterNames` - - :option:`MinimumExceptionNameLength`, :option:`IgnoredExceptionVariableNames` + - :option:`MinimumExceptionNameLength`, + :option:`IgnoredExceptionVariableNames` .. option:: MinimumVariableNameLength diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst index 6c4e0b7..2c0d69f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst @@ -31,12 +31,13 @@ The naming of virtual methods is reported where they occur in the base class, but not where they are overridden, as it can't be fixed locally there. This also applies for pseudo-override patterns like CRTP. -``Leading_upper_snake_case`` is a naming convention where the first word is capitalized -followed by lower case word(s) separated by underscore(s) '_'. Examples include: -`Cap_snake_case`, `Cobra_case`, `Foo_bar_baz`, and `Master_copy_8gb`. +``Leading_upper_snake_case`` is a naming convention where the first word is +capitalized followed by lower case word(s) separated by underscore(s) '_'. +Examples include: `Cap_snake_case`, `Cobra_case`, `Foo_bar_baz`, +and `Master_copy_8gb`. -Hungarian notation can be customized using different *HungarianPrefix* settings. -The options and their corresponding values are: +Hungarian notation can be customized using different *HungarianPrefix* +settings. The options and their corresponding values are: - ``Off`` - the default setting - ``On`` - example: ``int iVariable`` @@ -57,62 +58,164 @@ The available options are summarized below: **Specific options** - - :option:`AbstractClassCase`, :option:`AbstractClassPrefix`, :option:`AbstractClassSuffix`, :option:`AbstractClassIgnoredRegexp`, :option:`AbstractClassHungarianPrefix` - - :option:`ClassCase`, :option:`ClassPrefix`, :option:`ClassSuffix`, :option:`ClassIgnoredRegexp`, :option:`ClassHungarianPrefix` - - :option:`ClassConstexprCase`, :option:`ClassConstexprPrefix`, :option:`ClassConstexprSuffix`, :option:`ClassConstexprIgnoredRegexp`, :option:`ClassConstexprHungarianPrefix` - - :option:`ClassConstantCase`, :option:`ClassConstantPrefix`, :option:`ClassConstantSuffix`, :option:`ClassConstantIgnoredRegexp`, :option:`ClassConstantHungarianPrefix` - - :option:`ClassMemberCase`, :option:`ClassMemberPrefix`, :option:`ClassMemberSuffix`, :option:`ClassMemberIgnoredRegexp`, :option:`ClassMemberHungarianPrefix` - - :option:`ClassMethodCase`, :option:`ClassMethodPrefix`, :option:`ClassMethodSuffix`, :option:`ClassMethodIgnoredRegexp` - - :option:`ConceptCase`, :option:`ConceptPrefix`, :option:`ConceptSuffix`, :option:`ConceptIgnoredRegexp` - - :option:`ConstantCase`, :option:`ConstantPrefix`, :option:`ConstantSuffix`, :option:`ConstantIgnoredRegexp`, :option:`ConstantHungarianPrefix` - - :option:`ConstantMemberCase`, :option:`ConstantMemberPrefix`, :option:`ConstantMemberSuffix`, :option:`ConstantMemberIgnoredRegexp`, :option:`ConstantMemberHungarianPrefix` - - :option:`ConstantParameterCase`, :option:`ConstantParameterPrefix`, :option:`ConstantParameterSuffix`, :option:`ConstantParameterIgnoredRegexp`, :option:`ConstantParameterHungarianPrefix` - - :option:`ConstantPointerParameterCase`, :option:`ConstantPointerParameterPrefix`, :option:`ConstantPointerParameterSuffix`, :option:`ConstantPointerParameterIgnoredRegexp`, :option:`ConstantPointerParameterHungarianPrefix` - - :option:`ConstexprFunctionCase`, :option:`ConstexprFunctionPrefix`, :option:`ConstexprFunctionSuffix`, :option:`ConstexprFunctionIgnoredRegexp` - - :option:`ConstexprMethodCase`, :option:`ConstexprMethodPrefix`, :option:`ConstexprMethodSuffix`, :option:`ConstexprMethodIgnoredRegexp` - - :option:`ConstexprVariableCase`, :option:`ConstexprVariablePrefix`, :option:`ConstexprVariableSuffix`, :option:`ConstexprVariableIgnoredRegexp`, :option:`ConstexprVariableHungarianPrefix` - - :option:`EnumCase`, :option:`EnumPrefix`, :option:`EnumSuffix`, :option:`EnumIgnoredRegexp` - - :option:`EnumConstantCase`, :option:`EnumConstantPrefix`, :option:`EnumConstantSuffix`, :option:`EnumConstantIgnoredRegexp`, :option:`EnumConstantHungarianPrefix` - - :option:`FunctionCase`, :option:`FunctionPrefix`, :option:`FunctionSuffix`, :option:`FunctionIgnoredRegexp` - - :option:`GlobalConstexprVariableCase`, :option:`GlobalConstexprVariablePrefix`, :option:`GlobalConstexprVariableSuffix`, :option:`GlobalConstexprVariableIgnoredRegexp`, :option:`GlobalConstexprVariableHungarianPrefix` - - :option:`GlobalConstantCase`, :option:`GlobalConstantPrefix`, :option:`GlobalConstantSuffix`, :option:`GlobalConstantIgnoredRegexp`, :option:`GlobalConstantHungarianPrefix` - - :option:`GlobalConstantPointerCase`, :option:`GlobalConstantPointerPrefix`, :option:`GlobalConstantPointerSuffix`, :option:`GlobalConstantPointerIgnoredRegexp`, :option:`GlobalConstantPointerHungarianPrefix` - - :option:`GlobalFunctionCase`, :option:`GlobalFunctionPrefix`, :option:`GlobalFunctionSuffix`, :option:`GlobalFunctionIgnoredRegexp` - - :option:`GlobalPointerCase`, :option:`GlobalPointerPrefix`, :option:`GlobalPointerSuffix`, :option:`GlobalPointerIgnoredRegexp`, :option:`GlobalPointerHungarianPrefix` - - :option:`GlobalVariableCase`, :option:`GlobalVariablePrefix`, :option:`GlobalVariableSuffix`, :option:`GlobalVariableIgnoredRegexp`, :option:`GlobalVariableHungarianPrefix` - - :option:`InlineNamespaceCase`, :option:`InlineNamespacePrefix`, :option:`InlineNamespaceSuffix`, :option:`InlineNamespaceIgnoredRegexp` - - :option:`LocalConstexprVariableCase`, :option:`LocalConstexprVariablePrefix`, :option:`LocalConstexprVariableSuffix`, :option:`LocalConstexprVariableIgnoredRegexp`, :option:`LocalConstexprVariableHungarianPrefix` - - :option:`LocalConstantCase`, :option:`LocalConstantPrefix`, :option:`LocalConstantSuffix`, :option:`LocalConstantIgnoredRegexp`, :option:`LocalConstantHungarianPrefix` - - :option:`LocalConstantPointerCase`, :option:`LocalConstantPointerPrefix`, :option:`LocalConstantPointerSuffix`, :option:`LocalConstantPointerIgnoredRegexp`, :option:`LocalConstantPointerHungarianPrefix` - - :option:`LocalPointerCase`, :option:`LocalPointerPrefix`, :option:`LocalPointerSuffix`, :option:`LocalPointerIgnoredRegexp`, :option:`LocalPointerHungarianPrefix` - - :option:`LocalVariableCase`, :option:`LocalVariablePrefix`, :option:`LocalVariableSuffix`, :option:`LocalVariableIgnoredRegexp`, :option:`LocalVariableHungarianPrefix` - - :option:`MacroDefinitionCase`, :option:`MacroDefinitionPrefix`, :option:`MacroDefinitionSuffix`, :option:`MacroDefinitionIgnoredRegexp` - - :option:`MemberCase`, :option:`MemberPrefix`, :option:`MemberSuffix`, :option:`MemberIgnoredRegexp`, :option:`MemberHungarianPrefix` - - :option:`MethodCase`, :option:`MethodPrefix`, :option:`MethodSuffix`, :option:`MethodIgnoredRegexp` - - :option:`NamespaceCase`, :option:`NamespacePrefix`, :option:`NamespaceSuffix`, :option:`NamespaceIgnoredRegexp` - - :option:`ParameterCase`, :option:`ParameterPrefix`, :option:`ParameterSuffix`, :option:`ParameterIgnoredRegexp`, :option:`ParameterHungarianPrefix` - - :option:`ParameterPackCase`, :option:`ParameterPackPrefix`, :option:`ParameterPackSuffix`, :option:`ParameterPackIgnoredRegexp` - - :option:`PointerParameterCase`, :option:`PointerParameterPrefix`, :option:`PointerParameterSuffix`, :option:`PointerParameterIgnoredRegexp`, :option:`PointerParameterHungarianPrefix` - - :option:`PrivateMemberCase`, :option:`PrivateMemberPrefix`, :option:`PrivateMemberSuffix`, :option:`PrivateMemberIgnoredRegexp`, :option:`PrivateMemberHungarianPrefix` - - :option:`PrivateMethodCase`, :option:`PrivateMethodPrefix`, :option:`PrivateMethodSuffix`, :option:`PrivateMethodIgnoredRegexp` - - :option:`ProtectedMemberCase`, :option:`ProtectedMemberPrefix`, :option:`ProtectedMemberSuffix`, :option:`ProtectedMemberIgnoredRegexp`, :option:`ProtectedMemberHungarianPrefix` - - :option:`ProtectedMethodCase`, :option:`ProtectedMethodPrefix`, :option:`ProtectedMethodSuffix`, :option:`ProtectedMethodIgnoredRegexp` - - :option:`PublicMemberCase`, :option:`PublicMemberPrefix`, :option:`PublicMemberSuffix`, :option:`PublicMemberIgnoredRegexp`, :option:`PublicMemberHungarianPrefix` - - :option:`PublicMethodCase`, :option:`PublicMethodPrefix`, :option:`PublicMethodSuffix`, :option:`PublicMethodIgnoredRegexp` - - :option:`ScopedEnumConstantCase`, :option:`ScopedEnumConstantPrefix`, :option:`ScopedEnumConstantSuffix`, :option:`ScopedEnumConstantIgnoredRegexp` - - :option:`StaticConstexprVariableCase`, :option:`StaticConstexprVariablePrefix`, :option:`StaticConstexprVariableSuffix`, :option:`StaticConstexprVariableIgnoredRegexp`, :option:`StaticConstexprVariableHungarianPrefix` - - :option:`StaticConstantCase`, :option:`StaticConstantPrefix`, :option:`StaticConstantSuffix`, :option:`StaticConstantIgnoredRegexp`, :option:`StaticConstantHungarianPrefix` - - :option:`StaticVariableCase`, :option:`StaticVariablePrefix`, :option:`StaticVariableSuffix`, :option:`StaticVariableIgnoredRegexp`, :option:`StaticVariableHungarianPrefix` - - :option:`StructCase`, :option:`StructPrefix`, :option:`StructSuffix`, :option:`StructIgnoredRegexp` - - :option:`TemplateParameterCase`, :option:`TemplateParameterPrefix`, :option:`TemplateParameterSuffix`, :option:`TemplateParameterIgnoredRegexp` - - :option:`TemplateTemplateParameterCase`, :option:`TemplateTemplateParameterPrefix`, :option:`TemplateTemplateParameterSuffix`, :option:`TemplateTemplateParameterIgnoredRegexp` - - :option:`TypeAliasCase`, :option:`TypeAliasPrefix`, :option:`TypeAliasSuffix`, :option:`TypeAliasIgnoredRegexp` - - :option:`TypedefCase`, :option:`TypedefPrefix`, :option:`TypedefSuffix`, :option:`TypedefIgnoredRegexp` - - :option:`TypeTemplateParameterCase`, :option:`TypeTemplateParameterPrefix`, :option:`TypeTemplateParameterSuffix`, :option:`TypeTemplateParameterIgnoredRegexp` - - :option:`UnionCase`, :option:`UnionPrefix`, :option:`UnionSuffix`, :option:`UnionIgnoredRegexp` - - :option:`ValueTemplateParameterCase`, :option:`ValueTemplateParameterPrefix`, :option:`ValueTemplateParameterSuffix`, :option:`ValueTemplateParameterIgnoredRegexp` - - :option:`VariableCase`, :option:`VariablePrefix`, :option:`VariableSuffix`, :option:`VariableIgnoredRegexp`, :option:`VariableHungarianPrefix` - - :option:`VirtualMethodCase`, :option:`VirtualMethodPrefix`, :option:`VirtualMethodSuffix`, :option:`VirtualMethodIgnoredRegexp` + - :option:`AbstractClassCase`, :option:`AbstractClassPrefix`, + :option:`AbstractClassSuffix`, :option:`AbstractClassIgnoredRegexp`, + :option:`AbstractClassHungarianPrefix` + - :option:`ClassCase`, :option:`ClassPrefix`, :option:`ClassSuffix`, + :option:`ClassIgnoredRegexp`, :option:`ClassHungarianPrefix` + - :option:`ClassConstexprCase`, :option:`ClassConstexprPrefix`, + :option:`ClassConstexprSuffix`, :option:`ClassConstexprIgnoredRegexp`, + :option:`ClassConstexprHungarianPrefix` + - :option:`ClassConstantCase`, :option:`ClassConstantPrefix`, + :option:`ClassConstantSuffix`, :option:`ClassConstantIgnoredRegexp`, + :option:`ClassConstantHungarianPrefix` + - :option:`ClassMemberCase`, :option:`ClassMemberPrefix`, + :option:`ClassMemberSuffix`, :option:`ClassMemberIgnoredRegexp`, + :option:`ClassMemberHungarianPrefix` + - :option:`ClassMethodCase`, :option:`ClassMethodPrefix`, + :option:`ClassMethodSuffix`, :option:`ClassMethodIgnoredRegexp` + - :option:`ConceptCase`, :option:`ConceptPrefix`, :option:`ConceptSuffix`, + :option:`ConceptIgnoredRegexp` + - :option:`ConstantCase`, :option:`ConstantPrefix`, :option:`ConstantSuffix`, + :option:`ConstantIgnoredRegexp`, :option:`ConstantHungarianPrefix` + - :option:`ConstantMemberCase`, :option:`ConstantMemberPrefix`, + :option:`ConstantMemberSuffix`, :option:`ConstantMemberIgnoredRegexp`, + :option:`ConstantMemberHungarianPrefix` + - :option:`ConstantParameterCase`, :option:`ConstantParameterPrefix`, + :option:`ConstantParameterSuffix`, :option:`ConstantParameterIgnoredRegexp`, + :option:`ConstantParameterHungarianPrefix` + - :option:`ConstantPointerParameterCase`, + :option:`ConstantPointerParameterPrefix`, + :option:`ConstantPointerParameterSuffix`, + :option:`ConstantPointerParameterIgnoredRegexp`, + :option:`ConstantPointerParameterHungarianPrefix` + - :option:`ConstexprFunctionCase`, :option:`ConstexprFunctionPrefix`, + :option:`ConstexprFunctionSuffix`, :option:`ConstexprFunctionIgnoredRegexp` + - :option:`ConstexprMethodCase`, :option:`ConstexprMethodPrefix`, + :option:`ConstexprMethodSuffix`, :option:`ConstexprMethodIgnoredRegexp` + - :option:`ConstexprVariableCase`, :option:`ConstexprVariablePrefix`, + :option:`ConstexprVariableSuffix`, :option:`ConstexprVariableIgnoredRegexp`, + :option:`ConstexprVariableHungarianPrefix` + - :option:`EnumCase`, :option:`EnumPrefix`, :option:`EnumSuffix`, + :option:`EnumIgnoredRegexp` + - :option:`EnumConstantCase`, :option:`EnumConstantPrefix`, + :option:`EnumConstantSuffix`, :option:`EnumConstantIgnoredRegexp`, + :option:`EnumConstantHungarianPrefix` + - :option:`FunctionCase`, :option:`FunctionPrefix`, :option:`FunctionSuffix`, + :option:`FunctionIgnoredRegexp` + - :option:`GlobalConstexprVariableCase`, + :option:`GlobalConstexprVariablePrefix`, + :option:`GlobalConstexprVariableSuffix`, + :option:`GlobalConstexprVariableIgnoredRegexp`, + :option:`GlobalConstexprVariableHungarianPrefix` + - :option:`GlobalConstantCase`, :option:`GlobalConstantPrefix`, + :option:`GlobalConstantSuffix`, :option:`GlobalConstantIgnoredRegexp`, + :option:`GlobalConstantHungarianPrefix` + - :option:`GlobalConstantPointerCase`, + :option:`GlobalConstantPointerPrefix`, + :option:`GlobalConstantPointerSuffix`, + :option:`GlobalConstantPointerIgnoredRegexp`, + :option:`GlobalConstantPointerHungarianPrefix` + - :option:`GlobalFunctionCase`, :option:`GlobalFunctionPrefix`, + :option:`GlobalFunctionSuffix`, :option:`GlobalFunctionIgnoredRegexp` + - :option:`GlobalPointerCase`, :option:`GlobalPointerPrefix`, + :option:`GlobalPointerSuffix`, :option:`GlobalPointerIgnoredRegexp`, + :option:`GlobalPointerHungarianPrefix` + - :option:`GlobalVariableCase`, :option:`GlobalVariablePrefix`, + :option:`GlobalVariableSuffix`, :option:`GlobalVariableIgnoredRegexp`, + :option:`GlobalVariableHungarianPrefix` + - :option:`InlineNamespaceCase`, :option:`InlineNamespacePrefix`, + :option:`InlineNamespaceSuffix`, :option:`InlineNamespaceIgnoredRegexp` + - :option:`LocalConstexprVariableCase`, + :option:`LocalConstexprVariablePrefix`, + :option:`LocalConstexprVariableSuffix`, + :option:`LocalConstexprVariableIgnoredRegexp`, + :option:`LocalConstexprVariableHungarianPrefix` + - :option:`LocalConstantCase`, :option:`LocalConstantPrefix`, + :option:`LocalConstantSuffix`, :option:`LocalConstantIgnoredRegexp`, + :option:`LocalConstantHungarianPrefix` + - :option:`LocalConstantPointerCase`, + :option:`LocalConstantPointerPrefix`, + :option:`LocalConstantPointerSuffix`, + :option:`LocalConstantPointerIgnoredRegexp`, + :option:`LocalConstantPointerHungarianPrefix` + - :option:`LocalPointerCase`, :option:`LocalPointerPrefix`, + :option:`LocalPointerSuffix`, :option:`LocalPointerIgnoredRegexp`, + :option:`LocalPointerHungarianPrefix` + - :option:`LocalVariableCase`, :option:`LocalVariablePrefix`, + :option:`LocalVariableSuffix`, :option:`LocalVariableIgnoredRegexp`, + :option:`LocalVariableHungarianPrefix` + - :option:`MacroDefinitionCase`, :option:`MacroDefinitionPrefix`, + :option:`MacroDefinitionSuffix`, :option:`MacroDefinitionIgnoredRegexp` + - :option:`MemberCase`, :option:`MemberPrefix`, :option:`MemberSuffix`, + :option:`MemberIgnoredRegexp`, :option:`MemberHungarianPrefix` + - :option:`MethodCase`, :option:`MethodPrefix`, :option:`MethodSuffix`, + :option:`MethodIgnoredRegexp` + - :option:`NamespaceCase`, :option:`NamespacePrefix`, + :option:`NamespaceSuffix`, :option:`NamespaceIgnoredRegexp` + - :option:`ParameterCase`, :option:`ParameterPrefix`, + :option:`ParameterSuffix`, :option:`ParameterIgnoredRegexp`, + :option:`ParameterHungarianPrefix` + - :option:`ParameterPackCase`, :option:`ParameterPackPrefix`, + :option:`ParameterPackSuffix`, :option:`ParameterPackIgnoredRegexp` + - :option:`PointerParameterCase`, :option:`PointerParameterPrefix`, + :option:`PointerParameterSuffix`, :option:`PointerParameterIgnoredRegexp`, + :option:`PointerParameterHungarianPrefix` + - :option:`PrivateMemberCase`, :option:`PrivateMemberPrefix`, + :option:`PrivateMemberSuffix`, :option:`PrivateMemberIgnoredRegexp`, + :option:`PrivateMemberHungarianPrefix` + - :option:`PrivateMethodCase`, :option:`PrivateMethodPrefix`, + :option:`PrivateMethodSuffix`, :option:`PrivateMethodIgnoredRegexp` + - :option:`ProtectedMemberCase`, :option:`ProtectedMemberPrefix`, + :option:`ProtectedMemberSuffix`, :option:`ProtectedMemberIgnoredRegexp`, + :option:`ProtectedMemberHungarianPrefix` + - :option:`ProtectedMethodCase`, :option:`ProtectedMethodPrefix`, + :option:`ProtectedMethodSuffix`, :option:`ProtectedMethodIgnoredRegexp` + - :option:`PublicMemberCase`, :option:`PublicMemberPrefix`, + :option:`PublicMemberSuffix`, :option:`PublicMemberIgnoredRegexp`, + :option:`PublicMemberHungarianPrefix` + - :option:`PublicMethodCase`, :option:`PublicMethodPrefix`, + :option:`PublicMethodSuffix`, :option:`PublicMethodIgnoredRegexp` + - :option:`ScopedEnumConstantCase`, :option:`ScopedEnumConstantPrefix`, + :option:`ScopedEnumConstantSuffix`, + :option:`ScopedEnumConstantIgnoredRegexp` + - :option:`StaticConstexprVariableCase`, + :option:`StaticConstexprVariablePrefix`, + :option:`StaticConstexprVariableSuffix`, + :option:`StaticConstexprVariableIgnoredRegexp`, + :option:`StaticConstexprVariableHungarianPrefix` + - :option:`StaticConstantCase`, :option:`StaticConstantPrefix`, + :option:`StaticConstantSuffix`, :option:`StaticConstantIgnoredRegexp`, + :option:`StaticConstantHungarianPrefix` + - :option:`StaticVariableCase`, :option:`StaticVariablePrefix`, + :option:`StaticVariableSuffix`, :option:`StaticVariableIgnoredRegexp`, + :option:`StaticVariableHungarianPrefix` + - :option:`StructCase`, :option:`StructPrefix`, :option:`StructSuffix`, + :option:`StructIgnoredRegexp` + - :option:`TemplateParameterCase`, :option:`TemplateParameterPrefix`, + :option:`TemplateParameterSuffix`, :option:`TemplateParameterIgnoredRegexp` + - :option:`TemplateTemplateParameterCase`, + :option:`TemplateTemplateParameterPrefix`, + :option:`TemplateTemplateParameterSuffix`, + :option:`TemplateTemplateParameterIgnoredRegexp` + - :option:`TypeAliasCase`, :option:`TypeAliasPrefix`, + :option:`TypeAliasSuffix`, :option:`TypeAliasIgnoredRegexp` + - :option:`TypedefCase`, :option:`TypedefPrefix`, :option:`TypedefSuffix`, + :option:`TypedefIgnoredRegexp` + - :option:`TypeTemplateParameterCase`, + :option:`TypeTemplateParameterPrefix`, + :option:`TypeTemplateParameterSuffix`, + :option:`TypeTemplateParameterIgnoredRegexp` + - :option:`UnionCase`, :option:`UnionPrefix`, :option:`UnionSuffix`, + :option:`UnionIgnoredRegexp` + - :option:`ValueTemplateParameterCase`, + :option:`ValueTemplateParameterPrefix`, + :option:`ValueTemplateParameterSuffix`, + :option:`ValueTemplateParameterIgnoredRegexp` + - :option:`VariableCase`, :option:`VariablePrefix`, :option:`VariableSuffix`, + :option:`VariableIgnoredRegexp`, :option:`VariableHungarianPrefix` + - :option:`VirtualMethodCase`, :option:`VirtualMethodPrefix`, + :option:`VirtualMethodSuffix`, :option:`VirtualMethodIgnoredRegexp` Options description @@ -1608,8 +1711,8 @@ After: #define pre_my_macro_definition_post -Note: This will not warn on builtin macros or macros defined on the command line -using the ``-D`` flag. +Note: This will not warn on builtin macros or macros defined on the +command line using the ``-D`` flag. .. option:: MemberCase @@ -2804,44 +2907,45 @@ distinguished as the given name. The first character of the given name can be capitalized to separate it from the type indicators (see also CamelCase). Otherwise the case of this character denotes scope. -The following table is the default mapping table of Hungarian Notation which -maps Decl to its prefix string. You can also have your own style in config file. - -================= ============== ====================== ============== ============== ============== -Primitive Type Microsoft Type ------------------ -------------- ---------------------- -------------- -------------- -------------- - Type Prefix Type Prefix Type Prefix -================= ============== ====================== ============== ============== ============== -int8_t i8 signed int si BOOL b -int16_t i16 signed short ss BOOLEAN b -int32_t i32 signed short int ssi BYTE by -int64_t i64 signed long long int slli CHAR c -uint8_t u8 signed long long sll UCHAR uc -uint16_t u16 signed long int sli SHORT s -uint32_t u32 signed long sl USHORT us -uint64_t u64 signed s WORD w -char8_t c8 unsigned long long int ulli DWORD dw -char16_t c16 unsigned long long ull DWORD32 dw32 -char32_t c32 unsigned long int uli DWORD64 dw64 -float f unsigned long ul LONG l -double d unsigned short int usi ULONG ul -char c unsigned short us ULONG32 ul32 -bool b unsigned int ui ULONG64 ul64 -_Bool b unsigned char uc ULONGLONG ull -int i unsigned u HANDLE h -size_t n long long int lli INT i -short s long double ld INT8 i8 -signed i long long ll INT16 i16 -unsigned u long int li INT32 i32 -long l long l INT64 i64 -long long ll ptrdiff_t p UINT ui -unsigned long ul void *none* UINT8 u8 -long double ld UINT16 u16 -ptrdiff_t p UINT32 u32 -wchar_t wc UINT64 u64 -short int si PVOID p -short s -================= ============== ====================== ============== ============== ============== +The following table is the default mapping table of Hungarian Notation +which maps Decl to its prefix string. You can also have your own style +in config file. + +============== ======== ====================== ======== ============== ======== +Primitive Type Microsoft Type +-------------- -------- ---------------------- -------- -------------- -------- + Type Prefix Type Prefix Type Prefix +============== ======== ====================== ======== ============== ======== +int8_t i8 signed int si BOOL b +int16_t i16 signed short ss BOOLEAN b +int32_t i32 signed short int ssi BYTE by +int64_t i64 signed long long int slli CHAR c +uint8_t u8 signed long long sll UCHAR uc +uint16_t u16 signed long int sli SHORT s +uint32_t u32 signed long sl USHORT us +uint64_t u64 signed s WORD w +char8_t c8 unsigned long long int ulli DWORD dw +char16_t c16 unsigned long long ull DWORD32 dw32 +char32_t c32 unsigned long int uli DWORD64 dw64 +float f unsigned long ul LONG l +double d unsigned short int usi ULONG ul +char c unsigned short us ULONG32 ul32 +bool b unsigned int ui ULONG64 ul64 +_Bool b unsigned char uc ULONGLONG ull +int i unsigned u HANDLE h +size_t n long long int lli INT i +short s long double ld INT8 i8 +signed i long long ll INT16 i16 +unsigned u long int li INT32 i32 +long l long l INT64 i64 +long long ll ptrdiff_t p UINT ui +unsigned long ul void *none* UINT8 u8 +long double ld UINT16 u16 +ptrdiff_t p UINT32 u32 +wchar_t wc UINT64 u64 +short int si PVOID p +short s +============== ======== ====================== ======== ============== ======== **There are more trivial options for Hungarian Notation:** diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/implicit-bool-conversion.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/implicit-bool-conversion.rst index 88cff38..3a37b25 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/implicit-bool-conversion.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/implicit-bool-conversion.rst @@ -4,9 +4,9 @@ readability-implicit-bool-conversion ==================================== This check can be used to find implicit conversions between built-in types and -booleans. Depending on use case, it may simply help with readability of the code, -or in some cases, point to potential bugs which remain unnoticed due to implicit -conversions. +booleans. Depending on use case, it may simply help with readability of the +code, or in some cases, point to potential bugs which remain unnoticed due to +implicit conversions. The following is a real-world example of bug which was hiding behind implicit ``bool`` conversion: diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst index 0b2d819..55d47d5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/magic-numbers.rst @@ -9,7 +9,7 @@ code and not introduced via constants or symbols. Many coding guidelines advise replacing the magic values with symbolic constants to improve readability. Here are a few references: - * `Rule ES.45: Avoid "magic constants"; use symbolic constants in C++ Core Guidelines <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-magic>`_ + * `Rule ES.45: Avoid "magic constants"; use symbolic constants in C++ Core Guidelines <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#res-magic>`_ * `Rule 5.1.1 Use symbolic names instead of literal values in code in High Integrity C++ <https://www.perforce.com/resources/qac/high-integrity-cpp-coding-standard-expressions>`_ * Item 17 in "C++ Coding Standards: 101 Rules, Guidelines and Best Practices" by Herb Sutter and Andrei Alexandrescu diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/make-member-function-const.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/make-member-function-const.rst index 5d1f8d1..73059e2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/make-member-function-const.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/make-member-function-const.rst @@ -37,7 +37,8 @@ In addition, this check ignores functions that * are templated or part of a class template * have an empty body * do not (implicitly) use ``this`` at all - (see :doc:`readability-convert-member-functions-to-static <../readability/convert-member-functions-to-static>`). + (see :doc:`readability-convert-member-functions-to-static + <../readability/convert-member-functions-to-static>`). The following real-world examples will be preserved by the check: diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst index 59f17eb..9bc98d5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst @@ -3,15 +3,16 @@ readability-math-missing-parentheses ==================================== -Check for missing parentheses in mathematical expressions that involve operators -of different priorities. +Check for missing parentheses in mathematical expressions that involve +operators of different priorities. Parentheses in mathematical expressions clarify the order -of operations, especially with different-priority operators. Lengthy or multiline -expressions can obscure this order, leading to coding errors. IDEs can aid clarity -by highlighting parentheses. Explicitly using parentheses also clarifies what the -developer had in mind when writing the expression. Ensuring their presence reduces -ambiguity and errors, promoting clearer and more maintainable code. +of operations, especially with different-priority operators. Lengthy or +multiline expressions can obscure this order, leading to coding errors. +IDEs can aid clarity by highlighting parentheses. Explicitly using parentheses +also clarifies what the developer had in mind when writing the expression. +Ensuring their presence reduces ambiguity and errors, promoting clearer and +more maintainable code. Before: diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/named-parameter.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/named-parameter.rst index 48b7e84..0dd25e2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/named-parameter.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/named-parameter.rst @@ -10,8 +10,9 @@ Guide: https://google.github.io/styleguide/cppguide.html#Function_Declarations_and_Definitions -All parameters should have the same name in both the function declaration and definition. -If a parameter is not utilized, its name can be commented out in a function definition. +All parameters should have the same name in both the function declaration and +definition. If a parameter is not utilized, its name can be commented out in a +function definition. .. code-block:: c++ diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/operators-representation.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/operators-representation.rst index b84f7a1..70cf75b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/operators-representation.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/operators-representation.rst @@ -69,9 +69,10 @@ To configure check to enforce Alternative Token Representation for all operators set options to `and;and_eq;bitand;bitor;compl;not;not_eq;or;or_eq;xor;xor_eq`. -Developers do not need to enforce all operators, and can mix the representations -as desired by specifying a semicolon-separated list of both traditional and -alternative tokens in the configuration, such as `and;||;not`. +Developers do not need to enforce all operators, and can mix the +representations as desired by specifying a semicolon-separated list of +both traditional and alternative tokens in the configuration, +such as `and;||;not`. .. option:: BinaryOperators diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-casting.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-casting.rst index 23eaa22..4b6c14b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-casting.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-casting.rst @@ -18,9 +18,9 @@ In this example, the ``static_cast<int>(value)`` is redundant, as it performs a cast from an ``int`` to another ``int``. Casting operations involving constructor conversions, user-defined conversions, -functional casts, type-dependent casts, casts between distinct type aliases that -refer to the same underlying type, as well as bitfield-related casts and casts -directly from lvalue to rvalue, are all disregarded by the check. +functional casts, type-dependent casts, casts between distinct type aliases +that refer to the same underlying type, as well as bitfield-related casts and +casts directly from lvalue to rvalue, are all disregarded by the check. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-control-flow.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-control-flow.rst index aeaf345..ac435af 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-control-flow.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-control-flow.rst @@ -4,7 +4,8 @@ readability-redundant-control-flow ================================== This check looks for procedures (functions returning no value) with ``return`` -statements at the end of the function. Such ``return`` statements are redundant. +statements at the end of the function. Such ``return`` statements are +redundant. Loop statements (``for``, ``while``, ``do while``) are checked for redundant ``continue`` statements at the end of the loop body. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-string-cstr.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-string-cstr.rst index 7b50777..84495a5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-string-cstr.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/redundant-string-cstr.rst @@ -4,7 +4,8 @@ readability-redundant-string-cstr ================================= -Finds unnecessary calls to ``std::string::c_str()`` and ``std::string::data()``. +Finds unnecessary calls to ``std::string::c_str()`` and +``std::string::data()``. Options ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/reference-to-constructed-temporary.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/reference-to-constructed-temporary.rst index 09fd0c7..5f1aea1 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/reference-to-constructed-temporary.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/reference-to-constructed-temporary.rst @@ -23,10 +23,10 @@ Examples of problematic code include: In the first example, a ``const std::string&`` reference variable ``str`` is assigned a temporary object created by the ``std::string("hello")`` constructor. In the second example, a ``const Point&`` reference variable ``p`` -is assigned an object that is constructed from an initializer list ``{ 1, 2 }``. -Both of these examples extend the lifetime of the temporary object to the -lifetime of the reference variable, which can make it difficult to reason about -and may lead to subtle bugs or misunderstanding. +is assigned an object that is constructed from an initializer list +``{ 1, 2 }``. Both of these examples extend the lifetime of the temporary +object to the lifetime of the reference variable, which can make it difficult +to reason about and may lead to subtle bugs or misunderstanding. To avoid these issues, it is recommended to change the reference variable to a (``const``) value variable. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/simplify-boolean-expr.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/simplify-boolean-expr.rst index 3d00d5b..5b733e5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/simplify-boolean-expr.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/simplify-boolean-expr.rst @@ -75,8 +75,9 @@ Examples: an implicit conversion of an integer quantity ``i & 1`` to ``bool`` and becomes ``return (i & 1) != 0;`` - 6. Given ``struct X { explicit operator bool(); };``, and an instance ``x`` of - ``struct X``, the conditional return ``if (x) return true; return false;`` + 6. Given ``struct X { explicit operator bool(); };``, and an instance ``x`` + of ``struct X``, the conditional return + ``if (x) return true; return false;`` becomes ``return static_cast<bool>(x);`` Options diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/string-compare.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/string-compare.rst index 4be2473..db9bec2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/string-compare.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/string-compare.rst @@ -8,11 +8,11 @@ Finds string comparisons using the compare method. A common mistake is to use the string's ``compare`` method instead of using the equality or inequality operators. The compare method is intended for sorting functions and thus returns a negative number, a positive number or -zero depending on the lexicographical relationship between the strings compared. -If an equality or inequality check can suffice, that is recommended. This is -recommended to avoid the risk of incorrect interpretation of the return value -and to simplify the code. The string equality and inequality operators can -also be faster than the ``compare`` method due to early termination. +zero depending on the lexicographical relationship between the strings +compared. If an equality or inequality check can suffice, that is recommended. +This is recommended to avoid the risk of incorrect interpretation of the return +value and to simplify the code. The string equality and inequality operators +can also be faster than the ``compare`` method due to early termination. Example ------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/suspicious-call-argument.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/suspicious-call-argument.rst index 03d9bba..2b3a265 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/suspicious-call-argument.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/suspicious-call-argument.rst @@ -235,8 +235,8 @@ Parameter names are the identifiers as written in the source code. Argument names are: * If a variable is passed, the variable's name. - * If a subsequent function call's return value is used as argument, the called - function's name. + * If a subsequent function call's return value is used as argument, the + called function's name. * Otherwise, empty string. Empty argument or parameter names are ignored by the heuristics. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/uppercase-literal-suffix.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/uppercase-literal-suffix.rst index f2809db..dcedfb1 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/uppercase-literal-suffix.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/uppercase-literal-suffix.rst @@ -10,8 +10,8 @@ By default, only the suffixes that begin with ``l`` (``l``, ``ll``, ``lu``, `hicpp-uppercase-literal-suffix` redirects here as an alias for this check. Detects when the integral literal or floating point (decimal or hexadecimal) -literal has a non-uppercase suffix and provides a fix-it hint with the uppercase -suffix. +literal has a non-uppercase suffix and provides a fix-it hint with the +uppercase suffix. All valid combinations of suffixes are supported. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst index 6e58766..cfbc551 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-anyofallof.rst @@ -3,9 +3,9 @@ readability-use-anyofallof ========================== -Finds range-based for loops that can be replaced by a call to ``std::any_of`` or -``std::all_of``. In C++20 mode, suggests ``std::ranges::any_of`` or -``std::ranges::all_of``. +Finds range-based for loops that can be replaced by a call to +``std::any_of`` or ``std::all_of``. In C++20 mode, suggests +``std::ranges::any_of`` or ``std::ranges::all_of``. Example: diff --git a/clang-tools-extra/include-cleaner/test/lit.cfg.py b/clang-tools-extra/include-cleaner/test/lit.cfg.py index fc67250..52f81bf 100644 --- a/clang-tools-extra/include-cleaner/test/lit.cfg.py +++ b/clang-tools-extra/include-cleaner/test/lit.cfg.py @@ -1,12 +1,25 @@ +import os + import lit.llvm lit.llvm.initialize(lit_config, config) lit.llvm.llvm_config.use_default_substitutions() +# TODO: Consolidate the logic for turning on the internal shell by default for all LLVM test suites. +# See https://github.com/llvm/llvm-project/issues/106636 for more details. +# +# We prefer the lit internal shell which provides a better user experience on failures +# and is faster unless the user explicitly disables it with LIT_USE_INTERNAL_SHELL=0 +# env var. +use_lit_shell = True +lit_shell_env = os.environ.get("LIT_USE_INTERNAL_SHELL") +if lit_shell_env: + use_lit_shell = lit.util.pythonize_bool(lit_shell_env) + config.name = "ClangIncludeCleaner" config.suffixes = [".test", ".c", ".cpp"] config.excludes = ["Inputs"] -config.test_format = lit.formats.ShTest(not lit.llvm.llvm_config.use_lit_shell) +config.test_format = lit.formats.ShTest(not use_lit_shell) config.test_source_root = config.clang_include_cleaner_source_dir + "/test" config.test_exec_root = config.clang_include_cleaner_binary_dir + "/test" diff --git a/clang-tools-extra/modularize/CMakeLists.txt b/clang-tools-extra/modularize/CMakeLists.txt index eb5383c..a775b79 100644 --- a/clang-tools-extra/modularize/CMakeLists.txt +++ b/clang-tools-extra/modularize/CMakeLists.txt @@ -20,6 +20,7 @@ clang_target_link_libraries(modularize clangAST clangBasic clangDriver + clangOptions clangFrontend clangLex clangSerialization diff --git a/clang-tools-extra/modularize/CoverageChecker.cpp b/clang-tools-extra/modularize/CoverageChecker.cpp index 1345a6e..d80d78c 100644 --- a/clang-tools-extra/modularize/CoverageChecker.cpp +++ b/clang-tools-extra/modularize/CoverageChecker.cpp @@ -50,18 +50,18 @@ // //===----------------------------------------------------------------------===// +#include "CoverageChecker.h" #include "ModularizeUtilities.h" #include "clang/AST/ASTConsumer.h" -#include "CoverageChecker.h" #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceManager.h" -#include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Options/Options.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Tooling/Tooling.h" #include "llvm/Option/Option.h" @@ -73,7 +73,7 @@ using namespace Modularize; using namespace clang; using namespace clang::driver; -using namespace clang::driver::options; +using namespace clang::options; using namespace clang::tooling; namespace cl = llvm::cl; namespace sys = llvm::sys; diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp index 376ad0c..33966b4 100644 --- a/clang-tools-extra/modularize/Modularize.cpp +++ b/clang-tools-extra/modularize/Modularize.cpp @@ -231,11 +231,11 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceManager.h" -#include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Options/Options.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Tooling/Tooling.h" #include "llvm/Option/Arg.h" @@ -254,7 +254,7 @@ using namespace clang; using namespace clang::driver; -using namespace clang::driver::options; +using namespace clang::options; using namespace clang::tooling; using namespace llvm; using namespace llvm::opt; diff --git a/clang-tools-extra/modularize/ModularizeUtilities.cpp b/clang-tools-extra/modularize/ModularizeUtilities.cpp index 4dd84fe..6978a6b 100644 --- a/clang-tools-extra/modularize/ModularizeUtilities.cpp +++ b/clang-tools-extra/modularize/ModularizeUtilities.cpp @@ -12,17 +12,17 @@ // //===----------------------------------------------------------------------===// +#include "ModularizeUtilities.h" +#include "CoverageChecker.h" #include "clang/Basic/SourceManager.h" -#include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" -#include "CoverageChecker.h" +#include "clang/Options/Options.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" -#include "ModularizeUtilities.h" using namespace clang; using namespace llvm; diff --git a/clang-tools-extra/pp-trace/CMakeLists.txt b/clang-tools-extra/pp-trace/CMakeLists.txt index 1323adb..da36582 100644 --- a/clang-tools-extra/pp-trace/CMakeLists.txt +++ b/clang-tools-extra/pp-trace/CMakeLists.txt @@ -14,6 +14,7 @@ clang_target_link_libraries(pp-trace PRIVATE clangAST clangBasic + clangOptions clangFrontend clangLex clangSerialization diff --git a/clang-tools-extra/pp-trace/PPTrace.cpp b/clang-tools-extra/pp-trace/PPTrace.cpp index 0b078c4..ba5a06a 100644 --- a/clang-tools-extra/pp-trace/PPTrace.cpp +++ b/clang-tools-extra/pp-trace/PPTrace.cpp @@ -28,11 +28,11 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/SourceManager.h" -#include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Options/Options.h" #include "clang/Tooling/Execution.h" #include "clang/Tooling/Tooling.h" #include "llvm/Option/Arg.h" diff --git a/clang-tools-extra/test/clang-doc/assets.cpp b/clang-tools-extra/test/clang-doc/assets.cpp index c5933e5..853dfe5 100644 --- a/clang-tools-extra/test/clang-doc/assets.cpp +++ b/clang-tools-extra/test/clang-doc/assets.cpp @@ -1,19 +1,7 @@ // RUN: rm -rf %t && mkdir %t // RUN: clang-doc --format=html --output=%t --asset=%S/Inputs/test-assets --executor=standalone %s --base base_dir -// RUN: FileCheck %s -input-file=%t/index.html -check-prefix=INDEX -// RUN: FileCheck %s -input-file=%t/test.css -check-prefix=CSS -// RUN: FileCheck %s -input-file=%t/test.js -check-prefix=JS - -// INDEX: <!DOCTYPE html> -// INDEX-NEXT: <meta charset="utf-8"/> -// INDEX-NEXT: <title>Index</title> -// INDEX-NEXT: <link rel="stylesheet" href="test.css"/> -// INDEX-NEXT: <script src="index_json.js"></script> -// INDEX-NEXT: <script src="test.js"></script> -// INDEX-NEXT: <header id="project-title"></header> -// INDEX-NEXT: <main> -// INDEX-NEXT: <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left" style="flex: 0 100%;"></div> -// INDEX-NEXT: </main> +// RUN: FileCheck %s -input-file=%t/html/test.css -check-prefix=CSS +// RUN: FileCheck %s -input-file=%t/html/test.js -check-prefix=JS // CSS: body { // CSS-NEXT: padding: 0; diff --git a/clang-tools-extra/test/clang-doc/basic-project.mustache.test b/clang-tools-extra/test/clang-doc/basic-project.mustache.test index 5a40a6b..b985a392 100644 --- a/clang-tools-extra/test/clang-doc/basic-project.mustache.test +++ b/clang-tools-extra/test/clang-doc/basic-project.mustache.test @@ -1,7 +1,7 @@ // RUN: rm -rf %t && mkdir -p %t/docs %t/build // RUN: sed 's|$test_dir|%/S|g' %S/Inputs/basic-project/database_template.json > %t/build/compile_commands.json -// RUN: clang-doc --format=mustache --output=%t/docs --executor=all-TUs %t/build/compile_commands.json +// RUN: clang-doc --format=html --output=%t/docs --executor=all-TUs %t/build/compile_commands.json // RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV5Shape.html -check-prefix=HTML-SHAPE // RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV10Calculator.html -check-prefix=HTML-CALC // RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV9Rectangle.html -check-prefix=HTML-RECTANGLE @@ -60,84 +60,54 @@ HTML-SHAPE: <div class="content"> HTML-SHAPE: <section class="hero section-container"> HTML-SHAPE: <div class="hero__title"> HTML-SHAPE: <h1 class="hero__title-large">class Shape</h1> -HTML-SHAPE: <div class="hero__subtitle"> -HTML-SHAPE: <div> -HTML-SHAPE: <p> Abstract base class for shapes.</p> -HTML-SHAPE: </div> -HTML-SHAPE: <div> -HTML-SHAPE: <p></p> -HTML-SHAPE: </div> -HTML-SHAPE: <div> -HTML-SHAPE: <p> Provides a common interface for different types of shapes.</p> -HTML-SHAPE: </div> -HTML-SHAPE: </div> +HTML-SHAPE: <div class="hero__subtitle"> +HTML-SHAPE: <div> +HTML-SHAPE: <p> Abstract base class for shapes.</p> +HTML-SHAPE: </div> +HTML-SHAPE: <div> +HTML-SHAPE: <p> Provides a common interface for different types of shapes.</p> +HTML-SHAPE: </div> +HTML-SHAPE: </div> HTML-SHAPE: </div> HTML-SHAPE: </section> HTML-SHAPE: <section id="PublicMethods" class="section-container"> HTML-SHAPE: <h2>Public Methods</h2> HTML-SHAPE: <div> -HTML-SHAPE: <div class="delimiter-container"> -HTML-SHAPE: <div id="{{([0-9A-F]{40})}}"> -HTML-SHAPE: <pre> -HTML-SHAPE: <code class="language-cpp code-clang-doc"> -HTML-SHAPE: double area () -HTML-SHAPE: </code> -HTML-SHAPE: </pre> -HTML-SHAPE: <div> -HTML-SHAPE: <div> -HTML-SHAPE: <p> Calculates the area of the shape.</p> -HTML-SHAPE: </div> -HTML-SHAPE: <div> -HTML-SHAPE: <p></p> -HTML-SHAPE: </div> -HTML-SHAPE: <div> -HTML-SHAPE: <p></p> -HTML-SHAPE: </div> -HTML-SHAPE: <h3>Returns</h3> -HTML-SHAPE: <p> double The area of the shape.</p> -HTML-SHAPE: </div> -HTML-SHAPE: </div> -HTML-SHAPE: </div> -HTML-SHAPE: <div class="delimiter-container"> -HTML-SHAPE: <div id="{{([0-9A-F]{40})}}"> -HTML-SHAPE: <pre> -HTML-SHAPE: <code class="language-cpp code-clang-doc"> -HTML-SHAPE: double perimeter () -HTML-SHAPE: </code> -HTML-SHAPE: </pre> -HTML-SHAPE: <div> -HTML-SHAPE: <div> -HTML-SHAPE: <p> Calculates the perimeter of the shape.</p> -HTML-SHAPE: </div> -HTML-SHAPE: <div> -HTML-SHAPE: <p></p> -HTML-SHAPE: </div> -HTML-SHAPE: <div> -HTML-SHAPE: <p></p> -HTML-SHAPE: </div> -HTML-SHAPE: <h3>Returns</h3> -HTML-SHAPE: <p> double The perimeter of the shape.</p> -HTML-SHAPE: </div> -HTML-SHAPE: </div> -HTML-SHAPE: </div> -HTML-SHAPE: <div class="delimiter-container"> -HTML-SHAPE: <div id="{{([0-9A-F]{40})}}"> -HTML-SHAPE: <pre> -HTML-SHAPE: <code class="language-cpp code-clang-doc"> -HTML-SHAPE: void ~Shape () -HTML-SHAPE: </code> -HTML-SHAPE: </pre> -HTML-SHAPE: <div> -HTML-SHAPE: <div> -HTML-SHAPE: <p> Virtual destructor.</p> -HTML-SHAPE: </div> -HTML-SHAPE: <div> -HTML-SHAPE: <p></p> -HTML-SHAPE: </div> -HTML-SHAPE: </div> -HTML-SHAPE: </div> -HTML-SHAPE: </div> -HTML-SHAPE: </div> +HTML-SHAPE: <div class="delimiter-container"> +HTML-SHAPE: <div id="{{([0-9A-F]{40})}}"> +HTML-SHAPE: <pre><code class="language-cpp code-clang-doc">double area ()</code></pre> +HTML-SHAPE: <div> +HTML-SHAPE: <div> +HTML-SHAPE: <p> Calculates the area of the shape.</p> +HTML-SHAPE: </div> +HTML-SHAPE: <h3>Returns</h3> +HTML-SHAPE: <p> double The area of the shape.</p> +HTML-SHAPE: </div> +HTML-SHAPE: </div> +HTML-SHAPE: </div> +HTML-SHAPE: <div class="delimiter-container"> +HTML-SHAPE: <div id="{{([0-9A-F]{40})}}"> +HTML-SHAPE: <pre><code class="language-cpp code-clang-doc">double perimeter ()</code></pre> +HTML-SHAPE: <div> +HTML-SHAPE: <div> +HTML-SHAPE: <p> Calculates the perimeter of the shape.</p> +HTML-SHAPE: </div> +HTML-SHAPE: <h3>Returns</h3> +HTML-SHAPE: <p> double The perimeter of the shape.</p> +HTML-SHAPE: </div> +HTML-SHAPE: </div> +HTML-SHAPE: </div> +HTML-SHAPE: <div class="delimiter-container"> +HTML-SHAPE: <div id="{{([0-9A-F]{40})}}"> +HTML-SHAPE: <pre><code class="language-cpp code-clang-doc">void ~Shape ()</code></pre> +HTML-SHAPE: <div> +HTML-SHAPE: <div> +HTML-SHAPE: <p> Virtual destructor.</p> +HTML-SHAPE: </div> +HTML-SHAPE: </div> +HTML-SHAPE: </div> +HTML-SHAPE: </div> +HTML-SHAPE: </div> HTML-SHAPE: </section> HTML-SHAPE: </div> HTML-SHAPE: </div> @@ -217,216 +187,130 @@ HTML-CALC: <div class="content"> HTML-CALC: <section class="hero section-container"> HTML-CALC: <div class="hero__title"> HTML-CALC: <h1 class="hero__title-large">class Calculator</h1> -HTML-CALC: <div> -HTML-CALC: <p> A simple calculator class.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p> Provides basic arithmetic operations.</p> -HTML-CALC: </div> -HTML-CALC: </div> +HTML-CALC: <div class="hero__subtitle"> +HTML-CALC: <div> +HTML-CALC: <p> A simple calculator class.</p> +HTML-CALC: </div> +HTML-CALC: <div> +HTML-CALC: <p> Provides basic arithmetic operations.</p> +HTML-CALC: </div> +HTML-CALC: </div> HTML-CALC: </div> HTML-CALC: </section> HTML-CALC: <section id="PublicMembers" class="section-container"> HTML-CALC: <h2>Public Members</h2> HTML-CALC: <div> HTML-CALC: <div id="public_val" class="delimiter-container"> -HTML-CALC: <pre> -HTML-CALC: <code class="language-cpp code-clang-doc" >int public_val</code> -HTML-CALC: </pre> +HTML-CALC: <pre><code class="language-cpp code-clang-doc" >int public_val</code></pre> HTML-CALC: </div> HTML-CALC: <div id="static_val" class="delimiter-container"> -HTML-CALC: <pre> -HTML-CALC: <code class="language-cpp code-clang-doc" >const int static_val</code> -HTML-CALC: </pre> +HTML-CALC: <pre><code class="language-cpp code-clang-doc" >const int static_val</code></pre> HTML-CALC: </div> HTML-CALC: </div> HTML-CALC: </section> HTML-CALC: <section id="PublicMethods" class="section-container"> HTML-CALC: <h2>Public Methods</h2> HTML-CALC: <div> -HTML-CALC: <div class="delimiter-container"> -HTML-CALC: <div id="{{([0-9A-F]{40})}}"> -HTML-CALC: <pre> -HTML-CALC: <code class="language-cpp code-clang-doc"> -HTML-CALC: int add (int a, int b) -HTML-CALC: </code> -HTML-CALC: </pre> -HTML-CALC: <div> -HTML-CALC: <div> -HTML-CALC: <p> Adds two integers.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <h3>Parameters</h3> -HTML-CALC: <div> -HTML-CALC: <b>a</b> <div> -HTML-CALC: <p> First integer.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <b>b</b> <div> -HTML-CALC: <p> Second integer.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <h3>Returns</h3> -HTML-CALC: <p> int The sum of a and b.</p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <div class="delimiter-container"> -HTML-CALC: <div id="{{([0-9A-F]{40})}}"> -HTML-CALC: <pre> -HTML-CALC: <code class="language-cpp code-clang-doc"> -HTML-CALC: int subtract (int a, int b) -HTML-CALC: </code> -HTML-CALC: </pre> -HTML-CALC: <div> -HTML-CALC: <div> -HTML-CALC: <p> Subtracts the second integer from the first.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <h3>Returns</h3> -HTML-CALC: <p> int The result of a - b.</p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <div class="delimiter-container"> -HTML-CALC: <div id="{{([0-9A-F]{40})}}"> -HTML-CALC: <pre> -HTML-CALC: <code class="language-cpp code-clang-doc"> -HTML-CALC: int multiply (int a, int b) -HTML-CALC: </code> -HTML-CALC: </pre> -HTML-CALC: <div> -HTML-CALC: <div> -HTML-CALC: <p> Multiplies two integers.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <h3>Parameters</h3> -HTML-CALC: <div> -HTML-CALC: <b>a</b> <div> -HTML-CALC: <p> First integer.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <b>b</b> <div> -HTML-CALC: <p> Second integer.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <h3>Returns</h3> -HTML-CALC: <p> int The product of a and b.</p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <div class="delimiter-container"> -HTML-CALC: <div id="{{([0-9A-F]{40})}}"> -HTML-CALC: <pre> -HTML-CALC: <code class="language-cpp code-clang-doc"> -HTML-CALC: double divide (int a, int b) -HTML-CALC: </code> -HTML-CALC: </pre> -HTML-CALC: <div> -HTML-CALC: <div> -HTML-CALC: <p> Divides the first integer by the second.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <h3>Parameters</h3> -HTML-CALC: <div> -HTML-CALC: <b>a</b> <div> -HTML-CALC: <p> First integer.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <b>b</b> <div> -HTML-CALC: <p> Second integer.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <h3>Returns</h3> -HTML-CALC: <p> double The result of a / b.</p> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <div class="delimiter-container"> -HTML-CALC: <div id="{{([0-9A-F]{40})}}"> -HTML-CALC: <pre> -HTML-CALC: <code class="language-cpp code-clang-doc"> -HTML-CALC: int mod (int a, int b) -HTML-CALC: </code> -HTML-CALC: </pre> -HTML-CALC: <div> -HTML-CALC: <div> -HTML-CALC: <p> Performs the mod operation on integers.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: <h3>Parameters</h3> -HTML-CALC: <div> -HTML-CALC: <b>a</b> <div> -HTML-CALC: <p> First integer.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <b>b</b> <div> -HTML-CALC: <p> Second integer.</p> -HTML-CALC: </div> -HTML-CALC: <div> -HTML-CALC: <p></p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: <h3>Returns</h3> -HTML-CALC: <p> The result of a % b.</p> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: </div> -HTML-CALC: </div> +HTML-CALC: <div class="delimiter-container"> +HTML-CALC: <div id="{{([0-9A-F]{40})}}"> +HTML-CALC: <pre><code class="language-cpp code-clang-doc">int add (int a, int b)</code></pre> +HTML-CALC: <div> +HTML-CALC: <div> +HTML-CALC: <p> Adds two integers.</p> +HTML-CALC: </div> +HTML-CALC: <h3>Parameters</h3> +HTML-CALC: <div> +HTML-CALC: <b>a</b> First integer. +HTML-CALC: </div> +HTML-CALC: <div> +HTML-CALC: <b>b</b> Second integer. +HTML-CALC: </div> +HTML-CALC: <h3>Returns</h3> +HTML-CALC: <p> int The sum of a and b.</p> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: <div class="delimiter-container"> +HTML-CALC: <div id="{{([0-9A-F]{40})}}"> +HTML-CALC: <pre><code class="language-cpp code-clang-doc">int subtract (int a, int b)</code></pre> +HTML-CALC: <div> +HTML-CALC: <div> +HTML-CALC: <p> Subtracts the second integer from the first.</p> +HTML-CALC: </div> +HTML-CALC: <h3>Parameters</h3> +HTML-CALC: <div> +HTML-CALC: <b>a</b> First integer. +HTML-CALC: </div> +HTML-CALC: <div> +HTML-CALC: <b>b</b> Second integer. +HTML-CALC: </div> +HTML-CALC: <h3>Returns</h3> +HTML-CALC: <p> int The result of a - b.</p> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: <div class="delimiter-container"> +HTML-CALC: <div id="{{([0-9A-F]{40})}}"> +HTML-CALC: <pre><code class="language-cpp code-clang-doc">int multiply (int a, int b)</code></pre> +HTML-CALC: <div> +HTML-CALC: <div> +HTML-CALC: <p> Multiplies two integers.</p> +HTML-CALC: </div> +HTML-CALC: <h3>Parameters</h3> +HTML-CALC: <div> +HTML-CALC: <b>a</b> First integer. +HTML-CALC: </div> +HTML-CALC: <div> +HTML-CALC: <b>b</b> Second integer. +HTML-CALC: </div> +HTML-CALC: <h3>Returns</h3> +HTML-CALC: <p> int The product of a and b.</p> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: <div class="delimiter-container"> +HTML-CALC: <div id="{{([0-9A-F]{40})}}"> +HTML-CALC: <pre><code class="language-cpp code-clang-doc">double divide (int a, int b)</code></pre> +HTML-CALC: <div> +HTML-CALC: <div> +HTML-CALC: <p> Divides the first integer by the second.</p> +HTML-CALC: </div> +HTML-CALC: <h3>Parameters</h3> +HTML-CALC: <div> +HTML-CALC: <b>a</b> First integer. +HTML-CALC: </div> +HTML-CALC: <div> +HTML-CALC: <b>b</b> Second integer. +HTML-CALC: </div> +HTML-CALC: <h3>Returns</h3> +HTML-CALC: <p> double The result of a / b.</p> +HTML-CALC: <h3>Throws</h3> +HTML-CALC: <div> +HTML-CALC: <b>std::invalid_argument</b> if b is zero. +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: <div class="delimiter-container"> +HTML-CALC: <div id="{{([0-9A-F]{40})}}"> +HTML-CALC: <pre><code class="language-cpp code-clang-doc">int mod (int a, int b)</code></pre> +HTML-CALC: <div> +HTML-CALC: <div> +HTML-CALC: <p> Performs the mod operation on integers.</p> +HTML-CALC: </div> +HTML-CALC: <h3>Parameters</h3> +HTML-CALC: <div> +HTML-CALC: <b>a</b> First integer. +HTML-CALC: </div> +HTML-CALC: <div> +HTML-CALC: <b>b</b> Second integer. +HTML-CALC: </div> +HTML-CALC: <h3>Returns</h3> +HTML-CALC: <p> The result of a % b.</p> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: </div> +HTML-CALC: </div> HTML-CALC: </section> HTML-CALC: </div> HTML-CALC: </div> @@ -435,6 +319,7 @@ HTML-CALC: </body> HTML-CALC: </html> + HTML-RECTANGLE: <!DOCTYPE html> HTML-RECTANGLE: <html lang="en-US"> HTML-RECTANGLE: <head> @@ -489,101 +374,61 @@ HTML-RECTANGLE: <div class="content"> HTML-RECTANGLE: <section class="hero section-container"> HTML-RECTANGLE: <div class="hero__title"> HTML-RECTANGLE: <h1 class="hero__title-large">class Rectangle</h1> -HTML-RECTANGLE: <div class="hero__subtitle"> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p> Rectangle class derived from Shape.</p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p></p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p> Represents a rectangle with a given width and height.</p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> +HTML-RECTANGLE: <div class="hero__subtitle"> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <p> Rectangle class derived from Shape.</p> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <p> Represents a rectangle with a given width and height.</p> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: </div> HTML-RECTANGLE: </div> HTML-RECTANGLE: </section> HTML-RECTANGLE: <section id="PublicMethods" class="section-container"> HTML-RECTANGLE: <h2>Public Methods</h2> HTML-RECTANGLE: <div> -HTML-RECTANGLE: <div class="delimiter-container"> -HTML-RECTANGLE: <div id="{{([0-9A-F]{40})}}"> -HTML-RECTANGLE: <pre> -HTML-RECTANGLE: <code class="language-cpp code-clang-doc"> -HTML-RECTANGLE: void Rectangle (double width, double height) -HTML-RECTANGLE: </code> -HTML-RECTANGLE: </pre> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p> Constructs a new Rectangle object.</p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p></p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p></p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <h3>Parameters</h3> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <b>width</b> <div> -HTML-RECTANGLE: <p> Width of the rectangle.</p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p></p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <b>height</b> <div> -HTML-RECTANGLE: <p> Height of the rectangle.</p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div class="delimiter-container"> -HTML-RECTANGLE: <div id="{{([0-9A-F]{40})}}"> -HTML-RECTANGLE: <pre> -HTML-RECTANGLE: <code class="language-cpp code-clang-doc"> -HTML-RECTANGLE: double area () -HTML-RECTANGLE: </code> -HTML-RECTANGLE: </pre> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p> Calculates the area of the rectangle.</p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p></p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p></p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <h3>Returns</h3> -HTML-RECTANGLE: <p> double The area of the rectangle.</p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div class="delimiter-container"> -HTML-RECTANGLE: <div id="{{([0-9A-F]{40})}}"> -HTML-RECTANGLE: <pre> -HTML-RECTANGLE: <code class="language-cpp code-clang-doc"> -HTML-RECTANGLE: double perimeter () -HTML-RECTANGLE: </code> -HTML-RECTANGLE: </pre> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p> Calculates the perimeter of the rectangle.</p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p></p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <div> -HTML-RECTANGLE: <p></p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: <h3>Returns</h3> -HTML-RECTANGLE: <p> double The perimeter of the rectangle.</p> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> -HTML-RECTANGLE: </div> +HTML-RECTANGLE: <div class="delimiter-container"> +HTML-RECTANGLE: <div id="{{([0-9A-F]{40})}}"> +HTML-RECTANGLE: <pre><code class="language-cpp code-clang-doc">void Rectangle (double width, double height)</code></pre> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <p> Constructs a new Rectangle object.</p> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: <h3>Parameters</h3> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <b>width</b> Width of the rectangle. +HTML-RECTANGLE: </div> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <b>height</b> Height of the rectangle. +HTML-RECTANGLE: </div> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: <div class="delimiter-container"> +HTML-RECTANGLE: <div id="{{([0-9A-F]{40})}}"> +HTML-RECTANGLE: <pre><code class="language-cpp code-clang-doc">double area ()</code></pre> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <p> Calculates the area of the rectangle.</p> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: <h3>Returns</h3> +HTML-RECTANGLE: <p> double The area of the rectangle.</p> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: <div class="delimiter-container"> +HTML-RECTANGLE: <div id="{{([0-9A-F]{40})}}"> +HTML-RECTANGLE: <pre><code class="language-cpp code-clang-doc">double perimeter ()</code></pre> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <div> +HTML-RECTANGLE: <p> Calculates the perimeter of the rectangle.</p> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: <h3>Returns</h3> +HTML-RECTANGLE: <p> double The perimeter of the rectangle.</p> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: </div> +HTML-RECTANGLE: </div> HTML-RECTANGLE: </section> HTML-RECTANGLE: </div> HTML-RECTANGLE: </div> @@ -592,6 +437,7 @@ HTML-RECTANGLE: </body> HTML-RECTANGLE: </html> + HTML-CIRCLE: <!DOCTYPE html> HTML-CIRCLE: <html lang="en-US"> HTML-CIRCLE: <head> @@ -646,102 +492,67 @@ HTML-CIRCLE: <div class="content"> HTML-CIRCLE: <section class="hero section-container"> HTML-CIRCLE: <div class="hero__title"> HTML-CIRCLE: <h1 class="hero__title-large">class Circle</h1> -HTML-CIRCLE: <div class="hero__subtitle"> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p> Circle class derived from Shape.</p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p></p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p> Represents a circle with a given radius.</p> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> +HTML-CIRCLE: <div class="hero__subtitle"> +HTML-CIRCLE: <div> +HTML-CIRCLE: <p> Circle class derived from Shape.</p> +HTML-CIRCLE: </div> +HTML-CIRCLE: <div> +HTML-CIRCLE: <p> Represents a circle with a given radius.</p> +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> HTML-CIRCLE: </div> HTML-CIRCLE: </section> HTML-CIRCLE: <section id="PublicMethods" class="section-container"> HTML-CIRCLE: <h2>Public Methods</h2> HTML-CIRCLE: <div> -HTML-CIRCLE: <div class="delimiter-container"> -HTML-CIRCLE: <div id="{{([0-9A-F]{40})}}"> -HTML-CIRCLE: <pre> -HTML-CIRCLE: <code class="language-cpp code-clang-doc"> -HTML-CIRCLE: void Circle (double radius) -HTML-CIRCLE: </code> -HTML-CIRCLE: </pre> -HTML-CIRCLE: <div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p> Constructs a new Circle object.</p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p></p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p></p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <h3>Parameters</h3> -HTML-CIRCLE: <div> -HTML-CIRCLE: <b>radius</b> <div> -HTML-CIRCLE: <p> Radius of the circle.</p> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div class="delimiter-container"> -HTML-CIRCLE: <div id="{{([0-9A-F]{40})}}"> -HTML-CIRCLE: <pre> -HTML-CIRCLE: <code class="language-cpp code-clang-doc"> -HTML-CIRCLE: double area () -HTML-CIRCLE: </code> -HTML-CIRCLE: </pre> -HTML-CIRCLE: <div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p> Calculates the area of the circle.</p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p></p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p></p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <h3>Returns</h3> -HTML-CIRCLE: <p> double The area of the circle.</p> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div class="delimiter-container"> -HTML-CIRCLE: <div id="{{([0-9A-F]{40})}}"> -HTML-CIRCLE: <pre> -HTML-CIRCLE: <code class="language-cpp code-clang-doc"> -HTML-CIRCLE: double perimeter () -HTML-CIRCLE: </code> -HTML-CIRCLE: </pre> -HTML-CIRCLE: <div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p> Calculates the perimeter of the circle.</p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p></p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <div> -HTML-CIRCLE: <p></p> -HTML-CIRCLE: </div> -HTML-CIRCLE: <h3>Returns</h3> -HTML-CIRCLE: <p> double The perimeter of the circle.</p> -HTML-CIRCLE: <h3>Code</h3> -HTML-CIRCLE: <div> -HTML-CIRCLE: <pre class="code-block"> -HTML-CIRCLE: <code> -HTML-CIRCLE: Circle circle(5.0); -HTML-CIRCLE: double perimeter = circle.perimeter(); -HTML-CIRCLE: </code> -HTML-CIRCLE: </pre> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> -HTML-CIRCLE: </div> +HTML-CIRCLE: <div class="delimiter-container"> +HTML-CIRCLE: <div id="{{([0-9A-F]{40})}}"> +HTML-CIRCLE: <pre><code class="language-cpp code-clang-doc">void Circle (double radius)</code></pre> +HTML-CIRCLE: <div> +HTML-CIRCLE: <div> +HTML-CIRCLE: <p> Constructs a new Circle object.</p> +HTML-CIRCLE: </div> +HTML-CIRCLE: <h3>Parameters</h3> +HTML-CIRCLE: <div> +HTML-CIRCLE: <b>radius</b> Radius of the circle. +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> +HTML-CIRCLE: <div class="delimiter-container"> +HTML-CIRCLE: <div id="{{([0-9A-F]{40})}}"> +HTML-CIRCLE: <pre><code class="language-cpp code-clang-doc">double area ()</code></pre> +HTML-CIRCLE: <div> +HTML-CIRCLE: <div> +HTML-CIRCLE: <p> Calculates the area of the circle.</p> +HTML-CIRCLE: </div> +HTML-CIRCLE: <h3>Returns</h3> +HTML-CIRCLE: <p> double The area of the circle.</p> +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> +HTML-CIRCLE: <div class="delimiter-container"> +HTML-CIRCLE: <div id="{{([0-9A-F]{40})}}"> +HTML-CIRCLE: <pre><code class="language-cpp code-clang-doc">double perimeter ()</code></pre> +HTML-CIRCLE: <div> +HTML-CIRCLE: <div> +HTML-CIRCLE: <p> Calculates the perimeter of the circle.</p> +HTML-CIRCLE: </div> +HTML-CIRCLE: <h3>Returns</h3> +HTML-CIRCLE: <p> double The perimeter of the circle.</p> +HTML-CIRCLE: <h3>Code</h3> +HTML-CIRCLE: <div> +HTML-CIRCLE: <pre class="code-block"> +HTML-CIRCLE: <code> +HTML-CIRCLE: Circle circle(5.0); +HTML-CIRCLE: double perimeter = circle.perimeter(); +HTML-CIRCLE: </code> +HTML-CIRCLE: </pre> +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> +HTML-CIRCLE: </div> HTML-CIRCLE: </section> HTML-CIRCLE: </div> HTML-CIRCLE: </div> diff --git a/clang-tools-extra/test/clang-doc/basic-project.test b/clang-tools-extra/test/clang-doc/basic-project.test index 9c1ed29..9220dc6 100644 --- a/clang-tools-extra/test/clang-doc/basic-project.test +++ b/clang-tools-extra/test/clang-doc/basic-project.test @@ -1,31 +1,6 @@ // RUN: rm -rf %t && mkdir -p %t/docs %t/build // RUN: sed 's|$test_dir|%/S|g' %S/Inputs/basic-project/database_template.json > %t/build/compile_commands.json -// RUN: clang-doc --format=html --output=%t/docs --executor=all-TUs %t/build/compile_commands.json -// RUN: FileCheck %s -input-file=%t/docs/index_json.js -check-prefix=JSON-INDEX -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Shape.html -check-prefix=HTML-SHAPE -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Calculator.html -check-prefix=HTML-CALC -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Rectangle.html -check-prefix=HTML-RECTANGLE -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Circle.html -check-prefix=HTML-CIRCLE - -// RUN: clang-doc --format=html --output=%t/docs-with-prefix --executor=all-TUs %t/build/compile_commands.json --repository=https://repository.com --repository-line-prefix=L -// RUN: FileCheck %s -input-file=%t/docs-with-prefix/GlobalNamespace/Shape.html -check-prefixes=HTML-SHAPE,SHAPE-LINE-PREFIX -// RUN: FileCheck %s -input-file=%t/docs-with-prefix/GlobalNamespace/Calculator.html -check-prefixes=HTML-CALC,CALC-LINE-PREFIX -// RUN: FileCheck %s -input-file=%t/docs-with-prefix/GlobalNamespace/Rectangle.html -check-prefixes=HTML-RECTANGLE,RECTANGLE-LINE-PREFIX -// RUN: FileCheck %s -input-file=%t/docs-with-prefix/GlobalNamespace/Circle.html -check-prefixes=HTML-CIRCLE,CIRCLE-LINE-PREFIX - -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Shape.html -check-prefixes=HTML-SHAPE,SHAPE-NO-REPOSITORY -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Calculator.html -check-prefixes=HTML-CALC,CALC-NO-REPOSITORY -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Rectangle.html -check-prefixes=HTML-RECTANGLE,RECTANGLE-NO-REPOSITORY -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Circle.html -check-prefixes=HTML-CIRCLE,CIRCLE-NO-REPOSITORY - -// RUN: clang-doc --format=html --output=%t/docs --executor=all-TUs %t/build/compile_commands.json --repository=https://repository.com -// RUN: FileCheck %s -input-file=%t/docs/index_json.js -check-prefixes=JSON-INDEX -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Shape.html -check-prefixes=HTML-SHAPE,SHAPE-REPOSITORY -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Calculator.html -check-prefixes=HTML-CALC,CALC-REPOSITORY -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Rectangle.html -check-prefixes=HTML-RECTANGLE,RECTANGLE-REPOSITORY -// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Circle.html -check-prefixes=HTML-CIRCLE,CIRCLE-REPOSITORY - // RUN: clang-doc --format=md --output=%t/docs --executor=all-TUs %t/build/compile_commands.json // RUN: FileCheck %s -input-file=%t/docs/all_files.md -check-prefixes=MD-ALL-FILES // RUN: FileCheck %s -input-file=%t/docs/index.md -check-prefixes=MD-INDEX @@ -81,248 +56,6 @@ // JSON-INDEX-NEXT: }; // JSON-INDEX-NEXT: } -// HTML-SHAPE: <h1>class Shape</h1> -// SHAPE-NO-REPOSITORY: <p>Defined at line 8 of file .{{.}}include{{.}}Shape.h</p> -// SHAPE-REPOSITORY: <p> -// SHAPE-REPOSITORY-NEXT: Defined at line -// SHAPE-REPOSITORY-NEXT: <a href="https://repository.com/./include/Shape.h#8">8</a> -// SHAPE-LINE-PREFIX: <a href="https://repository.com/./include/Shape.h#L8">8</a> -// SHAPE-REPOSITORY-NEXT: of file -// SHAPE-REPOSITORY-NEXT: <a href="https://repository.com/./include/Shape.h">Shape.h</a> -// SHAPE-REPOSITORY-NEXT: </p> -// HTML-SHAPE: <div>brief</div> -// HTML-SHAPE: <p> Abstract base class for shapes.</p> -// HTML-SHAPE: <p> Provides a common interface for different types of shapes.</p> -// HTML-SHAPE: <h2 id="Functions">Functions</h2> -// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">area</h3> -// HTML-SHAPE: <p>public double area()</p> -// HTML-SHAPE: <div>brief</div> -// HTML-SHAPE: <p> Calculates the area of the shape.</p> -// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">perimeter</h3> -// HTML-SHAPE: <p>public double perimeter()</p> -// HTML-SHAPE: <div>brief</div> -// HTML-SHAPE: <p> Calculates the perimeter of the shape.</p> -// HTML-SHAPE: <div>return</div> -// HTML-SHAPE: <p> double The perimeter of the shape.</p> -// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">~Shape</h3> -// HTML-SHAPE: <p>public void ~Shape()</p> - -// SHAPE-NO-REPOSITORY: Defined at line 13 of file .{{.}}include{{.}}Shape.h -// SHAPE-REPOSITORY: Defined at line -// SHAPE-REPOSITORY-NEXT: <a href="https://repository.com/./include/Shape.h#13">13</a> -// SHAPE-LINE-PREFIX: <a href="https://repository.com/./include/Shape.h#L13">13</a> -// SHAPE-REPOSITORY-NEXT: of file -// SHAPE-REPOSITORY-NEXT: <a href="https://repository.com/./include/Shape.h">Shape.h</a> - -// HTML-SHAPE: <div>brief</div> -// HTML-SHAPE: <p> Virtual destructor.</p> - -// HTML-CALC: <h1>class Calculator</h1> -// CALC-NO-REPOSITORY: <p>Defined at line 8 of file .{{.}}include{{.}}Calculator.h</p> -// CALC-REPOSITORY: <p> -// CALC-REPOSITORY-NEXT: Defined at line -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./include/Calculator.h#8">8</a> -// CALC-LINE-PREFIX: <a href="https://repository.com/./include/Calculator.h#L8">8</a> -// CALC-REPOSITORY-NEXT: of file -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./include/Calculator.h">Calculator.h</a> -// CALC-REPOSITORY-NEXT: </p> -// HTML-CALC: <div>brief</div> -// HTML-CALC: <p> A simple calculator class.</p> -// HTML-CALC: <p> Provides basic arithmetic operations.</p> - -// HTML-CALC: <h2 id="Members">Members</h2> -// HTML-CALC: <div>brief</div> -// HTML-CALC: <p> Holds a public value.</p> -// HTML-CALC: <div>public int public_val</div> -// HTML-CALC: <div>brief</div> -// HTML-CALC: <p> A static value.</p> -// HTML-CALC: <div>public static const int static_val</div> - -// HTML-CALC: <h2 id="Functions">Functions</h2> -// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">add</h3> -// HTML-CALC: <p>public int add(int a, int b)</p> -// CALC-NO-REPOSITORY: Defined at line 3 of file .{{.}}src{{.}}Calculator.cpp -// CALC-REPOSITORY: Defined at line -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./src/Calculator.cpp#3">3</a> -// CALC-LINE-PREFIX: <a href="https://repository.com/./src/Calculator.cpp#L3">3</a> -// CALC-REPOSITORY-NEXT: of file -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./src/Calculator.cpp">Calculator.cpp</a> - -// HTML-CALC: <div>brief</div> -// HTML-CALC: <p> Adds two integers.</p> -// HTML-CALC: <div>return</div> -// HTML-CALC: <p> int The sum of a and b.</p> -// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">subtract</h3> -// HTML-CALC: <p>public int subtract(int a, int b)</p> -// CALC-NO-REPOSITORY: Defined at line 7 of file .{{.}}src{{.}}Calculator.cpp -// CALC-REPOSITORY: Defined at line -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./src/Calculator.cpp#7">7</a> -// CALC-LINE-PREFIX: <a href="https://repository.com/./src/Calculator.cpp#L7">7</a> -// CALC-REPOSITORY-NEXT: of file -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./src/Calculator.cpp">Calculator.cpp</a> - -// HTML-CALC: <div>brief</div> -// HTML-CALC: <p> Subtracts the second integer from the first.</p> -// HTML-CALC: <div>return</div> -// HTML-CALC: <p> int The result of a - b.</p> -// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">multiply</h3> -// HTML-CALC: <p>public int multiply(int a, int b)</p> -// CALC-NO-REPOSITORY: Defined at line 11 of file .{{.}}src{{.}}Calculator.cpp -// CALC-REPOSITORY: Defined at line -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./src/Calculator.cpp#11">11</a> -// CALC-LINE-PREFIX: <a href="https://repository.com/./src/Calculator.cpp#L11">11</a> -// CALC-REPOSITORY-NEXT: of file -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./src/Calculator.cpp">Calculator.cpp</a> - -// HTML-CALC: <div>brief</div> -// HTML-CALC: <p> Multiplies two integers.</p> -// HTML-CALC: <div>return</div> -// HTML-CALC: <p> int The product of a and b.</p> -// HTML-CALC: <h3 id="{{([0-9A-F]{40})}}">divide</h3> -// HTML-CALC: <p>public double divide(int a, int b)</p> -// CALC-NO-REPOSITORY: Defined at line 15 of file .{{.}}src{{.}}Calculator.cpp -// CALC-REPOSITORY: Defined at line -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./src/Calculator.cpp#15">15</a> -// CALC-LINE-PREFIX: <a href="https://repository.com/./src/Calculator.cpp#L15">15</a> -// CALC-REPOSITORY-NEXT: of file -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./src/Calculator.cpp">Calculator.cpp</a> - -// HTML-CALC: <div>brief</div> -// HTML-CALC: <p> Divides the first integer by the second.</p> -// HTML-CALC: <div>return</div> -// HTML-CALC: <p> double The result of a / b.</p> -// HTML-CALC: <div>throw</div> -// HTML-CALC: <p>if b is zero.</p> - -// HTML-CALC: <p>public static int mod(int a, int b)</p> -// CALC-NO-REPOSITORY: Defined at line 54 of file .{{.}}include{{.}}Calculator.h -// CALC-REPOSITORY: Defined at line -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./include/Calculator.h#54">54</a> -// CALC-LINE-PREFIX: <a href="https://repository.com/./include/Calculator.h#L54">54</a> -// CALC-REPOSITORY-NEXT: of file -// CALC-REPOSITORY-NEXT: <a href="https://repository.com/./include/Calculator.h">Calculator.h</a> -// HTML-CALC: <div>brief</div> -// HTML-CALC: <p> Performs the mod operation on integers.</p> -// HTML-CALC: <div>return</div> -// HTML-CALC: <p> The result of a % b.</p> - -// HTML-RECTANGLE: <h1>class Rectangle</h1> -// RECTANGLE-NO-REPOSITORY: <p>Defined at line 10 of file .{{.}}include{{.}}Rectangle.h</p> -// RECTANGLE-REPOSITORY: <p> -// RECTANGLE-REPOSITORY-NEXT: Defined at line -// RECTANGLE-REPOSITORY-NEXT: <a href="https://repository.com/./include/Rectangle.h#10">10</a> -// RECTANGLE-LINE-PREFIX: <a href="https://repository.com/./include/Rectangle.h#L10">10</a> -// RECTANGLE-REPOSITORY-NEXT: of file -// RECTANGLE-REPOSITORY-NEXT: <a href="https://repository.com/./include/Rectangle.h">Rectangle.h</a> -// RECTANGLE-REPOSITORY-NEXT: </p> - -// HTML-RECTANGLE: <p> Represents a rectangle with a given width and height.</p> -// HTML-RECTANGLE: <p> -// HTML-RECTANGLE: Inherits from -// HTML-RECTANGLE: <a href="Shape.html">Shape</a> -// HTML-RECTANGLE: </p> -// HTML-RECTANGLE: <h2 id="Members">Members</h2> -// HTML-RECTANGLE: <p> Width of the rectangle.</p> -// HTML-RECTANGLE: <div>private double width_</div> -// HTML-RECTANGLE: <p> Height of the rectangle.</p> -// HTML-RECTANGLE: <div>private double height_</div> -// HTML-RECTANGLE: <h2 id="Functions">Functions</h2> -// HTML-RECTANGLE: <h3 id="{{([0-9A-F]{40})}}">Rectangle</h3> -// HTML-RECTANGLE: <p>public void Rectangle(double width, double height)</p> -// RECTANGLE-NO-REPOSITORY: Defined at line 3 of file .{{.}}src{{.}}Rectangle.cpp -// RECTANGLE-REPOSITORY: Defined at line -// RECTANGLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Rectangle.cpp#3">3</a> -// RECTANGLE-LINE-PREFIX: <a href="https://repository.com/./src/Rectangle.cpp#L3">3</a> -// RECTANGLE-REPOSITORY-NEXT: of file -// RECTANGLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Rectangle.cpp">Rectangle.cpp</a> - -// HTML-RECTANGLE: <div>brief</div> -// HTML-RECTANGLE: <p> Constructs a new Rectangle object.</p> -// HTML-RECTANGLE: <h3 id="{{([0-9A-F]{40})}}">area</h3> -// HTML-RECTANGLE: <p>public double area()</p> -// RECTANGLE-NO-REPOSITORY: Defined at line 6 of file .{{.}}src{{.}}Rectangle.cpp -// RECTANGLE-REPOSITORY: Defined at line -// RECTANGLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Rectangle.cpp#6">6</a> -// RECTANGLE-LINE-PREFIX: <a href="https://repository.com/./src/Rectangle.cpp#L6">6</a> -// RECTANGLE-REPOSITORY-NEXT: of file -// RECTANGLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Rectangle.cpp">Rectangle.cpp</a> - -// HTML-RECTANGLE: <div>brief</div> -// HTML-RECTANGLE: <p> Calculates the area of the rectangle.</p> -// HTML-RECTANGLE: <div>return</div> -// HTML-RECTANGLE: <p> double The area of the rectangle.</p> -// HTML-RECTANGLE: <h3 id="{{([0-9A-F]{40})}}">perimeter</h3> -// HTML-RECTANGLE: <p>public double perimeter()</p> -// RECTANGLE-NO-REPOSITORY: Defined at line 10 of file .{{.}}src{{.}}Rectangle.cpp -// RECTANGLE-REPOSITORY: Defined at line -// RECTANGLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Rectangle.cpp#10">10</a> -// RECTANGLE-LINE-PREFIX: <a href="https://repository.com/./src/Rectangle.cpp#L10">10</a> -// RECTANGLE-REPOSITORY-NEXT: of file -// RECTANGLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Rectangle.cpp">Rectangle.cpp</a> -// HTML-RECTANGLE: <div>brief</div> -// HTML-RECTANGLE: <p> Calculates the perimeter of the rectangle.</p> -// HTML-RECTANGLE: <div>return</div> -// HTML-RECTANGLE: <p> double The perimeter of the rectangle.</p> - -// HTML-CIRCLE: <h1>class Circle</h1> -// CIRCLE-NO-REPOSITORY: <p>Defined at line 10 of file .{{.}}include{{.}}Circle.h</p> -// CIRCLE-REPOSITORY: <p> -// CIRCLE-REPOSITORY-NEXT: Defined at line -// CIRCLE-REPOSITORY-NEXT: <a href="https://repository.com/./include/Circle.h#10">10</a> -// CIRCLE-LINE-PREFIX: <a href="https://repository.com/./include/Circle.h#L10">10</a> -// CIRCLE-REPOSITORY-NEXT: of file -// CIRCLE-REPOSITORY-NEXT: <a href="https://repository.com/./include/Circle.h">Circle.h</a> -// CIRCLE-REPOSITORY-NEXT: </p> - -// HTML-CIRCLE: <div>brief</div> -// HTML-CIRCLE: <p> Circle class derived from Shape.</p> -// HTML-CIRCLE: <p> Represents a circle with a given radius.</p> -// HTML-CIRCLE: <p> -// HTML-CIRCLE: Inherits from -// HTML-CIRCLE: <a href="Shape.html">Shape</a> -// HTML-CIRCLE: </p> -// HTML-CIRCLE: <h2 id="Members">Members</h2> -// HTML-CIRCLE: <p> Radius of the circle.</p> -// HTML-CIRCLE: <div>private double radius_</div> -// HTML-CIRCLE: <h2 id="Functions">Functions</h2> -// HTML-CIRCLE: <h3 id="{{([0-9A-F]{40})}}">Circle</h3> -// HTML-CIRCLE: <p>public void Circle(double radius)</p> -// CIRCLE-NO-REPOSITORY: Defined at line 3 of file .{{.}}src{{.}}Circle.cpp -// CIRCLE-REPOSITORY: Defined at line -// CIRCLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Circle.cpp#3">3</a> -// CIRCLE-LINE-PREFIX: <a href="https://repository.com/./src/Circle.cpp#L3">3</a> -// CIRCLE-REPOSITORY-NEXT: of file -// CIRCLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Circle.cpp">Circle.cpp</a> - -// HTML-CIRCLE: <div>brief</div> -// HTML-CIRCLE: <p> Constructs a new Circle object.</p> -// HTML-CIRCLE: <h3 id="{{([0-9A-F]{40})}}">area</h3> -// HTML-CIRCLE: <p>public double area()</p> -// CIRCLE-NO-REPOSITORY: Defined at line 5 of file .{{.}}src{{.}}Circle.cpp -// CIRCLE-REPOSITORY: Defined at line -// CIRCLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Circle.cpp#5">5</a> -// CIRCLE-LINE-PREFIX: <a href="https://repository.com/./src/Circle.cpp#L5">5</a> -// CIRCLE-REPOSITORY-NEXT: of file -// CIRCLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Circle.cpp">Circle.cpp</a> - -// HTML-CIRCLE: <div>brief</div> -// HTML-CIRCLE: <p> Calculates the area of the circle.</p> -// HTML-CIRCLE: <div>return</div> -// HTML-CIRCLE: <p> double The area of the circle.</p> -// HTML-CIRCLE: <h3 id="{{([0-9A-F]{40})}}">perimeter</h3> -// HTML-CIRCLE: <p>public double perimeter()</p> -// CIRCLE-NO-REPOSITORY: Defined at line 9 of file .{{.}}src{{.}}Circle.cpp -// CIRCLE-REPOSITORY: Defined at line -// CIRCLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Circle.cpp#9">9</a> -// CIRCLE-LINE-PREFIX: <a href="https://repository.com/./src/Circle.cpp#L9">9</a> -// CIRCLE-REPOSITORY-NEXT: of file -// CIRCLE-REPOSITORY-NEXT: <a href="https://repository.com/./src/Circle.cpp">Circle.cpp</a> - -// HTML-CIRCLE: <div>brief</div> -// HTML-CIRCLE: <p> Calculates the perimeter of the circle.</p> -// HTML-CIRCLE: <div>return</div> -// HTML-CIRCLE: <p> double The perimeter of the circle.</p> - // MD-CALC: # class Calculator // MD-CALC: *Defined at .{{[\/]}}include{{[\/]}}Calculator.h#8* // MD-CALC: **brief** A simple calculator class. diff --git a/clang-tools-extra/test/clang-doc/comments-in-macros.cpp b/clang-tools-extra/test/clang-doc/comments-in-macros.cpp index 0c70fad..bc0ec46 100644 --- a/clang-tools-extra/test/clang-doc/comments-in-macros.cpp +++ b/clang-tools-extra/test/clang-doc/comments-in-macros.cpp @@ -6,8 +6,8 @@ // RUN: FileCheck %s < %t/GlobalNamespace/MyClass.md --check-prefix=MD-MYCLASS // RUN: clang-doc --format=html --doxygen --output=%t --executor=standalone %s -// RUN: FileCheck %s < %t/GlobalNamespace/MyClass.html --check-prefix=HTML-MYCLASS-LINE -// RUN: FileCheck %s < %t/GlobalNamespace/MyClass.html --check-prefix=HTML-MYCLASS +// RUN: FileCheck %s < %t/html/GlobalNamespace/_ZTV7MyClass.html --check-prefix=HTML-MYCLASS-LINE +// RUN: FileCheck %s < %t/html/GlobalNamespace/_ZTV7MyClass.html --check-prefix=HTML-MYCLASS #define DECLARE_METHODS \ /** @@ -21,15 +21,18 @@ // MD-MYCLASS: *public int Add(int a, int b)* // MD-MYCLASS: **brief** Declare a method to calculate the sum of two numbers -// HTML-MYCLASS: <p>public int Add(int a, int b)</p> -// HTML-MYCLASS: <div>brief</div> -// HTML-MYCLASS: <p> Declare a method to calculate the sum of two numbers</p> + +// HTML-MYCLASS: <pre><code class="language-cpp code-clang-doc">int Add (int a, int b)</code></pre> +// HTML-MYCLASS: <div> +// HTML-MYCLASS: <div> +// HTML-MYCLASS: <p> Declare a method to calculate the sum of two numbers</p> +// HTML-MYCLASS: </div> class MyClass { public: -// MD-MYCLASS-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}comments-in-macros.cpp#[[@LINE+2]]* -// HTML-MYCLASS-LINE: <p>Defined at line [[@LINE+1]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}comments-in-macros.cpp</p> +// MD-MYCLASS-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}comments-in-macros.cpp#[[@LINE-2]]* +// HTML-MYCLASS-LINE: <p>Defined at line [[@LINE-3]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}comments-in-macros.cpp</p> DECLARE_METHODS }; diff --git a/clang-tools-extra/test/clang-doc/conversion_function.cpp b/clang-tools-extra/test/clang-doc/conversion_function.cpp index 0200a57..63df5d6 100644 --- a/clang-tools-extra/test/clang-doc/conversion_function.cpp +++ b/clang-tools-extra/test/clang-doc/conversion_function.cpp @@ -4,7 +4,7 @@ // RUN: find %t/ -regex ".*/[0-9A-F]*.yaml" -exec cat {} ";" | FileCheck %s --check-prefix=CHECK-YAML // RUN: clang-doc --format=html --output=%t --executor=standalone %s -// RUN: FileCheck %s < %t/GlobalNamespace/MyStruct.html --check-prefix=CHECK-HTML +// RUN: FileCheck %s < %t/html/GlobalNamespace/_ZTV8MyStruct.html --check-prefix=CHECK-HTML template <typename T> struct MyStruct { @@ -14,5 +14,6 @@ struct MyStruct { // Output correct conversion names. // CHECK-YAML: Name: 'operator T' -// CHECK-HTML: <h3 id="{{[0-9A-F]*}}">operator T</h3> -// CHECK-HTML: <p>public T operator T()</p> +// CHECK-HTML: <div id="{{([0-9A-F]{40})}}"> +// CHECK-HTML: <pre><code class="language-cpp code-clang-doc">T operator T ()</code></pre> +// CHECK-HTML: </div> diff --git a/clang-tools-extra/test/clang-doc/enum.cpp b/clang-tools-extra/test/clang-doc/enum.cpp index b05d8e2..bb0d51f 100644 --- a/clang-tools-extra/test/clang-doc/enum.cpp +++ b/clang-tools-extra/test/clang-doc/enum.cpp @@ -1,12 +1,12 @@ // RUN: rm -rf %t && mkdir -p %t // RUN: clang-doc --format=html --doxygen --output=%t --executor=standalone %s // RUN: clang-doc --format=md --doxygen --output=%t --executor=standalone %s -// RUN: FileCheck %s < %t/GlobalNamespace/index.html --check-prefix=HTML-INDEX-LINE -// RUN: FileCheck %s < %t/GlobalNamespace/index.html --check-prefix=HTML-INDEX -// RUN: FileCheck %s < %t/GlobalNamespace/Animals.html --check-prefix=HTML-ANIMAL-LINE -// RUN: FileCheck %s < %t/GlobalNamespace/Animals.html --check-prefix=HTML-ANIMAL -// RUN: FileCheck %s < %t/Vehicles/index.html --check-prefix=HTML-VEHICLES-LINE -// RUN: FileCheck %s < %t/Vehicles/index.html --check-prefix=HTML-VEHICLES +// RUN: FileCheck %s < %t/html/GlobalNamespace/index.html --check-prefix=HTML-INDEX-LINE +// RUN: FileCheck %s < %t/html/GlobalNamespace/index.html --check-prefix=HTML-INDEX +// RUN: FileCheck %s < %t/html/GlobalNamespace/_ZTV7Animals.html --check-prefix=HTML-ANIMAL-LINE +// RUN: FileCheck %s < %t/html/GlobalNamespace/_ZTV7Animals.html --check-prefix=HTML-ANIMAL +// RUN: FileCheck %s < %t/html/Vehicles/index.html --check-prefix=HTML-VEHICLES-LINE +// RUN: FileCheck %s < %t/html/Vehicles/index.html --check-prefix=HTML-VEHICLES // RUN: FileCheck %s < %t/GlobalNamespace/index.md --check-prefix=MD-INDEX-LINE // RUN: FileCheck %s < %t/GlobalNamespace/index.md --check-prefix=MD-INDEX // RUN: FileCheck %s < %t/GlobalNamespace/Animals.md --check-prefix=MD-ANIMAL-LINE @@ -14,12 +14,14 @@ // RUN: FileCheck %s < %t/Vehicles/index.md --check-prefix=MD-VEHICLES-LINE // RUN: FileCheck %s < %t/Vehicles/index.md --check-prefix=MD-VEHICLES +// COM: FIXME: Add enum value comments to template + /** * @brief For specifying RGB colors */ enum Color { // MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* - // HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> + // HTML-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> Red, ///< Comment 1 Green, ///< Comment 2 Blue ///< Comment 3 @@ -33,23 +35,36 @@ enum Color { // MD-INDEX: | Blue | // MD-INDEX: **brief** For specifying RGB colors -// HTML-INDEX: <th colspan="3">enum Color</th> -// HTML-INDEX: <td>Red</td> -// HTML-INDEX: <td>0</td> -// HTML-INDEX: <p> Comment 1</p> -// HTML-INDEX: <td>Green</td> -// HTML-INDEX: <td>1</td> -// HTML-INDEX: <p> Comment 2</p> -// HTML-INDEX: <td>Blue</td> -// HTML-INDEX: <td>2</td> -// HTML-INDEX: <p> Comment 3</p> +// HTML-INDEX: <div> +// HTML-INDEX: <pre><code class="language-cpp code-clang-doc">enum Color</code></pre> +// HTML-INDEX: </div> +// HTML-INDEX: <table class="table-wrapper"> +// HTML-INDEX: <tbody> +// HTML-INDEX: <tr> +// HTML-INDEX: <th>Name</th> +// HTML-INDEX: <th>Value</th> +// HTML-INDEX: </tr> +// HTML-INDEX: <tr> +// HTML-INDEX: <td>Red</td> +// HTML-INDEX: <td>0</td> +// HTML-INDEX: </tr> +// HTML-INDEX: <tr> +// HTML-INDEX: <td>Green</td> +// HTML-INDEX: <td>1</td> +// HTML-INDEX: </tr> +// HTML-INDEX: <tr> +// HTML-INDEX: <td>Blue</td> +// HTML-INDEX: <td>2</td> +// HTML-INDEX: </tr> +// HTML-INDEX: </tbody> +// HTML-INDEX: </table> /** * @brief Shape Types */ enum class Shapes { // MD-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* - // HTML-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> + // HTML-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> /// Comment 1 Circle, @@ -65,17 +80,32 @@ enum class Shapes { // MD-INDEX: | Triangle | // MD-INDEX: **brief** Shape Types -// HTML-INDEX: <th colspan="3">enum class Shapes</th> -// HTML-INDEX: <td>Circle</td> -// HTML-INDEX: <td>0</td> -// HTML-INDEX: <p> Comment 1</p> -// HTML-INDEX: <td>Rectangle</td> -// HTML-INDEX: <td>1</td> -// HTML-INDEX: <p> Comment 2</p> -// HTML-INDEX: <td>Triangle</td> -// HTML-INDEX: <td>2</td> -// HTML-INDEX: <p> Comment 3</p> - +// COM: FIXME: Serialize "enum class" in template +// HTML-INDEX: <div> +// HTML-INDEX: <pre><code class="language-cpp code-clang-doc">enum Shapes</code></pre> +// HTML-INDEX: </div> +// HTML-INDEX: <table class="table-wrapper"> +// HTML-INDEX: <tbody> +// HTML-INDEX: <tr> +// HTML-INDEX: <th>Name</th> +// HTML-INDEX: <th>Value</th> +// HTML-INDEX: </tr> +// HTML-INDEX: <tr> +// HTML-INDEX: <td>Circle</td> +// HTML-INDEX: <td>0</td> +// HTML-INDEX: </tr> +// HTML-INDEX: <tr> +// HTML-INDEX: <td>Rectangle</td> +// HTML-INDEX: <td>1</td> +// HTML-INDEX: </tr> +// HTML-INDEX: <tr> +// HTML-INDEX: <td>Triangle</td> +// HTML-INDEX: <td>2</td> +// HTML-INDEX: </tr> +// HTML-INDEX: </tbody> +// HTML-INDEX: </table> + +// COM: FIXME: Add enums declared inside of classes to class template class Animals { // MD-ANIMAL-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* // HTML-ANIMAL-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> @@ -85,25 +115,25 @@ public: */ enum AnimalType { // MD-ANIMAL-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* - // HTML-ANIMAL-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> + // HTML-ANIMAL-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> Dog, ///< Man's best friend Cat, ///< Man's other best friend Iguana ///< A lizard }; }; -// HTML-ANIMAL: <h1>class Animals</h1> -// HTML-ANIMAL: <h2 id="Enums">Enums</h2> -// HTML-ANIMAL: <th colspan="3">enum AnimalType</th> -// HTML-ANIMAL: <td>Dog</td> -// HTML-ANIMAL: <td>0</td> -// HTML-ANIMAL: <p> Man's best friend</p> -// HTML-ANIMAL: <td>Cat</td> -// HTML-ANIMAL: <td>1</td> -// HTML-ANIMAL: <p> Man's other best friend</p> -// HTML-ANIMAL: <td>Iguana</td> -// HTML-ANIMAL: <td>2</td> -// HTML-ANIMAL: <p> A lizard</p> +// HTML-ANIMAL-NOT: <h1>class Animals</h1> +// HTML-ANIMAL-NOT: <h2 id="Enums">Enums</h2> +// HTML-ANIMAL-NOT: <th colspan="3">enum AnimalType</th> +// HTML-ANIMAL-NOT: <td>Dog</td> +// HTML-ANIMAL-NOT: <td>0</td> +// HTML-ANIMAL-NOT: <p> Man's best friend</p> +// HTML-ANIMAL-NOT: <td>Cat</td> +// HTML-ANIMAL-NOT: <td>1</td> +// HTML-ANIMAL-NOT: <p> Man's other best friend</p> +// HTML-ANIMAL-NOT: <td>Iguana</td> +// HTML-ANIMAL-NOT: <td>2</td> +// HTML-ANIMAL-NOT: <p> A lizard</p> // MD-ANIMAL: # class Animals // MD-ANIMAL: ## Enums @@ -120,7 +150,7 @@ namespace Vehicles { */ enum Car { // MD-VEHICLES-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp#[[@LINE-1]]* - // HTML-VEHICLES-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp</p> + // HTML-VEHICLES-LINE: Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}enum.cpp Sedan, ///< Comment 1 SUV, ///< Comment 2 @@ -139,20 +169,33 @@ enum Car { // MD-VEHICLES: | Hatchback | // MD-VEHICLES: **brief** specify type of car -// HTML-VEHICLES: <h1>namespace Vehicles</h1> -// HTML-VEHICLES: <th colspan="3">enum Car</th> -// HTML-VEHICLES: <td>Sedan</td> -// HTML-VEHICLES: <td>0</td> -// HTML-VEHICLES: <p> Comment 1</p> -// HTML-VEHICLES: <td>SUV</td> -// HTML-VEHICLES: <td>1</td> -// HTML-VEHICLES: <p> Comment 2</p> -// HTML-VEHICLES: <td>Pickup</td> -// HTML-VEHICLES: <td>2</td> -// HTML-VEHICLES: <p> Comment 3</p> -// HTML-VEHICLES: <td>Hatchback</td> -// HTML-VEHICLES: <td>3</td> -// HTML-VEHICLES: <p> Comment 4</p> +// HTML-VEHICLES: <div> +// HTML-VEHICLES: <pre><code class="language-cpp code-clang-doc">enum Car</code></pre> +// HTML-VEHICLES: </div> +// HTML-VEHICLES: <table class="table-wrapper"> +// HTML-VEHICLES: <tbody> +// HTML-VEHICLES: <tr> +// HTML-VEHICLES: <th>Name</th> +// HTML-VEHICLES: <th>Value</th> +// HTML-VEHICLES: </tr> +// HTML-VEHICLES: <tr> +// HTML-VEHICLES: <td>Sedan</td> +// HTML-VEHICLES: <td>0</td> +// HTML-VEHICLES: </tr> +// HTML-VEHICLES: <tr> +// HTML-VEHICLES: <td>SUV</td> +// HTML-VEHICLES: <td>1</td> +// HTML-VEHICLES: </tr> +// HTML-VEHICLES: <tr> +// HTML-VEHICLES: <td>Pickup</td> +// HTML-VEHICLES: <td>2</td> +// HTML-VEHICLES: </tr> +// HTML-VEHICLES: <tr> +// HTML-VEHICLES: <td>Hatchback</td> +// HTML-VEHICLES: <td>3</td> +// HTML-VEHICLES: </tr> +// HTML-VEHICLES: </tbody> +// HTML-VEHICLES: </table> enum ColorUserSpecified { RedUserSpecified = 'A', @@ -166,10 +209,26 @@ enum ColorUserSpecified { // MD-INDEX: | GreenUserSpecified | // MD-INDEX: | BlueUserSpecified | -// HTML-INDEX: <th colspan="2">enum ColorUserSpecified</th> -// HTML-INDEX: <td>RedUserSpecified</td> -// HTML-INDEX: <td>'A'</td> -// HTML-INDEX: <td>GreenUserSpecified</td> -// HTML-INDEX: <td>2</td> -// HTML-INDEX: <td>BlueUserSpecified</td> -// HTML-INDEX: <td>'C'</td> +// HTML-INDEX: <div> +// HTML-INDEX: <pre><code class="language-cpp code-clang-doc">enum ColorUserSpecified</code></pre> +// HTML-INDEX: </div> +// HTML-INDEX: <table class="table-wrapper"> +// HTML-INDEX: <tbody> +// HTML-INDEX: <tr> +// HTML-INDEX: <th>Name</th> +// HTML-INDEX: <th>Value</th> +// HTML-INDEX: </tr> +// HTML-INDEX: <tr> +// HTML-INDEX: <td>RedUserSpecified</td> +// HTML-INDEX: <td>'A'</td> +// HTML-INDEX: </tr> +// HTML-INDEX: <tr> +// HTML-INDEX: <td>GreenUserSpecified</td> +// HTML-INDEX: <td>2</td> +// HTML-INDEX: </tr> +// HTML-INDEX: <tr> +// HTML-INDEX: <td>BlueUserSpecified</td> +// HTML-INDEX: <td>'C'</td> +// HTML-INDEX: </tr> +// HTML-INDEX: </tbody> +// HTML-INDEX: </table> diff --git a/clang-tools-extra/test/clang-doc/json/class.cpp b/clang-tools-extra/test/clang-doc/json/class.cpp index 9116058..8bf9402 100644 --- a/clang-tools-extra/test/clang-doc/json/class.cpp +++ b/clang-tools-extra/test/clang-doc/json/class.cpp @@ -47,9 +47,6 @@ protected: // CHECK-NEXT: }, // CHECK-NEXT: { // CHECK-NEXT: "TextComment": " It has some nice methods and fields." -// CHECK-NEXT: }, -// CHECK-NEXT: { -// CHECK-NEXT: "TextComment": "" // CHECK-NEXT: } // CHECK: "DocumentationFileName": "_ZTV7MyClass", // CHECK: "Enums": [ diff --git a/clang-tools-extra/test/clang-doc/long-name.cpp b/clang-tools-extra/test/clang-doc/long-name.cpp index 77e50b1..e4a5e29 100644 --- a/clang-tools-extra/test/clang-doc/long-name.cpp +++ b/clang-tools-extra/test/clang-doc/long-name.cpp @@ -1,7 +1,7 @@ // FIXME: This test seems to break on windows, so disable it for now. // UNSUPPORTED: system-windows // RUN: rm -rf %t && mkdir -p %t -// RUN: clang-doc --output=%t --format=mustache --executor=standalone %s +// RUN: clang-doc --output=%t --format=html --executor=standalone %s // RUN: ls %t/json/GlobalNamespace | FileCheck %s -check-prefix=CHECK-JSON // RUN: ls %t/html/GlobalNamespace | FileCheck %s -check-prefix=CHECK-HTML diff --git a/clang-tools-extra/test/clang-doc/mustache-index.cpp b/clang-tools-extra/test/clang-doc/mustache-index.cpp index 7b98c6b..0aa6e21 100644 --- a/clang-tools-extra/test/clang-doc/mustache-index.cpp +++ b/clang-tools-extra/test/clang-doc/mustache-index.cpp @@ -1,5 +1,5 @@ // RUN: rm -rf %t && mkdir -p %t -// RUN: clang-doc --format=mustache --output=%t --executor=standalone %s +// RUN: clang-doc --format=html --output=%t --executor=standalone %s // RUN: FileCheck %s < %t/html/GlobalNamespace/index.html enum Color { @@ -13,49 +13,47 @@ class Foo; // CHECK: <li class="sidebar-section"> // CHECK-NEXT: <a class="sidebar-item" href="#Enums">Enums</a> // CHECK-NEXT: </li> -// CHECK-NEXT: <ul> -// CHECK-NEXT: <li class="sidebar-item-container"> -// CHECK-NEXT: <a class="sidebar-item" href="#{{[0-9A-F]*}}">Color</a> -// CHECK-NEXT: </li> -// CHECK-NEXT: </ul> +// CHECK-NEXT: <li> +// CHECK-NEXT: <ul> +// CHECK-NEXT: <li class="sidebar-item-container"> +// CHECK-NEXT: <a class="sidebar-item" href="#{{[0-9A-F]*}}">Color</a> +// CHECK-NEXT: </li> +// CHECK-NEXT: </ul> // CHECK: <li class="sidebar-section"> // CHECK-NEXT: <a class="sidebar-item" href="#Classes">Inner Classes</a> // CHECK-NEXT: </li> -// CHECK-NEXT: <ul> -// CHECK-NEXT: <li class="sidebar-item-container"> -// CHECK-NEXT: <a class="sidebar-item" href="#{{[0-9A-F]*}}">Foo</a> -// CHECK-NEXT: </li> -// CHECK-NEXT: </ul> +// CHECK-NEXT: <li> +// CHECK-NEXT: <ul> +// CHECK-NEXT: <li class="sidebar-item-container"> +// CHECK-NEXT: <a class="sidebar-item" href="#{{[0-9A-F]*}}">Foo</a> +// CHECK-NEXT: </li> +// CHECK-NEXT: </ul> // CHECK: <section id="Enums" class="section-container"> // CHECK-NEXT: <h2>Enumerations</h2> // CHECK-NEXT: <div> // CHECK-NEXT: <div id="{{[0-9A-F]*}}" class="delimiter-container"> // CHECK-NEXT: <div> -// CHECK-NEXT: <pre> -// CHECK-NEXT: <code class="language-cpp code-clang-doc"> -// CHECK-NEXT: enum Color -// CHECK-NEXT: </code> -// CHECK-NEXT: </pre> +// CHECK-NEXT: <pre><code class="language-cpp code-clang-doc">enum Color</code></pre> // CHECK-NEXT: </div> // CHECK-NEXT: <table class="table-wrapper"> // CHECK-NEXT: <tbody> -// CHECK-NEXT: <tr> -// CHECK-NEXT: <th>Name</th> -// CHECK-NEXT: <th>Value</th> -// CHECK: </tr> +// CHECK-NEXT: <tr> +// CHECK-NEXT: <th>Name</th> +// CHECK-NEXT: <th>Value</th> +// CHECK-NEXT: </tr> // CHECK-NEXT: <tr> // CHECK-NEXT: <td>RED</td> // CHECK-NEXT: <td>0</td> -// CHECK: </tr> +// CHECK-NEXT: </tr> // CHECK-NEXT: <tr> // CHECK-NEXT: <td>BLUE</td> // CHECK-NEXT: <td>1</td> -// CHECK: </tr> +// CHECK-NEXT: </tr> // CHECK-NEXT: <tr> // CHECK-NEXT: <td>GREEN</td> // CHECK-NEXT: <td>2</td> -// CHECK: </tr> +// CHECK-NEXT: </tr> // CHECK-NEXT: </tbody> // CHECK-NEXT: </table> // CHECK-NEXT: <div> diff --git a/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp b/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp index ee8b844..add8a22 100644 --- a/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp +++ b/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp @@ -1,6 +1,7 @@ // RUN: rm -rf %t && mkdir -p %t -// RUN: clang-doc --format=mustache --output=%t --executor=standalone %s +// RUN: clang-doc --format=html --output=%t --executor=standalone %s // RUN: FileCheck %s < %t/html/MyNamespace/index.html +// RUN: FileCheck %s < %t/html/GlobalNamespace/index.html --check-prefix=CHECK-GLOBAL namespace MyNamespace { class Foo; @@ -13,3 +14,18 @@ namespace MyNamespace { // CHECK-NEXT: </a> // CHECK-NEXT: </li> // CHECK-NEXT: </ul> + +// COM: Check that the empty global namespace doesn't contain tag mismatches. +// CHECK-GLOBAL: <main> +// CHECK-GLOBAL-NEXT: <div class="container"> +// CHECK-GLOBAL-NEXT: <div class="sidebar"> +// CHECK-GLOBAL-NEXT: <h2> </h2> +// CHECK-GLOBAL-NEXT: <ul> +// CHECK-GLOBAL-NEXT: </ul> +// CHECK-GLOBAL-NEXT: </div> +// CHECK-GLOBAL-NEXT: <div class="resizer" id="resizer"></div> +// CHECK-GLOBAL-NEXT: <div class="content"> +// CHECK-GLOBAL-EMPTY: +// CHECK-GLOBAL-NEXT: </div> +// CHECK-GLOBAL-NEXT: </div> +// CHECK-GLOBAL-NEXT: </main> diff --git a/clang-tools-extra/test/clang-doc/namespace.cpp b/clang-tools-extra/test/clang-doc/namespace.cpp index 4fa11c7..029f997 100644 --- a/clang-tools-extra/test/clang-doc/namespace.cpp +++ b/clang-tools-extra/test/clang-doc/namespace.cpp @@ -1,23 +1,6 @@ // RUN: rm -rf %t && mkdir -p %t // RUN: clang-doc --format=html --output=%t --executor=standalone %s // RUN: clang-doc --format=md --output=%t --executor=standalone %s -// RUN: FileCheck %s < %t/index_json.js -check-prefix=JSON-INDEX -// RUN: FileCheck %s < %t/@nonymous_namespace/AnonClass.html -check-prefix=HTML-ANON-CLASS-LINE -// RUN: FileCheck %s < %t/@nonymous_namespace/AnonClass.html -check-prefix=HTML-ANON-CLASS -// RUN: FileCheck %s < %t/@nonymous_namespace/index.html -check-prefix=HTML-ANON-INDEX-LINE -// RUN: FileCheck %s < %t/@nonymous_namespace/index.html -check-prefix=HTML-ANON-INDEX -// RUN: FileCheck %s < %t/AnotherNamespace/ClassInAnotherNamespace.html -check-prefix=HTML-ANOTHER-CLASS-LINE -// RUN: FileCheck %s < %t/AnotherNamespace/ClassInAnotherNamespace.html -check-prefix=HTML-ANOTHER-CLASS -// RUN: FileCheck %s < %t/AnotherNamespace/index.html -check-prefix=HTML-ANOTHER-INDEX-LINE -// RUN: FileCheck %s < %t/AnotherNamespace/index.html -check-prefix=HTML-ANOTHER-INDEX -// RUN: FileCheck %s < %t/PrimaryNamespace/NestedNamespace/ClassInNestedNamespace.html -check-prefix=HTML-NESTED-CLASS-LINE -// RUN: FileCheck %s < %t/PrimaryNamespace/NestedNamespace/ClassInNestedNamespace.html -check-prefix=HTML-NESTED-CLASS -// RUN: FileCheck %s < %t/PrimaryNamespace/NestedNamespace/index.html -check-prefix=HTML-NESTED-INDEX-LINE -// RUN: FileCheck %s < %t/PrimaryNamespace/NestedNamespace/index.html -check-prefix=HTML-NESTED-INDEX -// RUN: FileCheck %s < %t/PrimaryNamespace/index.html -check-prefix=HTML-PRIMARY-INDEX-LINE -// RUN: FileCheck %s < %t/PrimaryNamespace/index.html -check-prefix=HTML-PRIMARY-INDEX -// RUN: FileCheck %s < %t/PrimaryNamespace/ClassInPrimaryNamespace.html -check-prefix=HTML-PRIMARY-CLASS-LINE -// RUN: FileCheck %s < %t/PrimaryNamespace/ClassInPrimaryNamespace.html -check-prefix=HTML-PRIMARY-CLASS // RUN: FileCheck %s < %t/@nonymous_namespace/AnonClass.md -check-prefix=MD-ANON-CLASS-LINE // RUN: FileCheck %s < %t/@nonymous_namespace/AnonClass.md -check-prefix=MD-ANON-CLASS // RUN: FileCheck %s < %t/@nonymous_namespace/index.md -check-prefix=MD-ANON-INDEX-LINE @@ -34,23 +17,42 @@ // RUN: FileCheck %s < %t/PrimaryNamespace/index.md -check-prefix=MD-PRIMARY-INDEX // RUN: FileCheck %s < %t/PrimaryNamespace/ClassInPrimaryNamespace.md -check-prefix=MD-PRIMARY-CLASS-LINE // RUN: FileCheck %s < %t/PrimaryNamespace/ClassInPrimaryNamespace.md -check-prefix=MD-PRIMARY-CLASS -// RUN: FileCheck %s < %t/GlobalNamespace/index.html -check-prefix=HTML-GLOBAL-INDEX +// RUN: FileCheck %s < %t/html/GlobalNamespace/index.html -check-prefix=HTML-GLOBAL-INDEX // RUN: FileCheck %s < %t/GlobalNamespace/index.md -check-prefix=MD-GLOBAL-INDEX // RUN: FileCheck %s < %t/all_files.md -check-prefix=MD-ALL-FILES // RUN: FileCheck %s < %t/index.md -check-prefix=MD-INDEX +// RUN: FileCheck %s < %t/html/@nonymous_namespace/_ZTVN12_GLOBAL__N_19AnonClassE.html -check-prefix=HTML-ANON-CLASS-LINE +// RUN: FileCheck %s < %t/html/@nonymous_namespace/_ZTVN12_GLOBAL__N_19AnonClassE.html -check-prefix=HTML-ANON-CLASS +// RUN: FileCheck %s < %t/html/@nonymous_namespace/index.html -check-prefix=HTML-ANON-INDEX-LINE +// RUN: FileCheck %s < %t/html/@nonymous_namespace/index.html -check-prefix=HTML-ANON-INDEX +// RUN: FileCheck %s < %t/html/AnotherNamespace/_ZTVN16AnotherNamespace23ClassInAnotherNamespaceE.html -check-prefix=HTML-ANOTHER-CLASS-LINE +// RUN: FileCheck %s < %t/html/AnotherNamespace/_ZTVN16AnotherNamespace23ClassInAnotherNamespaceE.html -check-prefix=HTML-ANOTHER-CLASS +// RUN: FileCheck %s < %t/html/AnotherNamespace/index.html -check-prefix=HTML-ANOTHER-INDEX-LINE +// RUN: FileCheck %s < %t/html/AnotherNamespace/index.html -check-prefix=HTML-ANOTHER-INDEX +// RUN: FileCheck %s < %t/html/PrimaryNamespace/NestedNamespace/_ZTVN16PrimaryNamespace15NestedNamespace22ClassInNestedNamespaceE.html -check-prefix=HTML-NESTED-CLASS-LINE +// RUN: FileCheck %s < %t/html/PrimaryNamespace/NestedNamespace/_ZTVN16PrimaryNamespace15NestedNamespace22ClassInNestedNamespaceE.html -check-prefix=HTML-NESTED-CLASS +// RUN: FileCheck %s < %t/html/PrimaryNamespace/NestedNamespace/index.html -check-prefix=HTML-NESTED-INDEX-LINE +// RUN: FileCheck %s < %t/html/PrimaryNamespace/NestedNamespace/index.html -check-prefix=HTML-NESTED-INDEX +// RUN: FileCheck %s < %t/html/PrimaryNamespace/index.html -check-prefix=HTML-PRIMARY-INDEX-LINE +// RUN: FileCheck %s < %t/html/PrimaryNamespace/index.html -check-prefix=HTML-PRIMARY-INDEX +// RUN: FileCheck %s < %t/html/PrimaryNamespace/_ZTVN16PrimaryNamespace23ClassInPrimaryNamespaceE.html -check-prefix=HTML-PRIMARY-CLASS-LINE +// RUN: FileCheck %s < %t/html/PrimaryNamespace/_ZTVN16PrimaryNamespace23ClassInPrimaryNamespaceE.html -check-prefix=HTML-PRIMARY-CLASS + +// COM: FIXME: Add global functions to the namespace template +// COM: FIXME: Add namespaces to the namespace template // Anonymous Namespace namespace { void anonFunction() {} // MD-ANON-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]* -// HTML-ANON-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p> +// HTML-ANON-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p> class AnonClass {}; // MD-ANON-CLASS-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]* // HTML-ANON-CLASS-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p> // MD-ANON-CLASS: # class AnonClass -// HTML-ANON-CLASS: <h1>class AnonClass</h1> +// HTML-ANON-CLASS: <h1 class="hero__title-large">class AnonClass</h1> } // namespace // MD-ANON-INDEX: # namespace @nonymous_namespace @@ -61,20 +63,24 @@ class AnonClass {}; // MD-ANON-INDEX: ### anonFunction // MD-ANON-INDEX: *void anonFunction()* -// HTML-ANON-INDEX: <h1>namespace @nonymous_namespace</h1> -// HTML-ANON-INDEX: <p> Anonymous Namespace</p> -// HTML-ANON-INDEX: <h2 id="Records">Records</h2> -// HTML-ANON-INDEX: <a href="AnonClass.html">AnonClass</a> -// HTML-ANON-INDEX: <h2 id="Functions">Functions</h2> -// HTML-ANON-INDEX: <h3 id="{{([0-9A-F]{40})}}">anonFunction</h3> -// HTML-ANON-INDEX: <p>void anonFunction()</p> +// HTML-ANON-INDEX: <h2> @nonymous_namespace</h2> +// HTML-ANON-INDEX: <h2>Inner Classes</h2> +// HTML-ANON-INDEX: <ul class="class-container"> +// HTML-ANON-INDEX: <li id="{{([0-9A-F]{40})}}" style="max-height: 40px;"> +// HTML-ANON-INDEX: <a href="_ZTVN12_GLOBAL__N_19AnonClassE.html"> +// HTML-ANON-INDEX: <pre><code class="language-cpp code-clang-doc">class AnonClass</code></pre> +// HTML-ANON-INDEX: </a> +// HTML-ANON-INDEX: </li> +// HTML-ANON-INDEX-NOT: <h2 id="Functions">Functions</h2> +// HTML-ANON-INDEX-NOT: <h3 id="{{([0-9A-F]{40})}}">anonFunction</h3> +// HTML-ANON-INDEX-NOT: <p>void anonFunction()</p> // Primary Namespace namespace PrimaryNamespace { // Function in PrimaryNamespace void functionInPrimaryNamespace() {} // MD-PRIMARY-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]* -// HTML-PRIMARY-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p> +// HTML-PRIMARY-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p> // Class in PrimaryNamespace class ClassInPrimaryNamespace {}; @@ -84,15 +90,14 @@ class ClassInPrimaryNamespace {}; // MD-PRIMARY-CLASS: # class ClassInPrimaryNamespace // MD-PRIMARY-CLASS: Class in PrimaryNamespace -// HTML-PRIMARY-CLASS: <h1>class ClassInPrimaryNamespace</h1> -// HTML-PRIMARY-CLASS: <p> Class in PrimaryNamespace</p> +// HTML-PRIMARY-CLASS: <h1 class="hero__title-large">class ClassInPrimaryNamespace</h1> // Nested namespace namespace NestedNamespace { // Function in NestedNamespace void functionInNestedNamespace() {} // MD-NESTED-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]* -// HTML-NESTED-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p> +// HTML-NESTED-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p> // Class in NestedNamespace class ClassInNestedNamespace {}; @@ -102,8 +107,7 @@ class ClassInNestedNamespace {}; // MD-NESTED-CLASS: # class ClassInNestedNamespace // MD-NESTED-CLASS: Class in NestedNamespace -// HTML-NESTED-CLASS: <h1>class ClassInNestedNamespace</h1> -// HTML-NESTED-CLASS: <p> Class in NestedNamespace</p> +// HTML-NESTED-CLASS: <h1 class="hero__title-large">class ClassInNestedNamespace</h1> } // namespace NestedNamespace // MD-NESTED-INDEX: # namespace NestedNamespace @@ -115,14 +119,19 @@ class ClassInNestedNamespace {}; // MD-NESTED-INDEX: *void functionInNestedNamespace()* // MD-NESTED-INDEX: Function in NestedNamespace -// HTML-NESTED-INDEX: <h1>namespace NestedNamespace</h1> -// HTML-NESTED-INDEX: <p> Nested namespace</p> -// HTML-NESTED-INDEX: <h2 id="Records">Records</h2> -// HTML-NESTED-INDEX: <a href="ClassInNestedNamespace.html">ClassInNestedNamespace</a> -// HTML-NESTED-INDEX: <h2 id="Functions">Functions</h2> -// HTML-NESTED-INDEX: <h3 id="{{([0-9A-F]{40})}}">functionInNestedNamespace</h3> -// HTML-NESTED-INDEX: <p>void functionInNestedNamespace()</p> -// HTML-NESTED-INDEX: <p> Function in NestedNamespace</p> +// HTML-NESTED-INDEX: <h2> NestedNamespace</h2> +// HTML-NESTED-INDEX: <h2>Inner Classes</h2> +// HTML-NESTED-INDEX: <ul class="class-container"> +// HTML-NESTED-INDEX: <li id="{{([0-9A-F]{40})}}" style="max-height: 40px;"> +// HTML-NESTED-INDEX: <a href="_ZTVN16PrimaryNamespace15NestedNamespace22ClassInNestedNamespaceE.html"> +// HTML-NESTED-INDEX: <pre><code class="language-cpp code-clang-doc">class ClassInNestedNamespace</code></pre> +// HTML-NESTED-INDEX: </a> +// HTML-NESTED-INDEX: </li> +// HTML-NESTED-INDEX: </ul> +// HTML-NESTED-INDEX-NOT: <h2 id="Functions">Functions</h2> +// HTML-NESTED-INDEX-NOT: <h3 id="{{([0-9A-F]{40})}}">functionInNestedNamespace</h3> +// HTML-NESTED-INDEX-NOT: <p>void functionInNestedNamespace()</p> +// HTML-NESTED-INDEX-NOT: <p> Function in NestedNamespace</p> } // namespace PrimaryNamespace // MD-PRIMARY-INDEX: # namespace PrimaryNamespace @@ -136,23 +145,28 @@ class ClassInNestedNamespace {}; // MD-PRIMARY-INDEX: *void functionInPrimaryNamespace()* // MD-PRIMARY-INDEX: Function in PrimaryNamespace -// HTML-PRIMARY-INDEX: <h1>namespace PrimaryNamespace</h1> -// HTML-PRIMARY-INDEX: <p> Primary Namespace</p> -// HTML-PRIMARY-INDEX: <h2 id="Namespaces">Namespaces</h2> -// HTML-PRIMARY-INDEX: <a href="NestedNamespace{{[\/]}}index.html">NestedNamespace</a> -// HTML-PRIMARY-INDEX: <h2 id="Records">Records</h2> -// HTML-PRIMARY-INDEX: <a href="ClassInPrimaryNamespace.html">ClassInPrimaryNamespace</a> -// HTML-PRIMARY-INDEX: <h2 id="Functions">Functions</h2> -// HTML-PRIMARY-INDEX: <h3 id="{{([0-9A-F]{40})}}">functionInPrimaryNamespace</h3> -// HTML-PRIMARY-INDEX: <p>void functionInPrimaryNamespace()</p> -// HTML-PRIMARY-INDEX: <p> Function in PrimaryNamespace</p> +// HTML-PRIMARY-INDEX: <h2> PrimaryNamespace</h2> +// HTML-PRIMARY-INDEX-NOT: <h2 id="Namespaces">Namespaces</h2> +// HTML-PRIMARY-INDEX-NOT: <a href="NestedNamespace{{[\/]}}index.html">NestedNamespace</a> +// HTML-PRIMARY-INDEX <h2>Inner Classes</h2> +// HTML-PRIMARY-INDEX <ul class="class-container"> +// HTML-PRIMARY-INDEX <li id="{{([0-9A-F]{40})}}" style="max-height: 40px;"> +// HTML-PRIMARY-INDEX <a href="_ZTVN16PrimaryNamespace23ClassInPrimaryNamespaceE.html"> +// HTML-PRIMARY-INDEX <pre><code class="language-cpp code-clang-doc">class ClassInPrimaryNamespace</code></pre> +// HTML-PRIMARY-INDEX </a> +// HTML-PRIMARY-INDEX </li> +// HTML-PRIMARY-INDEX </ul> +// HTML-PRIMARY-INDEX-NOT: <h2 id="Functions">Functions</h2> +// HTML-PRIMARY-INDEX-NOT: <h3 id="{{([0-9A-F]{40})}}">functionInPrimaryNamespace</h3> +// HTML-PRIMARY-INDEX-NOT: <p>void functionInPrimaryNamespace()</p> +// HTML-PRIMARY-INDEX-NOT: <p> Function in PrimaryNamespace</p> // AnotherNamespace namespace AnotherNamespace { // Function in AnotherNamespace void functionInAnotherNamespace() {} // MD-ANOTHER-INDEX-LINE: *Defined at {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp#[[@LINE-1]]* -// HTML-ANOTHER-INDEX-LINE: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p> +// HTML-ANOTHER-INDEX-LINE-NOT: <p>Defined at line [[@LINE-2]] of file {{.*}}clang-tools-extra{{[\/]}}test{{[\/]}}clang-doc{{[\/]}}namespace.cpp</p> // Class in AnotherNamespace class ClassInAnotherNamespace {}; @@ -162,8 +176,7 @@ class ClassInAnotherNamespace {}; // MD-ANOTHER-CLASS: # class ClassInAnotherNamespace // MD-ANOTHER-CLASS: Class in AnotherNamespace -// HTML-ANOTHER-CLASS: <h1>class ClassInAnotherNamespace</h1> -// HTML-ANOTHER-CLASS: <p> Class in AnotherNamespace</p> +// HTML-ANOTHER-CLASS: <h1 class="hero__title-large">class ClassInAnotherNamespace</h1> } // namespace AnotherNamespace @@ -176,99 +189,27 @@ class ClassInAnotherNamespace {}; // MD-ANOTHER-INDEX: *void functionInAnotherNamespace()* // MD-ANOTHER-INDEX: Function in AnotherNamespace -// HTML-ANOTHER-INDEX: <h1>namespace AnotherNamespace</h1> -// HTML-ANOTHER-INDEX: <p> AnotherNamespace</p> -// HTML-ANOTHER-INDEX: <h2 id="Records">Records</h2> -// HTML-ANOTHER-INDEX: <a href="ClassInAnotherNamespace.html">ClassInAnotherNamespace</a> -// HTML-ANOTHER-INDEX: <h2 id="Functions">Functions</h2> -// HTML-ANOTHER-INDEX: <h3 id="{{([0-9A-F]{40})}}">functionInAnotherNamespace</h3> -// HTML-ANOTHER-INDEX: <p>void functionInAnotherNamespace()</p> -// HTML-ANOTHER-INDEX: <p> Function in AnotherNamespace</p> - -// JSON-INDEX: async function LoadIndex() { -// JSON-INDEX-NEXT: return{ -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "", -// JSON-INDEX-NEXT: "RefType": "default", -// JSON-INDEX-NEXT: "Path": "", -// JSON-INDEX-NEXT: "Children": [ -// JSON-INDEX-NEXT: { -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "@nonymous_namespace", -// JSON-INDEX-NEXT: "RefType": "namespace", -// JSON-INDEX-NEXT: "Path": "@nonymous_namespace", -// JSON-INDEX-NEXT: "Children": [ -// JSON-INDEX-NEXT: { -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "AnonClass", -// JSON-INDEX-NEXT: "RefType": "record", -// JSON-INDEX-NEXT: "Path": "@nonymous_namespace", -// JSON-INDEX-NEXT: "Children": [] -// JSON-INDEX-NEXT: } -// JSON-INDEX-NEXT: ] -// JSON-INDEX-NEXT: }, -// JSON-INDEX-NEXT: { -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "AnotherNamespace", -// JSON-INDEX-NEXT: "RefType": "namespace", -// JSON-INDEX-NEXT: "Path": "AnotherNamespace", -// JSON-INDEX-NEXT: "Children": [ -// JSON-INDEX-NEXT: { -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "ClassInAnotherNamespace", -// JSON-INDEX-NEXT: "RefType": "record", -// JSON-INDEX-NEXT: "Path": "AnotherNamespace", -// JSON-INDEX-NEXT: "Children": [] -// JSON-INDEX-NEXT: } -// JSON-INDEX-NEXT: ] -// JSON-INDEX-NEXT: }, -// JSON-INDEX-NEXT: { -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "GlobalNamespace", -// JSON-INDEX-NEXT: "RefType": "namespace", -// JSON-INDEX-NEXT: "Path": "GlobalNamespace", -// JSON-INDEX-NEXT: "Children": [] -// JSON-INDEX-NEXT: }, -// JSON-INDEX-NEXT: { -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "PrimaryNamespace", -// JSON-INDEX-NEXT: "RefType": "namespace", -// JSON-INDEX-NEXT: "Path": "PrimaryNamespace", -// JSON-INDEX-NEXT: "Children": [ -// JSON-INDEX-NEXT: { -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "ClassInPrimaryNamespace", -// JSON-INDEX-NEXT: "RefType": "record", -// JSON-INDEX-NEXT: "Path": "PrimaryNamespace", -// JSON-INDEX-NEXT: "Children": [] -// JSON-INDEX-NEXT: }, -// JSON-INDEX-NEXT: { -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "NestedNamespace", -// JSON-INDEX-NEXT: "RefType": "namespace", -// JSON-INDEX-NEXT: "Path": "PrimaryNamespace{{[\/]+}}NestedNamespace", -// JSON-INDEX-NEXT: "Children": [ -// JSON-INDEX-NEXT: { -// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}", -// JSON-INDEX-NEXT: "Name": "ClassInNestedNamespace", -// JSON-INDEX-NEXT: "RefType": "record", -// JSON-INDEX-NEXT: "Path": "PrimaryNamespace{{[\/]+}}NestedNamespace", -// JSON-INDEX-NEXT: "Children": [] -// JSON-INDEX-NEXT: } -// JSON-INDEX-NEXT: ] -// JSON-INDEX-NEXT: } -// JSON-INDEX-NEXT: ] -// JSON-INDEX-NEXT: } -// JSON-INDEX-NEXT: ] -// JSON-INDEX-NEXT: }; -// JSON-INDEX-NEXT: } - -// HTML-GLOBAL-INDEX: <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content"> -// HTML-GLOBAL-INDEX: <h1>Global Namespace</h1> -// HTML-GLOBAL-INDEX: <h2 id="Namespaces">Namespaces</h2> -// HTML-GLOBAL-INDEX: <li>@nonymous_namespace</li> -// HTML-GLOBAL-INDEX: <li>AnotherNamespace</li> -// HTML-GLOBAL-INDEX: <li>PrimaryNamespace</li> +// HTML-ANOTHER-INDEX: <h2> AnotherNamespace</h2> +// HTML-ANOTHER-INDEX: <h2>Inner Classes</h2> +// HTML-ANOTHER-INDEX: <ul class="class-container"> +// HTML-ANOTHER-INDEX: <li id="{{([0-9A-F]{40})}}" style="max-height: 40px;"> +// HTML-ANOTHER-INDEX: <a href="_ZTVN16AnotherNamespace23ClassInAnotherNamespaceE.html"> +// HTML-ANOTHER-INDEX: <pre><code class="language-cpp code-clang-doc">class ClassInAnotherNamespace</code></pre> +// HTML-ANOTHER-INDEX: </a> +// HTML-ANOTHER-INDEX: </li> +// HTML-ANOTHER-INDEX: </ul> +// HTML-ANOTHER-INDEX-NOT: <h2 id="Functions">Functions</h2> +// HTML-ANOTHER-INDEX-NOT: <h3 id="{{([0-9A-F]{40})}}">functionInAnotherNamespace</h3> +// HTML-ANOTHER-INDEX-NOT: <p>void functionInAnotherNamespace()</p> +// HTML-ANOTHER-INDEX-NOT: <p> Function in AnotherNamespace</p> + +// COM: FIXME: Add namespaces to namespace template +// HTML-GLOBAL-INDEX-NOT: <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content"> +// HTML-GLOBAL-INDEX-NOT: <h1>Global Namespace</h1> +// HTML-GLOBAL-INDEX-NOT: <h2 id="Namespaces">Namespaces</h2> +// HTML-GLOBAL-INDEX-NOT: <li>@nonymous_namespace</li> +// HTML-GLOBAL-INDEX-NOT: <li>AnotherNamespace</li> +// HTML-GLOBAL-INDEX-NOT: <li>PrimaryNamespace</li> // MD-GLOBAL-INDEX: # Global Namespace // MD-GLOBAL-INDEX: ## Namespaces diff --git a/clang-tools-extra/test/clang-doc/test-path-abs.cpp b/clang-tools-extra/test/clang-doc/test-path-abs.cpp deleted file mode 100644 index 8875a3a..0000000 --- a/clang-tools-extra/test/clang-doc/test-path-abs.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// RUN: rm -rf %t && mkdir -p %t -// RUN: clang-doc --format=html --executor=standalone %s --output=%t --base base_dir -// RUN: FileCheck %s -input-file=%t/index_json.js -check-prefix=JSON-INDEX - -// JSON-INDEX: var RootPath = "{{.*}}test-path-abs.cpp.tmp"; -// JSON-INDEX-NEXT: var Base = "base_dir"; - diff --git a/clang-tools-extra/test/clang-tidy/.clang-tidy b/clang-tools-extra/test/clang-tidy/.clang-tidy new file mode 100644 index 0000000..612bd0e --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/.clang-tidy @@ -0,0 +1 @@ +Checks: '-*' diff --git a/clang-tools-extra/test/clang-tidy/check_clang_tidy.py b/clang-tools-extra/test/clang-tidy/check_clang_tidy.py index 183b33f..b173ecf 100755 --- a/clang-tools-extra/test/clang-tidy/check_clang_tidy.py +++ b/clang-tools-extra/test/clang-tidy/check_clang_tidy.py @@ -398,6 +398,8 @@ def parse_arguments() -> Tuple[argparse.Namespace, List[str]]: def main() -> None: + sys.stdout.reconfigure(encoding="utf-8") + sys.stderr.reconfigure(encoding="utf-8") args, extra_args = parse_arguments() abbreviated_stds = args.std diff --git a/clang-tools-extra/test/clang-tidy/checkers/cert/throw-exception-type.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-copy-constructor-throws.cpp index 34ca837..7e2d586 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cert/throw-exception-type.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-copy-constructor-throws.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++11,c++14 %s cert-err60-cpp %t -- -- -fcxx-exceptions +// RUN: %check_clang_tidy -std=c++11,c++14 %s bugprone-exception-copy-constructor-throws %t -- -- -fcxx-exceptions // FIXME: Split off parts of this test that rely on dynamic exception // specifications, and run this test in all language modes. // FIXME: Fix the checker to work in C++17 or later mode. @@ -92,7 +92,7 @@ void f() { throw U(); // ok throw V(); // ok throw W(); // match, noexcept(false) - // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible [cert-err60-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible [bugprone-exception-copy-constructor-throws] throw X(); // match, no noexcept clause, nontrivial // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible throw Y(); // ok diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp new file mode 100644 index 0000000..48c9bac --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-options.cpp @@ -0,0 +1,47 @@ +// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-exception-escape %t -- \ +// RUN: -config="{CheckOptions: { \ +// RUN: bugprone-exception-escape.CheckDestructors: false, \ +// RUN: bugprone-exception-escape.CheckMoveMemberFunctions: false, \ +// RUN: bugprone-exception-escape.CheckMain: false, \ +// RUN: bugprone-exception-escape.CheckedSwapFunctions: '', \ +// RUN: bugprone-exception-escape.CheckNothrowFunctions: false \ +// RUN: }}" \ +// RUN: -- -fexceptions + +// CHECK-MESSAGES-NOT: warning: + +struct destructor { + ~destructor() { + throw 1; + } +}; + +struct move { + move(move&&) { throw 42; } + move& operator=(move&&) { throw 42; } +}; + +void swap(int&, int&) { + throw 1; +} + +void iter_swap(int&, int&) { + throw 1; +} + +void iter_move(int&) { + throw 1; +} + +void nothrow_func() throw() { + throw 1; +} + +void noexcept_func() noexcept { + throw 1; +} + +int main() { + throw 1; + return 0; +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/cert/msc32-c.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/random-generator-seed.c index 0a1d79b..7f2a068 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cert/msc32-c.c +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/random-generator-seed.c @@ -1,4 +1,5 @@ -// RUN: %check_clang_tidy %s cert-msc32-c %t -- -config="{CheckOptions: {cert-msc32-c.DisallowedSeedTypes: 'some_type,time_t'}}" -- -std=c99 +// RUN: %check_clang_tidy %s bugprone-random-generator-seed %t -- \ +// RUN: -config="{CheckOptions: {bugprone-random-generator-seed.DisallowedSeedTypes: 'some_type,time_t'}}" void srand(int seed); typedef int time_t; @@ -6,15 +7,15 @@ time_t time(time_t *t); void f(void) { srand(1); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc32-c] + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] const int a = 1; srand(a); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc32-c] + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] time_t t; srand(time(&t)); // Disallowed seed type - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc32-c] + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] } void g(void) { diff --git a/clang-tools-extra/test/clang-tidy/checkers/cert/msc51-cpp.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/random-generator-seed.cpp index 637ba58..c8818d6 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cert/msc51-cpp.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/random-generator-seed.cpp @@ -1,5 +1,5 @@ -// RUN: %check_clang_tidy %s cert-msc51-cpp %t -- \ -// RUN: -config="{CheckOptions: {cert-msc51-cpp.DisallowedSeedTypes: 'some_type,time_t'}}" +// RUN: %check_clang_tidy %s bugprone-random-generator-seed %t -- \ +// RUN: -config="{CheckOptions: {bugprone-random-generator-seed.DisallowedSeedTypes: 'some_type,time_t'}}" namespace std { @@ -71,114 +71,114 @@ void f() { time_t t; std::srand(0); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::srand(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::srand(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] // One instantiation for every engine std::default_random_engine engine1; - // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] std::default_random_engine engine2(1); - // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::default_random_engine engine3(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::default_random_engine engine4(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] engine1.seed(); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] engine1.seed(1); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine1.seed(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine1.seed(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] std::mt19937 engine5; - // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] std::mt19937 engine6(1); - // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::mt19937 engine7(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::mt19937 engine8(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] engine5.seed(); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] engine5.seed(1); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine5.seed(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine5.seed(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] std::ranlux24_base engine9; - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] std::ranlux24_base engine10(1); - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::ranlux24_base engine11(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::ranlux24_base engine12(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] engine9.seed(); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] engine9.seed(1); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine9.seed(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine9.seed(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] std::ranlux24 engine13; - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] std::ranlux24 engine14(1); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::ranlux24 engine15(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::ranlux24 engine16(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] engine13.seed(); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] engine13.seed(1); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine13.seed(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine13.seed(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] std::independent_bits engine17; - // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] std::independent_bits engine18(1); - // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::independent_bits engine19(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::independent_bits engine20(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] engine17.seed(); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] engine17.seed(1); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine17.seed(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine17.seed(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] std::shuffle_order engine21; - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] std::shuffle_order engine22(1); - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::shuffle_order engine23(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] std::shuffle_order engine24(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] engine21.seed(); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a default argument will generate a predictable sequence of values [bugprone-random-generator-seed] engine21.seed(1); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine21.seed(seed); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a constant value will generate a predictable sequence of values [bugprone-random-generator-seed] engine21.seed(time(&t)); - // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [cert-msc51-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: random number generator seeded with a disallowed source of seed value will generate a predictable sequence of values [bugprone-random-generator-seed] } struct A { diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access-ignore-value.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access-ignore-value.cpp new file mode 100644 index 0000000..f546212 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unchecked-optional-access-ignore-value.cpp @@ -0,0 +1,25 @@ +// RUN: %check_clang_tidy %s bugprone-unchecked-optional-access %t -- \ +// RUN: -config="{CheckOptions: \ +// RUN: {bugprone-unchecked-optional-access.IgnoreValueCalls: true}}" -- \ +// RUN: -I %S/Inputs/unchecked-optional-access + +#include "absl/types/optional.h" + +struct Foo { + void foo() const {} +}; + +void unchecked_value_access(const absl::optional<int> &opt) { + opt.value(); // no-warning +} + +void unchecked_deref_operator_access(const absl::optional<int> &opt) { + *opt; + // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: unchecked access to optional value +} + +void unchecked_arrow_operator_access(const absl::optional<Foo> &opt) { + opt->foo(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: unchecked access to optional value +} + diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom.c b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom.c index 7fd71ec..7eaf015 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom.c +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unsafe-functions-custom.c @@ -1,5 +1,5 @@ // RUN: %check_clang_tidy -check-suffix=NON-STRICT-REGEX %s bugprone-unsafe-functions %t --\ -// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: '::name_match,replacement,is a qualname match;^::prefix_match,,is matched on qualname prefix'}}" +// RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: \"::name_match,,>is a qualname match, but with a fully 'custom' message;^::prefix_match,,is matched on qualname prefix\"}}" // RUN: %check_clang_tidy -check-suffix=STRICT-REGEX %s bugprone-unsafe-functions %t --\ // RUN: -config="{CheckOptions: {bugprone-unsafe-functions.CustomFunctions: '^name_match$,replacement,is matched on function name only;^::prefix_match$,,is a full qualname match'}}" @@ -11,14 +11,14 @@ void prefix_match_regex(); void f1() { name_match(); - // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match' is a qualname match; 'replacement' should be used instead + // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match' is a qualname match, but with a fully 'custom' message // CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'name_match' is matched on function name only; 'replacement' should be used instead prefix_match(); // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'prefix_match' is matched on qualname prefix; it should not be used // CHECK-MESSAGES-STRICT-REGEX: :[[@LINE-2]]:3: warning: function 'prefix_match' is a full qualname match; it should not be used name_match_regex(); - // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match_regex' is a qualname match; 'replacement' should be used instead + // CHECK-MESSAGES-NON-STRICT-REGEX: :[[@LINE-1]]:3: warning: function 'name_match_regex' is a qualname match, but with a fully 'custom' message // no-warning STRICT-REGEX prefix_match_regex(); diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp index 87dfec4..b2df263 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp @@ -1,5 +1,13 @@ -// RUN: %check_clang_tidy -std=c++11 -check-suffixes=,CXX11 %s bugprone-use-after-move %t -- -- -fno-delayed-template-parsing -// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-use-after-move %t -- -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy -std=c++11 -check-suffixes=,CXX11 %s bugprone-use-after-move %t -- \ +// RUN: -config='{CheckOptions: { \ +// RUN: bugprone-use-after-move.InvalidationFunctions: "::Database<>::StaticCloseConnection;Database<>::CloseConnection;FriendCloseConnection" \ +// RUN: }}' -- \ +// RUN: -fno-delayed-template-parsing +// RUN: %check_clang_tidy -std=c++17-or-later %s bugprone-use-after-move %t -- \ +// RUN: -config='{CheckOptions: { \ +// RUN: bugprone-use-after-move.InvalidationFunctions: "::Database<>::StaticCloseConnection;Database<>::CloseConnection;FriendCloseConnection" \ +// RUN: }}' -- \ +// RUN: -fno-delayed-template-parsing typedef decltype(nullptr) nullptr_t; @@ -1645,3 +1653,53 @@ void create() { } } // namespace issue82023 + +namespace custom_invalidation +{ + +template<class T = int> +struct Database { + template<class...> + void CloseConnection(T = T()) {} + template<class...> + static void StaticCloseConnection(Database&, T = T()) {} + template<class...> + friend void FriendCloseConnection(Database&, T = T()) {} + void Query(); +}; + +void Run() { + using DB = Database<>; + + DB db1; + db1.CloseConnection(); + db1.Query(); + // CHECK-NOTES: [[@LINE-1]]:3: warning: 'db1' used after it was invalidated + // CHECK-NOTES: [[@LINE-3]]:7: note: invalidation occurred here + + DB db2; + DB::StaticCloseConnection(db2); + db2.Query(); + // CHECK-NOTES: [[@LINE-1]]:3: warning: 'db2' used after it was invalidated + // CHECK-NOTES: [[@LINE-3]]:3: note: invalidation occurred here + + DB db3; + DB().StaticCloseConnection(db3); + db3.Query(); + // CHECK-NOTES: [[@LINE-1]]:3: warning: 'db3' used after it was invalidated + // CHECK-NOTES: [[@LINE-3]]:3: note: invalidation occurred here + + DB db4; + FriendCloseConnection(db4); + db4.Query(); + // CHECK-NOTES: [[@LINE-1]]:3: warning: 'db4' used after it was invalidated + // CHECK-NOTES: [[@LINE-3]]:3: note: invalidation occurred here + + DB db5; + FriendCloseConnection(db5, /*disconnect timeout*/ 5); + db5.Query(); + // CHECK-NOTES: [[@LINE-1]]:3: warning: 'db5' used after it was invalidated + // CHECK-NOTES: [[@LINE-3]]:3: note: invalidation occurred here +} + +} // namespace custom_invalidation diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.ignorearrays.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.ignorearrays.cpp index 01859b3..e4cfe67 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.ignorearrays.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.ignorearrays.cpp @@ -14,3 +14,39 @@ struct HasArrayMember { int RawArray[4]; int Number; }; + +namespace std { +template <typename T, int N> +struct array { + T _Elems[N]; + void fill(const T &); +}; +} + +void test_local_std_array() { + std::array<int, 4> a; +} + +struct OnlyArray { + int a[4]; +}; + +void test_local_only_array() { + OnlyArray a; +} + +struct Mixed { + int a[4]; + int b; +}; + +void test_local_mixed() { + Mixed m; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'm' +} + +void test_std_array_fill() { + std::array<char, 10> someArray; + // CHECK-MESSAGES-NOT: warning: uninitialized record type: 'someArray' + someArray.fill('n'); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/fuchsia/multiple-inheritance.cpp b/clang-tools-extra/test/clang-tidy/checkers/fuchsia/multiple-inheritance.cpp index d53b3fd..c60649f 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/fuchsia/multiple-inheritance.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/fuchsia/multiple-inheritance.cpp @@ -148,3 +148,18 @@ void test_no_crash() { auto foo = []() {}; WithTemplBase<decltype(foo)>(); } + +struct S1 {}; +struct S2 {}; + +struct S3 : S1, S2 {}; + +namespace N { + +struct S1 { int i; }; +struct S2 { int i; }; + +// CHECK-MESSAGES: [[@LINE+1]]:1: warning: inheriting multiple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance] +struct S3 : S1, S2 {}; + +} // namespace N diff --git a/clang-tools-extra/test/clang-tidy/checkers/google/readability-casting.c b/clang-tools-extra/test/clang-tidy/checkers/google/readability-casting.c deleted file mode 100644 index f0d5339..0000000 --- a/clang-tools-extra/test/clang-tidy/checkers/google/readability-casting.c +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: %check_clang_tidy %s google-readability-casting %t -- -- -x c -// The testing script always adds .cpp extension to the input file name, so we -// need to run clang-tidy directly in order to verify handling of .c files: -// RUN: clang-tidy --checks=-*,google-readability-casting %s -- -x c++ | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not='{{warning|error}}:' -// RUN: cp %s %t.main_file.cpp -// RUN: clang-tidy --checks=-*,google-readability-casting -header-filter='.*' %t.main_file.cpp -- -I%S -DTEST_INCLUDE -x c++ | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not='{{warning|error}}:' - -#ifdef TEST_INCLUDE - -#undef TEST_INCLUDE -#include "readability-casting.c" - -#else - -void f(const char *cpc) { - const char *cpc2 = (const char*)cpc; - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type [google-readability-casting] - // CHECK-FIXES: const char *cpc2 = cpc; - char *pc = (char*)cpc; - typedef const char *Typedef1; - (Typedef1)cpc; -} - -#endif diff --git a/clang-tools-extra/test/clang-tidy/checkers/google/readability-todo-hyphen.cpp b/clang-tools-extra/test/clang-tidy/checkers/google/readability-todo-hyphen.cpp new file mode 100644 index 0000000..5701b30 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/google/readability-todo-hyphen.cpp @@ -0,0 +1,40 @@ +// RUN: %check_clang_tidy %s google-readability-todo %t -- -config="{User: 'some user'}" -- + +// TODOfix this1 +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO +// CHECK-FIXES: // TODO: some user - fix this1 + +// TODO fix this2 +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO +// CHECK-FIXES: // TODO: some user - fix this2 + +// TODO fix this3 +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO +// CHECK-FIXES: // TODO: some user - fix this3 + +// TODO: fix this4 +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO +// CHECK-FIXES: // TODO: some user - fix this4 + +// TODO: bug 12345 - +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing details in TODO + +// TODO: a message without a reference +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO +// CHECK-FIXES: // TODO: some user - a message without a reference + +// TODO(clang)fix this5 + +// TODO: foo - shave yaks +// TODO:foo - no space bewteen semicolon and username +// TODO: foo- no space bewteen username and dash +// TODO: foo - extra spaces between semicolon and username +// TODO: foo - extra spaces between username and dash +// TODO: b/12345 - use a b/ prefix +// TODO: bug 12345 - use a space in username/bug reference +// TODO(foo):shave yaks +// TODO(bar): +// TODO(foo): paint bikeshed +// TODO(b/12345): find the holy grail +// TODO (b/12345): allow spaces before parentheses +// TODO(asdf) allow missing semicolon diff --git a/clang-tools-extra/test/clang-tidy/checkers/google/readability-todo.cpp b/clang-tools-extra/test/clang-tidy/checkers/google/readability-todo-parentheses.cpp index 6b900aa..f97e395 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/google/readability-todo.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/google/readability-todo-parentheses.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s google-readability-todo %t -- -config="{User: 'some user'}" -- +// RUN: %check_clang_tidy %s google-readability-todo %t -- -config="{User: 'some user', CheckOptions: {google-readability-todo.Style: 'Parentheses'}}" -- // TODOfix this1 // CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO @@ -16,8 +16,22 @@ // CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO // CHECK-FIXES: // TODO(some user): fix this4 +// TODO: bug 12345 - +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing details in TODO + +// TODO: a message without a reference +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: missing username/bug in TODO +// CHECK-FIXES: // TODO(some user): a message without a reference + // TODO(clang)fix this5 +// TODO: foo - shave yaks +// TODO:foo - no space bewteen semicolon and username +// TODO: foo- no space bewteen username and dash +// TODO: foo - extra spaces between semicolon and username +// TODO: foo - extra spaces between username and dash +// TODO: b/12345 - use a b/ prefix +// TODO: bug 12345 - use a space in username/bug reference // TODO(foo):shave yaks // TODO(bar): // TODO(foo): paint bikeshed diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp index 4c847b5..0cb58c2 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-pointer-as-pointers.cpp @@ -73,3 +73,18 @@ void ignoreNonConstRefOps() { int* p2 {nullptr}; int*& r2 = (int*&)p2; } + +void pointer_to_pointer_param(int**); +void pass_address_to_pointer_to_pointer() { + int i = 0; + int* ip = &i; + // CHECK-NOT: warning + pointer_to_pointer_param(&ip); +} + +void void_pointer_to_pointer_param(void**); +void pass_address_to_void_pointer_to_pointer() { + void* ptr = nullptr; + // CHECK-NOT: warning + void_pointer_to_pointer_param(&ptr); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp index c23c355..dff73ae 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/coroutine-hostile-raii.cpp @@ -1,7 +1,8 @@ // RUN: %check_clang_tidy -std=c++20 %s misc-coroutine-hostile-raii %t \ // RUN: -config="{CheckOptions: {\ // RUN: misc-coroutine-hostile-raii.RAIITypesList: 'my::Mutex; ::my::other::Mutex', \ -// RUN: misc-coroutine-hostile-raii.AllowedAwaitablesList: 'safe::awaitable; ::transformable::awaitable' \ +// RUN: misc-coroutine-hostile-raii.AllowedAwaitablesList: 'safe::awaitable; ::transformable::awaitable', \ +// RUN: misc-coroutine-hostile-raii.AllowedCallees: 'safe::AwaitFunc; ::safe::Obj::AwaitMethod; retExemptedAwaitable' \ // RUN: }}" namespace std { @@ -145,18 +146,27 @@ namespace safe { void await_suspend(std::coroutine_handle<>) noexcept {} void await_resume() noexcept {} }; + std::suspend_always AwaitFunc(); + struct Obj { + std::suspend_always AwaitMethod(); + }; } // namespace safe ReturnObject RAIISafeSuspendTest() { absl::Mutex a; co_await safe::awaitable{}; using other = safe::awaitable; co_await other{}; + co_await safe::AwaitFunc(); + co_await safe::Obj().AwaitMethod(); } // ================================================================================ // Safe transformable awaitable // ================================================================================ -struct transformable { struct awaitable{}; }; +struct transformable { + struct awaitable{}; + struct unsafe_awaitable{}; +}; using alias_transformable_awaitable = transformable::awaitable; struct UseTransformAwaitable { struct promise_type { @@ -165,13 +175,18 @@ struct UseTransformAwaitable { std::suspend_always final_suspend() noexcept { return {}; } void unhandled_exception() {} std::suspend_always await_transform(transformable::awaitable) { return {}; } + std::suspend_always await_transform(transformable::unsafe_awaitable) { + return {}; + } }; }; auto retAwaitable() { return transformable::awaitable{}; } +auto retExemptedAwaitable() { return transformable::unsafe_awaitable{}; } UseTransformAwaitable RAIISafeSuspendTest2() { absl::Mutex a; co_await retAwaitable(); + co_await retExemptedAwaitable(); co_await transformable::awaitable{}; co_await alias_transformable_awaitable{}; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/cert/limited-randomness.c b/clang-tools-extra/test/clang-tidy/checkers/misc/predictable-rand.c index 32e4a07..d823309 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cert/limited-randomness.c +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/predictable-rand.c @@ -1,11 +1,11 @@ -// RUN: %check_clang_tidy %s cert-msc30-c %t +// RUN: %check_clang_tidy %s misc-predictable-rand %t extern int rand(void); int nonrand(void); int cTest(void) { int i = rand(); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness [cert-msc30-c] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness [misc-predictable-rand] int k = nonrand(); diff --git a/clang-tools-extra/test/clang-tidy/checkers/cert/limited-randomness.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/predictable-rand.cpp index 845b735..8f00186 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cert/limited-randomness.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/predictable-rand.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s cert-msc50-cpp %t +// RUN: %check_clang_tidy %s misc-predictable-rand %t int rand(); int rand(int); @@ -13,16 +13,16 @@ namespace nonstd { void testFunction1() { int i = std::rand(); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [cert-msc50-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [misc-predictable-rand] int j = ::rand(); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [cert-msc50-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [misc-predictable-rand] int k = rand(i); int l = nonstd::rand(); int m = rand(); - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [cert-msc50-cpp] + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: rand() has limited randomness; use C++11 random library instead [misc-predictable-rand] } diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-style-cast.c b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-style-cast.c new file mode 100644 index 0000000..7dfdc7b --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-style-cast.c @@ -0,0 +1,24 @@ +// RUN: %check_clang_tidy %s modernize-avoid-c-style-cast %t -- -- -x c +// The testing script always adds .cpp extension to the input file name, so we +// need to run clang-tidy directly in order to verify handling of .c files: +// RUN: clang-tidy --checks=-*,modernize-avoid-c-style-cast %s -- -x c++ | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not='{{warning|error}}:' +// RUN: cp %s %t.main_file.cpp +// RUN: clang-tidy --checks=-*,modernize-avoid-c-style-cast -header-filter='.*' %t.main_file.cpp -- -I%S -DTEST_INCLUDE -x c++ | FileCheck %s -check-prefix=CHECK-MESSAGES -implicit-check-not='{{warning|error}}:' + +#ifdef TEST_INCLUDE + +#undef TEST_INCLUDE +#include "avoid-c-style-cast.c" + +#else + +void f(const char *cpc) { + const char *cpc2 = (const char*)cpc; + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type [modernize-avoid-c-style-cast] + // CHECK-FIXES: const char *cpc2 = cpc; + char *pc = (char*)cpc; + typedef const char *Typedef1; + (Typedef1)cpc; +} + +#endif diff --git a/clang-tools-extra/test/clang-tidy/checkers/google/readability-casting.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-style-cast.cpp index 7ccdf70..52b4d47 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/google/readability-casting.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-style-cast.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++11-or-later %s google-readability-casting %t -- -- -fexceptions +// RUN: %check_clang_tidy -std=c++11-or-later %s modernize-avoid-c-style-cast %t -- -- -fexceptions bool g() { return false; } @@ -8,14 +8,14 @@ struct Y : public X {}; void f(int a, double b, const char *cpc, const void *cpv, X *pX) { const char *cpc2 = (const char*)cpc; - // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type [google-readability-casting] + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type [modernize-avoid-c-style-cast] // CHECK-FIXES: const char *cpc2 = cpc; typedef const char *Typedef1; typedef const char *Typedef2; Typedef1 t1; (Typedef2)t1; - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C-style casts are discouraged; use static_cast (if needed, the cast may be redundant) [google-readability-casting] + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C-style casts are discouraged; use static_cast (if needed, the cast may be redundant) [modernize-avoid-c-style-cast] // CHECK-FIXES: static_cast<Typedef2>(t1); (const char*)t1; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed @@ -28,7 +28,7 @@ void f(int a, double b, const char *cpc, const void *cpv, X *pX) { // CHECK-FIXES: t1; char *pc = (char*)cpc; - // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use const_cast [google-readability-casting] + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use const_cast [modernize-avoid-c-style-cast] // CHECK-FIXES: char *pc = const_cast<char*>(cpc); typedef char Char; Char *pChar = (Char*)pc; @@ -102,9 +102,15 @@ void f(int a, double b, const char *cpc, const void *cpv, X *pX) { // CHECK-FIXES: b1 = static_cast<int>(b); Y *pB = (Y*)pX; - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [ + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast {{.*}} + // CHECK-FIXES: Y *pB = static_cast<Y*>(pX); Y &rB = (Y&)*pX; - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [ + // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast {{.*}} + // CHECK-FIXES: Y &rB = static_cast<Y&>(*pX); + + void *vp = (void *) pX; + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}}; use reinterpret_cast + // CHECK-FIXES: void *vp = reinterpret_cast<void *>(pX); const char *pc3 = (const char*)cpv; // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}}; use static_cast [ diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp index ec37f07..63972cc 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-print.cpp @@ -54,6 +54,12 @@ void printf_deceptive_newline() { // CHECK-FIXES: std::println("Hello"); } +void printf_utf8_text() { + printf("你好世界\n"); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'printf' [modernize-use-std-print] + // CHECK-FIXES: std::println("你好世界"); +} + void printf_crlf_newline() { printf("Hello\r\n"); // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print] @@ -303,6 +309,12 @@ void fprintf_simple() { // CHECK-FIXES: std::print(stderr, "Hello"); } +void fprintf_utf8_text() { + fprintf(stderr, "你好世界\n"); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::println' instead of 'fprintf' [modernize-use-std-print] + // CHECK-FIXES: std::println(stderr, "你好世界"); +} + void std_printf_simple() { std::printf("std::Hello"); // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use 'std::print' instead of 'printf' [modernize-use-std-print] diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/duplicate-include/pack_begin.h b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/duplicate-include/pack_begin.h new file mode 100644 index 0000000..fc9369c --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/duplicate-include/pack_begin.h @@ -0,0 +1 @@ +// Intentionally unguarded begin-pack header used in tests diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/duplicate-include/pack_end.h b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/duplicate-include/pack_end.h new file mode 100644 index 0000000..78fd0a9 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/Inputs/duplicate-include/pack_end.h @@ -0,0 +1 @@ +// Intentionally unguarded end-pack header used in tests diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp index a8e0eb6..2ed1e93 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp @@ -35,6 +35,12 @@ template <typename T> struct enable_if<true, T> { typedef T type; }; + +template <typename T> +struct unique_ptr { + T &operator*() const; + T *operator->() const; +}; } template <typename T> @@ -144,3 +150,20 @@ int *r() { // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] // CHECK-FIXES: return holder.v.data(); } + +void s(std::unique_ptr<std::vector<unsigned char>> p) { + f(&(*p)[0]); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer] + // CHECK-FIXES: f((*p).data()); +} + +void t(std::unique_ptr<container_without_data<unsigned char>> p) { + // p has no "data" member function, so no warning + f(&(*p)[0]); +} + +template <typename T> +void u(std::unique_ptr<T> p) { + // we don't know if 'T' will always have "data" member function, so no warning + f(&(*p)[0]); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/duplicate-include-ignored-files.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/duplicate-include-ignored-files.cpp new file mode 100644 index 0000000..cdc2f44 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/duplicate-include-ignored-files.cpp @@ -0,0 +1,24 @@ +// RUN: %check_clang_tidy %s readability-duplicate-include %t -- \ +// RUN: -config="{CheckOptions: {readability-duplicate-include.IgnoredFilesList: 'pack_.*\\.h'}}" \ +// RUN: -header-filter='' -- -I %S/Inputs/duplicate-include + +int g; +#include "duplicate-include.h" +int h; +#include "duplicate-include.h" +int i; +// CHECK-MESSAGES: :[[@LINE-2]]:1: warning: duplicate include [readability-duplicate-include] +// CHECK-FIXES: int g; +// CHECK-FIXES-NEXT: #include "duplicate-include.h" +// CHECK-FIXES-NEXT: int h; +// CHECK-FIXES-NEXT: int i; + +#include "pack_begin.h" +struct A { int x; }; +#include "pack_end.h" + +#include "pack_begin.h" +struct B { int x; }; +#include "pack_end.h" + +// No warning here. diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/inconsistent-declaration-parameter-name.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/inconsistent-declaration-parameter-name.cpp index 9822432..119a3c85 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/inconsistent-declaration-parameter-name.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/inconsistent-declaration-parameter-name.cpp @@ -191,3 +191,26 @@ struct S { void S::f(int y) { } + +////////////////////////////////////////////////////// + +template<typename... Args> +void variadicFunctionNoWarning(Args... args); + +template<> +void variadicFunctionNoWarning(int a) {} + +template<> +void variadicFunctionNoWarning(int a, int b) {} + +template<typename... Args> +void variadicFunction2WithWarning(int fixed, Args... args); + +template<> +void variadicFunction2WithWarning(int fixed, int a) {} + +template<> +// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: function template specialization 'variadicFunction2WithWarning<float>' has a primary template +// CHECK-MESSAGES: :[[@LINE-7]]:6: note: the primary template declaration seen here +// CHECK-MESSAGES: :[[@LINE+1]]:6: note: differing parameters are named here: ('wrong'), in primary template declaration: ('fixed') +void variadicFunction2WithWarning(int wrong, float a) {} diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp index fa91995..3e723b8 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-casting.cpp @@ -235,3 +235,13 @@ void testRedundantDependentNTTPCasting() { // CHECK-MESSAGES: :[[@LINE-4]]:25: note: source type originates from referencing this non-type template parameter // CHECK-FIXES: T a = V; } + +namespace gh170476 { +int f(void); +int g1() { + int (*fp)() = (int(*)(void))&f; + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: redundant explicit casting to the same type 'int (*)()' as the sub-expression, remove this casting [readability-redundant-casting] + // CHECK-FIXES: int (*fp)() = (&f); + return fp(); +} +} // namespace gh170476 diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp index 7764490..94e4fc6 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp @@ -7,16 +7,16 @@ void f() { return; } // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement at the end of a function with a void return type [readability-redundant-control-flow] -// CHECK-FIXES: void f() { -// CHECK-FIXES-NEXT: {{^ *}$}} +// CHECK-FIXES: void f() { +// CHECK-FIXES-NEXT: } void g() { f(); return; } // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement -// CHECK-FIXES: f(); -// CHECK-FIXES-NEXT: {{^ *}$}} +// CHECK-FIXES: f(); +// CHECK-FIXES-NEXT: } void g(int i) { if (i < 0) { @@ -40,8 +40,8 @@ void k() { } } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement at the end of loop statement -// CHECK-FIXES: for (int i = 0; i < 10; ++i) { -// CHECK-FIXES-NEXT: {{^ *}$}} +// CHECK-FIXES: for (int i = 0; i < 10; ++i) { +// CHECK-FIXES-NEXT: } void k2() { int v[10] = { 0 }; @@ -50,8 +50,8 @@ void k2() { } } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement -// CHECK-FIXES: for (auto i : v) { -// CHECK-FIXES-NEXT: {{^ *}$}} +// CHECK-FIXES: for (auto i : v) { +// CHECK-FIXES-NEXT: } void m() { int i = 0; @@ -61,8 +61,8 @@ void m() { } while (i < 10); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement -// CHECK-FIXES: {{^ do {$}} -// CHECK-FIXES-NEXT: ++i; +// CHECK-FIXES: do { +// CHECK-FIXES-NEXT: ++i; // CHECK-FIXES-NEXT: } while (i < 10); void p() { @@ -73,9 +73,9 @@ void p() { } } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement -// CHECK-FIXES: while (i < 10) { -// CHECK-FIXES-NEXT: ++i; -// CHECK-FIXES-NEXT: {{^ *}$}} +// CHECK-FIXES: while (i < 10) { +// CHECK-FIXES-NEXT: ++i; +// CHECK-FIXES-NEXT: } void im_not_dead(int i) { if (i > 0) { @@ -176,10 +176,10 @@ void template_return(T check) { return; } // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement -// CHECK-FIXES: if (check < T(0)) { -// CHECK-FIXES-NEXT: {{^ return;$}} -// CHECK-FIXES-NEXT: {{^ *}$}} -// CHECK-FIXES-NEXT: {{^ *}$}} +// CHECK-FIXES: if (check < T(0)) { +// CHECK-FIXES-NEXT: return; +// CHECK-FIXES-NEXT: } +// CHECK-FIXES-NEXT: } template <> void template_return(int check) { @@ -189,10 +189,10 @@ void template_return(int check) { return; } // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement -// CHECK-FIXES: if (check < 0) { -// CHECK-FIXES-NEXT: {{^ return;$}} -// CHECK-FIXES-NEXT: {{^ *}$}} -// CHECK-FIXES-NEXT: {{^ *}$}} +// CHECK-FIXES: if (check < 0) { +// CHECK-FIXES-NEXT: return; +// CHECK-FIXES-NEXT: } +// CHECK-FIXES-NEXT: } template <typename T> void template_loop(T end) { @@ -201,8 +201,8 @@ void template_loop(T end) { } } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement -// CHECK-FIXES: for (T i = 0; i < end; ++i) { -// CHECK-FIXES-NEXT: {{^ *}$}} +// CHECK-FIXES: for (T i = 0; i < end; ++i) { +// CHECK-FIXES-NEXT: } template <> void template_loop(int end) { @@ -211,8 +211,8 @@ void template_loop(int end) { } } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement -// CHECK-FIXES: for (int i = 0; i < end; ++i) { -// CHECK-FIXES-NEXT: {{^ *}$}} +// CHECK-FIXES: for (int i = 0; i < end; ++i) { +// CHECK-FIXES-NEXT: } void call_templates() { template_return(10); diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-typename.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-typename.cpp index 2efafd1..e8fcd9b 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-typename.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-typename.cpp @@ -267,3 +267,27 @@ WHOLE_TYPE_IN_MACRO Macro2; #define WHOLE_DECLARATION_IN_MACRO typename NotDependent::R Macro3 WHOLE_DECLARATION_IN_MACRO; + +template <typename T> struct Wrapper {}; +template <typename T> +struct ClassWrapper { + using R = T; + Wrapper<R> f(); +}; + +template <typename T> +Wrapper<typename ClassWrapper<T>::R> ClassWrapper<T>::f() { + return {}; +} + +template <typename T> struct StructWrapper {}; +template <typename T> +class ClassWithNestedStruct { + struct Nested {}; + StructWrapper<Nested> f(); +}; + +template <typename T> +StructWrapper<typename ClassWithNestedStruct<T>::Nested> ClassWithNestedStruct<T>::f() { + return {}; +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp index 35ade8a..3557018 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp @@ -273,3 +273,99 @@ void useRight() { } } // namespace gh121676 + +void testComments() { + int box_depth = 10; + int max_depth = 5; + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); // here + if (box_depth > max_depth) // here + { + box_depth = max_depth; + } + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); /* here */ + if (box_depth > max_depth) /* here */ + { + box_depth = max_depth; + } + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); // here + if (box_depth > max_depth) + // here + { + box_depth = max_depth; + } + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); /* here */ + if (box_depth > max_depth) + /* here */ + { + box_depth = max_depth; + } + + // CHECK-MESSAGES: :[[@LINE+4]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); /* here + // CHECK-FIXES-NEXT: and here + // CHECK-FIXES-NEXT: */ + if (box_depth > max_depth) /* here + and here + */ + { + box_depth = max_depth; + } + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); /* here */ + if (box_depth > max_depth) { /* here */ + box_depth = max_depth; + } + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); // here + if (box_depth > max_depth) { // here + box_depth = max_depth; + } + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); /* here */ + if (box_depth > max_depth) { + box_depth = max_depth; /* here */ + } + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); // here + if (box_depth > max_depth) { + box_depth = max_depth; // here + } + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); /* here */ + if (box_depth > max_depth) { + box_depth = max_depth; + /* here */ + } + + // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); // here + if (box_depth > max_depth) { + box_depth = max_depth; + // here + } + + // CHECK-MESSAGES: :[[@LINE+5]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max] + // CHECK-FIXES: box_depth = std::min(box_depth, max_depth); // here + // CHECK-FIXES-NEXT: // and + // CHECK-FIXES-NEXT: /* there + // CHECK-FIXES-NEXT: again*/ + if (box_depth > max_depth) { + // here + box_depth = max_depth; // and + /* there + again*/ + } +} diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/param/parameters.txt b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/param/parameters.txt index a6d8fa7e..5cf5693 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/param/parameters.txt +++ b/clang-tools-extra/test/clang-tidy/infrastructure/Inputs/param/parameters.txt @@ -1,2 +1,2 @@ --checks='-*,llvm-namespace-comment' +-checks=-*,llvm-namespace-comment --warnings-as-errors=llvm-namespace-comment diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/alphabetical-order.test b/clang-tools-extra/test/clang-tidy/infrastructure/alphabetical-order.test new file mode 100644 index 0000000..6cb0da7 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/infrastructure/alphabetical-order.test @@ -0,0 +1,5 @@ +// RUN: %python %S/../../../clang-tidy/tool/check_alphabetical_order.py -o %t.clang-tidy-checks-list.rst +// RUN: diff --strip-trailing-cr %S/../../../docs/clang-tidy/checks/list.rst %t.clang-tidy-checks-list.rst + +// RUN: %python %S/../../../clang-tidy/tool/check_alphabetical_order.py -o %t.ReleaseNotes.rst +// RUN: diff --strip-trailing-cr %S/../../../docs/ReleaseNotes.rst %t.ReleaseNotes.rst diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/empty-database.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/empty-database.cpp index c4c504c..0331dcc 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/empty-database.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/empty-database.cpp @@ -1,5 +1,5 @@ // UNSUPPORTED: system-windows -// RUN: clang-tidy -p %S/Inputs/empty-database %s 2>&1 | FileCheck %s +// RUN: clang-tidy -checks='-*,clang-analyzer-*' -p %S/Inputs/empty-database %s 2>&1 | FileCheck %s // CHECK: 'directory' field of compilation database is empty; using the current working directory instead. diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/invalid-database.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/invalid-database.cpp index 7935385..ea9e102 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/invalid-database.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/invalid-database.cpp @@ -1,5 +1,5 @@ // UNSUPPORTED: system-windows -// RUN: not --crash clang-tidy -p %S/Inputs/invalid-database %s 2>&1 | FileCheck %s +// RUN: not --crash clang-tidy -checks='-*,clang-analyzer-*' -p %S/Inputs/invalid-database %s 2>&1 | FileCheck %s // CHECK: LLVM ERROR: Cannot chdir into "/invalid/"! diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-LIFO.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-LIFO.cpp index ee5b1cc..e86b3df 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-LIFO.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-LIFO.cpp @@ -1,11 +1,11 @@ -// RUN: not clang-tidy %s --checks='-*,google-explicit-constructor,google-readability-casting' 2>&1 | FileCheck %s +// RUN: not clang-tidy %s --checks='-*,google-explicit-constructor,modernize-avoid-c-style-cast' 2>&1 | FileCheck %s // NOLINTBEGIN(google-explicit-constructor) -// NOLINTBEGIN(google-readability-casting) +// NOLINTBEGIN(modernize-avoid-c-style-cast) class A { A(int i); }; auto Num = (unsigned int)(-1); // NOLINTEND(google-explicit-constructor) -// NOLINTEND(google-readability-casting) +// NOLINTEND(modernize-avoid-c-style-cast) // Note: the expected output has been split over several lines so that clang-tidy // does not see the "no lint" suppression comment and mistakenly assume it diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-multiple-end-single.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-multiple-end-single.cpp index 150913c..156a5cb 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-multiple-end-single.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-multiple-end-single.cpp @@ -1,10 +1,10 @@ -// RUN: not clang-tidy %s --checks='-*,google-explicit-constructor,google-readability-casting' 2>&1 | FileCheck %s +// RUN: not clang-tidy %s --checks='-*,google-explicit-constructor,modernize-avoid-c-style-cast' 2>&1 | FileCheck %s -// NOLINTBEGIN(google-explicit-constructor,google-readability-casting) +// NOLINTBEGIN(google-explicit-constructor,modernize-avoid-c-style-cast) class B { B(int i); }; // NOLINTEND(google-explicit-constructor) auto Num2 = (unsigned int)(-1); -// NOLINTEND(google-readability-casting) +// NOLINTEND(modernize-avoid-c-style-cast) // Note: the expected output has been split over several lines so that clang-tidy // does not see the "no lint" suppression comment and mistakenly assume it diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-single-end-multiple.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-single-end-multiple.cpp index f9a915c..8372132 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-single-end-multiple.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-begin-single-end-multiple.cpp @@ -1,10 +1,10 @@ -// RUN: not clang-tidy %s --checks='-*,google-explicit-constructor,google-readability-casting' 2>&1 | FileCheck %s +// RUN: not clang-tidy %s --checks='-*,google-explicit-constructor,modernize-avoid-c-style-cast' 2>&1 | FileCheck %s // NOLINTBEGIN(google-explicit-constructor) -// NOLINTBEGIN(google-readability-casting) +// NOLINTBEGIN(modernize-avoid-c-style-cast) class B { B(int i); }; auto Num2 = (unsigned int)(-1); -// NOLINTEND(google-explicit-constructor,google-readability-casting) +// NOLINTEND(google-explicit-constructor,modernize-avoid-c-style-cast) // Note: the expected output has been split over several lines so that clang-tidy // does not see the "no lint" suppression comment and mistakenly assume it diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-mismatched-check-names.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-mismatched-check-names.cpp index 8d7786f..ddd399d 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-mismatched-check-names.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-mismatched-check-names.cpp @@ -1,9 +1,9 @@ -// RUN: not clang-tidy %s --checks='-*,google-explicit-constructor,google-readability-casting' 2>&1 | FileCheck %s +// RUN: not clang-tidy %s --checks='-*,google-explicit-constructor,modernize-avoid-c-style-cast' 2>&1 | FileCheck %s // NOLINTBEGIN(google-explicit-constructor) class A { A(int i); }; auto Num = (unsigned int)(-1); -// NOLINTEND(google-readability-casting) +// NOLINTEND(modernize-avoid-c-style-cast) // Note: the expected output has been split over several lines so that clang-tidy // does not see the "no lint" suppression comment and mistakenly assume it diff --git a/clang-tools-extra/test/lit.cfg.py b/clang-tools-extra/test/lit.cfg.py index c1da37d..c39ea29 100644 --- a/clang-tools-extra/test/lit.cfg.py +++ b/clang-tools-extra/test/lit.cfg.py @@ -57,6 +57,7 @@ if config.clang_tidy_staticanalyzer: if config.clang_tidy_custom_check: config.available_features.add("custom-check") python_exec = shlex.quote(config.python_executable) +config.substitutions.append(("%python", python_exec)) check_clang_tidy = os.path.join( config.test_source_root, "clang-tidy", "check_clang_tidy.py" ) diff --git a/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp b/clang-tools-extra/unittests/clang-doc/BitcodeTest.cpp index d88b0c9..918c7b3 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/CMakeLists.txt b/clang-tools-extra/unittests/clang-doc/CMakeLists.txt index 18166ac..01b34ec 100644 --- a/clang-tools-extra/unittests/clang-doc/CMakeLists.txt +++ b/clang-tools-extra/unittests/clang-doc/CMakeLists.txt @@ -26,7 +26,6 @@ add_extra_unittest(ClangDocTests ClangDocTest.cpp GeneratorTest.cpp HTMLGeneratorTest.cpp - HTMLMustacheGeneratorTest.cpp MDGeneratorTest.cpp MergeTest.cpp SerializeTest.cpp diff --git a/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp b/clang-tools-extra/unittests/clang-doc/ClangDocTest.cpp index f408c91..73891ab 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 2e189ca..2875cf1c 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 14341435..cf510af 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp @@ -9,484 +9,56 @@ #include "ClangDocTest.h" #include "Generators.h" #include "Representation.h" +#include "config.h" +#include "support/Utils.h" #include "clang/Basic/Version.h" +#include "llvm/Testing/Support/Error.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" -namespace clang { -namespace doc { +using namespace llvm; +using namespace testing; +using namespace clang; +using namespace clang::doc; -static const std::string ClangDocVersion = - clang::getClangToolFullVersion("clang-doc"); +static const std::string ClangDocVersion = getClangToolFullVersion("clang-doc"); static std::unique_ptr<Generator> getHTMLGenerator() { - auto G = doc::findGeneratorByName("html"); + auto G = findGeneratorByName("html"); if (!G) return nullptr; 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) { - NamespaceInfo I; - I.Name = "Namespace"; - I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - - I.Children.Namespaces.emplace_back(EmptySID, "ChildNamespace", - InfoType::IT_namespace, - "Namespace::ChildNamespace", "Namespace"); - I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, - "Namespace::ChildStruct", "Namespace"); - I.Children.Functions.emplace_back(); - I.Children.Functions.back().Access = AccessSpecifier::AS_none; - I.Children.Functions.back().Name = "OneFunction"; - I.Children.Enums.emplace_back(); - I.Children.Enums.back().Name = "OneEnum"; - - auto G = getHTMLGenerator(); - assert(G); - std::string Buffer; - llvm::raw_string_ostream Actual(Buffer); - ClangDocContext CDCtx = getClangDocContext({"user-provided-stylesheet.css"}); - auto Err = G->generateDocForInfo(&I, Actual, CDCtx); - assert(!Err); - std::string Expected = R"raw(<!DOCTYPE html> -<meta charset="utf-8"/> -<title>namespace Namespace</title> -<link rel="stylesheet" href="../clang-doc-default-stylesheet.css"/> -<link rel="stylesheet" href="../user-provided-stylesheet.css"/> -<script src="../index_json.js"></script> -<script src="../index.js"></script> -<header id="project-title">test-project</header> -<main> - <div id="sidebar-left" path="Namespace" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div> - <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content"> - <h1>namespace Namespace</h1> - <h2 id="Namespaces">Namespaces</h2> - <ul> - <li> - <a href="ChildNamespace/index.html">ChildNamespace</a> - </li> - </ul> - <h2 id="Records">Records</h2> - <ul> - <li> - <a href="ChildStruct.html">ChildStruct</a> - </li> - </ul> - <h2 id="Functions">Functions</h2> - <div> - <h3 id="0000000000000000000000000000000000000000">OneFunction</h3> - <p>OneFunction()</p> - </div> - <h2 id="Enums">Enums</h2> - <div> - <table id="0000000000000000000000000000000000000000"> - <thead> - <tr> - <th colspan="2">enum OneEnum</th> - </tr> - </thead> - </table> - </div> - </div> - <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"> - <ol> - <li> - <span> - <a href="#Namespaces">Namespaces</a> - </span> - </li> - <li> - <span> - <a href="#Records">Records</a> - </span> - </li> - <li> - <span> - <a href="#Functions">Functions</a> - </span> - <ul> - <li> - <span> - <a href="#0000000000000000000000000000000000000000">OneFunction</a> - </span> - </li> - </ul> - </li> - <li> - <span> - <a href="#Enums">Enums</a> - </span> - <ul> - <li> - <span> - <a href="#0000000000000000000000000000000000000000">OneEnum</a> - </span> - </li> - </ul> - </li> - </ol> - </div> -</main> -<footer> - <span class="no-break">)raw" + - ClangDocVersion + R"raw(</span> -</footer> -)raw"; - - EXPECT_EQ(Expected, Actual.str()); -} - -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, 10, "dir/test.cpp", true); - I.Loc.emplace_back(12, 12, "test.cpp"); - - SmallString<16> PathTo; - llvm::sys::path::native("path/to", PathTo); - I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private); - I.TagType = TagTypeKind::Class; - I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "F", PathTo); - I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record); - - I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, - "X::Y::Z::r::ChildStruct", "X/Y/Z/r"); - I.Children.Functions.emplace_back(); - I.Children.Functions.back().Name = "OneFunction"; - I.Children.Enums.emplace_back(); - I.Children.Enums.back().Name = "OneEnum"; - - auto G = getHTMLGenerator(); - assert(G); - std::string Buffer; - llvm::raw_string_ostream Actual(Buffer); - ClangDocContext CDCtx = getClangDocContext({}, "http://www.repository.com"); - auto Err = G->generateDocForInfo(&I, Actual, CDCtx); - assert(!Err); - std::string Expected = R"raw(<!DOCTYPE html> -<meta charset="utf-8"/> -<title>class r</title> -<link rel="stylesheet" href="../../../clang-doc-default-stylesheet.css"/> -<script src="../../../index_json.js"></script> -<script src="../../../index.js"></script> -<header id="project-title">test-project</header> -<main> - <div id="sidebar-left" path="X/Y/Z" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div> - <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content"> - <h1>class r</h1> - <p> - Defined at line - <a href="http://www.repository.com/dir/test.cpp#10">10</a> - of file - <a href="http://www.repository.com/dir/test.cpp">test.cpp</a> - </p> - <p> - Inherits from - <a href="../../../path/to/F.html">F</a> - , G - </p> - <h2 id="Members">Members</h2> - <ul> - <li> - <div>private int X</div> - </li> - </ul> - <h2 id="Records">Records</h2> - <ul> - <li> - <a href="../../../X/Y/Z/r/ChildStruct.html">ChildStruct</a> - </li> - </ul> - <h2 id="Functions">Functions</h2> - <div> - <h3 id="0000000000000000000000000000000000000000">OneFunction</h3> - <p>public OneFunction()</p> - </div> - <h2 id="Enums">Enums</h2> - <div> - <table id="0000000000000000000000000000000000000000"> - <thead> - <tr> - <th colspan="2">enum OneEnum</th> - </tr> - </thead> - </table> - </div> - </div> - <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"> - <ol> - <li> - <span> - <a href="#Members">Members</a> - </span> - </li> - <li> - <span> - <a href="#Records">Records</a> - </span> - </li> - <li> - <span> - <a href="#Functions">Functions</a> - </span> - <ul> - <li> - <span> - <a href="#0000000000000000000000000000000000000000">OneFunction</a> - </span> - </li> - </ul> - </li> - <li> - <span> - <a href="#Enums">Enums</a> - </span> - <ul> - <li> - <span> - <a href="#0000000000000000000000000000000000000000">OneEnum</a> - </span> - </li> - </ul> - </li> - </ol> - </div> -</main> -<footer> - <span class="no-break">)raw" + - ClangDocVersion + R"raw(</span> -</footer> -)raw"; - - EXPECT_EQ(Expected, Actual.str()); -} - -TEST(HTMLGeneratorTest, emitFunctionHTML) { - FunctionInfo I; - I.Name = "f"; - I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - - I.DefLoc = Location(10, 10, "dir/test.cpp", true); - I.Loc.emplace_back(12, 12, "test.cpp"); - - I.Access = AccessSpecifier::AS_none; - - SmallString<16> PathTo; - llvm::sys::path::native("path/to", PathTo); - I.ReturnType = TypeInfo( - Reference(EmptySID, "float", InfoType::IT_default, "float", PathTo)); - I.Params.emplace_back(TypeInfo("int", PathTo), "P"); - I.IsMethod = true; - I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record); - +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, createResources) { auto G = getHTMLGenerator(); - assert(G); - std::string Buffer; - llvm::raw_string_ostream Actual(Buffer); - ClangDocContext CDCtx = getClangDocContext({}, "https://www.repository.com"); - auto Err = G->generateDocForInfo(&I, Actual, CDCtx); - assert(!Err); - std::string Expected = R"raw(<!DOCTYPE html> -<meta charset="utf-8"/> -<title></title> -<link rel="stylesheet" href="clang-doc-default-stylesheet.css"/> -<script src="index_json.js"></script> -<script src="index.js"></script> -<header id="project-title">test-project</header> -<main> - <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div> - <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content"> - <h3 id="0000000000000000000000000000000000000000">f</h3> - <p> - <a href="path/to/float.html">float</a> - f( - <a href="path/to/int.html">int</a> - P) - </p> - <p> - Defined at line - <a href="https://www.repository.com/dir/test.cpp#10">10</a> - of file - <a href="https://www.repository.com/dir/test.cpp">test.cpp</a> - </p> - </div> - <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div> -</main> -<footer> - <span class="no-break">)raw" + - ClangDocVersion + R"raw(</span> -</footer> -)raw"; - - EXPECT_EQ(Expected, Actual.str()); -} - -TEST(HTMLGeneratorTest, emitEnumHTML) { - EnumInfo I; - I.Name = "e"; - I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); - - I.DefLoc = Location(10, 10, "test.cpp", true); - I.Loc.emplace_back(12, 12, "test.cpp"); - - I.Members.emplace_back("X"); - I.Scoped = true; - - auto G = getHTMLGenerator(); - assert(G); - std::string Buffer; - llvm::raw_string_ostream Actual(Buffer); - ClangDocContext CDCtx = getClangDocContext({}, "www.repository.com"); - auto Err = G->generateDocForInfo(&I, Actual, CDCtx); - assert(!Err); - std::string Expected = R"raw(<!DOCTYPE html> -<meta charset="utf-8"/> -<title></title> -<link rel="stylesheet" href="clang-doc-default-stylesheet.css"/> -<script src="index_json.js"></script> -<script src="index.js"></script> -<header id="project-title">test-project</header> -<main> - <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div> - <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content"> - <table id="0000000000000000000000000000000000000000"> - <thead> - <tr> - <th colspan="2">enum class e</th> - </tr> - </thead> - <tbody> - <tr> - <td>X</td> - <td>0</td> - </tr> - </tbody> - </table> - <p> - Defined at line - <a href="https://www.repository.com/test.cpp#10">10</a> - of file - <a href="https://www.repository.com/test.cpp">test.cpp</a> - </p> - </div> - <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div> -</main> -<footer> - <span class="no-break">)raw" + - ClangDocVersion + R"raw(</span> -</footer> -)raw"; - - EXPECT_EQ(Expected, Actual.str()); -} - -TEST(HTMLGeneratorTest, emitCommentHTML) { - FunctionInfo I; - I.Name = "f"; - I.DefLoc = Location(10, 10, "test.cpp", true); - I.ReturnType = TypeInfo("void"); - I.Params.emplace_back(TypeInfo("int"), "I"); - I.Params.emplace_back(TypeInfo("int"), "J"); - I.Access = AccessSpecifier::AS_none; - - CommentInfo Top; - Top.Kind = CommentKind::CK_FullComment; - - Top.Children.emplace_back(std::make_unique<CommentInfo>()); - CommentInfo *BlankLine = Top.Children.back().get(); - BlankLine->Kind = CommentKind::CK_ParagraphComment; - BlankLine->Children.emplace_back(std::make_unique<CommentInfo>()); - BlankLine->Children.back()->Kind = CommentKind::CK_TextComment; - - Top.Children.emplace_back(std::make_unique<CommentInfo>()); - CommentInfo *Brief = Top.Children.back().get(); - Brief->Kind = CommentKind::CK_ParagraphComment; - Brief->Children.emplace_back(std::make_unique<CommentInfo>()); - Brief->Children.back()->Kind = CommentKind::CK_TextComment; - Brief->Children.back()->Name = "ParagraphComment"; - Brief->Children.back()->Text = " Brief description."; - - Top.Children.emplace_back(std::make_unique<CommentInfo>()); - CommentInfo *Extended = Top.Children.back().get(); - Extended->Kind = CommentKind::CK_ParagraphComment; - Extended->Children.emplace_back(std::make_unique<CommentInfo>()); - Extended->Children.back()->Kind = CommentKind::CK_TextComment; - Extended->Children.back()->Text = " Extended description that"; - Extended->Children.emplace_back(std::make_unique<CommentInfo>()); - Extended->Children.back()->Kind = CommentKind::CK_TextComment; - Extended->Children.back()->Text = " continues onto the next line."; - - Top.Children.emplace_back(std::make_unique<CommentInfo>()); - CommentInfo *Entities = Top.Children.back().get(); - Entities->Kind = CommentKind::CK_ParagraphComment; - Entities->Children.emplace_back(std::make_unique<CommentInfo>()); - Entities->Children.back()->Kind = CommentKind::CK_TextComment; - Entities->Children.back()->Name = "ParagraphComment"; - Entities->Children.back()->Text = - " Comment with html entities: &, <, >, \", \'."; - - I.Description.emplace_back(std::move(Top)); - - auto G = getHTMLGenerator(); - assert(G); - std::string Buffer; - llvm::raw_string_ostream Actual(Buffer); + ASSERT_THAT(G, NotNull()) << "Could not find HTMLGenerator"; ClangDocContext CDCtx = getClangDocContext(); - auto Err = G->generateDocForInfo(&I, Actual, CDCtx); - assert(!Err); - std::string Expected = R"raw(<!DOCTYPE html> -<meta charset="utf-8"/> -<title></title> -<link rel="stylesheet" href="clang-doc-default-stylesheet.css"/> -<script src="index_json.js"></script> -<script src="index.js"></script> -<header id="project-title">test-project</header> -<main> - <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div> - <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content"> - <h3 id="0000000000000000000000000000000000000000">f</h3> - <p>void f(int I, int J)</p> - <p> - Defined at line - <a href="test.cpp#10">10</a> - of file - <a href="test.cpp">test.cpp</a> - </p> - <div> - <div> - <p> Brief description.</p> - <p> Extended description that continues onto the next line.</p> - <p> Comment with html entities: &, <, >, ", '.</p> - </div> - </div> - </div> - <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div> -</main> -<footer> - <span class="no-break">)raw" + - ClangDocVersion + R"raw(</span> -</footer> -)raw"; - - EXPECT_EQ(Expected, Actual.str()); + EXPECT_THAT_ERROR(G->createResources(CDCtx), Failed()) + << "Empty UserStylesheets or JsScripts should fail!"; } - -} // namespace doc -} // namespace clang diff --git a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp deleted file mode 100644 index c7ac387..0000000 --- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//===-- clang-doc/HTMLMustacheGeneratorTest.cpp ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "ClangDocTest.h" -#include "Generators.h" -#include "Representation.h" -#include "config.h" -#include "support/Utils.h" -#include "clang/Basic/Version.h" -#include "llvm/Testing/Support/Error.h" -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -using namespace llvm; -using namespace testing; -using namespace clang; -using namespace clang::doc; - -// FIXME: Don't enable unit tests that can read files. Remove once we can use -// lit to test these properties. -#define ENABLE_LOCAL_TEST 0 - -static const std::string ClangDocVersion = getClangToolFullVersion("clang-doc"); - -static std::unique_ptr<Generator> getHTMLMustacheGenerator() { - auto G = findGeneratorByName("mustache"); - if (!G) - return nullptr; - 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; -} - -TEST(HTMLMustacheGeneratorTest, createResources) { - auto G = getHTMLMustacheGenerator(); - ASSERT_THAT(G, NotNull()) << "Could not find HTMLMustacheGenerator"; - ClangDocContext CDCtx = getClangDocContext(); - EXPECT_THAT_ERROR(G->createResources(CDCtx), Failed()) - << "Empty UserStylesheets or JsScripts should fail!"; -} diff --git a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp index 2706a5145..bd43755 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 f4c69cf..b44b09b 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 ade744e..6bffd98 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 6d5e7da6..f59ea02 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 @@ public: 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 @@ public: 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 a9e7c64..db62c92 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 @@ ChildEnums: 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 @@ ChildEnums: 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 @@ ReturnType: // 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 @@ Members: // 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 @@ Members: 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(--- |
