[clang-tools-extra] r248785 - Create modernize-make-unique check.
Angel Garcia Gomez via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 29 02:36:42 PDT 2015
Author: angelgarcia
Date: Tue Sep 29 04:36:41 2015
New Revision: 248785
URL: http://llvm.org/viewvc/llvm-project?rev=248785&view=rev
Log:
Create modernize-make-unique check.
Summary: create a check that replaces 'std::unique_ptr<type>(new type(args...))' with 'std::make_unique<type>(args...)'. It was on the list of "Ideas for new Tools". It needs to be tested more carefully, but first I wanted to know if you think it is worth the effort.
Reviewers: klimek
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D13166
Added:
clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.cpp
clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.h
clang-tools-extra/trunk/test/clang-tidy/modernize-make-unique.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
Modified: 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=248785&r1=248784&r2=248785&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt Tue Sep 29 04:36:41 2015
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyModernizeModule
LoopConvertCheck.cpp
LoopConvertUtils.cpp
+ MakeUniqueCheck.cpp
ModernizeTidyModule.cpp
PassByValueCheck.cpp
ReplaceAutoPtrCheck.cpp
Added: clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.cpp?rev=248785&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.cpp Tue Sep 29 04:36:41 2015
@@ -0,0 +1,108 @@
+//===--- MakeUniqueCheck.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 "MakeUniqueCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+const char PointerType[] = "pointerType";
+const char ConstructorCall[] = "constructorCall";
+const char NewExpression[] = "newExpression";
+
+void MakeUniqueCheck::registerMatchers(MatchFinder *Finder) {
+ if (getLangOpts().CPlusPlus11) {
+ Finder->addMatcher(
+ cxxBindTemporaryExpr(has(
+ cxxConstructExpr(
+ hasType(qualType(hasDeclaration(classTemplateSpecializationDecl(
+ matchesName("::std::unique_ptr"),
+ templateArgumentCountIs(1),
+ hasTemplateArgument(
+ 0, templateArgument(
+ refersToType(qualType().bind(PointerType)))))))),
+ argumentCountIs(1),
+ hasArgument(0, cxxNewExpr(hasType(pointsTo(qualType(
+ equalsBoundNode(PointerType)))))
+ .bind(NewExpression)))
+ .bind(ConstructorCall))),
+ this);
+ }
+}
+
+void MakeUniqueCheck::check(const MatchFinder::MatchResult &Result) {
+ SourceManager &SM = *Result.SourceManager;
+ const auto *Construct =
+ Result.Nodes.getNodeAs<CXXConstructExpr>(ConstructorCall);
+ const auto *New = Result.Nodes.getNodeAs<CXXNewExpr>(NewExpression);
+ const auto *Type = Result.Nodes.getNodeAs<QualType>(PointerType);
+
+ SourceLocation ConstructCallStart = Construct->getExprLoc();
+
+ bool Invalid = false;
+ StringRef ExprStr = Lexer::getSourceText(
+ CharSourceRange::getCharRange(
+ ConstructCallStart, Construct->getParenOrBraceRange().getBegin()),
+ SM, LangOptions(), &Invalid);
+ if (Invalid)
+ return;
+
+ auto Diag = diag(ConstructCallStart, "use std::make_unique instead");
+
+ // Find the location of the template's left angle.
+ size_t LAngle = ExprStr.find("<");
+ SourceLocation ConstructCallEnd;
+ if (LAngle == StringRef::npos) {
+ // If the template argument is missing (because it is part of the alias)
+ // we have to add it back.
+ ConstructCallEnd = ConstructCallStart.getLocWithOffset(ExprStr.size());
+ Diag << FixItHint::CreateInsertion(ConstructCallEnd,
+ "<" + Type->getAsString() + ">");
+ } else {
+ ConstructCallEnd = ConstructCallStart.getLocWithOffset(LAngle);
+ }
+
+ Diag << FixItHint::CreateReplacement(
+ CharSourceRange::getCharRange(ConstructCallStart, ConstructCallEnd),
+ "std::make_unique");
+
+ SourceLocation NewStart = New->getSourceRange().getBegin();
+ SourceLocation NewEnd = New->getSourceRange().getEnd();
+ switch (New->getInitializationStyle()) {
+ case CXXNewExpr::NoInit: {
+ Diag << FixItHint::CreateRemoval(SourceRange(NewStart, NewEnd));
+ break;
+ }
+ case CXXNewExpr::CallInit: {
+ SourceRange InitRange = New->getDirectInitRange();
+ Diag << FixItHint::CreateRemoval(
+ SourceRange(NewStart, InitRange.getBegin()));
+ Diag << FixItHint::CreateRemoval(SourceRange(InitRange.getEnd(), NewEnd));
+ break;
+ }
+ case CXXNewExpr::ListInit: {
+ SourceRange InitRange = New->getInitializer()->getSourceRange();
+ Diag << FixItHint::CreateRemoval(
+ SourceRange(NewStart, InitRange.getBegin().getLocWithOffset(-1)));
+ Diag << FixItHint::CreateRemoval(
+ SourceRange(InitRange.getEnd().getLocWithOffset(1), NewEnd));
+ break;
+ }
+ }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.h?rev=248785&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/MakeUniqueCheck.h Tue Sep 29 04:36:41 2015
@@ -0,0 +1,41 @@
+//===--- MakeUniqueCheck.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_MAKE_UNIQUE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_UNIQUE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Replace the pattern:
+/// \code
+/// std::unique_ptr<type>(new type(args...))
+/// \endcode
+///
+/// With the C++14 version:
+/// \code
+/// std::make_unique<type>(args...)
+/// \endcode
+class MakeUniqueCheck : public ClangTidyCheck {
+public:
+ MakeUniqueCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKE_UNIQUE_H
+
Modified: 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=248785&r1=248784&r2=248785&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp Tue Sep 29 04:36:41 2015
@@ -11,6 +11,7 @@
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "LoopConvertCheck.h"
+#include "MakeUniqueCheck.h"
#include "PassByValueCheck.h"
#include "ReplaceAutoPtrCheck.h"
#include "ShrinkToFitCheck.h"
@@ -28,6 +29,8 @@ class ModernizeModule : public ClangTidy
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<LoopConvertCheck>("modernize-loop-convert");
+ CheckFactories.registerCheck<MakeUniqueCheck>(
+ "modernize-make-unique");
CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
CheckFactories.registerCheck<ReplaceAutoPtrCheck>(
"modernize-replace-auto-ptr");
Added: clang-tools-extra/trunk/test/clang-tidy/modernize-make-unique.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-make-unique.cpp?rev=248785&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-make-unique.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-make-unique.cpp Tue Sep 29 04:36:41 2015
@@ -0,0 +1,122 @@
+// RUN: %python %S/check_clang_tidy.py %s modernize-make-unique %t
+
+namespace std {
+
+template <typename type>
+class unique_ptr {
+public:
+ unique_ptr(type *ptr);
+ unique_ptr(const unique_ptr<type> &t) = delete;
+ unique_ptr(unique_ptr<type> &&t);
+ ~unique_ptr();
+ type &operator*() { return *ptr; }
+ type *operator->() { return ptr; }
+ type *release();
+ void reset();
+ void reset(type *pt);
+
+private:
+ type *ptr;
+};
+
+}
+
+struct Base {
+ Base();
+ Base(int, int);
+};
+
+struct Derived : public Base {
+ Derived();
+ Derived(int, int);
+};
+
+struct Pair {
+ int a, b;
+};
+
+template<class T> using unique_ptr_ = std::unique_ptr<T>;
+
+int g(std::unique_ptr<int> P);
+
+std::unique_ptr<Base> getPointer() {
+ return std::unique_ptr<Base>(new Base);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_unique instead
+ // CHECK-FIXES: return std::make_unique<Base>();
+}
+
+void f() {
+ std::unique_ptr<int> P1 = std::unique_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+ // CHECK-FIXES: std::unique_ptr<int> P1 = std::make_unique<int>();
+
+ // Without parenthesis.
+ std::unique_ptr<int> P2 = std::unique_ptr<int>(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_unique instead [modernize-make-unique]
+ // CHECK-FIXES: std::unique_ptr<int> P2 = std::make_unique<int>();
+
+ // With auto.
+ auto P3 = std::unique_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+ // CHECK-FIXES: auto P3 = std::make_unique<int>();
+
+ {
+ // No std.
+ using namespace std;
+ unique_ptr<int> Q = unique_ptr<int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_unique instead
+ // CHECK-FIXES: unique_ptr<int> Q = std::make_unique<int>();
+ }
+
+ std::unique_ptr<int> R(new int());
+
+ // Create the unique_ptr as a parameter to a function.
+ int T = g(std::unique_ptr<int>(new int()));
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_unique instead
+ // CHECK-FIXES: int T = g(std::make_unique<int>());
+
+ // Arguments are correctly handled.
+ std::unique_ptr<Base> Pbase = std::unique_ptr<Base>(new Base(5, T));
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<Base> Pbase = std::make_unique<Base>(5, T);
+
+ // Works with init lists.
+ std::unique_ptr<Pair> Ppair = std::unique_ptr<Pair>(new Pair{T, 1});
+ // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<Pair> Ppair = std::make_unique<Pair>({T, 1});
+
+ // Only replace if the type in the template is the same than the type returned
+ // by the new operator.
+ auto Pderived = std::unique_ptr<Base>(new Derived());
+
+ // The pointer is returned by the function, nothing to do.
+ std::unique_ptr<Base> RetPtr = getPointer();
+
+ // Aliases.
+ typedef std::unique_ptr<int> IntPtr;
+ IntPtr Typedef = IntPtr(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_unique instead
+ // CHECK-FIXES: IntPtr Typedef = std::make_unique<int>();
+
+#define PTR unique_ptr<int>
+ std::unique_ptr<int> Macro = std::PTR(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<int> Macro = std::make_unique<int>();
+#undef PTR
+
+ std::unique_ptr<int> Using = unique_ptr_<int>(new int);
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<int> Using = std::make_unique<int>();
+
+ // This emulates std::move.
+ std::unique_ptr<int> Move = static_cast<std::unique_ptr<int>&&>(P1);
+
+ // Adding whitespaces.
+ auto Space = std::unique_ptr <int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_unique instead
+ // CHECK-FIXES: auto Space = std::make_unique<int>();
+
+ auto Spaces = std :: unique_ptr <int>(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_unique instead
+ // CHECK-FIXES: auto Spaces = std::make_unique<int>();
+}
More information about the cfe-commits
mailing list