clang-tools 17.0.0git
DeprecatedIosBaseAliasesCheck.cpp
Go to the documentation of this file.
1//===--- DeprecatedIosBaseAliasesCheck.cpp - clang-tidy--------------------===//
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/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include <optional>
13
14using namespace clang::ast_matchers;
15
16namespace clang::tidy::modernize {
17
18static constexpr std::array<StringRef, 5> DeprecatedTypes = {
19 "::std::ios_base::io_state", "::std::ios_base::open_mode",
20 "::std::ios_base::seek_dir", "::std::ios_base::streamoff",
21 "::std::ios_base::streampos"};
22
23static std::optional<const char *> getReplacementType(StringRef Type) {
24 return llvm::StringSwitch<std::optional<const char *>>(Type)
25 .Case("io_state", "iostate")
26 .Case("open_mode", "openmode")
27 .Case("seek_dir", "seekdir")
28 .Default(std::nullopt);
29}
30
32 auto IoStateDecl = typedefDecl(hasAnyName(DeprecatedTypes)).bind("TypeDecl");
33 auto IoStateType =
34 qualType(hasDeclaration(IoStateDecl), unless(elaboratedType()));
35
36 Finder->addMatcher(typeLoc(loc(IoStateType)).bind("TypeLoc"), this);
37}
38
40 const MatchFinder::MatchResult &Result) {
41 SourceManager &SM = *Result.SourceManager;
42
43 const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("TypeDecl");
44 StringRef TypeName = Typedef->getName();
45 auto Replacement = getReplacementType(TypeName);
46
47 const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("TypeLoc");
48 SourceLocation IoStateLoc = TL->getBeginLoc();
49
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", cl::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))
CodeCompletionBuilder Builder
NodeType Type
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
static std::optional< const char * > getReplacementType(StringRef Type)
static constexpr std::array< StringRef, 5 > DeprecatedTypes