[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / clang-tools-extra / clang-tidy / cppcoreguidelines / MissingStdForwardCheck.cpp
blob0b85ea19735eef90aec2efd37e637614c627d33d
1 //===--- MissingStdForwardCheck.cpp - clang-tidy --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "MissingStdForwardCheck.h"
10 #include "../utils/Matchers.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/ExprConcepts.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
15 using namespace clang::ast_matchers;
17 namespace clang::tidy::cppcoreguidelines {
19 namespace {
21 using matchers::hasUnevaluatedContext;
23 AST_MATCHER_P(QualType, possiblyPackExpansionOf,
24 ast_matchers::internal::Matcher<QualType>, InnerMatcher) {
25 return InnerMatcher.matches(Node.getNonPackExpansionType(), Finder, Builder);
28 AST_MATCHER(ParmVarDecl, isTemplateTypeParameter) {
29 ast_matchers::internal::Matcher<QualType> Inner = possiblyPackExpansionOf(
30 qualType(rValueReferenceType(),
31 references(templateTypeParmType(
32 hasDeclaration(templateTypeParmDecl()))),
33 unless(references(qualType(isConstQualified())))));
34 if (!Inner.matches(Node.getType(), Finder, Builder))
35 return false;
37 const auto *Function = dyn_cast<FunctionDecl>(Node.getDeclContext());
38 if (!Function)
39 return false;
41 const FunctionTemplateDecl *FuncTemplate =
42 Function->getDescribedFunctionTemplate();
43 if (!FuncTemplate)
44 return false;
46 QualType ParamType =
47 Node.getType().getNonPackExpansionType()->getPointeeType();
48 const auto *TemplateType = ParamType->getAs<TemplateTypeParmType>();
49 if (!TemplateType)
50 return false;
52 return TemplateType->getDepth() ==
53 FuncTemplate->getTemplateParameters()->getDepth();
56 } // namespace
58 void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
59 auto ToParam = hasAnyParameter(parmVarDecl(equalsBoundNode("param")));
61 auto ForwardCallMatcher = callExpr(
62 forCallable(equalsBoundNode("func")), argumentCountIs(1),
63 callee(unresolvedLookupExpr(hasAnyDeclaration(
64 namedDecl(hasUnderlyingDecl(hasName("::std::forward")))))),
65 hasArgument(0, declRefExpr(to(equalsBoundNode("param"))).bind("ref")),
66 unless(anyOf(hasAncestor(typeLoc()),
67 hasAncestor(expr(hasUnevaluatedContext())))));
69 Finder->addMatcher(
70 parmVarDecl(parmVarDecl().bind("param"), isTemplateTypeParameter(),
71 hasAncestor(functionDecl().bind("func")),
72 hasAncestor(functionDecl(
73 isDefinition(), equalsBoundNode("func"), ToParam,
74 unless(hasDescendant(std::move(ForwardCallMatcher)))))),
75 this);
78 void MissingStdForwardCheck::check(const MatchFinder::MatchResult &Result) {
79 const auto *Param = Result.Nodes.getNodeAs<ParmVarDecl>("param");
81 if (!Param)
82 return;
84 diag(Param->getLocation(),
85 "forwarding reference parameter %0 is never forwarded "
86 "inside the function body")
87 << Param;
90 } // namespace clang::tidy::cppcoreguidelines