File indexing completed on 2024-05-12 05:40:56
0001 /* 0002 SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB a KDAB Group company info@kdab.com 0003 SPDX-FileContributor: Sérgio Martins <sergio.martins@kdab.com> 0004 0005 SPDX-FileCopyrightText: 2015 Sergio Martins <smartins@kde.org> 0006 SPDX-FileCopyrightText: 2024 Alexander Lohnau <alexander.lohnau@gmx.de> 0007 0008 SPDX-License-Identifier: LGPL-2.0-or-later 0009 */ 0010 0011 #include "qdatetime-utc.h" 0012 #include "FixItUtils.h" 0013 #include "Utils.h" 0014 0015 #include <clang/AST/Decl.h> 0016 #include <clang/AST/DeclCXX.h> 0017 #include <clang/AST/Expr.h> 0018 #include <clang/AST/ExprCXX.h> 0019 #include <clang/AST/Stmt.h> 0020 #include <clang/Basic/Diagnostic.h> 0021 #include <clang/Basic/LLVM.h> 0022 #include <llvm/Support/Casting.h> 0023 0024 #include <vector> 0025 0026 class ClazyContext; 0027 0028 using namespace clang; 0029 0030 QDateTimeUtc::QDateTimeUtc(const std::string &name, ClazyContext *context) 0031 : CheckBase(name, context) 0032 { 0033 } 0034 0035 void QDateTimeUtc::VisitStmt(clang::Stmt *stmt) 0036 { 0037 auto *secondCall = dyn_cast<CXXMemberCallExpr>(stmt); 0038 if (!secondCall || !secondCall->getMethodDecl()) { 0039 return; 0040 } 0041 CXXMethodDecl *secondMethod = secondCall->getMethodDecl(); 0042 const std::string secondMethodName = secondMethod->getQualifiedNameAsString(); 0043 const bool isMSecSinceEpoc = secondMethodName == "QDateTime::toMSecsSinceEpoch"; 0044 const bool isSecSinceEpoc = secondMethodName == "QDateTime::toSecsSinceEpoch" || secondMethodName == "QDateTime::toTime_t"; 0045 const bool isToUtcConversion = secondMethodName == "QDateTime::toUTC"; 0046 if (!isMSecSinceEpoc && !isSecSinceEpoc && !isToUtcConversion) { 0047 return; 0048 } 0049 0050 std::vector<CallExpr *> chainedCalls = Utils::callListForChain(secondCall); 0051 if (chainedCalls.size() != 2) { 0052 return; 0053 } 0054 0055 CallExpr *firstCall = chainedCalls[chainedCalls.size() - 1]; 0056 FunctionDecl *firstFunc = firstCall->getDirectCallee(); 0057 if (!firstFunc) { 0058 return; 0059 } 0060 0061 if (auto *firstMethod = dyn_cast<CXXMethodDecl>(firstFunc); !firstMethod 0062 || (firstMethod->getQualifiedNameAsString() != "QDateTime::currentDateTime" 0063 && firstMethod->getQualifiedNameAsString() != "QDateTime::currentDateTimeUtc")) { 0064 return; 0065 } 0066 0067 std::string replacement = "::currentDateTimeUtc()"; 0068 if (isMSecSinceEpoc) { 0069 replacement = "::currentMSecsSinceEpoch()"; 0070 } else if (isSecSinceEpoc) { 0071 replacement = "::currentSecsSinceEpoch()"; 0072 } 0073 0074 std::vector<FixItHint> fixits; 0075 const bool success = clazy::transformTwoCallsIntoOneV2(&m_astContext, secondCall, replacement, fixits); 0076 if (!success) { 0077 queueManualFixitWarning(secondCall->getBeginLoc()); 0078 } 0079 0080 emitWarning(stmt->getBeginLoc(), "Use QDateTime" + replacement + " instead. It is significantly faster", fixits); 0081 }