[clang-tidy] Adding Fuchsia checker for trailing returns

Adds a check to the Fuchsia module to warn if a function has a trailing
return.

See https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md for
reference.

Differential Revision: https://reviews.llvm.org/D42116

llvm-svn: 322759
This commit is contained in:
Julie Hockett 2018-01-17 21:18:15 +00:00
parent 75d7ee6af5
commit 93a88e33ef
8 changed files with 163 additions and 0 deletions

View File

@ -5,6 +5,7 @@ add_clang_library(clangTidyFuchsiaModule
FuchsiaTidyModule.cpp
OverloadedOperatorCheck.cpp
StaticallyConstructedObjectsCheck.cpp
TrailingReturnCheck.cpp
VirtualInheritanceCheck.cpp
LINK_LIBS

View File

@ -13,6 +13,7 @@
#include "DefaultArgumentsCheck.h"
#include "OverloadedOperatorCheck.h"
#include "StaticallyConstructedObjectsCheck.h"
#include "TrailingReturnCheck.h"
#include "VirtualInheritanceCheck.h"
using namespace clang::ast_matchers;
@ -31,6 +32,8 @@ public:
"fuchsia-overloaded-operator");
CheckFactories.registerCheck<StaticallyConstructedObjectsCheck>(
"fuchsia-statically-constructed-objects");
CheckFactories.registerCheck<TrailingReturnCheck>(
"fuchsia-trailing-return");
CheckFactories.registerCheck<VirtualInheritanceCheck>(
"fuchsia-virtual-inheritance");
}

View File

@ -0,0 +1,56 @@
//===--- TrailingReturnCheck.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 "TrailingReturnCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
using namespace clang::ast_matchers;
namespace clang {
namespace ast_matchers {
const internal::VariadicDynCastAllOfMatcher<Type, DecltypeType> decltypeType;
} // namespace ast_matchers
namespace tidy {
namespace fuchsia {
AST_MATCHER(FunctionDecl, hasTrailingReturn) {
return Node.getType()->castAs<FunctionProtoType>()->hasTrailingReturn();
}
void TrailingReturnCheck::registerMatchers(MatchFinder *Finder) {
// Requires C++11 or later.
if (!getLangOpts().CPlusPlus11)
return;
// Functions that have trailing returns are disallowed, except for those
// using decltype specifiers and lambda with otherwise unutterable
// return types.
Finder->addMatcher(
functionDecl(allOf(hasTrailingReturn(),
unless(anyOf(returns(decltypeType()),
hasParent(cxxRecordDecl(isLambda()))))))
.bind("decl"),
this);
}
void TrailingReturnCheck::check(const MatchFinder::MatchResult &Result) {
if (const auto *D = Result.Nodes.getNodeAs<Decl>("decl"))
diag(D->getLocStart(),
"a trailing return type is disallowed for this type of declaration");
}
} // namespace fuchsia
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,37 @@
//===--- TrailingReturnCheck.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_FUCHSIA_TRAILING_RETURN_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_TRAILING_RETURN_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace fuchsia {
/// Functions that have trailing returns are disallowed, except for those
/// using decltype specifiers and lambda with otherwise unutterable
/// return types.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-trailing-return.html
class TrailingReturnCheck : public ClangTidyCheck {
public:
TrailingReturnCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace fuchsia
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_FUCHSIA_TRAILING_RETURN_H

View File

@ -70,7 +70,14 @@ Improvements to clang-tidy
Warns if global, non-trivial objects with static storage are constructed, unless the
object is statically initialized with a ``constexpr`` constructor or has no
explicit constructor.
- New `fuchsia-trailing-return
<http://clang.llvm.org/extra/clang-tidy/checks/fuchsia-trailing-return.html>`_ check
Functions that have trailing returns are disallowed, except for those
using decltype specifiers and lambda with otherwise unutterable
return types.
- New alias `hicpp-avoid-goto
<http://clang.llvm.org/extra/clang-tidy/checks/hicpp-avoid-goto.html>`_ to
`cppcoreguidelines-avoid-goto <http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-avoid-goto.html>`_

View File

@ -0,0 +1,35 @@
.. title:: clang-tidy - fuchsia-trailing-return
fuchsia-trailing-return
=======================
Functions that have trailing returns are disallowed, except for those using
decltype specifiers and lambda with otherwise unutterable return types.
For example:
.. code-block:: c++
// No warning
int add_one(const int arg) { return arg; }
// Warning
auto get_add_one() -> int (*)(const int) {
return add_one;
}
Exceptions are made for lambdas and decltype specifiers:
.. code-block:: c++
// No warning
auto lambda = [](double x, double y) -> double {return x + y;};
// No warning
template <typename T1, typename T2>
auto fn(const T1 &lhs, const T2 &rhs) -> decltype(lhs + rhs) {
return lhs + rhs;
}
See the features disallowed in Fuchsia at https://fuchsia.googlesource.com/zircon/+/master/docs/cxx.md

View File

@ -72,6 +72,7 @@ Clang-Tidy Checks
fuchsia-default-arguments
fuchsia-overloaded-operator
fuchsia-statically-constructed-objects
fuchsia-trailing-return
fuchsia-virtual-inheritance
google-build-explicit-make-pair
google-build-namespaces

View File

@ -0,0 +1,23 @@
// RUN: %check_clang_tidy %s fuchsia-trailing-return %t
int add_one(const int arg) { return arg; }
auto get_add_one() -> int (*)(const int) {
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: a trailing return type is disallowed for this type of declaration
// CHECK-NEXT: auto get_add_one() -> int (*)(const int) {
return add_one;
}
auto lambda = [](double x, double y) {return x + y;};
auto lambda2 = [](double x, double y) -> double {return x + y;};
int main() {
get_add_one()(5);
return 0;
}
template <typename T1, typename T2>
auto fn(const T1 &lhs, const T2 &rhs) -> decltype(lhs + rhs) {
return lhs + rhs;
}