10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
18 if (Node.needsOverloadResolutionForCopyConstructor() &&
19 Node.needsImplicitCopyConstructor()) {
21 for (
const CXXBaseSpecifier &BS : Node.bases()) {
22 const CXXRecordDecl *BRD = BS.getType()->getAsCXXRecordDecl();
27 if (Node.hasSimpleCopyConstructor())
29 for (
const CXXConstructorDecl *Ctor : Node.ctors())
30 if (Ctor->isCopyConstructor())
31 return !Ctor->isDeleted();
36 if (Node.needsOverloadResolutionForMoveConstructor() &&
37 Node.needsImplicitMoveConstructor()) {
39 for (
const CXXBaseSpecifier &BS : Node.bases()) {
40 const CXXRecordDecl *BRD = BS.getType()->getAsCXXRecordDecl();
45 if (Node.hasSimpleMoveConstructor())
47 for (
const CXXConstructorDecl *Ctor : Node.ctors())
48 if (Ctor->isMoveConstructor())
49 return !Ctor->isDeleted();
54 if (Node.needsOverloadResolutionForCopyAssignment() &&
55 Node.needsImplicitCopyAssignment()) {
57 for (
const CXXBaseSpecifier &BS : Node.bases()) {
58 const CXXRecordDecl *BRD = BS.getType()->getAsCXXRecordDecl();
63 if (Node.hasSimpleCopyAssignment())
65 for (
const CXXMethodDecl *Method : Node.methods())
66 if (Method->isCopyAssignmentOperator())
67 return !Method->isDeleted();
72 if (Node.needsOverloadResolutionForMoveAssignment() &&
73 Node.needsImplicitMoveAssignment()) {
75 for (
const CXXBaseSpecifier &BS : Node.bases()) {
76 const CXXRecordDecl *BRD = BS.getType()->getAsCXXRecordDecl();
81 if (Node.hasSimpleMoveAssignment())
83 for (
const CXXMethodDecl *Method : Node.methods())
84 if (Method->isMoveAssignmentOperator())
85 return !Method->isDeleted();
91AST_MATCHER(FieldDecl, isMemberOfLambda) {
92 return Node.getParent()->isLambda();
95AST_MATCHER(CXXRecordDecl, isCopyableOrMovable) {
105 unless(isMemberOfLambda()),
107 fieldDecl(hasType(hasCanonicalType(referenceType()))).bind(
"ref"),
108 fieldDecl(hasType(qualType(isConstQualified()))).bind(
"const")),
109 hasDeclContext(cxxRecordDecl(isCopyableOrMovable()))),
114 const MatchFinder::MatchResult &Result) {
115 if (
const auto *MatchedDecl = Result.Nodes.getNodeAs<FieldDecl>(
"ref"))
116 diag(MatchedDecl->getLocation(),
"member %0 of type %1 is a reference")
117 << MatchedDecl << MatchedDecl->getType();
118 if (
const auto *MatchedDecl = Result.Nodes.getNodeAs<FieldDecl>(
"const"))
119 diag(MatchedDecl->getLocation(),
"member %0 of type %1 is const qualified")
120 << MatchedDecl << MatchedDecl->getType();
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
static bool isMoveAssignable(const CXXRecordDecl &Node)
static bool isMoveConstructible(const CXXRecordDecl &Node)
static bool isCopyConstructible(const CXXRecordDecl &Node)
static bool isCopyAssignable(const CXXRecordDecl &Node)