diff --git a/CheckSources.cmake b/CheckSources.cmake --- a/CheckSources.cmake +++ b/CheckSources.cmake @@ -79,6 +79,7 @@ ${CMAKE_CURRENT_LIST_DIR}/src/checks/level2/rule-of-three.cpp ${CMAKE_CURRENT_LIST_DIR}/src/checks/level2/static-pmf.cpp ${CMAKE_CURRENT_LIST_DIR}/src/checks/level2/virtual-call-ctor.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/checks/level2/obsolete-qvariant-functions.cpp ) if(HAS_STD_REGEX OR CLAZY_BUILD_WITH_CLANG) diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -301,6 +301,7 @@ - [rule-of-three](docs/checks/README-rule-of-three.md) - [static-pmf](docs/checks/README-static-pmf.md) - [virtual-call-ctor](docs/checks/README-virtual-call-ctor.md) + - [obsolete-qvariant-functions](docs/checks/README-obsolete-qvariant-functions.md) # Selecting which checks to enable diff --git a/docs/checks/README-obsolete-qvariant-functions.md b/docs/checks/README-obsolete-qvariant-functions.md new file mode 100644 --- /dev/null +++ b/docs/checks/README-obsolete-qvariant-functions.md @@ -0,0 +1,3 @@ +# obsolete-qvariant-functions + +Warns when you're using obsolete functions that deal with QVariants and suggests proper replacements. diff --git a/src/Checks.h b/src/Checks.h --- a/src/Checks.h +++ b/src/Checks.h @@ -107,6 +107,7 @@ #include "checks/level2/rule-of-three.h" #include "checks/level2/static-pmf.h" #include "checks/level2/virtual-call-ctor.h" +#include "checks/level2/obsolete-qvariant-functions.h" template RegisteredCheck check(const char *name, CheckLevel level, RegisteredCheck::Options options = RegisteredCheck::Option_None) @@ -214,4 +215,5 @@ registerCheck(check("rule-of-three", CheckLevel2, RegisteredCheck::Option_VisitsDecls)); registerCheck(check("static-pmf", CheckLevel2, RegisteredCheck::Option_VisitsDecls)); registerCheck(check("virtual-call-ctor", CheckLevel2, RegisteredCheck::Option_VisitsDecls)); + registerCheck(check("obsolete-qvariant-functions", CheckLevel2, RegisteredCheck::Option_VisitsStmts)); } diff --git a/src/checks/level2/obsolete-qvariant-functions.h b/src/checks/level2/obsolete-qvariant-functions.h new file mode 100644 --- /dev/null +++ b/src/checks/level2/obsolete-qvariant-functions.h @@ -0,0 +1,46 @@ +/* + This file is part of the clazy static checker. + + Copyright (C) 2019 Nicolas Fella + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef CLAZY_OBSOLETE_QVARIANT_FUNCTIONS_H +#define CLAZY_OBSOLETE_QVARIANT_FUNCTIONS_H + +#include "checkbase.h" + +#include + +class ClazyContext; +namespace clang { +class Stmt; +} // namespace clang + +/** + * See README-obsolete-qvariant-functions for more info. + */ +class ObsoleteQVariantFunctions + : public CheckBase +{ +public: + explicit ObsoleteQVariantFunctions(const std::string &name, ClazyContext *context); +private: + void VisitStmt(clang::Stmt *stm) override; +}; + +#endif diff --git a/src/checks/level2/obsolete-qvariant-functions.cpp b/src/checks/level2/obsolete-qvariant-functions.cpp new file mode 100644 --- /dev/null +++ b/src/checks/level2/obsolete-qvariant-functions.cpp @@ -0,0 +1,59 @@ +/* + This file is part of the clazy static checker. + + Copyright (C) 2019 Nicolas Fella + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "obsolete-qvariant-functions.h" +#include "ClazyContext.h" +#include "StringUtils.h" +#include + +using namespace std; +using namespace clang; + +ObsoleteQVariantFunctions::ObsoleteQVariantFunctions(const std::string &name, ClazyContext *context) + : CheckBase(name, context) +{ +} + +void ObsoleteQVariantFunctions::VisitStmt(clang::Stmt *stm) +{ + auto callExpr = dyn_cast(stm); + if (!callExpr) + return; + + FunctionDecl *funDecl = callExpr->getDirectCallee(); + + if (!funDecl) + return; + + if (clazy::name(funDecl) == "qVariantFromValue") { + std::string error = std::string("qVariantFromValue() is obsolete. Use QVariant::fromValue() instead"); + emitWarning(clazy::getLocStart(stm), error.c_str()); + } else if (clazy::name(funDecl) == "qVariantCanConvert") { + std::string error = std::string("qVariantCanConvert() is obsolete. Use QVariant::canConvert() instead"); + emitWarning(clazy::getLocStart(stm), error.c_str()); + } else if (clazy::name(funDecl) == "qVariantSetValue") { + std::string error = std::string("qVariantSetValue() is obsolete. Use QVariant::setValue() instead"); + emitWarning(clazy::getLocStart(stm), error.c_str()); + } else if (clazy::name(funDecl) == "qVariantValue") { + std::string error = std::string("qVariantValue() is obsolete. Use QVariant::value() instead"); + emitWarning(clazy::getLocStart(stm), error.c_str()); + } +} diff --git a/tests/obsolete-qvariant-functions/config.json b/tests/obsolete-qvariant-functions/config.json new file mode 100644 --- /dev/null +++ b/tests/obsolete-qvariant-functions/config.json @@ -0,0 +1,9 @@ +{ + "minimum_clang_version" : 370, + "minimum_qt_version" : 50500, + "tests" : [ + { + "filename" : "main.cpp" + } + ] +} diff --git a/tests/obsolete-qvariant-functions/main.cpp b/tests/obsolete-qvariant-functions/main.cpp new file mode 100644 --- /dev/null +++ b/tests/obsolete-qvariant-functions/main.cpp @@ -0,0 +1,11 @@ +#include + +void fun() { + QVariant v = qVariantFromValue(5); + + if (qVariantCanConvert(v)) { + qVariantSetValue(v, 6); + } + + int foo = qVariantValue(v); +} diff --git a/tests/obsolete-qvariant-functions/main.cpp.expected b/tests/obsolete-qvariant-functions/main.cpp.expected new file mode 100644 --- /dev/null +++ b/tests/obsolete-qvariant-functions/main.cpp.expected @@ -0,0 +1,4 @@ +obsolete-qvariant-functions/main.cpp:4:18: warning: qVariantFromValue() is obsolete. Use QVariant::fromValue() instead [-Wclazy-obsolete-qvariant-functions] +obsolete-qvariant-functions/main.cpp:6:9: warning: qVariantCanConvert() is obsolete. Use QVariant::canConvert() instead [-Wclazy-obsolete-qvariant-functions] +obsolete-qvariant-functions/main.cpp:7:9: warning: qVariantSetValue() is obsolete. Use QVariant::setValue() instead [-Wclazy-obsolete-qvariant-functions] +obsolete-qvariant-functions/main.cpp:10:15: warning: qVariantValue() is obsolete. Use QVariant::value() instead [-Wclazy-obsolete-qvariant-functions]