brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.6 KiB · a19d2ec Raw
99 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "UseEqualsDeleteCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12#include "clang/Lex/Lexer.h"13 14using namespace clang::ast_matchers;15 16namespace clang::tidy::modernize {17 18namespace {19AST_MATCHER(FunctionDecl, hasAnyDefinition) {20  if (Node.hasBody() || Node.isPureVirtual() || Node.isDefaulted() ||21      Node.isDeleted())22    return true;23 24  if (const FunctionDecl *Definition = Node.getDefinition())25    if (Definition->hasBody() || Definition->isPureVirtual() ||26        Definition->isDefaulted() || Definition->isDeleted())27      return true;28 29  return false;30}31 32AST_MATCHER(Decl, isUsed) { return Node.isUsed(); }33 34AST_MATCHER(CXXMethodDecl, isSpecialFunction) {35  if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(&Node))36    return Constructor->isDefaultConstructor() ||37           Constructor->isCopyOrMoveConstructor();38 39  return isa<CXXDestructorDecl>(Node) || Node.isCopyAssignmentOperator() ||40         Node.isMoveAssignmentOperator();41}42} // namespace43 44static const char SpecialFunction[] = "SpecialFunction";45static const char DeletedNotPublic[] = "DeletedNotPublic";46 47UseEqualsDeleteCheck::UseEqualsDeleteCheck(StringRef Name,48                                           ClangTidyContext *Context)49    : ClangTidyCheck(Name, Context),50      IgnoreMacros(Options.get("IgnoreMacros", true)) {}51 52void UseEqualsDeleteCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {53  Options.store(Opts, "IgnoreMacros", IgnoreMacros);54}55 56void UseEqualsDeleteCheck::registerMatchers(MatchFinder *Finder) {57  auto PrivateSpecialFn = cxxMethodDecl(isPrivate(), isSpecialFunction());58 59  Finder->addMatcher(60      cxxMethodDecl(61          PrivateSpecialFn, unless(hasAnyDefinition()), unless(isUsed()),62          // Ensure that all methods except private special member functions are63          // defined.64          unless(ofClass(hasMethod(cxxMethodDecl(unless(PrivateSpecialFn),65                                                 unless(hasAnyDefinition()))))))66          .bind(SpecialFunction),67      this);68 69  Finder->addMatcher(70      cxxMethodDecl(isDeleted(), unless(isPublic())).bind(DeletedNotPublic),71      this);72}73 74void UseEqualsDeleteCheck::check(const MatchFinder::MatchResult &Result) {75  if (const auto *Func =76          Result.Nodes.getNodeAs<CXXMethodDecl>(SpecialFunction)) {77    const SourceLocation EndLoc = Lexer::getLocForEndOfToken(78        Func->getEndLoc(), 0, *Result.SourceManager, getLangOpts());79 80    if (IgnoreMacros && Func->getLocation().isMacroID())81      return;82    // FIXME: Improve FixItHint to make the method public.83    diag(Func->getLocation(),84         "use '= delete' to prohibit calling of a special member function")85        << FixItHint::CreateInsertion(EndLoc, " = delete");86  } else if (const auto *Func =87                 Result.Nodes.getNodeAs<CXXMethodDecl>(DeletedNotPublic)) {88    // Ignore this warning in macros, since it's extremely noisy in code using89    // DISALLOW_COPY_AND_ASSIGN-style macros and there's no easy way to90    // automatically fix the warning when macros are in play.91    if (IgnoreMacros && Func->getLocation().isMacroID())92      return;93    // FIXME: Add FixItHint to make the method public.94    diag(Func->getLocation(), "deleted member function should be public");95  }96}97 98} // namespace clang::tidy::modernize99