Index: clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp =================================================================== --- clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp +++ clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp @@ -24,17 +24,6 @@ namespace tidy { namespace cppcoreguidelines { -#if 0 -// FIXME Copied from NoMallocCheck!! -namespace { -Matcher hasAnyListedName(const std::string &FunctionNames) { - const std::vector NameList = - utils::options::parseStringList(FunctionNames); - return hasAnyName(std::vector(NameList.begin(), NameList.end())); -} -} // namespace -#endif - /// Match common cases, where the owner semantic is relevant, like function /// calls, delete expressions and others. void OwningMemoryCheck::registerMatchers(MatchFinder *Finder) { @@ -46,15 +35,7 @@ const auto createsOwner = anyOf(cxxNewExpr(), callExpr(callee(functionDecl( returns(qualType(hasDeclaration(ownerDecl))))))); - // FIXME Integrate custom C functions, which return values must be assigned to - // owners. -#if 0 - const auto legacyOwnerFunctions = - hasDescendant(callExpr(callee(functionDecl(hasAnyListedName( - "::malloc,::calloc,::align_malloc,::realloc,::align_realloc"))))); -#endif - const auto consideredOwner = - anyOf(isOwnerType, createsOwner /*, legacyOwnerFunctions*/); + const auto consideredOwner = anyOf(isOwnerType, createsOwner); // Find delete expressions, that delete non owners. Finder->addMatcher( @@ -146,7 +127,6 @@ } void OwningMemoryCheck::check(const MatchFinder::MatchResult &Result) { - // std::clog << "Hier" << std::endl; const auto &Nodes = Result.Nodes; // Result of delete matchers. Index: clang-tidy/modernize/CMakeLists.txt =================================================================== --- clang-tidy/modernize/CMakeLists.txt +++ clang-tidy/modernize/CMakeLists.txt @@ -9,7 +9,6 @@ MakeSharedCheck.cpp MakeUniqueCheck.cpp ModernizeTidyModule.cpp - NoMallocCheck.cpp PassByValueCheck.cpp RawStringLiteralCheck.cpp RedundantVoidArgCheck.cpp Index: clang-tidy/modernize/LoopConvertCheck.cpp =================================================================== --- clang-tidy/modernize/LoopConvertCheck.cpp +++ clang-tidy/modernize/LoopConvertCheck.cpp @@ -513,7 +513,7 @@ } /// \brief Computes the changes needed to convert a given for loop, and -/// pplies them. +/// applies them. void LoopConvertCheck::doConversion( ASTContext *Context, const VarDecl *IndexVar, const ValueDecl *MaybeContainer, const UsageResult &Usages, Index: clang-tidy/modernize/ModernizeTidyModule.cpp =================================================================== --- clang-tidy/modernize/ModernizeTidyModule.cpp +++ clang-tidy/modernize/ModernizeTidyModule.cpp @@ -15,7 +15,6 @@ #include "LoopConvertCheck.h" #include "MakeSharedCheck.h" #include "MakeUniqueCheck.h" -#include "NoMallocCheck.h" #include "PassByValueCheck.h" #include "RawStringLiteralCheck.h" #include "RedundantVoidArgCheck.h" @@ -51,8 +50,6 @@ CheckFactories.registerCheck("modernize-loop-convert"); CheckFactories.registerCheck("modernize-make-shared"); CheckFactories.registerCheck("modernize-make-unique"); - CheckFactories.registerCheck( - "modernize-no-malloc"); CheckFactories.registerCheck("modernize-pass-by-value"); CheckFactories.registerCheck( "modernize-raw-string-literal"); Index: clang-tidy/modernize/NoMallocCheck.h =================================================================== --- clang-tidy/modernize/NoMallocCheck.h +++ /dev/null @@ -1,80 +0,0 @@ -//===--- NoMallocCheck.h - clang-tidy----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_NO_MALLOC_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_NO_MALLOC_H - -#include "../ClangTidy.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" - -namespace clang { -namespace tidy { -namespace modernize { - -/// This checker is concerned with c-style memory management and tries to -/// sanitize its use. -/// For CPP, it follows cppcoreguidelines (Resource Management) and for C -/// it checks for common bugs and tries to clarify the code. -/// -/// For the user-facing documentation see: -/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-no-malloc.html /// -/// github - CPPCoreGuidelines -class NoMallocCheck : public ClangTidyCheck { -public: - NoMallocCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; - -private: - /// implements the cast check, calling malloc check with in - void handle_cast(const CStyleCastExpr *MatchedDecl); - - /// implements the malloc check and fixit hints for it - bool handle_malloc(const CallExpr *MatchedDecl, bool from_cast = false); - - /// implements the realloc check, suggests using std::vector for this variable - void handle_realloc(const CallExpr *MatchedDecl); - - /// implements the free call, suggest RAII - void handle_free(const CallExpr *MatchedDecl); - - /// Helper for malloc checking, if binaryOp in malloc, which one is the size - /// and which the count - bool determine_type_and_count(const BinaryOperator *arg, QualType &type, - bool &lhs_rhs_flag) const; - - /// handle single element and raw bytesize mallocs - bool single_or_raw(const CallExpr *malloc_call); - - /// handle malloc call with a multiplication as argument e.g. sizeof int * - /// count - bool multiplication(const CallExpr *call, const BinaryOperator *arg); - - /// just warn about a suspicious malloc argument - void suspicious_binary(const CallExpr *call); - - /// give a hint how to call malloc properly - void give_call_hint(const CallExpr *malloc_call); - - /// give notes about alternative ways to create dynamic arrays - void give_array_hint(const CallExpr *malloc_call, const std::string &t_hint, - const std::string &count_str); - - /// give deletion hint, when malloc is removed. delete/delete[] must be - /// adopted! - void give_deletion_hint(const CallExpr *malloc_call); -}; - -} // namespace modernize -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_NO_MALLOC_H Index: clang-tidy/modernize/NoMallocCheck.cpp =================================================================== --- clang-tidy/modernize/NoMallocCheck.cpp +++ /dev/null @@ -1,363 +0,0 @@ -//===--- NoMallocCheck.cpp - clang-tidy------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "NoMallocCheck.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include -#include - -using namespace clang::ast_matchers; - -/* -when calling diag(), supply a SourceRange as the first "argument" after the -closing parens. e.g., diag(someLoc, "some message %0") << SomeSourceRange << -SomeArg; - the source location corresponds to the ^ caret, the source range corresponds to -the ~ underlines - - how to make better diagnostic - */ -namespace clang { -namespace tidy { -namespace modernize { - -/// Register for all function calls, and filter malloc out -void NoMallocCheck::registerMatchers(MatchFinder *Finder) { - // register function calls to malloc - // Finder->addMatcher( - // callExpr(callee(functionDecl(hasName("::malloc")))).bind("malloc"), this); - - // this matcher finds statements in the form - // char* str = (char*) malloc(...); - // ~~~~~~~~~~~~~~~~~~~~ - Finder->addMatcher( - cStyleCastExpr( - hasDescendant(callExpr(callee(functionDecl(hasName("::malloc")))) - .bind("malloc"))) - .bind("c_cast"), - this); - - // registers realloc calls, suggest std::vector - Finder->addMatcher( - callExpr(callee(functionDecl(hasName("::realloc")))).bind("realloc"), - this); - - // registers free calls, suggest proper RAII and delete - Finder->addMatcher( - callExpr(callee(functionDecl(hasName("::free")))).bind("free"), this); -} - -// -------------------- -// Helper Functionality -// -------------------- -namespace { - -/// kinda inspired from here -/// http://stackoverflow.com/questions/9607852/print-arguments-of-a-function-using-clang-ast -std::string stmt_to_string(Stmt const *stmt, LangOptions l) { - // configuration - PrintingPolicy Policy(l); - - // printing - std::string stmt_str; - llvm::raw_string_ostream s(stmt_str); - stmt->printPretty(s, 0, Policy); - - return stmt_str; -} - -/// helper functions, to check if the expr is a sizeof expression -bool is_size_of(UnaryExprOrTypeTraitExpr const *expr) noexcept { - return expr->getKind() == UnaryExprOrTypeTrait::UETT_SizeOf; -} - -// try to infere the type of a potential sizeof expression, if it fails return -// false, otherwise true -bool infer_sizeof_type(Expr const *side, QualType &type) { - auto const size_of = dyn_cast(side); - if (size_of == nullptr) // could not cast expression to sizeof like expr - return false; - else { - // casted expression wasnt sizeof, maybe a typetrait of alignof - if (is_size_of(size_of) == false) - return false; - else { // we did find a sizeof expression, write the type and return true - type = size_of->getArgumentType(); - return true; - } - } -} - -std::string count_to_string(const BinaryOperator *expr, bool lhs_rhs_flag, - LangOptions l) { - const auto *count_expr = lhs_rhs_flag ? expr->getLHS() : expr->getRHS(); - return stmt_to_string(count_expr, l); -} - -} // namespace - -/// Check if the catched function call was malloc, and warn, propose new -void NoMallocCheck::check(const MatchFinder::MatchResult &Result) { - const auto *cast_match = Result.Nodes.getNodeAs("c_cast"); - if (cast_match != nullptr) - handle_cast(cast_match); - - const auto *malloc_match = Result.Nodes.getNodeAs("malloc"); - if (malloc_match != nullptr) - handle_malloc(malloc_match); - - const auto *realloc_match = Result.Nodes.getNodeAs("realloc"); - if (realloc_match != nullptr) - handle_realloc(realloc_match); - - const auto *free_match = Result.Nodes.getNodeAs("free"); - if (free_match != nullptr) - handle_free(free_match); -} - -/// handle cast expression, containing a malloc -/// (int*) malloc(sizeof(int) * 10); would be one example -void NoMallocCheck::handle_cast(const CStyleCastExpr *MatchedDecl) { - // first handle the malloc, check if a fix was supposed - const auto *malloc_call = - dyn_cast(MatchedDecl->getSubExprAsWritten()); - if (malloc_call == nullptr) - return; - - // handle the malloc, give information that is called from a cast expression - if (handle_malloc(malloc_call, true)) { - diag(MatchedDecl->getLocStart(), "Cast not needed anymore") - << FixItHint::CreateRemoval( - {MatchedDecl->getLocStart(), - malloc_call->getLocStart().getLocWithOffset(-1)}); - } -} - -/// implements the malloc check and its fixit hints -/// returns true, if a fix was supposed -bool NoMallocCheck::handle_malloc(const CallExpr *MatchedDecl, bool from_cast) { - // i belive this is done by CSA, but i added it just in case! - // does not work with c++, how to check on c only in testcases? - LangOptions l = getLangOpts(); - if (not from_cast and not(l.CPlusPlus or l.CPlusPlus11 or l.CPlusPlus14)) - diag(MatchedDecl->getLocStart(), - "Use of malloc with out explicit cast to return value!"); - - // getting the bytesize argument of the malloc call - // if its a binaryoperator (mulitplication), infer more information! - auto arg = dyn_cast(MatchedDecl->getArg(0)); - - // the arguent to malloc was not a computation -> no more information - // achievable - if (arg == nullptr) { - return single_or_raw(MatchedDecl); - } - - // we have a binary operation, try to infer type and size information - else { - // multiplication should be the common case - // since malloc(sizeof(int) * count) - form - if (arg->isMultiplicativeOp()) { - return multiplication(MatchedDecl, arg); - } - // we dont have a multiplication, this is shady! - else { - suspicious_binary(MatchedDecl); - return false; - } - } - return false; // since the method is to big, just do it here. needs to get - // fixed -} - -/// implements the realloc check and its suggestions (std::vector) -void NoMallocCheck::handle_realloc(const CallExpr *MatchedDecl) { - diag(MatchedDecl->getLocStart(), "Reallocation memory suggests, that either " - "std::vector or std::string is a better " - "match for your usecase than C-Style memory " - "management. [R.10?]") - << SourceRange{MatchedDecl->getLocStart(), MatchedDecl->getLocEnd()}; - diag(MatchedDecl->getLocStart(), "std::vector<>::resize does the job!", - DiagnosticIDs::Note); - give_deletion_hint(MatchedDecl); -} - -/// implements the free check and its suggestions (RAII) -void NoMallocCheck::handle_free(const CallExpr *MatchedDecl) { - diag(MatchedDecl->getLocStart(), "Do not use error prone C-Style memory " - "management. Consider using RAII Objects. " - "[R.10]") - << SourceRange{MatchedDecl->getLocStart(), MatchedDecl->getLocEnd()}; - give_deletion_hint(MatchedDecl); -} - -/// find out the type, if a sizeof expr exists -/// flag is true, when count will be on lhs -/// flag is false, when count will be on rhs -bool NoMallocCheck::determine_type_and_count(const BinaryOperator *arg, - QualType &type, - bool &lhs_rhs_flag) const { - auto const *lhs = arg->getLHS(); - auto const *rhs = arg->getRHS(); - - // on success, sets the type - // lhs inferes type - if (infer_sizeof_type(lhs, type) == true) { - lhs_rhs_flag = false; // rhs is count - return true; - } - // rhs inferes type - else if (infer_sizeof_type(rhs, type) == true) { - lhs_rhs_flag = true; // lhs is count - return true; - } - // could not infere type, therefore results are invalid! - else { - return false; - } -} - -/// handle malloc call that has not a binary expression as argument -/// returns true if a fix is suggested -bool NoMallocCheck::single_or_raw(const CallExpr *malloc_call) { - // check if its malloc(sizeof(int)) and transform to normal new - // otherwise warn - QualType t; - bool is_size_of_t = infer_sizeof_type(malloc_call->getArg(0), t); - - // we got a sizeof - if (is_size_of_t) { - Type const *type = t.split().asPair().first; - std::string replacement = - "new " + QualType::getAsString(type, Qualifiers()); - - diag(malloc_call->getLocStart(), - "Use new instead of malloc for object-creation. [R.10]") - << FixItHint::CreateReplacement( - {malloc_call->getLocStart(), malloc_call->getLocEnd()}, - replacement); - give_deletion_hint(malloc_call); - - return true; - } - // we got a suspicious malloc with no information - else { - diag(malloc_call->getLocStart(), "Could not infer your usecase of malloc!"); - give_call_hint(malloc_call); - - return false; - } -} - -/// handles malloc calls with multiplication as argument -/// returns true if a fix is suggested -bool NoMallocCheck::multiplication(const CallExpr *call, - const BinaryOperator *arg) { - // determine_type_and_count sets this flag. - // on true -> lhs is count expression - // on false -> rhs is count expression - bool lhs_rhs_flag = false; - QualType size_of_type; - - if (determine_type_and_count(arg, size_of_type, lhs_rhs_flag) == true) { - // either lhs or rhs are type/count. find it out and write to variables - // suggest an fix in the form 'new type[count]' - - // get the expression for the count amount - std::string count_expr_str = - count_to_string(arg, lhs_rhs_flag, this->getLangOpts()); - - // remove qualifiers from the infered type - Type const *type = size_of_type.split().asPair().first; - // generate string from it - std::string t_hint = QualType::getAsString(type, Qualifiers()); - std::string replacement = "new " + t_hint + "[" + count_expr_str + "]"; - - // warn the malloc and give a fix hint with new[] syntax - diag(call->getLocStart(), - "Create Dynamic Arrays with std::vector(resizeable), " - "std::make_unique, gsl::dyn_array(both " - "dynamic, but fixed size) [Resource Management]") - << SourceRange{call->getLocStart(), call->getLocEnd()} - << FixItHint::CreateReplacement( - SourceRange{call->getLocStart(), call->getLocEnd()}, replacement); - - give_array_hint(call, t_hint, count_expr_str); - give_deletion_hint(call); - - return true; - } - // failed to infer type and count - else { - diag(call->getLocStart(), - "suspicious malloc. weired multiplication as argument!") - << SourceRange{call->getLocStart(), call->getLocEnd()}; - - give_call_hint(call); - - return false; - } -} - -/// warning about a suspicious, possibly buggy malloc call -void NoMallocCheck::suspicious_binary(const CallExpr *call) { - // warn the suspicious malloc call - diag(call->getLocStart(), - "Suspicious malloc. Argument is a Binary Operation, but no " - "multiplication.") - << SourceRange{call->getLocStart(), call->getLocEnd()}; - - // note for a possible bug - diag(call->getLocStart(), - "Check for the 'malloc(sizeof(int) * 10 + 1)' - Bug", - DiagnosticIDs::Note) - << SourceRange{call->getLocStart(), call->getLocEnd()}; - - // note how to call properly - give_call_hint(call); -} - -/// hint how to call malloc properly as Diagnostic::Note -void NoMallocCheck::give_call_hint(const CallExpr *malloc_call) { - diag(malloc_call->getLocStart(), - "Write malloc in the form (type*) malloc(sizeof(type) * count)", - DiagnosticIDs::Note); -} - -/// notes about other ways to create a dynamic array -void NoMallocCheck::give_array_hint(const CallExpr *malloc_call, - const std::string &t_hint, - const std::string &count_str) { - std::string vec_hint = - "Consider std::vector<" + t_hint + ">(" + count_str + ")"; - std::string uni_hint = - "Consider std::make_unique<" + t_hint + "[]>(" + count_str + ")"; - std::string gsl_hint = - "Consider gsl::dyn_array<" + t_hint + ">(" + count_str + ")"; - - // notes on other possible replacements - diag(malloc_call->getLocStart(), vec_hint, DiagnosticIDs::Note); - diag(malloc_call->getLocStart(), uni_hint, DiagnosticIDs::Note); - diag(malloc_call->getLocStart(), gsl_hint, DiagnosticIDs::Note); -} - -/// give hint on deletion of the memory resource -void NoMallocCheck::give_deletion_hint(const CallExpr *malloc_call) { - diag(malloc_call->getLocStart(), - "You must manually remove free and replace it with delete/delete[]!", - DiagnosticIDs::Note); - diag(malloc_call->getLocStart(), "When using a RAII mechanism, remove the " - "explicit deleting of this variable!", - DiagnosticIDs::Note); -} - -} // namespace modernize -} // namespace tidy -} // namespace clang Index: clang-tidy/performance/CMakeLists.txt =================================================================== --- clang-tidy/performance/CMakeLists.txt +++ clang-tidy/performance/CMakeLists.txt @@ -7,7 +7,6 @@ InefficientStringConcatenationCheck.cpp InefficientVectorOperationCheck.cpp PerformanceTidyModule.cpp - UlfexpressionsCheck.cpp TypePromotionInMathFnCheck.cpp UnnecessaryCopyInitialization.cpp UnnecessaryValueParamCheck.cpp Index: clang-tidy/performance/PerformanceTidyModule.cpp =================================================================== --- clang-tidy/performance/PerformanceTidyModule.cpp +++ clang-tidy/performance/PerformanceTidyModule.cpp @@ -10,8 +10,6 @@ #include "../ClangTidy.h" #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" -#include "InefficientStringConcatenationCheck.h" -#include "UlfexpressionsCheck.h" #include "FasterStringFindCheck.h" #include "ForRangeCopyCheck.h" #include "ImplicitCastInLoopCheck.h" Index: clang-tidy/performance/UlfexpressionsCheck.h =================================================================== --- clang-tidy/performance/UlfexpressionsCheck.h +++ /dev/null @@ -1,49 +0,0 @@ -//===--- UlfexpressionsCheck.h - clang-tidy---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_ULFEXPRESSIONS_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_ULFEXPRESSIONS_H - -#include "../ClangTidy.h" - -namespace clang { -namespace tidy { -namespace performance { - -/// FIXME: Write a short description. -/// -/// For the user-facing documentation see: -/// http://clang.llvm.org/extra/clang-tidy/checks/performance-UlfExpressions.html -class UlfexpressionsCheck : public ClangTidyCheck { -public: - UlfexpressionsCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; - -private: - void fixExpressionTemplate(const CXXOperatorCallExpr *expr, - const DeclRefExpr *op1, const DeclRefExpr *op2); - void fixNegation(const DeclRefExpr *op); - void fixPointerAccess(const CXXOperatorCallExpr *calc, - const UnaryOperator *op1, const UnaryOperator *op2); - void fixProblematicScalar(const CXXOperatorCallExpr *problematic); - void fixProblematicVector(const CXXOperatorCallExpr *problematic); - void fixTemporary(const CXXBindTemporaryExpr *tmp); - - bool already_fixed(const SourceLocation &loc); - - std::vector FixedLocations; -}; - -} // namespace performance -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_ULFEXPRESSIONS_H Index: clang-tidy/performance/UlfexpressionsCheck.cpp =================================================================== --- clang-tidy/performance/UlfexpressionsCheck.cpp +++ /dev/null @@ -1,338 +0,0 @@ -//===--- UlfexpressionsCheck.cpp - clang-tidy------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "UlfexpressionsCheck.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include -#include - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { -namespace performance { - -void UlfexpressionsCheck::registerMatchers(MatchFinder *Finder) { - // expression templates only in c++ for now - if (!getLangOpts().CPlusPlus) - return; - - // experimental matchers from clang-query - // - // - // match cxxBindTemporaryExpr(hasAncestor(cxxOperatorCallExpr())) - // gives the expression where calculation happens - // - // cxxBindTemporaryExpr(hasAncestor(cxxOperatorCallExpr(hasAnyArgument(hasType(cxxRecordDecl(hasName("fieldDataTmpl"))))))).bind("overloaded_operators") - - // already pretty good - // - // cxxOperatorCallExpr(allOf(unless(cxxOperatorCallExpr(forEachDescendant(cxxBindTemporaryExpr()))), - // hasAnyArgument(hasType(cxxRecordDecl(hasName("fieldDataTmpl")))))) - // - // most likely wanted matcher - // - // cxxOperatorCallExpr(allOf(unless(cxxOperatorCallExpr(forEachDescendant(cxxBindTemporaryExpr()))), - // hasAnyArgument(hasType(cxxRecordDecl(hasName("fieldDataTmpl")))), - // anyOf(hasOverloadedOperatorName("+"), hasOverloadedOperatorName("-"), - // hasOverloadedOperatorName("*"), hasOverloadedOperatorName("/")))) - // - - // match operatorcalls, with non temporaries, and fieldDataTmpl as one - // argument, and only arithmetic - - Finder->addMatcher( - cxxOperatorCallExpr( - allOf(hasAnyArgument(hasType( - cxxRecordDecl(hasAnyName("fieldDataTmpl", "fieldTmpl")))), - // hasArgument(0, - // hasType(cxxRecordDecl(hasName("fieldDataTmpl")))), - // hasArgument(1, - // hasType(cxxRecordDecl(hasName("fieldDataTmpl")))), - anyOf(hasArgument(0, declRefExpr().bind("op1")), - hasArgument(0, anything())), - anyOf(hasArgument(1, declRefExpr().bind("op2")), - hasArgument(1, anything())), - unless(cxxOperatorCallExpr(has(cxxBindTemporaryExpr()))), - anyOf(hasOverloadedOperatorName("+"), - hasOverloadedOperatorName("-"), - hasOverloadedOperatorName("*"), - hasOverloadedOperatorName("/")))) - .bind("calculation"), - this); - - // negations of fields - Finder->addMatcher(cxxOperatorCallExpr(allOf( - hasOverloadedOperatorName("-"), argumentCountIs(1), - hasAnyArgument(hasType(cxxRecordDecl( - hasAnyName("fieldDataTmpl", "fieldTmpl")))), - hasArgument(0, declRefExpr().bind("negation")))), - this); - - // pointer dereferencing in equations - Finder->addMatcher( - cxxOperatorCallExpr( - allOf( - hasAnyArgument(hasType( - cxxRecordDecl(hasAnyName("fieldDataTmpl", "fieldTmpl")))), - anyOf( - hasArgument(0, unaryOperator( - allOf(hasOperatorName("*"), - hasType(cxxRecordDecl(hasAnyName( - "fieldDataTmpl", "fieldTmpl"))))) - .bind("deref1")), - hasArgument(1, unaryOperator( - allOf(hasOperatorName("*"), - hasType(cxxRecordDecl(hasAnyName( - "fieldDataTmpl", "fieldTmpl"))))) - .bind("deref2"))), - anyOf(hasOverloadedOperatorName("+"), - hasOverloadedOperatorName("-"), - hasOverloadedOperatorName("*"), - hasOverloadedOperatorName("/")))) - .bind("calc_with_deref"), - this); - -#if 0 - // calculation, that are not mathematically sound - Finder->addMatcher( - cxxOperatorCallExpr( - allOf(hasAnyArgument(hasType(cxxRecordDecl( - anyOf(hasName("fieldDataTmpl"), hasName("fieldTmpl"))))), - hasAnyArgument(hasType(asString("double"))), - anyOf(hasOverloadedOperatorName("+"), - hasOverloadedOperatorName("-")))) - .bind("problematic_scalar"), - this); -#endif - - // temporary - Finder->addMatcher( - cxxBindTemporaryExpr(allOf(hasType(cxxRecordDecl( - hasAnyName("fieldDataTmpl", "fieldTmpl"))), - unless(has(cxxOperatorCallExpr())))) - .bind("temporary_field"), - this); -} - -void UlfexpressionsCheck::check(const MatchFinder::MatchResult &Result) { - const auto &n = Result.Nodes; - - if (const auto *expression = - n.getNodeAs("calculation")) { - const DeclRefExpr *op1 = n.getNodeAs("op1"); - const DeclRefExpr *op2 = n.getNodeAs("op2"); - fixExpressionTemplate(expression, op1, op2); - } - - if (const auto *op = n.getNodeAs("negation")) { - fixNegation(op); - } - - if (const auto *deref = n.getNodeAs("calc_with_deref")) { - diag(deref->getLocStart(), "Equation with pointer deref"); - const auto *op1 = n.getNodeAs("deref1"); - const auto *op2 = n.getNodeAs("deref2"); - fixPointerAccess(deref, op1, op2); - } - - if (const auto *problematic = - n.getNodeAs("problematic_scalar")) { - fixProblematicScalar(problematic); - } - - if (const auto *problematic = - n.getNodeAs("problematic_vector")) { - fixProblematicVector(problematic); - } - - if (const auto *temporary = - n.getNodeAs("temporary_field")) { - fixTemporary(temporary); - } -} - -namespace { -bool isFieldData(const DeclRefExpr *op) { - - bool result; - if (op == nullptr) - result = false; - else { - - auto arg_type = op->getDecl()->getType(); - Type const *t = arg_type.split().asPair().first; - - // skip non fieldDatas - result = (QualType::getAsString(t, Qualifiers()).find("fieldData") != - std::string::npos) || - (QualType::getAsString(t, Qualifiers()).find("field") != - std::string::npos); - } - // std::cout << "is fielddata? " << op << " - " << result << std::endl; - return result; -} -} - -/// use expression template for fieldData-fieldData operations -void UlfexpressionsCheck::fixExpressionTemplate(const CXXOperatorCallExpr *expr, - const DeclRefExpr *op1, - const DeclRefExpr *op2) { - assert(expr->isInfixBinaryOp()); - - if (isFieldData(op1)) { - std::string op1_name = op1->getFoundDecl()->getNameAsString(); - auto location = op1->getLocation().getLocWithOffset(op1_name.size()); - - if (!already_fixed(location)) { - auto Diag = diag(location, "use expression templates"); - Diag << FixItHint::CreateInsertion(location, ".v()"); - FixedLocations.push_back(location); - } - } - - if (isFieldData(op2)) { - std::string op2_name = op2->getFoundDecl()->getNameAsString(); - auto location = op2->getLocation().getLocWithOffset(op2_name.size()); - - if (!already_fixed(location)) { - auto Diag = diag(location, "use expression templates"); - Diag << FixItHint::CreateInsertion(location, ".v()"); - FixedLocations.push_back(location); - } - } -} - -void UlfexpressionsCheck::fixNegation(const DeclRefExpr *op) { -#if 0 - std::string op_name = op->getFoundDecl()->getNameAsString(); - auto location = op->getLocation().getLocWithOffset(op_name.size()); - - diag(location, "Enabling expression template for negation") - << FixItHint::CreateInsertion(location, ".v()"); - - FixedLocations.push_back(location); -#endif -} - -namespace { -std::string stmt_to_string(Stmt const *stmt, LangOptions l) { - // configuration - PrintingPolicy Policy(l); - - // printing - std::string stmt_str; - llvm::raw_string_ostream s(stmt_str); - stmt->printPretty(s, 0, Policy); - - return stmt_str; -} -} - -void UlfexpressionsCheck::fixPointerAccess(const CXXOperatorCallExpr *calc, - const UnaryOperator *op1, - const UnaryOperator *op2) { - if (op1) { - std::string stmt = stmt_to_string(op1, this->getLangOpts()); - stmt += "->v()"; - stmt.erase(0, 1); - diag(op1->getLocStart(), "Dereferencing") << FixItHint::CreateReplacement( - SourceRange(op1->getLocStart(), op1->getLocEnd()), stmt); - } - if (op2) { - std::string stmt = stmt_to_string(op2, this->getLangOpts()); - stmt += "->v()"; - stmt.erase(0, 1); - diag(op2->getLocStart(), "Dereferencing") << FixItHint::CreateReplacement( - SourceRange(op2->getLocStart(), op2->getLocEnd()), stmt); - } -} - -/// scalar +/- vector, not defined in math -void UlfexpressionsCheck::fixProblematicScalar( - const CXXOperatorCallExpr *problematic) { - assert(problematic->isInfixBinaryOp()); - - // create the warning - auto Diag = - diag(problematic->getLocStart(), - "do not use problematic vector-scalar math") - << SourceRange{problematic->getLocStart(), problematic->getLocEnd()}; - -#if 0 - // generate the fixit hint - auto *args = problematic->getArgs(); - auto n = problematic->getNumArgs(); - - assert(n == 2); // we have binary expression - - for (unsigned short i = 0; i < n; ++i) { - auto arg_type = args[i]->getType(); - Type const *t = arg_type.split().asPair().first; - - // skip fieldData - if (QualType::getAsString(t, Qualifiers()).find("fieldData") != - std::string::npos) - continue; - - Diag << FixItHint::CreateInsertion(args[i]->getLocEnd(), " * ONES"); - } -#endif -} - -/// vector vector division -void UlfexpressionsCheck::fixProblematicVector( - const CXXOperatorCallExpr *problematic) { - assert(problematic->isInfixBinaryOp()); - - auto Diag = - diag(problematic->getLocStart(), "dont use problematic vector math"); - -#if 0 - // generate the fixit hint - auto *args = problematic->getArgs(); - auto n = problematic->getNumArgs(); - - assert(n == 2); // we have binary expression - - for (unsigned short i = 0; i < n; ++i) { - auto arg_type = args[i]->getType(); - Type const *t = arg_type.split().asPair().first; - - if (QualType::getAsString(t, Qualifiers()).find("fieldData") == - std::string::npos) - continue; - - Diag << FixItHint::CreateInsertion(args[i]->getLocEnd(), ".v()"); - } -#endif -} - -void UlfexpressionsCheck::fixTemporary(const CXXBindTemporaryExpr *tmp) { - auto Diag = - diag(tmp->getLocStart(), "created temporary field, check necessity") - << SourceRange{tmp->getLocStart(), tmp->getLocEnd()}; - auto location = tmp->getLocEnd().getLocWithOffset(1); - - if (!already_fixed(location)) { - Diag << FixItHint::CreateInsertion(location, ".v()"); - FixedLocations.push_back(location); - } -} - -bool UlfexpressionsCheck::already_fixed(const SourceLocation &loc) { - auto pos = - std::find(std::begin(FixedLocations), std::end(FixedLocations), loc); - return pos != std::end(FixedLocations); -} - -} // namespace performance -} // namespace tidy -} // namespace clang Index: docs/clang-tidy/checks/cppcoreguidelines-naked_new.rst =================================================================== --- docs/clang-tidy/checks/cppcoreguidelines-naked_new.rst +++ /dev/null @@ -1,6 +0,0 @@ -.. title:: clang-tidy - cppcoreguidelines-naked_new - -cppcoreguidelines-naked_new -=========================== - -FIXME: Describe what patterns does the check detect and why. Give examples. Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -30,7 +30,6 @@ cert-msc50-cpp cert-oop11-cpp (redirects to misc-move-constructor-init) cppcoreguidelines-interfaces-global-init - cppcoreguidelines-naked_new cppcoreguidelines-no-malloc cppcoreguidelines-owning-memory cppcoreguidelines-pro-bounds-array-to-pointer-decay @@ -129,7 +128,6 @@ modernize-loop-convert modernize-make-shared modernize-make-unique - modernize-no-malloc modernize-pass-by-value modernize-raw-string-literal modernize-redundant-void-arg @@ -151,7 +149,6 @@ modernize-use-using mpi-buffer-deref mpi-type-mismatch - performance-UlfExpressions performance-faster-string-find performance-for-range-copy performance-implicit-cast-in-loop Index: docs/clang-tidy/checks/modernize-no-malloc.rst =================================================================== --- docs/clang-tidy/checks/modernize-no-malloc.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. title:: clang-tidy - modernize-no-malloc - -modernize-no-malloc -=================== - -This check handles C-Style memory management using ``malloc()``, ``realloc()`` -and ``free()``. It warns about its use and tries to replace ``malloc()`` with -corresponding ``new`` expressions. If it fails to do so, a note will be emitted -how to write malloc calls with more information, making it easier to reason -about. -See `CppCoreGuidlines -` - -Both array... - -.. code-block:: c++ - - char* some_string = (char*) malloc(sizeof(char) * 20); - - // becomes - - char* some_string = new char[20]; - -... and single element creation are supported. - -.. code-block:: c++ - - int* integer = (int*) malloc(sizeof(int)); - - // becomes - - int* integer = new int; - - -Furthermore it warns about suspicious calls to malloc. - -.. code-block:: c++ - - // suspicious because not an multiplication of sizeof() and count - int* int_array = (int*) malloc(25); - int* buggy_array = (int*) malloc(sizeof(int) * 10 + 1); - - -Since general replacement of malloc with new requires the replacement of the -free calls as well, automatic fixing should be used with caution. The check will -warn about C-Style Memory Management, give hints how to do it better and -reference the cppcoreguidelines. - -Know Bug -======== - -The fixit-hint for struct, class and enum objects are incorrect. - Index: docs/clang-tidy/checks/performance-UlfExpressions.rst =================================================================== --- docs/clang-tidy/checks/performance-UlfExpressions.rst +++ /dev/null @@ -1,6 +0,0 @@ -.. title:: clang-tidy - performance-UlfExpressions - -performance-UlfExpressions -=========================== - -FIXME: Describe what patterns does the check detect and why. Give examples. Index: test/clang-tidy/cppcoreguidelines-owning-memory.cpp =================================================================== --- test/clang-tidy/cppcoreguidelines-owning-memory.cpp +++ test/clang-tidy/cppcoreguidelines-owning-memory.cpp @@ -1,15 +1,5 @@ // RUN: %check_clang_tidy %s cppcoreguidelines-owning-memory %t -#if 0 -// Copied from NoMallocCheck -using size_t = __SIZE_TYPE__; -void *malloc(size_t size); -void *align_malloc(size_t size, unsigned short aligmnent); -void *calloc(size_t num, size_t size); -void *realloc(void *ptr, size_t size); -void *align_realloc(void *ptr, size_t size, unsigned short alignment); -#endif - namespace gsl { template using owner = T; @@ -138,13 +128,6 @@ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: assigning newly created owner/resource to non-owner gsl::owner owned_int13 = nullptr; // Ok - -#if 0 - gsl::owner owned_int14 = (int *)malloc(20 * sizeof(int)); // Ok - gsl::owner owned_int15 = static_cast(malloc(20 * sizeof(int))); // Ok - int *unowned_int9 = (int *)malloc(20 * sizeof(int)); // Bad, since must be catched by an owner - // CHECK - MESSAGES: [[@LINE-1]]:3: warning: assigning newly created owner/resource to non-owner -#endif } void test_deletion() {