File indexing completed on 2024-05-19 05:41:40

0001 /*
0002     SPDX-FileCopyrightText: 2015 Sergio Martins <smartins@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "rule-of-two-soft.h"
0008 
0009 #include <clang/AST/Decl.h>
0010 #include <clang/AST/DeclCXX.h>
0011 #include <clang/AST/ExprCXX.h>
0012 #include <clang/AST/Stmt.h>
0013 #include <clang/Basic/LLVM.h>
0014 #include <llvm/Support/Casting.h>
0015 
0016 class ClazyContext;
0017 
0018 using namespace clang;
0019 
0020 RuleOfTwoSoft::RuleOfTwoSoft(const std::string &name, ClazyContext *context)
0021     : RuleOfBase(name, context)
0022 {
0023 }
0024 
0025 void RuleOfTwoSoft::VisitStmt(Stmt *s)
0026 {
0027     if (auto *op = dyn_cast<CXXOperatorCallExpr>(s)) {
0028         FunctionDecl *func = op->getDirectCallee();
0029         auto *method = func ? dyn_cast<CXXMethodDecl>(func) : nullptr;
0030         if (method && method->getParent() && method->isCopyAssignmentOperator()) {
0031             CXXRecordDecl *record = method->getParent();
0032             const bool hasCopyCtor = record->hasNonTrivialCopyConstructor();
0033             const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment() || method->isExplicitlyDefaulted();
0034 
0035             if (hasCopyCtor && !hasCopyAssignOp && !isBlacklisted(record)) {
0036                 std::string msg = "Using assign operator but class " + record->getQualifiedNameAsString() + " has copy-ctor but no assign operator";
0037                 emitWarning(s->getBeginLoc(), msg);
0038             }
0039         }
0040     } else if (auto *ctorExpr = dyn_cast<CXXConstructExpr>(s)) {
0041         CXXConstructorDecl *ctorDecl = ctorExpr->getConstructor();
0042         CXXRecordDecl *record = ctorDecl->getParent();
0043         if (ctorDecl->isCopyConstructor() && record) {
0044             const bool hasCopyCtor = record->hasNonTrivialCopyConstructor() || ctorDecl->isExplicitlyDefaulted();
0045             const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment();
0046             if (!hasCopyCtor && hasCopyAssignOp && !isBlacklisted(record)) {
0047                 std::string msg =
0048                     "Using copy-ctor but class " + record->getQualifiedNameAsString() + " has a trivial copy-ctor but non trivial assign operator";
0049                 emitWarning(s->getBeginLoc(), msg);
0050             }
0051         }
0052     }
0053 }