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
9#include "DeprecatedIosBaseAliasesCheck.h"
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(S: "io_state", Value: "iostate")
26 .Case(S: "open_mode", Value: "openmode")
27 .Case(S: "seek_dir", Value: "seekdir")
28 .Default(Value: std::nullopt);
29}
30
31void DeprecatedIosBaseAliasesCheck::registerMatchers(MatchFinder *Finder) {
32 auto IoStateDecl = typedefDecl(hasAnyName(DeprecatedTypes)).bind(ID: "TypeDecl");
33 auto IoStateType =
34 qualType(hasDeclaration(InnerMatcher: IoStateDecl), unless(elaboratedType()));
35
36 Finder->addMatcher(NodeMatch: typeLoc(loc(InnerMatcher: IoStateType)).bind(ID: "TypeLoc"), Action: this);
37}
38
39void DeprecatedIosBaseAliasesCheck::check(
40 const MatchFinder::MatchResult &Result) {
41 SourceManager &SM = *Result.SourceManager;
42
43 const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>(ID: "TypeDecl");
44 StringRef TypeName = Typedef->getName();
45 auto Replacement = getReplacementType(Type: TypeName);
46
47 const auto *TL = Result.Nodes.getNodeAs<TypeLoc>(ID: "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(Loc: IoStateLoc);
55 Fix = false;
56 }
57
58 SourceLocation EndLoc = IoStateLoc.getLocWithOffset(Offset: TypeName.size() - 1);
59
60 if (Replacement) {
61 const char *FixName = *Replacement;
62 auto Builder = diag(Loc: IoStateLoc, Description: "'std::ios_base::%0' is deprecated; use "
63 "'std::ios_base::%1' instead")
64 << TypeName << FixName;
65
66 if (Fix)
67 Builder << FixItHint::CreateReplacement(RemoveRange: SourceRange(IoStateLoc, EndLoc),
68 Code: FixName);
69 } else
70 diag(Loc: IoStateLoc, Description: "'std::ios_base::%0' is deprecated") << TypeName;
71}
72
73} // namespace clang::tidy::modernize
74

source code of clang-tools-extra/clang-tidy/modernize/DeprecatedIosBaseAliasesCheck.cpp