62 auto ForwardingRefParm =
64 hasType(qualType(rValueReferenceType(),
65 references(templateTypeParmType(hasDeclaration(
66 templateTypeParmDecl().bind(
"type-parm-decl")))),
67 unless(references(isConstQualified())))))
70 DeclarationMatcher FindOverload =
72 hasParameter(0, ForwardingRefParm), unless(isDeleted()),
73 unless(hasAnyParameter(
75 parmVarDecl(hasType(isEnableIf())))),
76 unless(hasParent(functionTemplateDecl(anyOf(
79 hasAssociatedConstraints(),
81 has(templateTypeParmDecl(hasDefaultArgument(isEnableIf()))),
83 has(nonTypeTemplateParmDecl(
84 hasType(isEnableIf()),
85 anyOf(hasDescendant(cxxBoolLiteral()),
86 hasDescendant(cxxNullPtrLiteralExpr()),
87 hasDescendant(integerLiteral())))))))))
89 Finder->addMatcher(FindOverload,
this);
93 const MatchFinder::MatchResult &Result) {
94 const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>(
"parm-var");
95 const auto *TypeParmDecl =
96 Result.Nodes.getNodeAs<TemplateTypeParmDecl>(
"type-parm-decl");
100 const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());
103 const FunctionTemplateDecl *FuncTemplate =
104 FuncForParam->getDescribedFunctionTemplate();
111 const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();
112 if (!llvm::is_contained(*Params, TypeParmDecl))
116 const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>(
"ctor");
117 for (
const auto *Param : llvm::drop_begin(Ctor->parameters())) {
118 if (!Param->hasDefaultArg())
121 bool EnabledCopy =
false, DisabledCopy =
false, EnabledMove =
false,
122 DisabledMove =
false;
123 for (
const auto *OtherCtor : Ctor->getParent()->ctors()) {
124 if (OtherCtor->isCopyOrMoveConstructor()) {
125 if (OtherCtor->isDeleted() || OtherCtor->getAccess() == AS_private)
126 (OtherCtor->isCopyConstructor() ? DisabledCopy : DisabledMove) =
true;
128 (OtherCtor->isCopyConstructor() ? EnabledCopy : EnabledMove) =
true;
131 bool Copy = (!EnabledMove && !DisabledMove && !DisabledCopy) || EnabledCopy;
132 bool Move = !DisabledMove || EnabledMove;
135 diag(Ctor->getLocation(),
136 "constructor accepting a forwarding reference can "
137 "hide the %select{copy|move|copy and move}0 constructor%s1")
138 << (Copy &&
Move ? 2 : (Copy ? 0 : 1)) << Copy +
Move;
139 for (
const auto *OtherCtor : Ctor->getParent()->ctors()) {
140 if (OtherCtor->isCopyOrMoveConstructor() && !OtherCtor->isDeleted() &&
141 OtherCtor->getAccess() != AS_private) {
142 diag(OtherCtor->getLocation(),
143 "%select{copy|move}0 constructor declared here", DiagnosticIDs::Note)
144 << OtherCtor->isMoveConstructor();