[clang-tools-extra] r245045 - [clang-tidy] Create clang-tidy module modernize. Add pass-by-value check.
Alexander Kornienko via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 14 06:17:13 PDT 2015
Author: alexfh
Date: Fri Aug 14 08:17:11 2015
New Revision: 245045
URL: http://llvm.org/viewvc/llvm-project?rev=245045&view=rev
Log:
[clang-tidy] Create clang-tidy module modernize. Add pass-by-value check.
This is the first step for migrating cppmodernize to clang-tidy.
http://reviews.llvm.org/D11946
Patch by Angel Garcia!
Added:
clang-tools-extra/trunk/clang-tidy/modernize/
clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/modernize/Makefile
clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.cpp
clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.h
clang-tools-extra/trunk/test/clang-tidy/modernize-pass-by-value.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/Makefile
clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
clang-tools-extra/trunk/clang-tidy/tool/Makefile
Modified: clang-tools-extra/trunk/clang-tidy/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/CMakeLists.txt?rev=245045&r1=245044&r2=245045&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/CMakeLists.txt Fri Aug 14 08:17:11 2015
@@ -31,5 +31,6 @@ add_subdirectory(tool)
add_subdirectory(llvm)
add_subdirectory(google)
add_subdirectory(misc)
+add_subdirectory(modernize)
add_subdirectory(readability)
add_subdirectory(utils)
Modified: clang-tools-extra/trunk/clang-tidy/Makefile
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/Makefile?rev=245045&r1=245044&r2=245045&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/Makefile (original)
+++ clang-tools-extra/trunk/clang-tidy/Makefile Fri Aug 14 08:17:11 2015
@@ -11,6 +11,6 @@ CLANG_LEVEL := ../../..
LIBRARYNAME := clangTidy
include $(CLANG_LEVEL)/../../Makefile.config
-DIRS = utils readability llvm google misc tool
+DIRS = utils readability llvm google misc modernize tool
include $(CLANG_LEVEL)/Makefile
Added: clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt?rev=245045&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt Fri Aug 14 08:17:11 2015
@@ -0,0 +1,14 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyModernizeModule
+ ModernizeTidyModule.cpp
+ PassByValueCheck.cpp
+
+ LINK_LIBS
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangLex
+ clangTidy
+ clangTidyReadabilityModule
+ )
Added: clang-tools-extra/trunk/clang-tidy/modernize/Makefile
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/Makefile?rev=245045&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/Makefile (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/Makefile Fri Aug 14 08:17:11 2015
@@ -0,0 +1,12 @@
+##===- clang-tidy/modernize/Makefile -----------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+CLANG_LEVEL := ../../../..
+LIBRARYNAME := clangTidyModernizeModule
+
+include $(CLANG_LEVEL)/Makefile
Added: clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp?rev=245045&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp Fri Aug 14 08:17:11 2015
@@ -0,0 +1,46 @@
+//===--- ModernizeTidyModule.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 "../ClangTidy.h"
+#include "../ClangTidyModule.h"
+#include "../ClangTidyModuleRegistry.h"
+#include "PassByValueCheck.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+class ModernizeModule : public ClangTidyModule {
+public:
+ void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
+ }
+
+ ClangTidyOptions getModuleOptions() override {
+ ClangTidyOptions Options;
+ auto &Opts = Options.CheckOptions;
+ Opts["modernize-pass-by-value.IncludeStyle"] = "llvm"; // Also: "google".
+ return Options;
+ }
+};
+
+// Register the ModernizeTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<ModernizeModule> X("modernize-module",
+ "Add modernize checks.");
+
+} // namespace modernize
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the ModernizeModule.
+volatile int ModernizeModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.cpp?rev=245045&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.cpp Fri Aug 14 08:17:11 2015
@@ -0,0 +1,223 @@
+//===--- PassByValueCheck.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 "PassByValueCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+
+using namespace clang::ast_matchers;
+using namespace llvm;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// \brief Matches move-constructible classes.
+///
+/// Given
+/// \code
+/// // POD types are trivially move constructible.
+/// struct Foo { int a; };
+///
+/// struct Bar {
+/// Bar(Bar &&) = deleted;
+/// int a;
+/// };
+/// \endcode
+/// recordDecl(isMoveConstructible())
+/// matches "Foo".
+AST_MATCHER(CXXRecordDecl, isMoveConstructible) {
+ for (const CXXConstructorDecl *Ctor : Node.ctors()) {
+ if (Ctor->isMoveConstructor() && !Ctor->isDeleted())
+ return true;
+ }
+ return false;
+}
+
+/// \brief Matches non-deleted copy constructors.
+///
+/// Given
+/// \code
+/// struct Foo { Foo(const Foo &) = default; };
+/// struct Bar { Bar(const Bar &) = deleted; };
+/// \endcode
+/// constructorDecl(isNonDeletedCopyConstructor())
+/// matches "Foo(const Foo &)".
+AST_MATCHER(CXXConstructorDecl, isNonDeletedCopyConstructor) {
+ return Node.isCopyConstructor() && !Node.isDeleted();
+}
+
+static TypeMatcher constRefType() {
+ return lValueReferenceType(pointee(isConstQualified()));
+}
+
+static TypeMatcher nonConstValueType() {
+ return qualType(unless(anyOf(referenceType(), isConstQualified())));
+}
+
+/// \brief Whether or not \p ParamDecl is used exactly one time in \p Ctor.
+///
+/// Checks both in the init-list and the body of the constructor.
+static bool paramReferredExactlyOnce(const CXXConstructorDecl *Ctor,
+ const ParmVarDecl *ParamDecl) {
+ /// \brief \c clang::RecursiveASTVisitor that checks that the given
+ /// \c ParmVarDecl is used exactly one time.
+ ///
+ /// \see ExactlyOneUsageVisitor::hasExactlyOneUsageIn()
+ class ExactlyOneUsageVisitor
+ : public RecursiveASTVisitor<ExactlyOneUsageVisitor> {
+ friend class RecursiveASTVisitor<ExactlyOneUsageVisitor>;
+
+ public:
+ ExactlyOneUsageVisitor(const ParmVarDecl *ParamDecl)
+ : ParamDecl(ParamDecl) {}
+
+ /// \brief Whether or not the parameter variable is referred only once in
+ /// the
+ /// given constructor.
+ bool hasExactlyOneUsageIn(const CXXConstructorDecl *Ctor) {
+ Count = 0;
+ TraverseDecl(const_cast<CXXConstructorDecl *>(Ctor));
+ return Count == 1;
+ }
+
+ private:
+ /// \brief Counts the number of references to a variable.
+ ///
+ /// Stops the AST traversal if more than one usage is found.
+ bool VisitDeclRefExpr(DeclRefExpr *D) {
+ if (const ParmVarDecl *To = dyn_cast<ParmVarDecl>(D->getDecl())) {
+ if (To == ParamDecl) {
+ ++Count;
+ if (Count > 1) {
+ // No need to look further, used more than once.
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ const ParmVarDecl *ParamDecl;
+ unsigned Count;
+ };
+
+ return ExactlyOneUsageVisitor(ParamDecl).hasExactlyOneUsageIn(Ctor);
+}
+
+/// \brief Find all references to \p ParamDecl across all of the
+/// redeclarations of \p Ctor.
+static SmallVector<const ParmVarDecl *, 2>
+collectParamDecls(const CXXConstructorDecl *Ctor,
+ const ParmVarDecl *ParamDecl) {
+ SmallVector<const ParmVarDecl *, 2> Results;
+ unsigned ParamIdx = ParamDecl->getFunctionScopeIndex();
+
+ for (const FunctionDecl *Redecl : Ctor->redecls())
+ Results.push_back(Redecl->getParamDecl(ParamIdx));
+ return Results;
+}
+
+PassByValueCheck::PassByValueCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ IncludeStyle(Options.get("IncludeStyle", "llvm") == "llvm" ?
+ IncludeSorter::IS_LLVM : IncludeSorter::IS_Google) {}
+
+void PassByValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "IncludeStyle",
+ IncludeStyle == IncludeSorter::IS_LLVM ? "llvm" : "google");
+}
+
+void PassByValueCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ constructorDecl(
+ forEachConstructorInitializer(
+ ctorInitializer(
+ // Clang builds a CXXConstructExpr only whin it knows which
+ // constructor will be called. In dependent contexts a
+ // ParenListExpr is generated instead of a CXXConstructExpr,
+ // filtering out templates automatically for us.
+ withInitializer(constructExpr(
+ has(declRefExpr(to(
+ parmVarDecl(
+ hasType(qualType(
+ // Match only const-ref or a non-const value
+ // parameters. Rvalues and const-values
+ // shouldn't be modified.
+ anyOf(constRefType(), nonConstValueType()))))
+ .bind("Param")))),
+ hasDeclaration(constructorDecl(
+ isNonDeletedCopyConstructor(),
+ hasDeclContext(recordDecl(isMoveConstructible())))))))
+ .bind("Initializer")))
+ .bind("Ctor"),
+ this);
+}
+
+void PassByValueCheck::registerPPCallbacks(CompilerInstance &Compiler) {
+ Inserter.reset(new IncludeInserter(Compiler.getSourceManager(),
+ Compiler.getLangOpts(), IncludeStyle));
+ Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
+}
+
+void PassByValueCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("Ctor");
+ const auto *ParamDecl = Result.Nodes.getNodeAs<ParmVarDecl>("Param");
+ const auto *Initializer =
+ Result.Nodes.getNodeAs<CXXCtorInitializer>("Initializer");
+ SourceManager &SM = *Result.SourceManager;
+
+ // If the parameter is used or anything other than the copy, do not apply
+ // the changes.
+ if (!paramReferredExactlyOnce(Ctor, ParamDecl))
+ return;
+
+ auto Diag = diag(ParamDecl->getLocStart(), "pass by value and use std::move");
+
+ // Iterate over all declarations of the constructor.
+ for (const ParmVarDecl *ParmDecl : collectParamDecls(Ctor, ParamDecl)) {
+ auto ParamTL = ParmDecl->getTypeSourceInfo()->getTypeLoc();
+ auto RefTL = ParamTL.getAs<ReferenceTypeLoc>();
+
+ // Do not replace if it is already a value, skip.
+ if (RefTL.isNull())
+ continue;
+
+ TypeLoc ValueTL = RefTL.getPointeeLoc();
+ auto TypeRange = CharSourceRange::getTokenRange(ParmDecl->getLocStart(),
+ ParamTL.getLocEnd());
+ std::string ValueStr =
+ Lexer::getSourceText(
+ CharSourceRange::getTokenRange(ValueTL.getSourceRange()), SM,
+ Result.Context->getLangOpts())
+ .str();
+ ValueStr += ' ';
+ Diag << FixItHint::CreateReplacement(TypeRange, ValueStr);
+ }
+
+ // Use std::move in the initialization list.
+ Diag << FixItHint::CreateInsertion(Initializer->getRParenLoc(), ")")
+ << FixItHint::CreateInsertion(
+ Initializer->getLParenLoc().getLocWithOffset(1), "std::move(");
+
+ auto Insertion =
+ Inserter->CreateIncludeInsertion(SM.getMainFileID(), "utility",
+ /*IsAngled=*/true);
+ if (Insertion.hasValue())
+ Diag << Insertion.getValue();
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.h?rev=245045&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/PassByValueCheck.h Fri Aug 14 08:17:11 2015
@@ -0,0 +1,39 @@
+//===--- PassByValueCheck.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_PASS_BY_VALUE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_PASS_BY_VALUE_H
+
+#include "../ClangTidy.h"
+#include "../IncludeInserter.h"
+
+#include <memory>
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+class PassByValueCheck : public ClangTidyCheck {
+public:
+ PassByValueCheck(StringRef Name, ClangTidyContext *Context);
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerPPCallbacks(clang::CompilerInstance &Compiler) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ std::unique_ptr<IncludeInserter> Inserter;
+ const IncludeSorter::IncludeStyle IncludeStyle;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_PASS_BY_VALUE_H
Modified: clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt?rev=245045&r1=245044&r2=245045&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/tool/CMakeLists.txt Fri Aug 14 08:17:11 2015
@@ -13,6 +13,7 @@ target_link_libraries(clang-tidy
clangTidyGoogleModule
clangTidyLLVMModule
clangTidyMiscModule
+ clangTidyModernizeModule
clangTidyReadabilityModule
clangTooling
)
Modified: clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp?rev=245045&r1=245044&r2=245045&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/tool/ClangTidyMain.cpp Fri Aug 14 08:17:11 2015
@@ -346,6 +346,10 @@ static int LLVM_ATTRIBUTE_UNUSED GoogleM
extern volatile int MiscModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED MiscModuleAnchorDestination = MiscModuleAnchorSource;
+// This anchor is used to force the linker to link the ModernizeModule.
+extern volatile int ModernizeModuleAnchorSource;
+static int ModernizeModuleAnchorDestination = ModernizeModuleAnchorSource;
+
// This anchor is used to force the linker to link the ReadabilityModule.
extern volatile int ReadabilityModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination = ReadabilityModuleAnchorSource;
Modified: clang-tools-extra/trunk/clang-tidy/tool/Makefile
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/tool/Makefile?rev=245045&r1=245044&r2=245045&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/tool/Makefile (original)
+++ clang-tools-extra/trunk/clang-tidy/tool/Makefile Fri Aug 14 08:17:11 2015
@@ -17,9 +17,9 @@ TOOL_NO_EXPORTS = 1
include $(CLANG_LEVEL)/../../Makefile.config
LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option
USEDLIBS = clangTidy.a clangTidyLLVMModule.a clangTidyGoogleModule.a \
- clangTidyMiscModule.a clangTidyReadability.a clangTidyUtils.a \
- clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a \
- clangStaticAnalyzerCore.a \
+ clangTidyMiscModule.a clangTidyModernizeModule.a clangTidyReadability.a \
+ clangTidyUtils.a clangStaticAnalyzerFrontend.a \
+ clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \
clangFormat.a clangASTMatchers.a clangTooling.a clangToolingCore.a \
clangFrontend.a clangSerialization.a clangDriver.a clangParse.a \
clangSema.a clangAnalysis.a clangRewriteFrontend.a clangRewrite.a \
Added: clang-tools-extra/trunk/test/clang-tidy/modernize-pass-by-value.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-pass-by-value.cpp?rev=245045&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-pass-by-value.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-pass-by-value.cpp Fri Aug 14 08:17:11 2015
@@ -0,0 +1,197 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-pass-by-value %t
+// REQUIRES: shell
+
+// CHECK-FIXES: #include <utility>
+
+namespace {
+// POD types are trivially move constructible.
+struct Movable {
+ int a, b, c;
+};
+
+struct NotMovable {
+ NotMovable() = default;
+ NotMovable(const NotMovable &) = default;
+ NotMovable(NotMovable &&) = delete;
+ int a, b, c;
+};
+}
+
+struct A {
+ A(const Movable &M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
+ // CHECK-FIXES: A(Movable M) : M(std::move(M)) {}
+ Movable M;
+};
+
+// Test that we aren't modifying other things than a parameter.
+Movable GlobalObj;
+struct B {
+ B(const Movable &M) : M(GlobalObj) {}
+ // CHECK-FIXES: B(const Movable &M) : M(GlobalObj) {}
+ Movable M;
+};
+
+// Test that a parameter with more than one reference to it won't be changed.
+struct C {
+ // Tests extra-reference in body.
+ C(const Movable &M) : M(M) { this->i = M.a; }
+ // CHECK-FIXES: C(const Movable &M) : M(M) { this->i = M.a; }
+
+ // Tests extra-reference in init-list.
+ C(const Movable &M, int) : M(M), i(M.a) {}
+ // CHECK-FIXES: C(const Movable &M, int) : M(M), i(M.a) {}
+ Movable M;
+ int i;
+};
+
+// Test that both declaration and definition are updated.
+struct D {
+ D(const Movable &M);
+ // CHECK-FIXES: D(Movable M);
+ Movable M;
+};
+D::D(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: D::D(Movable M) : M(std::move(M)) {}
+
+// Test with default parameter.
+struct E {
+ E(const Movable &M = Movable()) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: E(Movable M = Movable()) : M(std::move(M)) {}
+ Movable M;
+};
+
+// Test with object that can't be moved.
+struct F {
+ F(const NotMovable &NM) : NM(NM) {}
+ // CHECK-FIXES: F(const NotMovable &NM) : NM(NM) {}
+ NotMovable NM;
+};
+
+// Test unnamed parameter in declaration.
+struct G {
+ G(const Movable &);
+ // CHECK-FIXES: G(Movable );
+ Movable M;
+};
+G::G(const Movable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: G::G(Movable M) : M(std::move(M)) {}
+
+// Test parameter with and without qualifier.
+namespace ns_H {
+typedef ::Movable HMovable;
+}
+struct H {
+ H(const ns_H::HMovable &M);
+ // CHECK-FIXES: H(ns_H::HMovable M);
+ ns_H::HMovable M;
+};
+using namespace ns_H;
+H::H(const HMovable &M) : M(M) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
+// CHECK-FIXES: H(HMovable M) : M(std::move(M)) {}
+
+// Try messing up with macros.
+#define MOVABLE_PARAM(Name) const Movable & Name
+// CHECK-FIXES: #define MOVABLE_PARAM(Name) const Movable & Name
+struct I {
+ I(MOVABLE_PARAM(M)) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: I(MOVABLE_PARAM(M)) : M(M) {}
+ Movable M;
+};
+#undef MOVABLE_PARAM
+
+// Test that templates aren't modified.
+template <typename T> struct J {
+ J(const T &M) : M(M) {}
+ // CHECK-FIXES: J(const T &M) : M(M) {}
+ T M;
+};
+J<Movable> j1(Movable());
+J<NotMovable> j2(NotMovable());
+
+struct K_Movable {
+ K_Movable() = default;
+ K_Movable(const K_Movable &) = default;
+ K_Movable(K_Movable &&o) { dummy = o.dummy; }
+ int dummy;
+};
+
+// Test with movable type with an user defined move constructor.
+struct K {
+ K(const K_Movable &M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: K(K_Movable M) : M(std::move(M)) {}
+ K_Movable M;
+};
+
+template <typename T> struct L {
+ L(const Movable &M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: L(Movable M) : M(std::move(M)) {}
+ Movable M;
+};
+L<int> l(Movable());
+
+// Test with a non-instantiated template class.
+template <typename T> struct N {
+ N(const Movable &M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: N(Movable M) : M(std::move(M)) {}
+
+ Movable M;
+ T A;
+};
+
+// Test with value parameter.
+struct O {
+ O(Movable M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: O(Movable M) : M(std::move(M)) {}
+ Movable M;
+};
+
+// Test with a const-value parameter.
+struct P {
+ P(const Movable M) : M(M) {}
+ // CHECK-FIXES: P(const Movable M) : M(M) {}
+ Movable M;
+};
+
+// Test with multiples parameters where some need to be changed and some don't.
+// need to.
+struct Q {
+ Q(const Movable &A, const Movable &B, const Movable &C, double D)
+ : A(A), B(B), C(C), D(D) {}
+ // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: pass by value and use std::move
+ // CHECK-MESSAGES: :[[@LINE-3]]:41: warning: pass by value and use std::move
+ // CHECK-FIXES: Q(const Movable &A, Movable B, Movable C, double D)
+ // CHECK-FIXES: : A(A), B(std::move(B)), C(std::move(C)), D(D) {}
+ const Movable &A;
+ Movable B;
+ Movable C;
+ double D;
+};
+
+// Test that value-parameters with a nested name specifier are left as-is.
+namespace ns_R {
+typedef ::Movable RMovable;
+}
+struct R {
+ R(ns_R::RMovable M) : M(M) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
+ // CHECK-FIXES: R(ns_R::RMovable M) : M(std::move(M)) {}
+ ns_R::RMovable M;
+};
+
+// Test with rvalue parameter.
+struct S {
+ S(Movable &&M) : M(M) {}
+ // CHECK-FIXES: S(Movable &&M) : M(M) {}
+ Movable M;
+};
+
More information about the cfe-commits
mailing list