[clang-tools-extra] r295199 - [clang-tidy] Add check 'modernize-return-braced-init-list'
Jonas Devlieghere via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 15 09:06:07 PST 2017
Author: jdevlieghere
Date: Wed Feb 15 11:06:06 2017
New Revision: 295199
URL: http://llvm.org/viewvc/llvm-project?rev=295199&view=rev
Log:
[clang-tidy] Add check 'modernize-return-braced-init-list'
Summary:
Replaces explicit calls to the constructor in a return with a braced
initializer list. This way the return type is not needlessly duplicated in the
return type and the return statement.
```
Foo bar() {
Baz baz;
return Foo(baz);
}
// transforms to:
Foo bar() {
Baz baz;
return {baz};
}
```
Reviewers: hokein, Prazek, aaron.ballman, alexfh
Reviewed By: Prazek, aaron.ballman, alexfh
Subscribers: malcolm.parsons, mgorny, cfe-commits
Tags: #clang-tools-extra
Differential Revision: https://reviews.llvm.org/D28768
Added:
clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.cpp
clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-return-braced-init-list.rst
clang-tools-extra/trunk/test/clang-tidy/modernize-return-braced-init-list.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
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=295199&r1=295198&r2=295199&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt Wed Feb 15 11:06:06 2017
@@ -13,6 +13,7 @@ add_clang_library(clangTidyModernizeModu
RawStringLiteralCheck.cpp
RedundantVoidArgCheck.cpp
ReplaceAutoPtrCheck.cpp
+ ReturnBracedInitListCheck.cpp
ShrinkToFitCheck.cpp
UseAutoCheck.cpp
UseBoolLiteralsCheck.cpp
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=295199&r1=295198&r2=295199&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp Wed Feb 15 11:06:06 2017
@@ -19,6 +19,7 @@
#include "RawStringLiteralCheck.h"
#include "RedundantVoidArgCheck.h"
#include "ReplaceAutoPtrCheck.h"
+#include "ReturnBracedInitListCheck.h"
#include "ShrinkToFitCheck.h"
#include "UseAutoCheck.h"
#include "UseBoolLiteralsCheck.h"
@@ -53,6 +54,8 @@ public:
"modernize-redundant-void-arg");
CheckFactories.registerCheck<ReplaceAutoPtrCheck>(
"modernize-replace-auto-ptr");
+ CheckFactories.registerCheck<ReturnBracedInitListCheck>(
+ "modernize-return-braced-init-list");
CheckFactories.registerCheck<ShrinkToFitCheck>("modernize-shrink-to-fit");
CheckFactories.registerCheck<UseAutoCheck>("modernize-use-auto");
CheckFactories.registerCheck<UseBoolLiteralsCheck>(
Added: clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.cpp?rev=295199&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.cpp Wed Feb 15 11:06:06 2017
@@ -0,0 +1,97 @@
+//===--- ReturnBracedInitListCheck.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 "ReturnBracedInitListCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+void ReturnBracedInitListCheck::registerMatchers(MatchFinder *Finder) {
+ // Only register the matchers for C++.
+ if (!getLangOpts().CPlusPlus11)
+ return;
+
+ // Skip list initialization and constructors with an initializer list.
+ auto ConstructExpr =
+ cxxConstructExpr(
+ unless(anyOf(hasDeclaration(cxxConstructorDecl(isExplicit())),
+ isListInitialization(), hasDescendant(initListExpr()),
+ isInTemplateInstantiation())))
+ .bind("ctor");
+
+ auto CtorAsArgument = materializeTemporaryExpr(anyOf(
+ has(ConstructExpr), has(cxxFunctionalCastExpr(has(ConstructExpr)))));
+
+ Finder->addMatcher(
+ functionDecl(isDefinition(), // Declarations don't have return statements.
+ returns(unless(anyOf(builtinType(), autoType()))),
+ hasDescendant(returnStmt(hasReturnValue(
+ has(cxxConstructExpr(has(CtorAsArgument)))))))
+ .bind("fn"),
+ this);
+}
+
+void ReturnBracedInitListCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *MatchedFunctionDecl = Result.Nodes.getNodeAs<FunctionDecl>("fn");
+ const auto *MatchedConstructExpr =
+ Result.Nodes.getNodeAs<CXXConstructExpr>("ctor");
+
+ // Don't make replacements in macro.
+ SourceLocation Loc = MatchedConstructExpr->getExprLoc();
+ if (Loc.isMacroID())
+ return;
+
+ // Make sure that the return type matches the constructed type.
+ const QualType ReturnType =
+ MatchedFunctionDecl->getReturnType().getCanonicalType();
+ const QualType ConstructType =
+ MatchedConstructExpr->getType().getCanonicalType();
+ if (ReturnType != ConstructType)
+ return;
+
+ auto Diag = diag(Loc, "avoid repeating the return type from the "
+ "declaration; use a braced initializer list instead");
+
+ const SourceRange CallParensRange =
+ MatchedConstructExpr->getParenOrBraceRange();
+
+ // Make sure there is an explicit constructor call.
+ if (CallParensRange.isInvalid())
+ return;
+
+ // Make sure that the ctor arguments match the declaration.
+ for (unsigned I = 0, NumParams = MatchedConstructExpr->getNumArgs();
+ I < NumParams; ++I) {
+ if (const auto *VD = dyn_cast<VarDecl>(
+ MatchedConstructExpr->getConstructor()->getParamDecl(I))) {
+ if (MatchedConstructExpr->getArg(I)->getType().getCanonicalType() !=
+ VD->getType().getCanonicalType())
+ return;
+ }
+ }
+
+ // Range for constructor name and opening brace.
+ CharSourceRange CtorCallSourceRange = CharSourceRange::getTokenRange(
+ Loc, CallParensRange.getBegin().getLocWithOffset(-1));
+
+ Diag << FixItHint::CreateRemoval(CtorCallSourceRange)
+ << FixItHint::CreateReplacement(CallParensRange.getBegin(), "{")
+ << FixItHint::CreateReplacement(CallParensRange.getEnd(), "}");
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.h?rev=295199&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/ReturnBracedInitListCheck.h Wed Feb 15 11:06:06 2017
@@ -0,0 +1,36 @@
+//===--- ReturnBracedInitListCheck.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_RETURN_BRACED_INIT_LIST_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_RETURN_BRACED_INIT_LIST_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Use a braced init list for return statements rather than unnecessary
+/// repeating the return type name.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-return-braced-init-list.html
+class ReturnBracedInitListCheck : public ClangTidyCheck {
+public:
+ ReturnBracedInitListCheck(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_RETURN_BRACED_INIT_LIST_H
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=295199&r1=295198&r2=295199&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Wed Feb 15 11:06:06 2017
@@ -67,6 +67,12 @@ Improvements to clang-tidy
Finds uses of inline assembler.
+- New `modernize-return-braced-init-list
+ <http://clang.llvm.org/extra/clang-tidy/checks/modernize-return-braced-init-list.html>`_ check
+
+ Finds and replaces explicit calls to the constructor in a return statement by
+ a braced initializer list so that the return type is not needlessly repeated.
+
Improvements to include-fixer
-----------------------------
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=295199&r1=295198&r2=295199&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Wed Feb 15 11:06:06 2017
@@ -109,6 +109,7 @@ Clang-Tidy Checks
modernize-raw-string-literal
modernize-redundant-void-arg
modernize-replace-auto-ptr
+ modernize-return-braced-init-list
modernize-shrink-to-fit
modernize-use-auto
modernize-use-bool-literals
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-return-braced-init-list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-return-braced-init-list.rst?rev=295199&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-return-braced-init-list.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-return-braced-init-list.rst Wed Feb 15 11:06:06 2017
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - modernize-return-braced-init-list
+
+modernize-return-braced-init-list
+=================================
+
+Replaces explicit calls to the constructor in a return with a braced
+initializer list. This way the return type is not needlessly duplicated in the
+function definition and the return statement.
+
+.. code:: c++
+
+ Foo bar() {
+ Baz baz;
+ return Foo(baz);
+ }
+
+ // transforms to:
+
+ Foo bar() {
+ Baz baz;
+ return {baz};
+ }
Added: clang-tools-extra/trunk/test/clang-tidy/modernize-return-braced-init-list.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-return-braced-init-list.cpp?rev=295199&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-return-braced-init-list.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-return-braced-init-list.cpp Wed Feb 15 11:06:06 2017
@@ -0,0 +1,199 @@
+// RUN: %check_clang_tidy %s modernize-return-braced-init-list %t -- --
+// -std=c++14
+
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+
+// libc++'s implementation
+template <class _E>
+class initializer_list {
+ const _E *__begin_;
+ size_t __size_;
+
+ initializer_list(const _E *__b, size_t __s)
+ : __begin_(__b),
+ __size_(__s) {}
+
+public:
+ typedef _E value_type;
+ typedef const _E &reference;
+ typedef const _E &const_reference;
+ typedef size_t size_type;
+
+ typedef const _E *iterator;
+ typedef const _E *const_iterator;
+
+ initializer_list() : __begin_(nullptr), __size_(0) {}
+
+ size_t size() const { return __size_; }
+ const _E *begin() const { return __begin_; }
+ const _E *end() const { return __begin_ + __size_; }
+};
+
+template <typename T>
+class vector {
+public:
+ vector(T) {}
+ vector(std::initializer_list<T>) {}
+};
+}
+
+class Bar {};
+
+Bar b0;
+
+class Foo {
+public:
+ Foo(Bar) {}
+ explicit Foo(Bar, unsigned int) {}
+ Foo(unsigned int) {}
+};
+
+class Baz {
+public:
+ Foo m() {
+ Bar bm;
+ return Foo(bm);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: avoid repeating the return type from the declaration; use a braced initializer list instead [modernize-return-braced-init-list]
+ // CHECK-FIXES: return {bm};
+ }
+};
+
+class Quux : public Foo {
+public:
+ Quux(Bar bar) : Foo(bar) {}
+ Quux(unsigned, unsigned, unsigned k = 0) : Foo(k) {}
+};
+
+Foo f() {
+ Bar b1;
+ return Foo(b1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {b1};
+}
+
+Foo f2() {
+ Bar b2;
+ return {b2};
+}
+
+auto f3() {
+ Bar b3;
+ return Foo(b3);
+}
+
+#define A(b) Foo(b)
+
+Foo f4() {
+ Bar b4;
+ return A(b4);
+}
+
+Foo f5() {
+ Bar b5;
+ return Quux(b5);
+}
+
+Foo f6() {
+ Bar b6;
+ return Foo(b6, 1);
+}
+
+std::vector<int> f7() {
+ int i7 = 1;
+ return std::vector<int>(i7);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+}
+
+Bar f8() {
+ return {};
+}
+
+Bar f9() {
+ return Bar();
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+}
+
+Bar f10() {
+ return Bar{};
+}
+
+Foo f11(Bar b11) {
+ return Foo(b11);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {b11};
+}
+
+Foo f12() {
+ return f11(Bar());
+}
+
+Foo f13() {
+ return Foo(Bar()); // 13
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {Bar()}; // 13
+}
+
+Foo f14() {
+ // FIXME: Type narrowing should not occur!
+ return Foo(-1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {-1};
+}
+
+Foo f15() {
+ return Foo(f10());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {f10()};
+}
+
+Quux f16() {
+ return Quux(1, 2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {1, 2};
+}
+
+Quux f17() {
+ return Quux(1, 2, 3);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: avoid repeating the return type
+ // CHECK-FIXES: return {1, 2, 3};
+}
+
+template <typename T>
+T f19() {
+ return T();
+}
+
+Bar i1 = f19<Bar>();
+Baz i2 = f19<Baz>();
+
+template <typename T>
+Foo f20(T t) {
+ return Foo(t);
+}
+
+Foo i3 = f20(b0);
+
+template <typename T>
+class BazT {
+public:
+ T m() {
+ Bar b;
+ return T(b);
+ }
+
+ Foo m2(T t) {
+ return Foo(t);
+ }
+};
+
+BazT<Foo> bazFoo;
+Foo i4 = bazFoo.m();
+Foo i5 = bazFoo.m2(b0);
+
+BazT<Quux> bazQuux;
+Foo i6 = bazQuux.m();
+Foo i7 = bazQuux.m2(b0);
+
+auto v1 = []() { return std::vector<int>({1, 2}); }();
+auto v2 = []() -> std::vector<int> { return std::vector<int>({1, 2}); }();
More information about the cfe-commits
mailing list