UseEqualsDeleteCheck.cpp 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. //===--- UseEqualsDeleteCheck.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 "UseEqualsDeleteCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/ASTMatchers/ASTMatchFinder.h"
  11. #include "clang/Lex/Lexer.h"
  12. using namespace clang::ast_matchers;
  13. namespace clang::tidy::modernize {
  14. static const char SpecialFunction[] = "SpecialFunction";
  15. static const char DeletedNotPublic[] = "DeletedNotPublic";
  16. void UseEqualsDeleteCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  17. Options.store(Opts, "IgnoreMacros", IgnoreMacros);
  18. }
  19. void UseEqualsDeleteCheck::registerMatchers(MatchFinder *Finder) {
  20. auto PrivateSpecialFn = cxxMethodDecl(
  21. isPrivate(),
  22. anyOf(cxxConstructorDecl(anyOf(isDefaultConstructor(),
  23. isCopyConstructor(), isMoveConstructor())),
  24. cxxMethodDecl(
  25. anyOf(isCopyAssignmentOperator(), isMoveAssignmentOperator())),
  26. cxxDestructorDecl()));
  27. Finder->addMatcher(
  28. cxxMethodDecl(
  29. PrivateSpecialFn,
  30. unless(anyOf(hasAnyBody(stmt()), isDefaulted(), isDeleted(),
  31. ast_matchers::isTemplateInstantiation(),
  32. // Ensure that all methods except private special member
  33. // functions are defined.
  34. hasParent(cxxRecordDecl(hasMethod(unless(
  35. anyOf(PrivateSpecialFn, hasAnyBody(stmt()), isPure(),
  36. isDefaulted(), isDeleted()))))))))
  37. .bind(SpecialFunction),
  38. this);
  39. Finder->addMatcher(
  40. cxxMethodDecl(isDeleted(), unless(isPublic())).bind(DeletedNotPublic),
  41. this);
  42. }
  43. void UseEqualsDeleteCheck::check(const MatchFinder::MatchResult &Result) {
  44. if (const auto *Func =
  45. Result.Nodes.getNodeAs<CXXMethodDecl>(SpecialFunction)) {
  46. SourceLocation EndLoc = Lexer::getLocForEndOfToken(
  47. Func->getEndLoc(), 0, *Result.SourceManager, getLangOpts());
  48. if (Func->getLocation().isMacroID() && IgnoreMacros)
  49. return;
  50. // FIXME: Improve FixItHint to make the method public.
  51. diag(Func->getLocation(),
  52. "use '= delete' to prohibit calling of a special member function")
  53. << FixItHint::CreateInsertion(EndLoc, " = delete");
  54. } else if (const auto *Func =
  55. Result.Nodes.getNodeAs<CXXMethodDecl>(DeletedNotPublic)) {
  56. // Ignore this warning in macros, since it's extremely noisy in code using
  57. // DISALLOW_COPY_AND_ASSIGN-style macros and there's no easy way to
  58. // automatically fix the warning when macros are in play.
  59. if (Func->getLocation().isMacroID() && IgnoreMacros)
  60. return;
  61. // FIXME: Add FixItHint to make the method public.
  62. diag(Func->getLocation(), "deleted member function should be public");
  63. }
  64. }
  65. } // namespace clang::tidy::modernize