11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14 #include "clang/Tooling/FixIt.h"
16 using namespace clang::ast_matchers;
22 void ReturnBracedInitListCheck::registerMatchers(MatchFinder *
Finder) {
24 if (!getLangOpts().CPlusPlus11)
30 unless(anyOf(hasDeclaration(cxxConstructorDecl(isExplicit())),
31 isListInitialization(), hasDescendant(initListExpr()),
32 isInTemplateInstantiation())))
35 auto CtorAsArgument = materializeTemporaryExpr(anyOf(
36 has(ConstructExpr), has(cxxFunctionalCastExpr(has(ConstructExpr)))));
39 functionDecl(isDefinition(),
40 returns(unless(anyOf(builtinType(), autoType()))),
41 hasDescendant(returnStmt(hasReturnValue(
42 has(cxxConstructExpr(has(CtorAsArgument)))))))
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");
53 SourceLocation
Loc = MatchedConstructExpr->getExprLoc();
58 const QualType ReturnType =
59 MatchedFunctionDecl->getReturnType().getCanonicalType();
60 const QualType ConstructType =
61 MatchedConstructExpr->getType().getCanonicalType();
62 if (ReturnType != ConstructType)
65 auto Diag = diag(Loc,
"avoid repeating the return type from the "
66 "declaration; use a braced initializer list instead");
68 const SourceRange CallParensRange =
69 MatchedConstructExpr->getParenOrBraceRange();
72 if (CallParensRange.isInvalid())
76 for (
unsigned I = 0, NumParams = MatchedConstructExpr->getNumArgs();
78 if (
const auto *VD = dyn_cast<VarDecl>(
79 MatchedConstructExpr->getConstructor()->getParamDecl(I))) {
80 if (MatchedConstructExpr->getArg(I)->getType().getCanonicalType() !=
81 VD->getType().getCanonicalType())
87 CharSourceRange CtorCallSourceRange = CharSourceRange::getTokenRange(
88 Loc, CallParensRange.getBegin().getLocWithOffset(-1));
90 Diag << FixItHint::CreateRemoval(CtorCallSourceRange)
91 << FixItHint::CreateReplacement(CallParensRange.getBegin(),
"{")
92 << FixItHint::CreateReplacement(CallParensRange.getEnd(),
"}");
SourceLocation Loc
'#' location in the include directive
std::unique_ptr< ast_matchers::MatchFinder > Finder