20 auto SemanticallyDifferentContainer = allOf(
24 cxxConstructorDecl(parameterCountIs(3),
25 hasParameter(0, hasType(qualType(hasCanonicalType(
27 hasType(cxxRecordDecl(hasAnyName(
"::std::basic_string",
"::std::vector",
28 "::std::deque",
"::std::forward_list",
35 hasDeclaration(cxxConstructorDecl(isExplicit())),
38 isListInitialization(), hasDescendant(initListExpr()),
40 SemanticallyDifferentContainer)))
44 returnStmt(hasReturnValue(ConstructExpr),
45 forFunction(functionDecl(returns(unless(anyOf(builtinType(),
52 const auto *MatchedFunctionDecl = Result.Nodes.getNodeAs<FunctionDecl>(
"fn");
53 const auto *MatchedConstructExpr =
54 Result.Nodes.getNodeAs<CXXConstructExpr>(
"ctor");
57 SourceLocation Loc = MatchedConstructExpr->getExprLoc();
62 const QualType ReturnType =
63 MatchedFunctionDecl->getReturnType().getCanonicalType();
64 const QualType ConstructType =
65 MatchedConstructExpr->getType().getCanonicalType();
66 if (ReturnType != ConstructType)
69 auto Diag = diag(Loc,
"avoid repeating the return type from the "
70 "declaration; use a braced initializer list instead");
72 const SourceRange CallParensRange =
73 MatchedConstructExpr->getParenOrBraceRange();
76 if (CallParensRange.isInvalid())
80 for (
unsigned I = 0, NumParams = MatchedConstructExpr->getNumArgs();
82 if (
const auto *VD = dyn_cast<VarDecl>(
83 MatchedConstructExpr->getConstructor()->getParamDecl(I))) {
84 if (MatchedConstructExpr->getArg(I)->getType().getCanonicalType() !=
85 VD->getType().getCanonicalType())
91 CharSourceRange CtorCallSourceRange = CharSourceRange::getTokenRange(
92 Loc, CallParensRange.getBegin().getLocWithOffset(-1));
94 Diag << FixItHint::CreateRemoval(CtorCallSourceRange)
95 << FixItHint::CreateReplacement(CallParensRange.getBegin(),
"{")
96 << FixItHint::CreateReplacement(CallParensRange.getEnd(),
"}");