1 //===--- TrailingReturnCheck.cpp - clang-tidy------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "TrailingReturnCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/ASTMatchers/ASTMatchersInternal.h"
14 
15 using namespace clang::ast_matchers;
16 
17 namespace clang {
18 namespace tidy {
19 namespace fuchsia {
20 
21 namespace {
22 const internal::VariadicDynCastAllOfMatcher<Type, DecltypeType> decltypeType;
23 
24 AST_MATCHER(FunctionDecl, hasTrailingReturn) {
25   return Node.getType()->castAs<FunctionProtoType>()->hasTrailingReturn();
26 }
27 } // namespace
28 
29 void TrailingReturnCheck::registerMatchers(MatchFinder *Finder) {
30 
31   // Requires C++11 or later.
32   if (!getLangOpts().CPlusPlus11)
33     return;
34 
35   // Functions that have trailing returns are disallowed, except for those
36   // using decltype specifiers and lambda with otherwise unutterable
37   // return types.
38   Finder->addMatcher(
39       functionDecl(allOf(hasTrailingReturn(),
40                          unless(anyOf(returns(decltypeType()),
41                                       hasParent(cxxRecordDecl(isLambda()))))))
42           .bind("decl"),
43       this);
44 }
45 
46 void TrailingReturnCheck::check(const MatchFinder::MatchResult &Result) {
47   if (const auto *D = Result.Nodes.getNodeAs<Decl>("decl"))
48     diag(D->getLocStart(),
49          "a trailing return type is disallowed for this type of declaration");
50 }
51 
52 } // namespace fuchsia
53 } // namespace tidy
54 } // namespace clang
55