Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 1 | // 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 | |
Googler | 7f19b2b | 2023-05-01 09:44:57 -0700 | [diff] [blame] | 5 | #include "nullability/pointer_nullability_matchers.h" |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 6 | |
Dmitri Gribenko | 61645e1 | 2023-07-17 04:46:21 -0700 | [diff] [blame] | 7 | #include "clang/AST/DeclCXX.h" |
Wei Yi Tee | 1cd62af | 2022-06-09 00:56:46 -0700 | [diff] [blame] | 8 | #include "clang/AST/OperationKinds.h" |
Dmitri Gribenko | 61645e1 | 2023-07-17 04:46:21 -0700 | [diff] [blame] | 9 | #include "clang/AST/Stmt.h" |
Martin Brænne | d51ac6e | 2023-12-12 06:13:31 -0800 | [diff] [blame] | 10 | #include "clang/AST/Type.h" |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 11 | #include "clang/ASTMatchers/ASTMatchers.h" |
Martin Brænne | d51ac6e | 2023-12-12 06:13:31 -0800 | [diff] [blame] | 12 | #include "clang/ASTMatchers/ASTMatchersMacros.h" |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 13 | |
Sam McCall | 4f6be42 | 2023-06-27 02:51:22 -0700 | [diff] [blame] | 14 | namespace clang::tidy::nullability { |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 15 | |
Wei Yi Tee | f02698e | 2022-06-10 04:25:48 -0700 | [diff] [blame] | 16 | using ast_matchers::anyOf; |
Martin Brænne | a8fdadc | 2023-12-07 23:04:39 -0800 | [diff] [blame] | 17 | using ast_matchers::argumentCountIs; |
Martin Brænne | 40e29ca | 2023-12-14 01:56:59 -0800 | [diff] [blame] | 18 | using ast_matchers::arraySubscriptExpr; |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 19 | using ast_matchers::binaryOperator; |
Martin Brænne | c8f3713 | 2023-12-11 06:07:57 -0800 | [diff] [blame] | 20 | using ast_matchers::booleanType; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 21 | using ast_matchers::callee; |
Wei Yi Tee | c1e1d86 | 2022-08-19 14:11:28 -0700 | [diff] [blame] | 22 | using ast_matchers::callExpr; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 23 | using ast_matchers::compoundStmt; |
Wei Yi Tee | afbca01 | 2022-09-19 11:54:28 -0700 | [diff] [blame] | 24 | using ast_matchers::cxxConstructExpr; |
Martin Brænne | c8f3713 | 2023-12-11 06:07:57 -0800 | [diff] [blame] | 25 | using ast_matchers::cxxConversionDecl; |
Wei Yi Tee | 566e2df | 2022-09-19 11:59:03 -0700 | [diff] [blame] | 26 | using ast_matchers::cxxCtorInitializer; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 27 | using ast_matchers::cxxMemberCallExpr; |
| 28 | using ast_matchers::cxxMethodDecl; |
Martin Brænne | a8fdadc | 2023-12-07 23:04:39 -0800 | [diff] [blame] | 29 | using ast_matchers::cxxOperatorCallExpr; |
Martin Brænne | 7187dcf | 2023-12-12 23:10:43 -0800 | [diff] [blame] | 30 | using ast_matchers::cxxRecordDecl; |
Wei Yi Tee | cebc226 | 2022-06-10 04:27:57 -0700 | [diff] [blame] | 31 | using ast_matchers::cxxThisExpr; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 32 | using ast_matchers::decl; |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 33 | using ast_matchers::expr; |
Martin Brænne | 58122b9 | 2023-12-11 04:17:55 -0800 | [diff] [blame] | 34 | using ast_matchers::functionDecl; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 35 | using ast_matchers::has; |
Martin Brænne | 58122b9 | 2023-12-11 04:17:55 -0800 | [diff] [blame] | 36 | using ast_matchers::hasAnyName; |
Wei Yi Tee | 1cd62af | 2022-06-09 00:56:46 -0700 | [diff] [blame] | 37 | using ast_matchers::hasAnyOperatorName; |
Martin Brænne | d51ac6e | 2023-12-12 06:13:31 -0800 | [diff] [blame] | 38 | using ast_matchers::hasAnyOverloadedOperatorName; |
Martin Brænne | a8fdadc | 2023-12-07 23:04:39 -0800 | [diff] [blame] | 39 | using ast_matchers::hasArgument; |
Martin Brænne | 40e29ca | 2023-12-14 01:56:59 -0800 | [diff] [blame] | 40 | using ast_matchers::hasBase; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 41 | using ast_matchers::hasBody; |
Martin Brænne | 4c6e953 | 2023-12-14 01:39:04 -0800 | [diff] [blame] | 42 | using ast_matchers::hasCanonicalType; |
Wei Yi Tee | 264ee4d | 2022-06-10 04:20:10 -0700 | [diff] [blame] | 43 | using ast_matchers::hasCastKind; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 44 | using ast_matchers::hasDeclaration; |
Martin Brænne | 90b96ad | 2023-12-07 23:18:25 -0800 | [diff] [blame] | 45 | using ast_matchers::hasName; |
Martin Brænne | 4d97b2c | 2024-02-01 09:11:30 -0800 | [diff] [blame] | 46 | using ast_matchers::hasObjectExpression; |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 47 | using ast_matchers::hasOperands; |
| 48 | using ast_matchers::hasOperatorName; |
Martin Brænne | a8fdadc | 2023-12-07 23:04:39 -0800 | [diff] [blame] | 49 | using ast_matchers::hasOverloadedOperatorName; |
Wei Yi Tee | ed480d6 | 2022-08-26 03:19:54 -0700 | [diff] [blame] | 50 | using ast_matchers::hasReturnValue; |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 51 | using ast_matchers::hasType; |
| 52 | using ast_matchers::hasUnaryOperand; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 53 | using ast_matchers::ignoringParenImpCasts; |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 54 | using ast_matchers::implicitCastExpr; |
Wei Yi Tee | f02698e | 2022-06-10 04:25:48 -0700 | [diff] [blame] | 55 | using ast_matchers::isArrow; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 56 | using ast_matchers::isConst; |
Martin Brænne | 58122b9 | 2023-12-11 04:17:55 -0800 | [diff] [blame] | 57 | using ast_matchers::isInStdNamespace; |
Wei Yi Tee | 566e2df | 2022-09-19 11:59:03 -0700 | [diff] [blame] | 58 | using ast_matchers::isMemberInitializer; |
Wei Yi Tee | e314ca6 | 2022-06-10 04:23:08 -0700 | [diff] [blame] | 59 | using ast_matchers::memberExpr; |
Martin Brænne | ae72765 | 2024-02-21 23:46:27 -0800 | [diff] [blame] | 60 | using ast_matchers::ofClass; |
Googler | ca74c79 | 2023-11-08 11:27:22 -0800 | [diff] [blame] | 61 | using ast_matchers::parameterCountIs; |
Martin Brænne | 4d97b2c | 2024-02-01 09:11:30 -0800 | [diff] [blame] | 62 | using ast_matchers::pointee; |
| 63 | using ast_matchers::pointerType; |
Martin Brænne | dd76e94 | 2024-02-05 06:19:19 -0800 | [diff] [blame] | 64 | using ast_matchers::qualType; |
Wei Yi Tee | ed480d6 | 2022-08-26 03:19:54 -0700 | [diff] [blame] | 65 | using ast_matchers::returnStmt; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 66 | using ast_matchers::statementCountIs; |
Martin Brænne | 297c5cc | 2023-12-12 00:30:51 -0800 | [diff] [blame] | 67 | using ast_matchers::thisPointerType; |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 68 | using ast_matchers::unaryOperator; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 69 | using ast_matchers::unless; |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 70 | using ast_matchers::internal::Matcher; |
| 71 | |
Martin Brænne | c88c727 | 2023-11-13 06:13:37 -0800 | [diff] [blame] | 72 | Matcher<Stmt> isPointerExpr() { return expr(hasType(isSupportedRawPointer())); } |
Wei Yi Tee | 1cd62af | 2022-06-09 00:56:46 -0700 | [diff] [blame] | 73 | Matcher<Stmt> isNullPointerLiteral() { |
Wei Yi Tee | 9f55817 | 2022-07-25 08:34:56 -0700 | [diff] [blame] | 74 | return implicitCastExpr(anyOf(hasCastKind(CK_NullToPointer), |
| 75 | hasCastKind(CK_NullToMemberPointer))); |
Wei Yi Tee | 1cd62af | 2022-06-09 00:56:46 -0700 | [diff] [blame] | 76 | } |
| 77 | Matcher<Stmt> isAddrOf() { return unaryOperator(hasOperatorName("&")); } |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 78 | Matcher<Stmt> isPointerDereference() { |
| 79 | return unaryOperator(hasOperatorName("*"), hasUnaryOperand(isPointerExpr())); |
| 80 | } |
Martin Brænne | 40e29ca | 2023-12-14 01:56:59 -0800 | [diff] [blame] | 81 | Matcher<Stmt> isPointerSubscript() { |
| 82 | return arraySubscriptExpr(hasBase(isPointerExpr())); |
| 83 | } |
Wei Yi Tee | 1cd62af | 2022-06-09 00:56:46 -0700 | [diff] [blame] | 84 | Matcher<Stmt> isPointerCheckBinOp() { |
| 85 | return binaryOperator(hasAnyOperatorName("!=", "=="), |
| 86 | hasOperands(isPointerExpr(), isPointerExpr())); |
| 87 | } |
| 88 | Matcher<Stmt> isImplicitCastPointerToBool() { |
Wei Yi Tee | 264ee4d | 2022-06-10 04:20:10 -0700 | [diff] [blame] | 89 | return implicitCastExpr(hasCastKind(CK_PointerToBoolean)); |
Wei Yi Tee | 543af74 | 2022-06-01 06:52:24 -0700 | [diff] [blame] | 90 | } |
Wei Yi Tee | 8b58e19 | 2022-08-02 10:15:40 -0700 | [diff] [blame] | 91 | Matcher<Stmt> isMemberOfPointerType() { |
Martin Brænne | c88c727 | 2023-11-13 06:13:37 -0800 | [diff] [blame] | 92 | return memberExpr(hasType(isSupportedRawPointer())); |
Wei Yi Tee | e314ca6 | 2022-06-10 04:23:08 -0700 | [diff] [blame] | 93 | } |
Wei Yi Tee | 8b58e19 | 2022-08-02 10:15:40 -0700 | [diff] [blame] | 94 | Matcher<Stmt> isPointerArrow() { return memberExpr(isArrow()); } |
Wei Yi Tee | ed480d6 | 2022-08-26 03:19:54 -0700 | [diff] [blame] | 95 | Matcher<Stmt> isPointerReturn() { |
Martin Brænne | 412a678 | 2023-12-19 06:14:17 -0800 | [diff] [blame] | 96 | return returnStmt(hasReturnValue(hasType(isSupportedPointer()))); |
Wei Yi Tee | ed480d6 | 2022-08-26 03:19:54 -0700 | [diff] [blame] | 97 | } |
Wei Yi Tee | 566e2df | 2022-09-19 11:59:03 -0700 | [diff] [blame] | 98 | Matcher<CXXCtorInitializer> isCtorMemberInitializer() { |
| 99 | return cxxCtorInitializer(isMemberInitializer()); |
| 100 | } |
Wei Yi Tee | c1e1d86 | 2022-08-19 14:11:28 -0700 | [diff] [blame] | 101 | |
Googler | ca74c79 | 2023-11-08 11:27:22 -0800 | [diff] [blame] | 102 | Matcher<Stmt> isZeroParamConstMemberCall() { |
| 103 | return cxxMemberCallExpr( |
| 104 | callee(cxxMethodDecl(parameterCountIs(0), isConst()))); |
| 105 | } |
| 106 | |
Martin Brænne | ae72765 | 2024-02-21 23:46:27 -0800 | [diff] [blame] | 107 | Matcher<Stmt> isOptionalOperatorArrowCall() { |
| 108 | return cxxOperatorCallExpr( |
| 109 | hasOverloadedOperatorName("->"), |
| 110 | callee(cxxMethodDecl(ofClass(hasAnyName( |
| 111 | "::std::optional", "::absl::optional", "::folly::Optional"))))); |
| 112 | } |
| 113 | |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 114 | Matcher<Stmt> isNonConstMemberCall() { |
| 115 | return cxxMemberCallExpr(callee(cxxMethodDecl(unless(isConst())))); |
| 116 | } |
| 117 | |
Martin Brænne | c1f628c | 2024-02-20 23:52:57 -0800 | [diff] [blame] | 118 | Matcher<Stmt> isNonConstMemberOperatorCall() { |
| 119 | return cxxOperatorCallExpr(callee(cxxMethodDecl(unless(isConst())))); |
| 120 | } |
| 121 | |
Martin Brænne | 4d97b2c | 2024-02-01 09:11:30 -0800 | [diff] [blame] | 122 | Matcher<Stmt> isSmartPointerArrowMemberExpr() { |
Martin Brænne | dd76e94 | 2024-02-05 06:19:19 -0800 | [diff] [blame] | 123 | return memberExpr(hasObjectExpression(hasType(qualType( |
| 124 | hasCanonicalType(pointerType(pointee(isSupportedSmartPointer()))))))); |
Martin Brænne | 4d97b2c | 2024-02-01 09:11:30 -0800 | [diff] [blame] | 125 | } |
| 126 | |
Martin Brænne | 19128c9 | 2023-12-07 01:13:25 -0800 | [diff] [blame] | 127 | Matcher<Stmt> isSmartPointerConstructor() { |
| 128 | return cxxConstructExpr(hasType(isSupportedSmartPointer())); |
| 129 | } |
| 130 | |
Martin Brænne | b82e6f5 | 2023-12-12 00:41:40 -0800 | [diff] [blame] | 131 | Matcher<Stmt> isSmartPointerOperatorCall(llvm::StringRef Name) { |
Martin Brænne | a8fdadc | 2023-12-07 23:04:39 -0800 | [diff] [blame] | 132 | return cxxOperatorCallExpr( |
Martin Brænne | b82e6f5 | 2023-12-12 00:41:40 -0800 | [diff] [blame] | 133 | hasOverloadedOperatorName(Name), |
Martin Brænne | a8fdadc | 2023-12-07 23:04:39 -0800 | [diff] [blame] | 134 | hasArgument(0, hasType(isSupportedSmartPointer()))); |
| 135 | } |
| 136 | |
Martin Brænne | a6eca11 | 2023-12-11 04:12:43 -0800 | [diff] [blame] | 137 | Matcher<Stmt> isSmartPointerMethodCall(llvm::StringRef Name) { |
Martin Brænne | 297c5cc | 2023-12-12 00:30:51 -0800 | [diff] [blame] | 138 | return cxxMemberCallExpr(thisPointerType(isSupportedSmartPointer()), |
Martin Brænne | a6eca11 | 2023-12-11 04:12:43 -0800 | [diff] [blame] | 139 | callee(cxxMethodDecl(hasName(Name)))); |
Martin Brænne | 90b96ad | 2023-12-07 23:18:25 -0800 | [diff] [blame] | 140 | } |
| 141 | |
Martin Brænne | c97459c | 2023-12-11 05:19:34 -0800 | [diff] [blame] | 142 | Matcher<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ænne | c8f3713 | 2023-12-11 06:07:57 -0800 | [diff] [blame] | 149 | Matcher<Stmt> isSmartPointerBoolConversionCall() { |
Martin Brænne | 297c5cc | 2023-12-12 00:30:51 -0800 | [diff] [blame] | 150 | return cxxMemberCallExpr(thisPointerType(isSupportedSmartPointer()), |
Martin Brænne | c8f3713 | 2023-12-11 06:07:57 -0800 | [diff] [blame] | 151 | callee(cxxConversionDecl()), hasType(booleanType())); |
| 152 | } |
| 153 | |
Martin Brænne | 58122b9 | 2023-12-11 04:17:55 -0800 | [diff] [blame] | 154 | Matcher<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ænne | d51ac6e | 2023-12-12 06:13:31 -0800 | [diff] [blame] | 164 | Matcher<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ænne | 4c6e953 | 2023-12-14 01:39:04 -0800 | [diff] [blame] | 177 | Matcher<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ænne | 7187dcf | 2023-12-12 23:10:43 -0800 | [diff] [blame] | 188 | Matcher<Stmt> isWeakPtrLockCall() { |
| 189 | return cxxMemberCallExpr( |
| 190 | thisPointerType(cxxRecordDecl(isInStdNamespace(), hasName("weak_ptr"))), |
| 191 | callee(cxxMethodDecl(hasName("lock")))); |
| 192 | } |
| 193 | |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 194 | Matcher<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ænne | c88c727 | 2023-11-13 06:13:37 -0800 | [diff] [blame] | 201 | hasType(isSupportedRawPointer()), |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 202 | hasDeclaration(decl().bind("member-decl")))))))))))))); |
| 203 | } |
| 204 | |
Sam McCall | 4f6be42 | 2023-06-27 02:51:22 -0700 | [diff] [blame] | 205 | } // namespace clang::tidy::nullability |