clang 20.0.0git
SmartPointerAccessorCaching.cpp
Go to the documentation of this file.
2
4#include "clang/AST/DeclCXX.h"
8
9namespace clang::dataflow {
10
11namespace {
12
13using ast_matchers::callee;
19using ast_matchers::ofClass;
20using ast_matchers::parameterCountIs;
23using ast_matchers::returns;
24
25bool hasSmartPointerClassShape(const CXXRecordDecl &RD, bool &HasGet,
26 bool &HasValue) {
27 // We may want to cache this search, but in current profiles it hasn't shown
28 // up as a hot spot (possibly because there aren't many hits, relatively).
29 bool HasArrow = false;
30 bool HasStar = false;
31 CanQualType StarReturnType, ArrowReturnType, GetReturnType, ValueReturnType;
32 for (const auto *MD : RD.methods()) {
33 // We only consider methods that are const and have zero parameters.
34 // It may be that there is a non-const overload for the method, but
35 // there should at least be a const overload as well.
36 if (!MD->isConst() || MD->getNumParams() != 0)
37 continue;
38 switch (MD->getOverloadedOperator()) {
39 case OO_Star:
40 if (MD->getReturnType()->isReferenceType()) {
41 HasStar = true;
42 StarReturnType = MD->getReturnType()
43 .getNonReferenceType()
44 ->getCanonicalTypeUnqualified();
45 }
46 break;
47 case OO_Arrow:
48 if (MD->getReturnType()->isPointerType()) {
49 HasArrow = true;
50 ArrowReturnType = MD->getReturnType()
51 ->getPointeeType()
52 ->getCanonicalTypeUnqualified();
53 }
54 break;
55 case OO_None: {
56 IdentifierInfo *II = MD->getIdentifier();
57 if (II == nullptr)
58 continue;
59 if (II->isStr("get")) {
60 if (MD->getReturnType()->isPointerType()) {
61 HasGet = true;
62 GetReturnType = MD->getReturnType()
63 ->getPointeeType()
64 ->getCanonicalTypeUnqualified();
65 }
66 } else if (II->isStr("value")) {
67 if (MD->getReturnType()->isReferenceType()) {
68 HasValue = true;
69 ValueReturnType = MD->getReturnType()
70 .getNonReferenceType()
71 ->getCanonicalTypeUnqualified();
72 }
73 }
74 } break;
75 default:
76 break;
77 }
78 }
79
80 if (!HasStar || !HasArrow || StarReturnType != ArrowReturnType)
81 return false;
82 HasGet = HasGet && (GetReturnType == StarReturnType);
83 HasValue = HasValue && (ValueReturnType == StarReturnType);
84 return true;
85}
86
87} // namespace
88} // namespace clang::dataflow
89
90// AST_MATCHER macros create an "internal" namespace, so we put it in
91// its own anonymous namespace instead of in clang::dataflow.
92namespace {
93
94AST_MATCHER(clang::CXXRecordDecl, smartPointerClassWithGet) {
95 bool HasGet = false;
96 bool HasValue = false;
97 bool HasStarAndArrow =
98 clang::dataflow::hasSmartPointerClassShape(Node, HasGet, HasValue);
99 return HasStarAndArrow && HasGet;
100}
101
102AST_MATCHER(clang::CXXRecordDecl, smartPointerClassWithValue) {
103 bool HasGet = false;
104 bool HasValue = false;
105 bool HasStarAndArrow =
106 clang::dataflow::hasSmartPointerClassShape(Node, HasGet, HasValue);
107 return HasStarAndArrow && HasValue;
108}
109
110AST_MATCHER(clang::CXXRecordDecl, smartPointerClassWithGetOrValue) {
111 bool HasGet = false;
112 bool HasValue = false;
113 bool HasStarAndArrow =
114 clang::dataflow::hasSmartPointerClassShape(Node, HasGet, HasValue);
115 return HasStarAndArrow && (HasGet || HasValue);
116}
117
118} // namespace
119
120namespace clang::dataflow {
121
123 return cxxOperatorCallExpr(
125 callee(cxxMethodDecl(parameterCountIs(0), returns(referenceType()),
126 ofClass(smartPointerClassWithGetOrValue()))));
127}
128
130 return cxxOperatorCallExpr(
132 callee(cxxMethodDecl(parameterCountIs(0), returns(pointerType()),
133 ofClass(smartPointerClassWithGetOrValue()))));
134}
136 return cxxMemberCallExpr(callee(
137 cxxMethodDecl(parameterCountIs(0), returns(referenceType()),
138 hasName("value"), ofClass(smartPointerClassWithValue()))));
139}
140
142 return cxxMemberCallExpr(callee(
143 cxxMethodDecl(parameterCountIs(0), returns(pointerType()), hasName("get"),
144 ofClass(smartPointerClassWithGet()))));
145}
146
147} // namespace clang::dataflow
DynTypedNode Node
#define AST_MATCHER(Type, DefineMatcher)
AST_MATCHER(Type, DefineMatcher) { ... } defines a zero parameter function named DefineMatcher() that...
static CanQualType GetReturnType(QualType RetTy)
Returns the "extra-canonicalized" return type, which discards qualifiers on the return type.
Definition: CGCall.cpp:110
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines an enumeration for C++ overloaded operators.
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
const AstTypeMatcher< PointerType > pointerType
Matches pointer types, but does not match Objective-C object pointer types.
internal::Matcher< NamedDecl > hasName(StringRef Name)
Matches NamedDecl nodes that have the specified name.
Definition: ASTMatchers.h:3090
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXMemberCallExpr > cxxMemberCallExpr
Matches member call expressions.
internal::Matcher< Stmt > StatementMatcher
Definition: ASTMatchers.h:144
const internal::VariadicDynCastAllOfMatcher< Stmt, CXXOperatorCallExpr > cxxOperatorCallExpr
Matches overloaded operator calls.
internal::PolymorphicMatcher< internal::HasOverloadedOperatorNameMatcher, AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl), std::vector< std::string > > hasOverloadedOperatorName(StringRef Name)
Matches overloaded operator names.
Definition: ASTMatchers.h:3153
const AstTypeMatcher< ReferenceType > referenceType
Matches both lvalue and rvalue reference types.
const internal::VariadicDynCastAllOfMatcher< Decl, CXXMethodDecl > cxxMethodDecl
Matches method declarations.
Dataflow Directional Tag Classes.
Definition: AdornedCFG.h:29
ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall()
ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall()
ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow()
ast_matchers::StatementMatcher isSmartPointerLikeOperatorStar()
Matchers: For now, these match on any class with an operator* or operator-> where the return types ha...
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.