10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/Lex/Lexer.h"
13#include "clang/Tooling/FixIt.h"
21 cxxMethodDecl(anyOf(cxxConstructorDecl(), hasOverloadedOperatorName(
"=")),
22 unless(isImplicit()), unless(isDeleted()))
28 const MatchFinder::MatchResult &Result) {
29 if (
const auto *
Decl = Result.Nodes.getNodeAs<CXXMethodDecl>(
"decl")) {
30 bool IsConstructor =
false;
31 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(
Decl)) {
32 if (!Ctor->isMoveConstructor())
35 }
else if (!
Decl->isMoveAssignmentOperator()) {
39 const auto *ProtoType =
Decl->getType()->castAs<FunctionProtoType>();
41 if (isUnresolvedExceptionSpec(ProtoType->getExceptionSpecType()))
44 if (!isNoexceptExceptionSpec(ProtoType->getExceptionSpecType())) {
45 auto Diag =
diag(
Decl->getLocation(),
46 "move %select{assignment operator|constructor}0s should "
50 SourceManager &SM = *Result.SourceManager;
51 assert(
Decl->getNumParams() > 0);
52 SourceLocation NoexceptLoc =
Decl->getParamDecl(
Decl->getNumParams() - 1)
55 if (NoexceptLoc.isValid())
56 NoexceptLoc = Lexer::findLocationAfterToken(
57 NoexceptLoc, tok::r_paren, SM, Result.Context->getLangOpts(),
true);
58 if (NoexceptLoc.isValid())
59 Diag << FixItHint::CreateInsertion(NoexceptLoc,
" noexcept ");
65 if (ProtoType->canThrow() == CT_Can) {
66 Expr *
E = ProtoType->getNoexceptExpr();
67 E =
E->IgnoreImplicit();
68 if (!isa<CXXBoolLiteralExpr>(
E)) {
70 "noexcept specifier on the move %select{assignment "
71 "operator|constructor}0 evaluates to 'false'")
const FunctionDecl * Decl
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.