clang-tools 6.0.0

ReturnBracedInitListCheck.cpp
Go to the documentation of this file.
1 //===--- ReturnBracedInitListCheck.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 "ReturnBracedInitListCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14 #include "clang/Tooling/FixIt.h"
15
16 using namespace clang::ast_matchers;
17
18 namespace clang {
19 namespace tidy {
20 namespace modernize {
21
22 void ReturnBracedInitListCheck::registerMatchers(MatchFinder *Finder) {
23 // Only register the matchers for C++.
24 if (!getLangOpts().CPlusPlus11)
25 return;
26
27 // Skip list initialization and constructors with an initializer list.
28 auto ConstructExpr =
29 cxxConstructExpr(
30 unless(anyOf(hasDeclaration(cxxConstructorDecl(isExplicit())),
31 isListInitialization(), hasDescendant(initListExpr()),
32 isInTemplateInstantiation())))
33 .bind("ctor");
34
35 auto CtorAsArgument = materializeTemporaryExpr(anyOf(
36 has(ConstructExpr), has(cxxFunctionalCastExpr(has(ConstructExpr)))));
37
38 Finder->addMatcher(
39 functionDecl(isDefinition(), // Declarations don't have return statements.
40 returns(unless(anyOf(builtinType(), autoType()))),
41 hasDescendant(returnStmt(hasReturnValue(
42 has(cxxConstructExpr(has(CtorAsArgument)))))))
43 .bind("fn"),
44 this);
45 }
46
47 void ReturnBracedInitListCheck::check(const MatchFinder::MatchResult &Result) {
48 const auto *MatchedFunctionDecl = Result.Nodes.getNodeAs<FunctionDecl>("fn");
49 const auto *MatchedConstructExpr =
50 Result.Nodes.getNodeAs<CXXConstructExpr>("ctor");
51
52 // Don't make replacements in macro.
53 SourceLocation Loc = MatchedConstructExpr->getExprLoc();
54 if (Loc.isMacroID())
55 return;
56
57 // Make sure that the return type matches the constructed type.
58 const QualType ReturnType =
59 MatchedFunctionDecl->getReturnType().getCanonicalType();
60 const QualType ConstructType =
61 MatchedConstructExpr->getType().getCanonicalType();
62 if (ReturnType != ConstructType)
63 return;
64
65 auto Diag = diag(Loc, "avoid repeating the return type from the "
66 "declaration; use a braced initializer list instead");
67
68 const SourceRange CallParensRange =
69 MatchedConstructExpr->getParenOrBraceRange();
70
71 // Make sure there is an explicit constructor call.
72 if (CallParensRange.isInvalid())
73 return;
74
75 // Make sure that the ctor arguments match the declaration.
76 for (unsigned I = 0, NumParams = MatchedConstructExpr->getNumArgs();
77 I < NumParams; ++I) {
78 if (const auto *VD = dyn_cast<VarDecl>(
79 MatchedConstructExpr->getConstructor()->getParamDecl(I))) {
80 if (MatchedConstructExpr->getArg(I)->getType().getCanonicalType() !=
81 VD->getType().getCanonicalType())
82 return;
83 }
84 }
85
86 // Range for constructor name and opening brace.
87 CharSourceRange CtorCallSourceRange = CharSourceRange::getTokenRange(
88 Loc, CallParensRange.getBegin().getLocWithOffset(-1));
89
90 Diag << FixItHint::CreateRemoval(CtorCallSourceRange)
91 << FixItHint::CreateReplacement(CallParensRange.getBegin(), "{")
92 << FixItHint::CreateReplacement(CallParensRange.getEnd(), "}");
93 }
94
95 } // namespace modernize
96 } // namespace tidy
97 } // namespace clang
Loc
SourceLocation Loc
&#39;#&#39; location in the include directive
Definition: IncludeOrderCheck.cpp:36
clang::ast_matchers
Definition: ClangTidyDiagnosticConsumer.h:27
clang
Definition: AndroidTidyModule.cpp:28
ReturnBracedInitListCheck.h