[clang-tools-extra] r226912 - [clang-tidy] Use shrink_to_fit instead of copy and swap trick
Alexander Kornienko
alexfh at google.com
Fri Jan 23 07:10:37 PST 2015
Author: alexfh
Date: Fri Jan 23 09:10:37 2015
New Revision: 226912
URL: http://llvm.org/viewvc/llvm-project?rev=226912&view=rev
Log:
[clang-tidy] Use shrink_to_fit instead of copy and swap trick
The shrink_to_fit() method is more readable and more effective than
the copy and swap trick to reduce the capacity of a shrinkable container.
Note that, the shrink_to_fit() method is only available in C++11 and up.
Example:
std::vector<int>(v).swap(v); will be replaced with v.shrink_to_fit();
http://reviews.llvm.org/D7087
Patch by Gábor Horváth!
Added:
clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.cpp
clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.h
clang-tools-extra/trunk/test/clang-tidy/readability-shrink-to-fit.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
Modified: clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt?rev=226912&r1=226911&r2=226912&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/CMakeLists.txt Fri Jan 23 09:10:37 2015
@@ -8,6 +8,7 @@ add_clang_library(clangTidyReadabilityMo
NamespaceCommentCheck.cpp
ReadabilityTidyModule.cpp
RedundantSmartptrGet.cpp
+ ShrinkToFitCheck.cpp
LINK_LIBS
clangAST
Modified: clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp?rev=226912&r1=226911&r2=226912&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/readability/ReadabilityTidyModule.cpp Fri Jan 23 09:10:37 2015
@@ -15,6 +15,7 @@
#include "ElseAfterReturnCheck.h"
#include "FunctionSize.h"
#include "RedundantSmartptrGet.h"
+#include "ShrinkToFitCheck.h"
namespace clang {
namespace tidy {
@@ -33,6 +34,8 @@ public:
"readability-function-size");
CheckFactories.registerCheck<RedundantSmartptrGet>(
"readability-redundant-smartptr-get");
+ CheckFactories.registerCheck<ShrinkToFitCheck>(
+ "readability-shrink-to-fit");
}
};
Added: clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.cpp?rev=226912&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.cpp Fri Jan 23 09:10:37 2015
@@ -0,0 +1,109 @@
+//===--- ShrinkToFitCheck.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 "ShrinkToFitCheck.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace {
+bool isShrinkableContainer(llvm::StringRef ClassName) {
+ static const llvm::StringSet<> Shrinkables = [] {
+ llvm::StringSet<> RetVal;
+ RetVal.insert("std::deque");
+ RetVal.insert("std::basic_string");
+ RetVal.insert("std::vector");
+ return RetVal;
+ }();
+ return Shrinkables.find(ClassName) != Shrinkables.end();
+}
+}
+
+namespace clang {
+namespace ast_matchers {
+AST_MATCHER(NamedDecl, stlShrinkableContainer) {
+ return isShrinkableContainer(Node.getQualifiedNameAsString());
+}
+} // namespace ast_matchesr
+} // namespace clang
+
+namespace clang {
+namespace tidy {
+
+void ShrinkToFitCheck::registerMatchers(MatchFinder *Finder) {
+ // Swap as a function need not to be considered, because rvalue can not
+ // be bound to a non-const reference.
+ const auto ShrinkableAsMember =
+ memberExpr(member(valueDecl().bind("ContainerDecl")));
+ const auto ShrinkableAsDecl =
+ declRefExpr(hasDeclaration(valueDecl().bind("ContainerDecl")));
+ const auto CopyCtorCall = constructExpr(
+ hasArgument(0, anyOf(ShrinkableAsMember, ShrinkableAsDecl,
+ unaryOperator(has(ShrinkableAsMember)),
+ unaryOperator(has(ShrinkableAsDecl)))));
+ const auto SwapParam = expr(anyOf(
+ memberExpr(member(equalsBoundNode("ContainerDecl"))),
+ declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl"))),
+ unaryOperator(has(memberExpr(member(equalsBoundNode("ContainerDecl"))))),
+ unaryOperator(
+ has(declRefExpr(hasDeclaration(equalsBoundNode("ContainerDecl")))))));
+
+ Finder->addMatcher(
+ memberCallExpr(on(hasType(namedDecl(stlShrinkableContainer()))),
+ callee(methodDecl(hasName("swap"))),
+ has(memberExpr(hasDescendant(CopyCtorCall))),
+ hasArgument(0, SwapParam.bind("ContainerToShrink")),
+ unless(isInTemplateInstantiation()))
+ .bind("CopyAndSwapTrick"),
+ this);
+}
+
+void ShrinkToFitCheck::check(const MatchFinder::MatchResult &Result) {
+ const LangOptions &Opts = Result.Context->getLangOpts();
+
+ if (!Opts.CPlusPlus11)
+ return;
+
+ const auto *MemberCall =
+ Result.Nodes.getNodeAs<CXXMemberCallExpr>("CopyAndSwapTrick");
+ const auto *Container = Result.Nodes.getNodeAs<Expr>("ContainerToShrink");
+ FixItHint Hint;
+
+ if (!MemberCall->getLocStart().isMacroID()) {
+ std::string ReplacementText;
+ if (const auto *UnaryOp = llvm::dyn_cast<UnaryOperator>(Container)) {
+ ReplacementText =
+ Lexer::getSourceText(CharSourceRange::getTokenRange(
+ UnaryOp->getSubExpr()->getSourceRange()),
+ *Result.SourceManager, Opts);
+ ReplacementText += "->shrink_to_fit()";
+ } else {
+ ReplacementText = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Container->getSourceRange()),
+ *Result.SourceManager, Opts);
+ ReplacementText += ".shrink_to_fit()";
+ }
+
+ Hint = FixItHint::CreateReplacement(MemberCall->getSourceRange(),
+ ReplacementText);
+ }
+
+ diag(MemberCall->getLocStart(), "the shrink_to_fit method should be used "
+ "to reduce the capacity of a shrinkable "
+ "container")
+ << Hint;
+}
+
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.h?rev=226912&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/readability/ShrinkToFitCheck.h Fri Jan 23 09:10:37 2015
@@ -0,0 +1,35 @@
+//===--- ShrinkToFitCheck.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_READABILITY_SHRINK_TO_FIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SHRINK_TO_FIT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+
+/// \brief Replace copy and swap tricks on shrinkable containers with the
+/// \c shrink_to_fit() method call.
+///
+/// The \c shrink_to_fit() method is more readable and more effective than
+/// the copy and swap trick to reduce the capacity of a shrinkable container.
+/// Note that, the \c shrink_to_fit() method is only available in C++11 and up.
+class ShrinkToFitCheck : public ClangTidyCheck {
+public:
+ ShrinkToFitCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SHRINK_TO_FIT_H
Added: clang-tools-extra/trunk/test/clang-tidy/readability-shrink-to-fit.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/readability-shrink-to-fit.cpp?rev=226912&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/readability-shrink-to-fit.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/readability-shrink-to-fit.cpp Fri Jan 23 09:10:37 2015
@@ -0,0 +1,75 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s readability-shrink-to-fit %t
+// REQUIRES: shell
+
+namespace std {
+template <typename T> struct vector { void swap(vector &other); };
+}
+
+void f() {
+ std::vector<int> v;
+
+ std::vector<int>(v).swap(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should be used to reduce the capacity of a shrinkable container [readability-shrink-to-fit]
+ // CHECK-FIXES: {{^ }}v.shrink_to_fit();{{$}}
+
+ std::vector<int> &vref = v;
+ std::vector<int>(vref).swap(vref);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}vref.shrink_to_fit();{{$}}
+
+ std::vector<int> *vptr = &v;
+ std::vector<int>(*vptr).swap(*vptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}vptr->shrink_to_fit();{{$}}
+}
+
+struct X {
+ std::vector<int> v;
+ void f() {
+ std::vector<int>(v).swap(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}v.shrink_to_fit();{{$}}
+
+ std::vector<int> *vptr = &v;
+ std::vector<int>(*vptr).swap(*vptr);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}vptr->shrink_to_fit();{{$}}
+ }
+};
+
+template <typename T> void g() {
+ std::vector<int> v;
+ std::vector<int>(v).swap(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}v.shrink_to_fit();{{$}}
+
+ std::vector<T> v2;
+ std::vector<T>(v2).swap(v2);
+ // CHECK-FIXES: {{^ }}std::vector<T>(v2).swap(v2);{{$}}
+}
+
+template <typename T> void g2() {
+ std::vector<int> v;
+ std::vector<int>(v).swap(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}v.shrink_to_fit();{{$}}
+
+ T v3;
+ T(v3).swap(v3);
+ // CHECK-FIXES: {{^ }}T(v3).swap(v3);{{$}}
+}
+
+#define COPY_AND_SWAP_INT_VEC(x) std::vector<int>(x).swap(x)
+// CHECK-FIXES: #define COPY_AND_SWAP_INT_VEC(x) std::vector<int>(x).swap(x)
+
+void h() {
+ g<int>();
+ g<double>();
+ g<bool>();
+ g2<std::vector<int>>();
+ std::vector<int> v;
+ COPY_AND_SWAP_INT_VEC(v);
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: the shrink_to_fit method should
+ // CHECK-FIXES: {{^ }}COPY_AND_SWAP_INT_VEC(v);{{$}}
+}
+
More information about the cfe-commits
mailing list