10 #include "clang/Lex/Lexer.h"
11 #include "llvm/Support/raw_ostream.h"
22 const ParmVarDecl *ParmVar,
23 const TemplateTypeParmDecl *TypeParmDecl,
24 DiagnosticBuilder &Diag,
25 const ASTContext &Context) {
26 const SourceManager &SM = Context.getSourceManager();
27 const LangOptions &LangOpts = Context.getLangOpts();
29 CharSourceRange CallRange =
30 Lexer::makeFileCharRange(CharSourceRange::getTokenRange(
31 Callee->getBeginLoc(), Callee->getEndLoc()),
34 if (CallRange.isValid()) {
35 const std::string TypeName =
36 (TypeParmDecl->getIdentifier() && !TypeParmDecl->isImplicit())
37 ? TypeParmDecl->getName().str()
38 : (llvm::Twine(
"decltype(") + ParmVar->getName() +
")").str();
40 const std::string ForwardName =
41 (llvm::Twine(
"forward<") + TypeName +
">").str();
47 NestedNameSpecifier *NNS = Callee->getQualifier();
52 Diag << FixItHint::CreateReplacement(CallRange,
"std::" + ForwardName);
53 }
else if (
const NamespaceDecl *Namespace = NNS->getAsNamespace()) {
54 if (Namespace->getName() ==
"std") {
55 if (!NNS->getPrefix()) {
57 Diag << FixItHint::CreateReplacement(CallRange,
58 "std::" + ForwardName);
59 }
else if (NNS->getPrefix()->getKind() == NestedNameSpecifier::Global) {
61 Diag << FixItHint::CreateReplacement(CallRange,
62 "::std::" + ForwardName);
69 void MoveForwardingReferenceCheck::registerMatchers(MatchFinder *Finder) {
72 auto ForwardingReferenceParmMatcher =
74 hasType(qualType(rValueReferenceType(),
75 references(templateTypeParmType(hasDeclaration(
76 templateTypeParmDecl().bind(
"type-parm-decl")))),
77 unless(references(qualType(isConstQualified()))))))
81 callExpr(callee(unresolvedLookupExpr(
82 hasAnyDeclaration(namedDecl(
83 hasUnderlyingDecl(hasName(
"::std::move")))))
86 hasArgument(0, ignoringParenImpCasts(declRefExpr(
87 to(ForwardingReferenceParmMatcher)))))
92 void MoveForwardingReferenceCheck::check(
93 const MatchFinder::MatchResult &Result) {
94 const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>(
"call-move");
95 const auto *UnresolvedLookup =
96 Result.Nodes.getNodeAs<UnresolvedLookupExpr>(
"lookup");
97 const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>(
"parm-var");
98 const auto *TypeParmDecl =
99 Result.Nodes.getNodeAs<TemplateTypeParmDecl>(
"type-parm-decl");
103 const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());
106 const FunctionTemplateDecl *FuncTemplate =
107 FuncForParam->getDescribedFunctionTemplate();
114 const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();
115 if (!std::count(Params->begin(), Params->end(), TypeParmDecl))
118 auto Diag = diag(CallMove->getExprLoc(),
119 "forwarding reference passed to std::move(), which may "
120 "unexpectedly cause lvalues to be moved; use "
121 "std::forward() instead");