clang-tools 22.0.0git
DeprecatedIosBaseAliasesCheck.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
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
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
38 const MatchFinder::MatchResult &Result) {
39 SourceManager &SM = *Result.SourceManager;
40
41 const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("TypeDecl");
42 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 and
51 // macro expansions.
52 bool Fix = Replacement && !TL.getType()->isDependentType();
53 if (IoStateLoc.isMacroID()) {
54 IoStateLoc = SM.getSpellingLoc(IoStateLoc);
55 Fix = false;
56 }
57
58 SourceLocation EndLoc = IoStateLoc.getLocWithOffset(TypeName.size() - 1);
59
60 if (Replacement) {
61 const char *FixName = *Replacement;
62 auto Builder = diag(IoStateLoc, "'std::ios_base::%0' is deprecated; use "
63 "'std::ios_base::%1' instead")
64 << TypeName << FixName;
65
66 if (Fix)
67 Builder << FixItHint::CreateReplacement(SourceRange(IoStateLoc, EndLoc),
68 FixName);
69 } else
70 diag(IoStateLoc, "'std::ios_base::%0' is deprecated") << TypeName;
71}
72
73} // namespace clang::tidy::modernize
static cl::opt< bool > Fix("fix", desc(R"( Apply suggested fixes. Without -fix-errors clang-tidy will bail out if any compilation errors were found. )"), cl::init(false), cl::cat(ClangTidyCategory))
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
static std::optional< const char * > getReplacementType(StringRef Type)
static constexpr std::array< StringRef, 5 > DeprecatedTypes