10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
13 #include "clang/Tooling/FixIt.h"
19 namespace performance {
21 void NoexceptMoveConstructorCheck::registerMatchers(MatchFinder *Finder) {
23 cxxMethodDecl(anyOf(cxxConstructorDecl(), hasOverloadedOperatorName(
"=")),
24 unless(isImplicit()), unless(isDeleted()))
29 void NoexceptMoveConstructorCheck::check(
30 const MatchFinder::MatchResult &Result) {
31 if (
const auto *
Decl = Result.Nodes.getNodeAs<CXXMethodDecl>(
"decl")) {
32 StringRef MethodType =
"assignment operator";
33 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(
Decl)) {
34 if (!Ctor->isMoveConstructor())
36 MethodType =
"constructor";
37 }
else if (!
Decl->isMoveAssignmentOperator()) {
41 const auto *ProtoType =
Decl->getType()->getAs<FunctionProtoType>();
43 if (isUnresolvedExceptionSpec(ProtoType->getExceptionSpecType()))
46 if (!isNoexceptExceptionSpec(ProtoType->getExceptionSpecType())) {
48 diag(
Decl->getLocation(),
"move %0s should be marked noexcept")
51 SourceManager &SM = *Result.SourceManager;
52 assert(
Decl->getNumParams() > 0);
53 SourceLocation NoexceptLoc =
Decl->getParamDecl(
Decl->getNumParams() - 1)
56 if (NoexceptLoc.isValid())
57 NoexceptLoc = Lexer::findLocationAfterToken(
58 NoexceptLoc, tok::r_paren, SM, Result.Context->getLangOpts(),
true);
59 if (NoexceptLoc.isValid())
60 Diag << FixItHint::CreateInsertion(NoexceptLoc,
" noexcept ");
66 if (ProtoType->canThrow() == CT_Can) {
67 Expr *
E = ProtoType->getNoexceptExpr();
68 E =
E->IgnoreImplicit();
69 if (!isa<CXXBoolLiteralExpr>(
E)) {
71 "noexcept specifier on the move %0 evaluates to 'false'")