[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / clang-tools-extra / clang-tidy / utils / DeclRefExprUtils.cpp
blob891529997787dbed49eb7b25bb71237f52b678ef
1 //===--- DeclRefExprUtils.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 "DeclRefExprUtils.h"
10 #include "Matchers.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/DeclCXX.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
15 namespace clang::tidy::utils::decl_ref_expr {
17 using namespace ::clang::ast_matchers;
18 using llvm::SmallPtrSet;
20 namespace {
22 template <typename S> bool isSetDifferenceEmpty(const S &S1, const S &S2) {
23 for (auto E : S1)
24 if (S2.count(E) == 0)
25 return false;
26 return true;
29 // Extracts all Nodes keyed by ID from Matches and inserts them into Nodes.
30 template <typename Node>
31 void extractNodesByIdTo(ArrayRef<BoundNodes> Matches, StringRef ID,
32 SmallPtrSet<const Node *, 16> &Nodes) {
33 for (const auto &Match : Matches)
34 Nodes.insert(Match.getNodeAs<Node>(ID));
37 } // namespace
39 // Finds all DeclRefExprs where a const method is called on VarDecl or VarDecl
40 // is the a const reference or value argument to a CallExpr or CXXConstructExpr.
41 SmallPtrSet<const DeclRefExpr *, 16>
42 constReferenceDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt,
43 ASTContext &Context) {
44 auto DeclRefToVar =
45 declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef");
46 auto ConstMethodCallee = callee(cxxMethodDecl(isConst()));
47 // Match method call expressions where the variable is referenced as the this
48 // implicit object argument and operator call expression for member operators
49 // where the variable is the 0-th argument.
50 auto Matches = match(
51 findAll(expr(anyOf(cxxMemberCallExpr(ConstMethodCallee, on(DeclRefToVar)),
52 cxxOperatorCallExpr(ConstMethodCallee,
53 hasArgument(0, DeclRefToVar))))),
54 Stmt, Context);
55 SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
56 extractNodesByIdTo(Matches, "declRef", DeclRefs);
57 auto ConstReferenceOrValue =
58 qualType(anyOf(matchers::isReferenceToConst(),
59 unless(anyOf(referenceType(), pointerType(),
60 substTemplateTypeParmType()))));
61 auto ConstReferenceOrValueOrReplaced = qualType(anyOf(
62 ConstReferenceOrValue,
63 substTemplateTypeParmType(hasReplacementType(ConstReferenceOrValue))));
64 auto UsedAsConstRefOrValueArg = forEachArgumentWithParam(
65 DeclRefToVar, parmVarDecl(hasType(ConstReferenceOrValueOrReplaced)));
66 Matches = match(findAll(invocation(UsedAsConstRefOrValueArg)), Stmt, Context);
67 extractNodesByIdTo(Matches, "declRef", DeclRefs);
68 // References and pointers to const assignments.
69 Matches =
70 match(findAll(declStmt(
71 has(varDecl(hasType(qualType(matchers::isReferenceToConst())),
72 hasInitializer(ignoringImpCasts(DeclRefToVar)))))),
73 Stmt, Context);
74 extractNodesByIdTo(Matches, "declRef", DeclRefs);
75 Matches =
76 match(findAll(declStmt(has(varDecl(
77 hasType(qualType(matchers::isPointerToConst())),
78 hasInitializer(ignoringImpCasts(unaryOperator(
79 hasOperatorName("&"), hasUnaryOperand(DeclRefToVar)))))))),
80 Stmt, Context);
81 extractNodesByIdTo(Matches, "declRef", DeclRefs);
82 return DeclRefs;
85 bool isOnlyUsedAsConst(const VarDecl &Var, const Stmt &Stmt,
86 ASTContext &Context) {
87 // Collect all DeclRefExprs to the loop variable and all CallExprs and
88 // CXXConstructExprs where the loop variable is used as argument to a const
89 // reference parameter.
90 // If the difference is empty it is safe for the loop variable to be a const
91 // reference.
92 auto AllDeclRefs = allDeclRefExprs(Var, Stmt, Context);
93 auto ConstReferenceDeclRefs = constReferenceDeclRefExprs(Var, Stmt, Context);
94 return isSetDifferenceEmpty(AllDeclRefs, ConstReferenceDeclRefs);
97 SmallPtrSet<const DeclRefExpr *, 16>
98 allDeclRefExprs(const VarDecl &VarDecl, const Stmt &Stmt, ASTContext &Context) {
99 auto Matches = match(
100 findAll(declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef")),
101 Stmt, Context);
102 SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
103 extractNodesByIdTo(Matches, "declRef", DeclRefs);
104 return DeclRefs;
107 SmallPtrSet<const DeclRefExpr *, 16>
108 allDeclRefExprs(const VarDecl &VarDecl, const Decl &Decl, ASTContext &Context) {
109 auto Matches = match(
110 decl(forEachDescendant(
111 declRefExpr(to(varDecl(equalsNode(&VarDecl)))).bind("declRef"))),
112 Decl, Context);
113 SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
114 extractNodesByIdTo(Matches, "declRef", DeclRefs);
115 return DeclRefs;
118 bool isCopyConstructorArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
119 ASTContext &Context) {
120 auto UsedAsConstRefArg = forEachArgumentWithParam(
121 declRefExpr(equalsNode(&DeclRef)),
122 parmVarDecl(hasType(matchers::isReferenceToConst())));
123 auto Matches = match(
124 decl(hasDescendant(
125 cxxConstructExpr(UsedAsConstRefArg, hasDeclaration(cxxConstructorDecl(
126 isCopyConstructor())))
127 .bind("constructExpr"))),
128 Decl, Context);
129 return !Matches.empty();
132 bool isCopyAssignmentArgument(const DeclRefExpr &DeclRef, const Decl &Decl,
133 ASTContext &Context) {
134 auto UsedAsConstRefArg = forEachArgumentWithParam(
135 declRefExpr(equalsNode(&DeclRef)),
136 parmVarDecl(hasType(matchers::isReferenceToConst())));
137 auto Matches = match(
138 decl(hasDescendant(
139 cxxOperatorCallExpr(UsedAsConstRefArg, hasOverloadedOperatorName("="),
140 callee(cxxMethodDecl(isCopyAssignmentOperator())))
141 .bind("operatorCallExpr"))),
142 Decl, Context);
143 return !Matches.empty();
146 } // namespace clang::tidy::utils::decl_ref_expr