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 }