in src/checks/level1/rule-of-two-soft.cpp [23:51]
void RuleOfTwoSoft::VisitStmt(Stmt *s)
{
if (auto *op = dyn_cast<CXXOperatorCallExpr>(s)) {
FunctionDecl *func = op->getDirectCallee();
auto *method = func ? dyn_cast<CXXMethodDecl>(func) : nullptr;
if (method && method->getParent() && method->isCopyAssignmentOperator()) {
CXXRecordDecl *record = method->getParent();
const bool hasCopyCtor = record->hasNonTrivialCopyConstructor();
const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment() || method->isExplicitlyDefaulted();
if (hasCopyCtor && !hasCopyAssignOp && !isBlacklisted(record)) {
std::string msg = "Using assign operator but class " + record->getQualifiedNameAsString() + " has copy-ctor but no assign operator";
emitWarning(s->getBeginLoc(), msg);
}
}
} else if (auto *ctorExpr = dyn_cast<CXXConstructExpr>(s)) {
CXXConstructorDecl *ctorDecl = ctorExpr->getConstructor();
CXXRecordDecl *record = ctorDecl->getParent();
if (ctorDecl->isCopyConstructor() && record) {
const bool hasCopyCtor = record->hasNonTrivialCopyConstructor() || ctorDecl->isExplicitlyDefaulted();
const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment();
if (!hasCopyCtor && hasCopyAssignOp && !isBlacklisted(record)) {
std::string msg =
"Using copy-ctor but class " + record->getQualifiedNameAsString() + " has a trivial copy-ctor but non trivial assign operator";
emitWarning(s->getBeginLoc(), msg);
}
}
}
}