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

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