Re: [PATCH] D21185: [clang-tidy] Add performance-emplace-into-containers
vsk abandoned this revision. vsk added a comment. Thanks for the valuable feedback! I'll keep all of it in mind when writing checks in the future. I'm closing this revision since http://reviews.llvm.org/D20964 is in. http://reviews.llvm.org/D21185 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21185: [clang-tidy] Add performance-emplace-into-containers
Prazek added a subscriber: Prazek. Prazek added a comment. In http://reviews.llvm.org/D21185#464517, @Eugene.Zelenko wrote: > Since http://reviews.llvm.org/D20964 was committed, I think we should close > this. Yep, I think the best idea is to take all the goodies from this check and add it to modernize-use-emplace http://reviews.llvm.org/D21185 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21185: [clang-tidy] Add performance-emplace-into-containers
Eugene.Zelenko added a comment. Since http://reviews.llvm.org/D20964 was committed, I think we should close this. http://reviews.llvm.org/D21185 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21185: [clang-tidy] Add performance-emplace-into-containers
aaron.ballman added inline comments. Comment at: clang-tidy/performance/EmplaceCheck.cpp:26 @@ +25,3 @@ + on(expr(hasType(cxxRecordDecl(hasName("std::vector"), + callee(functionDecl(hasName("push_back"))), + hasArgument(0, cxxConstructExpr().bind("construct_expr"))) sbenza wrote: > Just say functionDecl(hasName("std::vector::push_back")) and you can remove > the type check. Should use "::std::vector::push_back" just to be sure it doesn't explode when evil people have: ``` namespace frobble { namespace std { template class vector { void push_back(const T&); }; } } ``` Comment at: clang-tidy/performance/EmplaceCheck.cpp:38 @@ +37,3 @@ + if (SR.isInvalid()) +return {}; + return Lexer::getSourceText(Lexer::getAsCharRange(SR, SM, LO), SM, LO); I think this goes against our coding standards and should be `return StringRef();`. http://reviews.llvm.org/D21185 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21185: [clang-tidy] Add performance-emplace-into-containers
sbenza added a comment. Missing the .rst file. Did you use the check_clang_tidy.py script to create the template? Comment at: clang-tidy/performance/EmplaceCheck.cpp:25 @@ +24,3 @@ + cxxMemberCallExpr( + on(expr(hasType(cxxRecordDecl(hasName("std::vector"), + callee(functionDecl(hasName("push_back"))), This change can potentially break exception guarantees of the code. For example, push_back can throw before the object is constructed leaking the arguments. We should at least say something about it in the docs. Comment at: clang-tidy/performance/EmplaceCheck.cpp:26 @@ +25,3 @@ + on(expr(hasType(cxxRecordDecl(hasName("std::vector"), + callee(functionDecl(hasName("push_back"))), + hasArgument(0, cxxConstructExpr().bind("construct_expr"))) Just say functionDecl(hasName("std::vector::push_back")) and you can remove the type check. Comment at: clang-tidy/performance/EmplaceCheck.cpp:84 @@ +83,3 @@ + + StringRef ArgsStr = getAsString(SM, LO, ArgsR); + if (!ArgsStr.data()) It's usually preferable, and sometimes easier to write, to do erases instead of replacements. For example, you could simply erase `X(` and `)`. Something like `(Cons->getLogStart(), ArgsR.getBegin())` and `(Args.getEnd(), Args.getEnd())` Comment at: clang-tidy/performance/EmplaceCheck.cpp:88 @@ +87,3 @@ + + SourceRange CalleeR = getPreciseTokenRange(SM, LO, CalleeStartLoc); + SourceRange ConstructR = Cons->getSourceRange(); What you want is `getTokenRange(Call->getCallee()->getSourceRange())` No need to mess with the locations and offsets yourself. Comment at: clang-tidy/performance/EmplaceCheck.h:18 @@ +17,3 @@ +namespace performance { + +class EmplaceCheck : public ClangTidyCheck { Needs a comment Comment at: clang-tidy/performance/EmplaceCheck.h:19 @@ +18,3 @@ + +class EmplaceCheck : public ClangTidyCheck { +public: What's the scope? Is it just vector::push_back/emplace_back? Or is it going to be expanded to other map::insert, deque::push_front, etc. Comment at: test/clang-tidy/performance-emplace-into-containers.cpp:26 @@ +25,3 @@ + std::vector v1; + + v1.push_back(X()); We have to make sure the arguments are compatible with perfect forwarding. This means no brace init lists and no NULL. Eg: v.push_back(Y({})); // {} can't be passed to perfect forwarding v.push_back(Y(NULL)); // NULL can't be passed to perfect forwarding Comment at: test/clang-tidy/performance-emplace-into-containers.cpp:28 @@ +27,3 @@ + v1.push_back(X()); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Consider constructing {{.*}} + // CHECK-FIXES: v1.emplace_back() At least one of the cases should match the whole exact message, to make sure it is correct. Comment at: test/clang-tidy/performance-emplace-into-containers.cpp:42 @@ +41,3 @@ + // CHECK-FIXES: v1/*a*/./*b*/emplace_back(/*c*//*d*/0,/*e*/0/*f*//*g*/)/*h*/ ; + + // Do not try to deal with initializer lists. We should also test implicit conversions. Eg: v1.push_back(0); Comment at: test/clang-tidy/performance-emplace-into-containers.cpp:46 @@ +45,3 @@ + + // Do not try to deal with functional casts. FIXME? + X x{0, 0}; Why not? Comment at: test/clang-tidy/performance-emplace-into-containers.cpp:50 @@ +49,3 @@ + v1.push_back(X(0)); + + // Do not try to deal with weird expansions. We need tests for copy/move construction. Eg: v1.push_back(x); // should not be changed v1.push_back(FunctionThatReturnsX()); // should not be changed http://reviews.llvm.org/D21185 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21185: [clang-tidy] Add performance-emplace-into-containers
Eugene.Zelenko added a subscriber: Eugene.Zelenko. Eugene.Zelenko added a comment. See also http://reviews.llvm.org/D20964. I think modernize is better place for such check. http://reviews.llvm.org/D21185 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D21185: [clang-tidy] Add performance-emplace-into-containers
vsk updated this revision to Diff 60206. vsk added a comment. - Fix the diagnostic message. Suggested by Erik Pilkington. http://reviews.llvm.org/D21185 Files: clang-tidy/performance/CMakeLists.txt clang-tidy/performance/EmplaceCheck.cpp clang-tidy/performance/EmplaceCheck.h clang-tidy/performance/PerformanceTidyModule.cpp test/clang-tidy/performance-emplace-into-containers.cpp Index: test/clang-tidy/performance-emplace-into-containers.cpp === --- /dev/null +++ test/clang-tidy/performance-emplace-into-containers.cpp @@ -0,0 +1,57 @@ +// RUN: %check_clang_tidy %s performance-emplace-into-containers %t -- -- -std=c++11 + +namespace std { + +template +struct vector { + void push_back(const T ); + void push_back(T &); + + template + void emplace_back(Args &&... args); +}; + +} // std + +struct X { + int x; + X() : x(0) {} + X(int x) : x(x) {} + X(int x, int y) : x(x + y) {} + X(const X ) : x(Obj.x) {} +}; + +void f1() { + std::vector v1; + + v1.push_back(X()); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Consider constructing {{.*}} + // CHECK-FIXES: v1.emplace_back() + + v1.push_back(X(/*a*/)); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Consider constructing {{.*}} + // CHECK-FIXES: v1.emplace_back(/*a*/) + + v1.push_back(X(0, 0)); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Consider constructing {{.*}} + // CHECK-FIXES: v1.emplace_back(0, 0) + + v1/*a*/./*b*/push_back(/*c*/X(/*d*/0,/*e*/0/*f*/)/*g*/)/*h*/ ; + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: Consider constructing {{.*}} + // CHECK-FIXES: v1/*a*/./*b*/emplace_back(/*c*//*d*/0,/*e*/0/*f*//*g*/)/*h*/ ; + + // Do not try to deal with initializer lists. + v1.push_back({0, 0}); + + // Do not try to deal with functional casts. FIXME? + X x{0, 0}; + v1.push_back(X(x)); + v1.push_back(X(0)); + + // Do not try to deal with weird expansions. +#define M1 X(0, 0) +#define M2 push_back + v1.push_back(M1); + v1.M2(X(0, 0)); + v1.M2(M1); +} Index: clang-tidy/performance/PerformanceTidyModule.cpp === --- clang-tidy/performance/PerformanceTidyModule.cpp +++ clang-tidy/performance/PerformanceTidyModule.cpp @@ -11,6 +11,7 @@ #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "EmplaceCheck.h" #include "FasterStringFindCheck.h" #include "ForRangeCopyCheck.h" #include "ImplicitCastInLoopCheck.h" @@ -24,6 +25,8 @@ class PerformanceModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories ) override { +CheckFactories.registerCheck( +"performance-emplace-into-containers"); CheckFactories.registerCheck( "performance-faster-string-find"); CheckFactories.registerCheck( Index: clang-tidy/performance/EmplaceCheck.h === --- /dev/null +++ clang-tidy/performance/EmplaceCheck.h @@ -0,0 +1,30 @@ +//===--- EmplaceCheck.h - clang-tidy --===// +// +// 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_EMPLACE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_EMPLACE_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace performance { + +class EmplaceCheck : public ClangTidyCheck { +public: + EmplaceCheck(StringRef Name, ClangTidyContext *Context); + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult ) override; +}; + +} // namespace performance +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_EMPLACE_H Index: clang-tidy/performance/EmplaceCheck.cpp === --- /dev/null +++ clang-tidy/performance/EmplaceCheck.cpp @@ -0,0 +1,98 @@ +//===--- EmplaceCheck.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 "EmplaceCheck.h" +#include "clang/Lex/Lexer.h" + +namespace clang { +namespace tidy { +namespace performance { + +using namespace ast_matchers; + +EmplaceCheck::EmplaceCheck(StringRef Name, ClangTidyContext *Context) +: ClangTidyCheck(Name, Context) {} + +void EmplaceCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + cxxMemberCallExpr( + on(expr(hasType(cxxRecordDecl(hasName("std::vector"), +
Re: [PATCH] D21185: [clang-tidy] Add performance-emplace-into-containers
vsk added a reviewer: flx. vsk updated this revision to Diff 60194. vsk added a comment. - Fix handling of push_back(X(/* comment */)). - Don't try to emit a warning when the callee comes from a macro expansion. - Get rid of a weird/wrong comment about checking for "default constructors". As a side note, I'd appreciate advice on how to apply this check to the llvm codebase (via some kind of cmake invocation?) and gather numbers. http://reviews.llvm.org/D21185 Files: clang-tidy/performance/CMakeLists.txt clang-tidy/performance/EmplaceCheck.cpp clang-tidy/performance/EmplaceCheck.h clang-tidy/performance/PerformanceTidyModule.cpp test/clang-tidy/performance-emplace-into-containers.cpp Index: test/clang-tidy/performance-emplace-into-containers.cpp === --- /dev/null +++ test/clang-tidy/performance-emplace-into-containers.cpp @@ -0,0 +1,57 @@ +// RUN: %check_clang_tidy %s performance-emplace-into-containers %t -- -- -std=c++11 + +namespace std { + +template +struct vector { + void push_back(const T ); + void push_back(T &); + + template + void emplace_back(Args &&... args); +}; + +} // std + +struct X { + int x; + X() : x(0) {} + X(int x) : x(x) {} + X(int x, int y) : x(x + y) {} + X(const X ) : x(Obj.x) {} +}; + +void f1() { + std::vector v1; + + v1.push_back(X()); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Avoid a copy {{.*}} + // CHECK-FIXES: v1.emplace_back() + + v1.push_back(X(/*a*/)); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Avoid a copy {{.*}} + // CHECK-FIXES: v1.emplace_back(/*a*/) + + v1.push_back(X(0, 0)); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Avoid a copy {{.*}} + // CHECK-FIXES: v1.emplace_back(0, 0) + + v1/*a*/./*b*/push_back(/*c*/X(/*d*/0,/*e*/0/*f*/)/*g*/)/*h*/ ; + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: Avoid a copy {{.*}} + // CHECK-FIXES: v1/*a*/./*b*/emplace_back(/*c*//*d*/0,/*e*/0/*f*//*g*/)/*h*/ ; + + // Do not try to deal with initializer lists. + v1.push_back({0, 0}); + + // Do not try to deal with functional casts. FIXME? + X x{0, 0}; + v1.push_back(X(x)); + v1.push_back(X(0)); + + // Do not try to deal with weird expansions. +#define M1 X(0, 0) +#define M2 push_back + v1.push_back(M1); + v1.M2(X(0, 0)); + v1.M2(M1); +} Index: clang-tidy/performance/PerformanceTidyModule.cpp === --- clang-tidy/performance/PerformanceTidyModule.cpp +++ clang-tidy/performance/PerformanceTidyModule.cpp @@ -11,6 +11,7 @@ #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "EmplaceCheck.h" #include "FasterStringFindCheck.h" #include "ForRangeCopyCheck.h" #include "ImplicitCastInLoopCheck.h" @@ -24,6 +25,8 @@ class PerformanceModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories ) override { +CheckFactories.registerCheck( +"performance-emplace-into-containers"); CheckFactories.registerCheck( "performance-faster-string-find"); CheckFactories.registerCheck( Index: clang-tidy/performance/EmplaceCheck.h === --- /dev/null +++ clang-tidy/performance/EmplaceCheck.h @@ -0,0 +1,30 @@ +//===--- EmplaceCheck.h - clang-tidy --===// +// +// 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_EMPLACE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_EMPLACE_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace performance { + +class EmplaceCheck : public ClangTidyCheck { +public: + EmplaceCheck(StringRef Name, ClangTidyContext *Context); + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult ) override; +}; + +} // namespace performance +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_EMPLACE_H Index: clang-tidy/performance/EmplaceCheck.cpp === --- /dev/null +++ clang-tidy/performance/EmplaceCheck.cpp @@ -0,0 +1,98 @@ +//===--- EmplaceCheck.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 "EmplaceCheck.h" +#include "clang/Lex/Lexer.h" + +namespace clang { +namespace tidy { +namespace performance { + +using namespace ast_matchers; +
[PATCH] D21185: [clang-tidy] Add performance-emplace-into-containers
vsk created this revision. vsk added reviewers: aaron.ballman, alexfh. vsk added a subscriber: cfe-commits. Introduce a check which suggests when it might be helpful to use "emplace" methods. The initial version only works with std::vector and push_back (e.g `V.push_back(T(1, 2))` -> `V.emplace_back(1, 2)`). It could be extended to work with other containers and methods. http://reviews.llvm.org/D21185 Files: clang-tidy/performance/CMakeLists.txt clang-tidy/performance/EmplaceCheck.cpp clang-tidy/performance/EmplaceCheck.h clang-tidy/performance/PerformanceTidyModule.cpp test/clang-tidy/performance-emplace-into-containers.cpp Index: test/clang-tidy/performance-emplace-into-containers.cpp === --- /dev/null +++ test/clang-tidy/performance-emplace-into-containers.cpp @@ -0,0 +1,46 @@ +// RUN: %check_clang_tidy %s performance-emplace-into-containers %t -- -- -std=c++11 + +namespace std { + +template +struct vector { + void push_back(const T ); + void push_back(T &); + + template + void emplace_back(Args &&... args); +}; + +} // std + +struct X { + int x; + X() : x(0) {} + X(int x) : x(x) {} + X(int x, int y) : x(x + y) {} + X(const X ) : x(Obj.x) {} +}; + +void f1() { + std::vector v1; + + v1.push_back(X()); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Avoid a copy {{.*}} + // CHECK-FIXES: v1.emplace_back() + + v1.push_back(X(0, 0)); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Avoid a copy {{.*}} + // CHECK-FIXES: v1.emplace_back(0, 0) + + v1/*a*/./*b*/push_back(/*c*/X(/*d*/0,/*e*/0/*f*/)/*g*/)/*h*/ ; + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: Avoid a copy {{.*}} + // CHECK-FIXES: v1/*a*/./*b*/emplace_back(/*c*//*d*/0,/*e*/0/*f*//*g*/)/*h*/ ; + + // Do not try to deal with initializer lists. + v1.push_back({0, 0}); + + // Do not try to deal with functional casts. FIXME? + X x{0, 0}; + v1.push_back(X(x)); + v1.push_back(X(0)); +} Index: clang-tidy/performance/PerformanceTidyModule.cpp === --- clang-tidy/performance/PerformanceTidyModule.cpp +++ clang-tidy/performance/PerformanceTidyModule.cpp @@ -11,6 +11,7 @@ #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" +#include "EmplaceCheck.h" #include "FasterStringFindCheck.h" #include "ForRangeCopyCheck.h" #include "ImplicitCastInLoopCheck.h" @@ -24,6 +25,8 @@ class PerformanceModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories ) override { +CheckFactories.registerCheck( +"performance-emplace-into-containers"); CheckFactories.registerCheck( "performance-faster-string-find"); CheckFactories.registerCheck( Index: clang-tidy/performance/EmplaceCheck.h === --- /dev/null +++ clang-tidy/performance/EmplaceCheck.h @@ -0,0 +1,30 @@ +//===--- EmplaceCheck.h - clang-tidy --===// +// +// 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_EMPLACE_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_EMPLACE_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace performance { + +class EmplaceCheck : public ClangTidyCheck { +public: + EmplaceCheck(StringRef Name, ClangTidyContext *Context); + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult ) override; +}; + +} // namespace performance +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_EMPLACE_H Index: clang-tidy/performance/EmplaceCheck.cpp === --- /dev/null +++ clang-tidy/performance/EmplaceCheck.cpp @@ -0,0 +1,98 @@ +//===--- EmplaceCheck.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 "EmplaceCheck.h" +#include "clang/Lex/Lexer.h" + +namespace clang { +namespace tidy { +namespace performance { + +using namespace ast_matchers; + +EmplaceCheck::EmplaceCheck(StringRef Name, ClangTidyContext *Context) +: ClangTidyCheck(Name, Context) {} + +void EmplaceCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + cxxMemberCallExpr( + on(expr(hasType(cxxRecordDecl(hasName("std::vector"), + callee(functionDecl(hasName("push_back"))), + hasArgument(0,