2016-11-11 00:46:59 +08:00
|
|
|
//===--- 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) {
|
2016-12-28 06:14:40 +08:00
|
|
|
if (!getLangOpts().CPlusPlus)
|
|
|
|
return;
|
|
|
|
|
2016-11-11 00:46:59 +08:00
|
|
|
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(),
|
2016-11-17 19:40:02 +08:00
|
|
|
ast_matchers::isTemplateInstantiation(),
|
2016-11-11 00:46:59 +08:00
|
|
|
// 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<CXXMethodDecl>(SpecialFunction)) {
|
|
|
|
SourceLocation EndLoc = Lexer::getLocForEndOfToken(
|
|
|
|
Func->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
|
|
|
|
|
|
|
|
// FIXME: Improve FixItHint to make 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<CXXMethodDecl>(DeletedNotPublic)) {
|
|
|
|
// FIXME: Add FixItHint to make method public
|
|
|
|
diag(Func->getLocation(), "deleted member function should be public");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace modernize
|
|
|
|
} // namespace tidy
|
|
|
|
} // namespace clang
|