22 if (RD ==
nullptr || !RD->hasDefinition())
24 auto IsInitListCtor = [](
const CXXConstructorDecl *Ctor) {
25 return Ctor->hasOneParamOrDefaultArgs() &&
27 Ctor->getParamDecl(0)->getType().getNonReferenceType());
29 auto TestDecl = [&](
const Decl *D) {
30 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(D))
31 return IsInitListCtor(Ctor);
32 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
33 if (
const auto *Ctor =
34 dyn_cast<CXXConstructorDecl>(FTD->getTemplatedDecl()))
35 return IsInitListCtor(Ctor);
38 const ASTContext &Ctx = RD->getASTContext();
39 const DeclarationName Name =
40 Ctx.DeclarationNames.getCXXConstructorName(Ctx.getCanonicalTagType(RD));
41 return llvm::any_of(RD->lookup(Name), [&](
const NamedDecl *D) {
42 if (const auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(D))
43 return TestDecl(Shadow->getTargetDecl());
49 auto SemanticallyDifferentContainer = allOf(
53 cxxConstructorDecl(parameterCountIs(3),
54 hasParameter(0, hasType(qualType(hasCanonicalType(
56 hasType(cxxRecordDecl(hasAnyName(
"::std::basic_string",
"::std::vector",
57 "::std::deque",
"::std::forward_list",
60 const auto ConstructExpr =
64 hasDeclaration(cxxConstructorDecl(isExplicit())),
67 isListInitialization(), hasDescendant(initListExpr()),
69 SemanticallyDifferentContainer)))
73 returnStmt(hasReturnValue(ConstructExpr),
74 forFunction(functionDecl(returns(unless(anyOf(builtinType(),
81 const auto *MatchedFunctionDecl = Result.Nodes.getNodeAs<FunctionDecl>(
"fn");
82 const auto *MatchedConstructExpr =
83 Result.Nodes.getNodeAs<CXXConstructExpr>(
"ctor");
86 const SourceLocation Loc = MatchedConstructExpr->getExprLoc();
91 const QualType ReturnType =
92 MatchedFunctionDecl->getReturnType().getCanonicalType();
93 const QualType ConstructType =
94 MatchedConstructExpr->getType().getCanonicalType();
95 if (ReturnType != ConstructType)
106 diag(Loc,
"avoid repeating the return type from the "
107 "declaration; use a braced initializer list instead");
109 const SourceRange CallParensRange =
110 MatchedConstructExpr->getParenOrBraceRange();
113 if (CallParensRange.isInvalid())
117 for (
unsigned I = 0, NumParams = MatchedConstructExpr->getNumArgs();
118 I < NumParams; ++I) {
119 if (
const ParmVarDecl *VD =
120 MatchedConstructExpr->getConstructor()->getParamDecl(I)) {
121 const auto ArgType = MatchedConstructExpr->getArg(I)->getType();
122 const auto ParamType = VD->getType().getNonReferenceType();
123 if (ArgType.getCanonicalType().getUnqualifiedType() !=
124 ParamType.getCanonicalType().getUnqualifiedType())
130 const CharSourceRange CtorCallSourceRange = CharSourceRange::getTokenRange(
131 Loc, CallParensRange.getBegin().getLocWithOffset(-1));
133 Diag << FixItHint::CreateRemoval(CtorCallSourceRange)
134 << FixItHint::CreateReplacement(CallParensRange.getBegin(),
"{")
135 << FixItHint::CreateReplacement(CallParensRange.getEnd(),
"}");