DeprecatedIosBaseAliasesCheck.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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. #include "DeprecatedIosBaseAliasesCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/ASTMatchers/ASTMatchFinder.h"
  11. #include <optional>
  12. using namespace clang::ast_matchers;
  13. namespace clang::tidy::modernize {
  14. static constexpr std::array<StringRef, 5> DeprecatedTypes = {
  15. "::std::ios_base::io_state", "::std::ios_base::open_mode",
  16. "::std::ios_base::seek_dir", "::std::ios_base::streamoff",
  17. "::std::ios_base::streampos"};
  18. static std::optional<const char *> getReplacementType(StringRef Type) {
  19. return llvm::StringSwitch<std::optional<const char *>>(Type)
  20. .Case("io_state", "iostate")
  21. .Case("open_mode", "openmode")
  22. .Case("seek_dir", "seekdir")
  23. .Default(std::nullopt);
  24. }
  25. void DeprecatedIosBaseAliasesCheck::registerMatchers(MatchFinder *Finder) {
  26. auto IoStateDecl = typedefDecl(hasAnyName(DeprecatedTypes)).bind("TypeDecl");
  27. auto IoStateType =
  28. qualType(hasDeclaration(IoStateDecl), unless(elaboratedType()));
  29. Finder->addMatcher(typeLoc(loc(IoStateType)).bind("TypeLoc"), this);
  30. }
  31. void DeprecatedIosBaseAliasesCheck::check(
  32. const MatchFinder::MatchResult &Result) {
  33. SourceManager &SM = *Result.SourceManager;
  34. const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("TypeDecl");
  35. StringRef TypeName = Typedef->getName();
  36. auto Replacement = getReplacementType(TypeName);
  37. const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("TypeLoc");
  38. SourceLocation IoStateLoc = TL->getBeginLoc();
  39. // Do not generate fixits for matches depending on template arguments and
  40. // macro expansions.
  41. bool Fix = Replacement && !TL->getType()->isDependentType();
  42. if (IoStateLoc.isMacroID()) {
  43. IoStateLoc = SM.getSpellingLoc(IoStateLoc);
  44. Fix = false;
  45. }
  46. SourceLocation EndLoc = IoStateLoc.getLocWithOffset(TypeName.size() - 1);
  47. if (Replacement) {
  48. const char *FixName = *Replacement;
  49. auto Builder = diag(IoStateLoc, "'std::ios_base::%0' is deprecated; use "
  50. "'std::ios_base::%1' instead")
  51. << TypeName << FixName;
  52. if (Fix)
  53. Builder << FixItHint::CreateReplacement(SourceRange(IoStateLoc, EndLoc),
  54. FixName);
  55. } else
  56. diag(IoStateLoc, "'std::ios_base::%0' is deprecated") << TypeName;
  57. }
  58. } // namespace clang::tidy::modernize