Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -3,6 +3,7 @@ add_clang_library(clangTidyReadabilityModule AvoidConstParamsInDecls.cpp BracesAroundStatementsCheck.cpp + ConstValueReturnCheck.cpp ContainerSizeEmptyCheck.cpp DeleteNullPointerCheck.cpp DeletedDefaultCheck.cpp Index: clang-tidy/readability/ConstValueReturnCheck.h =================================================================== --- clang-tidy/readability/ConstValueReturnCheck.h +++ clang-tidy/readability/ConstValueReturnCheck.h @@ -0,0 +1,35 @@ +//===--- ConstValueReturnCheck.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_CONST_VALUE_RETURN_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONST_VALUE_RETURN_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Checks for functions that return a const-qualified value type. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-const-value-return.html +class ConstValueReturnCheck : public ClangTidyCheck { +public: + ConstValueReturnCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONST_VALUE_RETURN_H Index: clang-tidy/readability/ConstValueReturnCheck.cpp =================================================================== --- clang-tidy/readability/ConstValueReturnCheck.cpp +++ clang-tidy/readability/ConstValueReturnCheck.cpp @@ -0,0 +1,47 @@ +//===--- ConstValueReturnCheck.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 "ConstValueReturnCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +void ConstValueReturnCheck::registerMatchers(MatchFinder *Finder) { + // Returning const pointers (not pointers to const) does not make much sense, + // returning const references even less so, but it is harmless and we don't + // bother checking it. + // Template parameter types may end up being pointers or references, so we + // skip those too. + Finder->addMatcher(functionDecl(returns(qualType( + isConstQualified(), + unless(anyOf( + isAnyPointer(), + references(type()), + templateTypeParmType(), + hasCanonicalType(templateTypeParmType()) + ))))).bind("func"), this); +} + +void ConstValueReturnCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Func = Result.Nodes.getNodeAs("func"); + diag(Func->getLocation(), "function %0 has a const value return type; this " + "can cause unnecessary copies") + << Func; + // We do not have a FixItHint, because we cannot get the source range for the + // return type (getReturnTypeSourceRange excludes the const qualifier). +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -12,6 +12,7 @@ #include "../ClangTidyModuleRegistry.h" #include "AvoidConstParamsInDecls.h" #include "BracesAroundStatementsCheck.h" +#include "ConstValueReturnCheck.h" #include "ContainerSizeEmptyCheck.h" #include "DeleteNullPointerCheck.h" #include "DeletedDefaultCheck.h" @@ -46,6 +47,8 @@ "readability-avoid-const-params-in-decls"); CheckFactories.registerCheck( "readability-braces-around-statements"); + CheckFactories.registerCheck( + "readability-const-value-return"); CheckFactories.registerCheck( "readability-container-size-empty"); CheckFactories.registerCheck( Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -150,6 +150,7 @@ performance-unnecessary-value-param readability-avoid-const-params-in-decls readability-braces-around-statements + readability-const-value-return readability-container-size-empty readability-delete-null-pointer readability-deleted-default Index: docs/clang-tidy/checks/readability-const-value-return.rst =================================================================== --- docs/clang-tidy/checks/readability-const-value-return.rst +++ docs/clang-tidy/checks/readability-const-value-return.rst @@ -0,0 +1,28 @@ +.. title:: clang-tidy - readability-const-value-return + +readability-const-value-return +============================== + +Checks for functions that return a ``const``-qualified value type. That use of +``const`` is superfluous, and prevents moving the object. Therefore, it should +be avoided. + +Examples: + +.. code-block:: c++ + + const Foo f_bad(); + Foo f_good(); + + Foo foo; + foo = f_bad(); // This requires a copy. + foo = f_good(); // This can use a move. + + +Note that this does not apply to returning pointers or references to const +objects: + +.. code-block:: c++ + + const Foo* f_ptr(); // No issue. + const Foo& f_ref(); // No issue. Index: test/clang-tidy/readability-const-value-return.cpp =================================================================== --- test/clang-tidy/readability-const-value-return.cpp +++ test/clang-tidy/readability-const-value-return.cpp @@ -0,0 +1,33 @@ +// RUN: %check_clang_tidy %s readability-const-value-return %t + +struct X { + int a; +}; + +// This should trigger the check. +const X f_returns_const_value(); +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: function 'f_returns_const_value' has a const value return type; this can cause unnecessary copies [readability-const-value-return] + +// These should not trigger the check. +X f_returns_nonconst_value(); +const X* f_returns_pointer_to_const(); +X* const f_returns_const_pointer(); +const X& f_returns_reference_to_const(); + +typedef X* Xptr; +typedef X& Xref; +const Xptr f_returns_typedef_pointer(); +const Xref f_returns_typedef_reference(); + +// A template parameter type may end up being a pointer or a reference, so we skip it too. +template +const T f_returns_template_param(); + +template +struct S { + using Q = T; + const Q f_returns_template_param_alias(); +}; + +using R = X&; +const R f_returns_reference_alias();