123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file LICENSE.rst 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(MatchFinder::MatchResult const& Result)
- {
- TypeLoc const* ParentTypeNode =
- Result.Nodes.getNodeAs<TypeLoc>("parentType");
- NestedNameSpecifierLoc const* ParentNameNode =
- Result.Nodes.getNodeAs<NestedNameSpecifierLoc>("parentName");
- TypeLoc const* 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);
- }
- }
- }
- }
|