//===--- UseEqualsDeleteCheck.cpp - clang-tidy-----------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "UseEqualsDeleteCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Lex/Lexer.h" using namespace clang::ast_matchers; namespace clang { namespace tidy { namespace modernize { static const char SpecialFunction[] = "SpecialFunction"; static const char DeletedNotPublic[] = "DeletedNotPublic"; void UseEqualsDeleteCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; auto PrivateSpecialFn = cxxMethodDecl( isPrivate(), anyOf(cxxConstructorDecl(anyOf(isDefaultConstructor(), isCopyConstructor(), isMoveConstructor())), cxxMethodDecl( anyOf(isCopyAssignmentOperator(), isMoveAssignmentOperator())), cxxDestructorDecl())); Finder->addMatcher( cxxMethodDecl( PrivateSpecialFn, unless(anyOf(hasBody(stmt()), isDefaulted(), isDeleted(), ast_matchers::isTemplateInstantiation(), // Ensure that all methods except private special member // functions are defined. hasParent(cxxRecordDecl(hasMethod(unless( anyOf(PrivateSpecialFn, hasBody(stmt()), isPure(), isDefaulted(), isDeleted())))))))) .bind(SpecialFunction), this); Finder->addMatcher( cxxMethodDecl(isDeleted(), unless(isPublic())).bind(DeletedNotPublic), this); } void UseEqualsDeleteCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *Func = Result.Nodes.getNodeAs(SpecialFunction)) { SourceLocation EndLoc = Lexer::getLocForEndOfToken( Func->getLocEnd(), 0, *Result.SourceManager, getLangOpts()); // FIXME: Improve FixItHint to make the method public. diag(Func->getLocation(), "use '= delete' to prohibit calling of a special member function") << FixItHint::CreateInsertion(EndLoc, " = delete"); } else if (const auto *Func = Result.Nodes.getNodeAs(DeletedNotPublic)) { // Ignore this warning in macros, since it's extremely noisy in code using // DISALLOW_COPY_AND_ASSIGN-style macros and there's no easy way to // automatically fix the warning when macros are in play. if (Func->getLocation().isMacroID()) return; // FIXME: Add FixItHint to make the method public. diag(Func->getLocation(), "deleted member function should be public"); } } } // namespace modernize } // namespace tidy } // namespace clang