blob: 493799a19380af30dd19460f3598e94b8e8a7b57 [file] [log] [blame]
Wei Yi Tee543af742022-06-01 06:52:24 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
Googler7f19b2b2023-05-01 09:44:57 -07005#include "nullability/pointer_nullability_matchers.h"
Wei Yi Tee543af742022-06-01 06:52:24 -07006
Dmitri Gribenko61645e12023-07-17 04:46:21 -07007#include "clang/AST/DeclCXX.h"
Wei Yi Tee1cd62af2022-06-09 00:56:46 -07008#include "clang/AST/OperationKinds.h"
Dmitri Gribenko61645e12023-07-17 04:46:21 -07009#include "clang/AST/Stmt.h"
Martin Brænned51ac6e2023-12-12 06:13:31 -080010#include "clang/AST/Type.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070011#include "clang/ASTMatchers/ASTMatchers.h"
Martin Brænned51ac6e2023-12-12 06:13:31 -080012#include "clang/ASTMatchers/ASTMatchersMacros.h"
Wei Yi Tee543af742022-06-01 06:52:24 -070013
Sam McCall4f6be422023-06-27 02:51:22 -070014namespace clang::tidy::nullability {
Wei Yi Tee543af742022-06-01 06:52:24 -070015
Wei Yi Teef02698e2022-06-10 04:25:48 -070016using ast_matchers::anyOf;
Martin Brænnea8fdadc2023-12-07 23:04:39 -080017using ast_matchers::argumentCountIs;
Martin Brænne40e29ca2023-12-14 01:56:59 -080018using ast_matchers::arraySubscriptExpr;
Wei Yi Tee543af742022-06-01 06:52:24 -070019using ast_matchers::binaryOperator;
Martin Brænnec8f37132023-12-11 06:07:57 -080020using ast_matchers::booleanType;
Googlerbcfef622023-10-17 12:13:54 -070021using ast_matchers::callee;
Wei Yi Teec1e1d862022-08-19 14:11:28 -070022using ast_matchers::callExpr;
Googlerbcfef622023-10-17 12:13:54 -070023using ast_matchers::compoundStmt;
Wei Yi Teeafbca012022-09-19 11:54:28 -070024using ast_matchers::cxxConstructExpr;
Martin Brænnec8f37132023-12-11 06:07:57 -080025using ast_matchers::cxxConversionDecl;
Wei Yi Tee566e2df2022-09-19 11:59:03 -070026using ast_matchers::cxxCtorInitializer;
Googlerbcfef622023-10-17 12:13:54 -070027using ast_matchers::cxxMemberCallExpr;
28using ast_matchers::cxxMethodDecl;
Martin Brænnea8fdadc2023-12-07 23:04:39 -080029using ast_matchers::cxxOperatorCallExpr;
Martin Brænne7187dcf2023-12-12 23:10:43 -080030using ast_matchers::cxxRecordDecl;
Wei Yi Teecebc2262022-06-10 04:27:57 -070031using ast_matchers::cxxThisExpr;
Googlerbcfef622023-10-17 12:13:54 -070032using ast_matchers::decl;
Wei Yi Tee543af742022-06-01 06:52:24 -070033using ast_matchers::expr;
Martin Brænne58122b92023-12-11 04:17:55 -080034using ast_matchers::functionDecl;
Googlerbcfef622023-10-17 12:13:54 -070035using ast_matchers::has;
Martin Brænne58122b92023-12-11 04:17:55 -080036using ast_matchers::hasAnyName;
Wei Yi Tee1cd62af2022-06-09 00:56:46 -070037using ast_matchers::hasAnyOperatorName;
Martin Brænned51ac6e2023-12-12 06:13:31 -080038using ast_matchers::hasAnyOverloadedOperatorName;
Martin Brænnea8fdadc2023-12-07 23:04:39 -080039using ast_matchers::hasArgument;
Martin Brænne40e29ca2023-12-14 01:56:59 -080040using ast_matchers::hasBase;
Googlerbcfef622023-10-17 12:13:54 -070041using ast_matchers::hasBody;
Martin Brænne4c6e9532023-12-14 01:39:04 -080042using ast_matchers::hasCanonicalType;
Wei Yi Tee264ee4d2022-06-10 04:20:10 -070043using ast_matchers::hasCastKind;
Googlerbcfef622023-10-17 12:13:54 -070044using ast_matchers::hasDeclaration;
Martin Brænne90b96ad2023-12-07 23:18:25 -080045using ast_matchers::hasName;
Martin Brænne4d97b2c2024-02-01 09:11:30 -080046using ast_matchers::hasObjectExpression;
Wei Yi Tee543af742022-06-01 06:52:24 -070047using ast_matchers::hasOperands;
48using ast_matchers::hasOperatorName;
Martin Brænnea8fdadc2023-12-07 23:04:39 -080049using ast_matchers::hasOverloadedOperatorName;
Wei Yi Teeed480d62022-08-26 03:19:54 -070050using ast_matchers::hasReturnValue;
Wei Yi Tee543af742022-06-01 06:52:24 -070051using ast_matchers::hasType;
52using ast_matchers::hasUnaryOperand;
Googlerbcfef622023-10-17 12:13:54 -070053using ast_matchers::ignoringParenImpCasts;
Wei Yi Tee543af742022-06-01 06:52:24 -070054using ast_matchers::implicitCastExpr;
Wei Yi Teef02698e2022-06-10 04:25:48 -070055using ast_matchers::isArrow;
Googlerbcfef622023-10-17 12:13:54 -070056using ast_matchers::isConst;
Martin Brænne58122b92023-12-11 04:17:55 -080057using ast_matchers::isInStdNamespace;
Wei Yi Tee566e2df2022-09-19 11:59:03 -070058using ast_matchers::isMemberInitializer;
Wei Yi Teee314ca62022-06-10 04:23:08 -070059using ast_matchers::memberExpr;
Martin Brænneae727652024-02-21 23:46:27 -080060using ast_matchers::ofClass;
Googlerca74c792023-11-08 11:27:22 -080061using ast_matchers::parameterCountIs;
Martin Brænne4d97b2c2024-02-01 09:11:30 -080062using ast_matchers::pointee;
63using ast_matchers::pointerType;
Martin Brænnedd76e942024-02-05 06:19:19 -080064using ast_matchers::qualType;
Wei Yi Teeed480d62022-08-26 03:19:54 -070065using ast_matchers::returnStmt;
Googlerbcfef622023-10-17 12:13:54 -070066using ast_matchers::statementCountIs;
Martin Brænne297c5cc2023-12-12 00:30:51 -080067using ast_matchers::thisPointerType;
Wei Yi Tee543af742022-06-01 06:52:24 -070068using ast_matchers::unaryOperator;
Googlerbcfef622023-10-17 12:13:54 -070069using ast_matchers::unless;
Wei Yi Tee543af742022-06-01 06:52:24 -070070using ast_matchers::internal::Matcher;
71
Martin Brænnec88c7272023-11-13 06:13:37 -080072Matcher<Stmt> isPointerExpr() { return expr(hasType(isSupportedRawPointer())); }
Wei Yi Tee1cd62af2022-06-09 00:56:46 -070073Matcher<Stmt> isNullPointerLiteral() {
Wei Yi Tee9f558172022-07-25 08:34:56 -070074 return implicitCastExpr(anyOf(hasCastKind(CK_NullToPointer),
75 hasCastKind(CK_NullToMemberPointer)));
Wei Yi Tee1cd62af2022-06-09 00:56:46 -070076}
77Matcher<Stmt> isAddrOf() { return unaryOperator(hasOperatorName("&")); }
Wei Yi Tee543af742022-06-01 06:52:24 -070078Matcher<Stmt> isPointerDereference() {
79 return unaryOperator(hasOperatorName("*"), hasUnaryOperand(isPointerExpr()));
80}
Martin Brænne40e29ca2023-12-14 01:56:59 -080081Matcher<Stmt> isPointerSubscript() {
82 return arraySubscriptExpr(hasBase(isPointerExpr()));
83}
Wei Yi Tee1cd62af2022-06-09 00:56:46 -070084Matcher<Stmt> isPointerCheckBinOp() {
85 return binaryOperator(hasAnyOperatorName("!=", "=="),
86 hasOperands(isPointerExpr(), isPointerExpr()));
87}
88Matcher<Stmt> isImplicitCastPointerToBool() {
Wei Yi Tee264ee4d2022-06-10 04:20:10 -070089 return implicitCastExpr(hasCastKind(CK_PointerToBoolean));
Wei Yi Tee543af742022-06-01 06:52:24 -070090}
Wei Yi Tee8b58e192022-08-02 10:15:40 -070091Matcher<Stmt> isMemberOfPointerType() {
Martin Brænnec88c7272023-11-13 06:13:37 -080092 return memberExpr(hasType(isSupportedRawPointer()));
Wei Yi Teee314ca62022-06-10 04:23:08 -070093}
Wei Yi Tee8b58e192022-08-02 10:15:40 -070094Matcher<Stmt> isPointerArrow() { return memberExpr(isArrow()); }
Wei Yi Teeed480d62022-08-26 03:19:54 -070095Matcher<Stmt> isPointerReturn() {
Martin Brænne412a6782023-12-19 06:14:17 -080096 return returnStmt(hasReturnValue(hasType(isSupportedPointer())));
Wei Yi Teeed480d62022-08-26 03:19:54 -070097}
Wei Yi Tee566e2df2022-09-19 11:59:03 -070098Matcher<CXXCtorInitializer> isCtorMemberInitializer() {
99 return cxxCtorInitializer(isMemberInitializer());
100}
Wei Yi Teec1e1d862022-08-19 14:11:28 -0700101
Googlerca74c792023-11-08 11:27:22 -0800102Matcher<Stmt> isZeroParamConstMemberCall() {
103 return cxxMemberCallExpr(
104 callee(cxxMethodDecl(parameterCountIs(0), isConst())));
105}
106
Martin Brænneae727652024-02-21 23:46:27 -0800107Matcher<Stmt> isOptionalOperatorArrowCall() {
108 return cxxOperatorCallExpr(
109 hasOverloadedOperatorName("->"),
110 callee(cxxMethodDecl(ofClass(hasAnyName(
111 "::std::optional", "::absl::optional", "::folly::Optional")))));
112}
113
Googlerbcfef622023-10-17 12:13:54 -0700114Matcher<Stmt> isNonConstMemberCall() {
115 return cxxMemberCallExpr(callee(cxxMethodDecl(unless(isConst()))));
116}
117
Martin Brænnec1f628c2024-02-20 23:52:57 -0800118Matcher<Stmt> isNonConstMemberOperatorCall() {
119 return cxxOperatorCallExpr(callee(cxxMethodDecl(unless(isConst()))));
120}
121
Martin Brænne4d97b2c2024-02-01 09:11:30 -0800122Matcher<Stmt> isSmartPointerArrowMemberExpr() {
Martin Brænnedd76e942024-02-05 06:19:19 -0800123 return memberExpr(hasObjectExpression(hasType(qualType(
124 hasCanonicalType(pointerType(pointee(isSupportedSmartPointer())))))));
Martin Brænne4d97b2c2024-02-01 09:11:30 -0800125}
126
Martin Brænne19128c92023-12-07 01:13:25 -0800127Matcher<Stmt> isSmartPointerConstructor() {
128 return cxxConstructExpr(hasType(isSupportedSmartPointer()));
129}
130
Martin Brænneb82e6f52023-12-12 00:41:40 -0800131Matcher<Stmt> isSmartPointerOperatorCall(llvm::StringRef Name) {
Martin Brænnea8fdadc2023-12-07 23:04:39 -0800132 return cxxOperatorCallExpr(
Martin Brænneb82e6f52023-12-12 00:41:40 -0800133 hasOverloadedOperatorName(Name),
Martin Brænnea8fdadc2023-12-07 23:04:39 -0800134 hasArgument(0, hasType(isSupportedSmartPointer())));
135}
136
Martin Brænnea6eca112023-12-11 04:12:43 -0800137Matcher<Stmt> isSmartPointerMethodCall(llvm::StringRef Name) {
Martin Brænne297c5cc2023-12-12 00:30:51 -0800138 return cxxMemberCallExpr(thisPointerType(isSupportedSmartPointer()),
Martin Brænnea6eca112023-12-11 04:12:43 -0800139 callee(cxxMethodDecl(hasName(Name))));
Martin Brænne90b96ad2023-12-07 23:18:25 -0800140}
141
Martin Brænnec97459c2023-12-11 05:19:34 -0800142Matcher<Stmt> isSmartPointerFreeSwapCall() {
143 return callExpr(callee(functionDecl(isInStdNamespace(), hasName("swap"))),
144 argumentCountIs(2),
145 hasArgument(0, hasType(isSupportedSmartPointer())),
146 hasArgument(1, hasType(isSupportedSmartPointer())));
147}
148
Martin Brænnec8f37132023-12-11 06:07:57 -0800149Matcher<Stmt> isSmartPointerBoolConversionCall() {
Martin Brænne297c5cc2023-12-12 00:30:51 -0800150 return cxxMemberCallExpr(thisPointerType(isSupportedSmartPointer()),
Martin Brænnec8f37132023-12-11 06:07:57 -0800151 callee(cxxConversionDecl()), hasType(booleanType()));
152}
153
Martin Brænne58122b92023-12-11 04:17:55 -0800154Matcher<Stmt> isSmartPointerFactoryCall() {
155 return callExpr(
156 hasType(isSupportedSmartPointer()),
157 callee(functionDecl(
158 isInStdNamespace(),
159 hasAnyName("make_unique", "make_unique_for_overwrite", "make_shared",
160 "make_shared_for_overwrite", "allocate_shared",
161 "allocate_shared_for_overwrite"))));
162}
163
Martin Brænned51ac6e2023-12-12 06:13:31 -0800164Matcher<Stmt> isSmartPointerComparisonOpCall() {
165 return cxxOperatorCallExpr(
166 hasAnyOverloadedOperatorName("==", "!="), argumentCountIs(2),
167 anyOf(hasArgument(0, hasType(isSupportedSmartPointer())),
168 hasArgument(1, hasType(isSupportedSmartPointer()))),
169 // If one of the arguments isn't a smart pointer, it has to be
170 // `std::nullptr_t`.
171 hasArgument(0, anyOf(hasType(isSupportedSmartPointer()),
172 hasType(isNullPtrType()))),
173 hasArgument(1, anyOf(hasType(isSupportedSmartPointer()),
174 hasType(isNullPtrType()))));
175}
176
Martin Brænne4c6e9532023-12-14 01:39:04 -0800177Matcher<Stmt> isSharedPtrCastCall() {
178 return callExpr(
179 argumentCountIs(1),
180 hasArgument(0, hasType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
181 isInStdNamespace(), hasName("shared_ptr")))))),
182 callee(functionDecl(
183 isInStdNamespace(),
184 hasAnyName("static_pointer_cast", "dynamic_pointer_cast",
185 "const_pointer_cast", "reinterpret_pointer_cast"))));
186}
187
Martin Brænne7187dcf2023-12-12 23:10:43 -0800188Matcher<Stmt> isWeakPtrLockCall() {
189 return cxxMemberCallExpr(
190 thisPointerType(cxxRecordDecl(isInStdNamespace(), hasName("weak_ptr"))),
191 callee(cxxMethodDecl(hasName("lock"))));
192}
193
Googlerbcfef622023-10-17 12:13:54 -0700194Matcher<Stmt> isSupportedPointerAccessorCall() {
195 return cxxMemberCallExpr(callee(cxxMethodDecl(hasBody(compoundStmt(
196 statementCountIs(1),
197 has(returnStmt(has(implicitCastExpr(
198 hasCastKind(CK_LValueToRValue),
199 has(ignoringParenImpCasts(
200 memberExpr(has(ignoringParenImpCasts(cxxThisExpr())),
Martin Brænnec88c7272023-11-13 06:13:37 -0800201 hasType(isSupportedRawPointer()),
Googlerbcfef622023-10-17 12:13:54 -0700202 hasDeclaration(decl().bind("member-decl"))))))))))))));
203}
204
Sam McCall4f6be422023-06-27 02:51:22 -0700205} // namespace clang::tidy::nullability