diff options
author | Joe Blaauboer <jblaauboer67@gmail.com> | 2022-10-24 17:24:57 (GMT) |
---|---|---|
committer | Kyle Edwards <kyle.edwards@kitware.com> | 2022-11-04 15:33:23 (GMT) |
commit | d5208536824fb2c9ad3466b0ca140ea3d3d0ed2b (patch) | |
tree | d817b6c8061d1cad1ffc76531fb1a62ff5ffdb29 /Utilities | |
parent | c67b91a7a6472f23ce8d51c4bbf5e338418cc0a3 (diff) | |
download | CMake-d5208536824fb2c9ad3466b0ca140ea3d3d0ed2b.zip CMake-d5208536824fb2c9ad3466b0ca140ea3d3d0ed2b.tar.gz CMake-d5208536824fb2c9ad3466b0ca140ea3d3d0ed2b.tar.bz2 |
clang-tidy module: add check for cmsys::fstream
Co-Authored-by: Kyle Edwards <kyle.edwards@kitware.com>
Co-Authored-by: Igor-Mikhail-Valentin Glebov <iglebov@albany.edu>
Diffstat (limited to 'Utilities')
-rw-r--r-- | Utilities/ClangTidyModule/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Utilities/ClangTidyModule/Module.cxx | 3 | ||||
-rw-r--r-- | Utilities/ClangTidyModule/UseCmsysFstreamCheck.cxx | 101 | ||||
-rw-r--r-- | Utilities/ClangTidyModule/UseCmsysFstreamCheck.h | 24 |
4 files changed, 130 insertions, 0 deletions
diff --git a/Utilities/ClangTidyModule/CMakeLists.txt b/Utilities/ClangTidyModule/CMakeLists.txt index 6be13d6..51603aa 100644 --- a/Utilities/ClangTidyModule/CMakeLists.txt +++ b/Utilities/ClangTidyModule/CMakeLists.txt @@ -16,6 +16,8 @@ add_library(cmake-clang-tidy-module MODULE UseCmstrlenCheck.cxx UseCmstrlenCheck.h + UseCmsysFstreamCheck.cxx + UseCmsysFstreamCheck.h ) target_include_directories(cmake-clang-tidy-module PRIVATE ${CLANG_INCLUDE_DIRS}) target_link_libraries(cmake-clang-tidy-module PRIVATE clang-tidy) diff --git a/Utilities/ClangTidyModule/Module.cxx b/Utilities/ClangTidyModule/Module.cxx index a35c336..a9d344f 100644 --- a/Utilities/ClangTidyModule/Module.cxx +++ b/Utilities/ClangTidyModule/Module.cxx @@ -4,6 +4,7 @@ #include <clang-tidy/ClangTidyModuleRegistry.h> #include "UseCmstrlenCheck.h" +#include "UseCmsysFstreamCheck.h" namespace clang { namespace tidy { @@ -14,6 +15,8 @@ public: void addCheckFactories(ClangTidyCheckFactories& CheckFactories) override { CheckFactories.registerCheck<UseCmstrlenCheck>("cmake-use-cmstrlen"); + CheckFactories.registerCheck<UseCmsysFstreamCheck>( + "cmake-use-cmsys-fstream"); } }; diff --git a/Utilities/ClangTidyModule/UseCmsysFstreamCheck.cxx b/Utilities/ClangTidyModule/UseCmsysFstreamCheck.cxx new file mode 100644 index 0000000..95a0a4d --- /dev/null +++ b/Utilities/ClangTidyModule/UseCmsysFstreamCheck.cxx @@ -0,0 +1,101 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "UseCmsysFstreamCheck.h" + +#include <clang/ASTMatchers/ASTMatchFinder.h> + +namespace clang { +namespace tidy { +namespace cmake { +using namespace ast_matchers; + +UseCmsysFstreamCheck::UseCmsysFstreamCheck(StringRef Name, + ClangTidyContext* Context) + : ClangTidyCheck(Name, Context) +{ +} + +void UseCmsysFstreamCheck::registerMatchers(MatchFinder* Finder) +{ + this->createMatcher("::std::basic_ifstream", "::cmsys::ifstream", Finder, + "ifstream"); + this->createMatcher("::std::basic_ofstream", "::cmsys::ofstream", Finder, + "ofstream"); + this->createMatcher("::std::basic_fstream", "::cmsys::fstream", Finder, + "fstream"); +} + +void UseCmsysFstreamCheck::check(const MatchFinder::MatchResult& Result) +{ + const TypeLoc* ParentTypeNode = + Result.Nodes.getNodeAs<TypeLoc>("parentType"); + const NestedNameSpecifierLoc* ParentNameNode = + Result.Nodes.getNodeAs<NestedNameSpecifierLoc>("parentName"); + const TypeLoc* RootNode = nullptr; + StringRef BindName; + StringRef Warning; + + if ((RootNode = Result.Nodes.getNodeAs<TypeLoc>("ifstream")) != nullptr) { + BindName = "cmsys::ifstream"; + Warning = "use cmsys::ifstream"; + } else if ((RootNode = Result.Nodes.getNodeAs<TypeLoc>("ofstream")) != + nullptr) { + BindName = "cmsys::ofstream"; + Warning = "use cmsys::ofstream"; + } else if ((RootNode = Result.Nodes.getNodeAs<TypeLoc>("fstream")) != + nullptr) { + BindName = "cmsys::fstream"; + Warning = "use cmsys::fstream"; + } + + if (ParentTypeNode != nullptr) { + if (ParentTypeNode->getBeginLoc().isValid()) { + this->diag(ParentTypeNode->getBeginLoc(), Warning) + << FixItHint::CreateReplacement(ParentTypeNode->getSourceRange(), + BindName); + } + } else if (ParentNameNode != nullptr) { + if (ParentNameNode->getBeginLoc().isValid()) { + this->diag(ParentNameNode->getBeginLoc(), Warning) + << FixItHint::CreateReplacement( + SourceRange(ParentNameNode->getBeginLoc(), RootNode->getEndLoc()), + BindName); + } + } else if (RootNode != nullptr) { + if (RootNode->getBeginLoc().isValid()) { + this->diag(RootNode->getBeginLoc(), Warning) + << FixItHint::CreateReplacement(RootNode->getSourceRange(), BindName); + } + } +} + +void UseCmsysFstreamCheck::createMatcher(StringRef StdName, + StringRef CmsysName, + ast_matchers::MatchFinder* Finder, + StringRef Bind) +{ + TypeLocMatcher IsStd = loc(qualType(hasUnqualifiedDesugaredType( + recordType(hasDeclaration(classTemplateSpecializationDecl( + hasName(StdName), + hasTemplateArgument( + 0, templateArgument(refersToType(asString("char")))))))))); + + // TODO This only checks to see if the type directly refers to + // cmsys::fstream. There are some corner cases involving template parameters + // that refer to cmsys::fstream that are missed by this matcher, resulting in + // a false positive. Figure out how to find these indirect references to + // cmsys::fstream and filter them out. In the meantime, such false positives + // can be silenced with NOLINT(cmake-use-cmsys-fstream). + TypeLocMatcher IsCmsys = + loc(usingType(throughUsingDecl(namedDecl(hasName(CmsysName))))); + + Finder->addMatcher( + typeLoc(IsStd, unless(IsCmsys), unless(elaboratedTypeLoc()), + optionally(hasParent(elaboratedTypeLoc().bind("parentType"))), + optionally(hasParent(nestedNameSpecifierLoc().bind("parentName")))) + .bind(Bind), + this); +} +} +} +} diff --git a/Utilities/ClangTidyModule/UseCmsysFstreamCheck.h b/Utilities/ClangTidyModule/UseCmsysFstreamCheck.h new file mode 100644 index 0000000..782123c --- /dev/null +++ b/Utilities/ClangTidyModule/UseCmsysFstreamCheck.h @@ -0,0 +1,24 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include <clang-tidy/ClangTidyCheck.h> +#include <clang/ASTMatchers/ASTMatchFinder.h> + +namespace clang { +namespace tidy { +namespace cmake { +class UseCmsysFstreamCheck : public ClangTidyCheck +{ +public: + UseCmsysFstreamCheck(StringRef Name, ClangTidyContext* Context); + void registerMatchers(ast_matchers::MatchFinder* Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult& Result) override; + +private: + void createMatcher(StringRef name, StringRef CmsysName, + ast_matchers::MatchFinder* Finder, StringRef bind); +}; +} +} +} |