clang 22.0.0git
SmartPointerAccessorCaching.cpp
Go to the documentation of this file.
2
4#include "clang/AST/DeclCXX.h"
5#include "clang/AST/Type.h"
9
10namespace clang::dataflow {
11
12namespace {
13
14using ast_matchers::callee;
18using ast_matchers::hasCanonicalType;
21using ast_matchers::ofClass;
22using ast_matchers::parameterCountIs;
25using ast_matchers::returns;
26
27CanQualType getLikeReturnType(QualType RT) {
28 if (!RT.isNull() && RT->isPointerType()) {
29 return RT->getPointeeType()
30 ->getCanonicalTypeUnqualified()
31 .getUnqualifiedType();
32 }
33 return {};
34}
35
36CanQualType valueLikeReturnType(QualType RT) {
37 if (!RT.isNull() && RT->isReferenceType()) {
38 return RT.getNonReferenceType()
39 ->getCanonicalTypeUnqualified()
40 .getUnqualifiedType();
41 }
42 return {};
43}
44
45CanQualType pointerLikeReturnType(const CXXRecordDecl &RD) {
46 // We may want to cache this search, but in current profiles it hasn't shown
47 // up as a hot spot (possibly because there aren't many hits, relatively).
48 CanQualType StarReturnType, ArrowReturnType;
49 for (const auto *MD : RD.methods()) {
50 // We only consider methods that are const and have zero parameters.
51 // It may be that there is a non-const overload for the method, but
52 // there should at least be a const overload as well.
53 if (!MD->isConst() || MD->getNumParams() != 0)
54 continue;
55 switch (MD->getOverloadedOperator()) {
56 case OO_Star:
57 StarReturnType = valueLikeReturnType(MD->getReturnType());
58 break;
59 case OO_Arrow:
60 ArrowReturnType = getLikeReturnType(MD->getReturnType());
61 break;
62 default:
63 break;
64 }
65 }
66 if (!StarReturnType.isNull() && !ArrowReturnType.isNull() &&
67 StarReturnType == ArrowReturnType)
68 return StarReturnType;
69
70 return {};
71}
72
73QualType findReturnType(const CXXRecordDecl &RD, StringRef MethodName) {
74 for (const auto *MD : RD.methods()) {
75 // We only consider methods that are const and have zero parameters.
76 // It may be that there is a non-const overload for the method, but
77 // there should at least be a const overload as well.
78 if (!MD->isConst() || MD->getNumParams() != 0 ||
79 MD->getOverloadedOperator() != OO_None)
80 continue;
81 clang::IdentifierInfo *II = MD->getIdentifier();
82 if (II && II->isStr(MethodName))
83 return MD->getReturnType();
84 }
85 return {};
86}
87
88} // namespace
89} // namespace clang::dataflow
90
91// AST_MATCHER macros create an "internal" namespace, so we put it in
92// its own anonymous namespace instead of in clang::dataflow.
93namespace {
94
95using clang::dataflow::findReturnType;
96using clang::dataflow::getLikeReturnType;
97using clang::dataflow::pointerLikeReturnType;
98using clang::dataflow::valueLikeReturnType;
99
100AST_MATCHER_P(clang::CXXRecordDecl, smartPointerClassWithGetLike,
101 clang::StringRef, MethodName) {
102 auto RT = pointerLikeReturnType(Node);
103 if (RT.isNull())
104 return false;
105 return getLikeReturnType(findReturnType(Node, MethodName)) == RT;
106}
107
108AST_MATCHER_P(clang::CXXRecordDecl, smartPointerClassWithValueLike,
109 clang::StringRef, MethodName) {
110 auto RT = pointerLikeReturnType(Node);
111 if (RT.isNull())
112 return false;
113 return valueLikeReturnType(findReturnType(Node, MethodName)) == RT;
114}
115
116AST_MATCHER(clang::CXXRecordDecl, smartPointerClassWithGetOrValue) {
117 auto RT = pointerLikeReturnType(Node);
118 if (RT.isNull())
119 return false;
120 return getLikeReturnType(findReturnType(Node, "get")) == RT ||
121 valueLikeReturnType(findReturnType(Node, "value")) == RT;
122}
123
124AST_MATCHER(clang::CXXRecordDecl, pointerClass) {
125 return !pointerLikeReturnType(Node).isNull();
126}
127
128} // namespace
129
130namespace clang::dataflow {
131
133 return cxxOperatorCallExpr(
135 callee(cxxMethodDecl(parameterCountIs(0),
136 returns(hasCanonicalType(referenceType())),
137 ofClass(smartPointerClassWithGetOrValue()))));
138}
139
141 return cxxOperatorCallExpr(
143 callee(cxxMethodDecl(parameterCountIs(0),
144 returns(hasCanonicalType(pointerType())),
145 ofClass(smartPointerClassWithGetOrValue()))));
146}
147
149 return cxxOperatorCallExpr(
151 callee(cxxMethodDecl(parameterCountIs(0),
152 returns(hasCanonicalType(referenceType())),
153 ofClass(pointerClass()))));
154}
155
157 return cxxOperatorCallExpr(
159 callee(cxxMethodDecl(parameterCountIs(0),
160 returns(hasCanonicalType(pointerType())),
161 ofClass(pointerClass()))));
162}
163
165isSmartPointerLikeValueMethodCall(clang::StringRef MethodName) {
166 return cxxMemberCallExpr(callee(cxxMethodDecl(
167 parameterCountIs(0), returns(hasCanonicalType(referenceType())),
168 hasName(MethodName),
169 ofClass(smartPointerClassWithValueLike(MethodName)))));
170}
171
173isSmartPointerLikeGetMethodCall(clang::StringRef MethodName) {
174 return cxxMemberCallExpr(callee(cxxMethodDecl(
175 parameterCountIs(0), returns(hasCanonicalType(pointerType())),
176 hasName(MethodName), ofClass(smartPointerClassWithGetLike(MethodName)))));
177}
178
179const FunctionDecl *
181 const FunctionDecl *CanonicalCallee = nullptr;
182 const CXXMethodDecl *Callee =
183 cast_or_null<CXXMethodDecl>(CE->getDirectCallee());
184 if (Callee == nullptr)
185 return nullptr;
186 const CXXRecordDecl *RD = Callee->getParent();
187 if (RD == nullptr)
188 return nullptr;
189 for (const auto *MD : RD->methods()) {
190 if (MD->getOverloadedOperator() == OO_Star && MD->isConst() &&
191 MD->getNumParams() == 0 && MD->getReturnType()->isReferenceType()) {
192 CanonicalCallee = MD;
193 break;
194 }
195 }
196 return CanonicalCallee;
197}
198
199} // namespace clang::dataflow
#define AST_MATCHER(Type, DefineMatcher)
AST_MATCHER(Type, DefineMatcher) { ... } defines a zero parameter function named DefineMatcher() that...
#define AST_MATCHER_P(Type, DefineMatcher, ParamType, Param)
AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } defines a single-parameter function name...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines an enumeration for C++ overloaded operators.
C Language Family Type Representation.
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
method_range methods() const
Definition DeclCXX.h:650
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3060
Represents a function declaration or definition.
Definition Decl.h:1999
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
internal::Matcher< NamedDecl > hasName(StringRef Name)
Matches NamedDecl nodes that have the specified name.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXMemberCallExpr > cxxMemberCallExpr
Matches member call expressions.
internal::Matcher< Stmt > StatementMatcher
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXOperatorCallExpr > cxxOperatorCallExpr
Matches overloaded operator calls.
const AstTypeMatcher< PointerType > pointerType
internal::PolymorphicMatcher< internal::HasOverloadedOperatorNameMatcher, AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl), std::vector< std::string > > hasOverloadedOperatorName(StringRef Name)
Matches overloaded operator names.
const internal::VariadicDynCastAllOfMatcher< Decl, CXXMethodDecl > cxxMethodDecl
Matches method declarations.
const AstTypeMatcher< ReferenceType > referenceType
Dataflow Directional Tag Classes.
Definition AdornedCFG.h:29
ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall(clang::StringRef MethodName="value")
ast_matchers::StatementMatcher isPointerLikeOperatorStar()
Matchers: For now, these match on any class with an operator* or operator-> where the return types ha...
internal::Matcher< NamedDecl > hasName(StringRef Name)
Matches NamedDecl nodes that have the specified name.
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXMemberCallExpr > cxxMemberCallExpr
Matches member call expressions.
ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow()
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXOperatorCallExpr > cxxOperatorCallExpr
Matches overloaded operator calls.
const AstTypeMatcher< PointerType > pointerType
internal::PolymorphicMatcher< internal::HasOverloadedOperatorNameMatcher, AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl), std::vector< std::string > > hasOverloadedOperatorName(StringRef Name)
Matches overloaded operator names.
const FunctionDecl * getCanonicalSmartPointerLikeOperatorCallee(const CallExpr *CE)
Returns the "canonical" callee for smart pointer operators (* and ->) as a key for caching.
ast_matchers::StatementMatcher isSmartPointerLikeOperatorStar()
const internal::VariadicDynCastAllOfMatcher< Decl, CXXMethodDecl > cxxMethodDecl
Matches method declarations.
ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall(clang::StringRef MethodName="get")
ast_matchers::StatementMatcher isPointerLikeOperatorArrow()
const AstTypeMatcher< ReferenceType > referenceType
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
@ OO_None
Not an overloaded operator.