75 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DeprecatedIosBaseAliasesCheck.h"10#include "clang/ASTMatchers/ASTMatchFinder.h"11#include <optional>12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::modernize {16 17static constexpr std::array<StringRef, 5> DeprecatedTypes = {18 "::std::ios_base::io_state", "::std::ios_base::open_mode",19 "::std::ios_base::seek_dir", "::std::ios_base::streamoff",20 "::std::ios_base::streampos"};21 22static std::optional<const char *> getReplacementType(StringRef Type) {23 return llvm::StringSwitch<std::optional<const char *>>(Type)24 .Case("io_state", "iostate")25 .Case("open_mode", "openmode")26 .Case("seek_dir", "seekdir")27 .Default(std::nullopt);28}29 30void DeprecatedIosBaseAliasesCheck::registerMatchers(MatchFinder *Finder) {31 auto IoStateDecl = typedefDecl(hasAnyName(DeprecatedTypes)).bind("TypeDecl");32 auto IoStateType = typedefType(hasDeclaration(IoStateDecl));33 34 Finder->addMatcher(typeLoc(loc(IoStateType)).bind("TypeLoc"), this);35}36 37void DeprecatedIosBaseAliasesCheck::check(38 const MatchFinder::MatchResult &Result) {39 const SourceManager &SM = *Result.SourceManager;40 41 const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("TypeDecl");42 const StringRef TypeName = Typedef->getName();43 auto Replacement = getReplacementType(TypeName);44 45 TypeLoc TL = *Result.Nodes.getNodeAs<TypeLoc>("TypeLoc");46 if (auto QTL = TL.getAs<QualifiedTypeLoc>())47 TL = QTL.getUnqualifiedLoc();48 49 SourceLocation IoStateLoc = TL.castAs<TypedefTypeLoc>().getNameLoc();50 // Do not generate fixits for matches depending on template arguments and51 // macro expansions.52 bool Fix = Replacement && !TL.getType()->isDependentType();53 if (IoStateLoc.isMacroID()) {54 IoStateLoc = SM.getSpellingLoc(IoStateLoc);55 Fix = false;56 }57 58 const SourceLocation EndLoc =59 IoStateLoc.getLocWithOffset(TypeName.size() - 1);60 61 if (Replacement) {62 const char *FixName = *Replacement;63 auto Builder = diag(IoStateLoc, "'std::ios_base::%0' is deprecated; use "64 "'std::ios_base::%1' instead")65 << TypeName << FixName;66 67 if (Fix)68 Builder << FixItHint::CreateReplacement(SourceRange(IoStateLoc, EndLoc),69 FixName);70 } else71 diag(IoStateLoc, "'std::ios_base::%0' is deprecated") << TypeName;72}73 74} // namespace clang::tidy::modernize75