Googler | bcfef62 | 2023-10-17 12:13:54 -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 | |
| 5 | #include "nullability/pointer_nullability_matchers.h" |
| 6 | |
| 7 | #include "clang/ASTMatchers/ASTMatchFinder.h" |
| 8 | #include "clang/Testing/TestAST.h" |
| 9 | #include "llvm/ADT/StringRef.h" |
| 10 | #include "third_party/llvm/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h" |
| 11 | |
| 12 | namespace clang::tidy::nullability { |
| 13 | namespace { |
| 14 | |
| 15 | using ast_matchers::match; |
| 16 | |
| 17 | template <typename MatcherT> |
| 18 | bool matches(llvm::StringRef base_input, llvm::StringRef test_input, |
| 19 | MatcherT Matcher) { |
| 20 | TestAST InputAST(base_input.str() + test_input.str()); |
| 21 | return !match(Matcher, InputAST.context()).empty(); |
| 22 | } |
| 23 | |
| 24 | TEST(PointerNullabilityTest, MatchMemberFunctions) { |
| 25 | llvm::StringRef Input(R"cc( |
| 26 | struct DummyStruct { |
| 27 | int *p; |
| 28 | }; |
| 29 | class C { |
| 30 | public: |
| 31 | int *_Nullable get() const { return x; } |
| 32 | int *_Nullable get_member_in_parens() const { return (x); } |
| 33 | int *_Nullable get_this_in_parens() const { return (this)->x; } |
| 34 | int *_Nullable get(int i) const { return x; } |
| 35 | int *_Nullable get_nonconst() { return x; } |
| 36 | int *_Nullable get_external() { return ds.p; } |
Googler | e9a51b5 | 2023-10-25 08:41:19 -0700 | [diff] [blame] | 37 | void may_mutate(){}; |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 38 | |
| 39 | private: |
| 40 | int *x; |
| 41 | DummyStruct ds; |
| 42 | }; |
Googler | e9a51b5 | 2023-10-25 08:41:19 -0700 | [diff] [blame] | 43 | C foo() { return C(); } |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 44 | )cc"); |
| 45 | |
| 46 | EXPECT_TRUE(matches(Input, "void target(){ C().get(); }", |
| 47 | isSupportedPointerAccessorCall())); |
| 48 | EXPECT_TRUE(matches(Input, "void target(){ C().get_member_in_parens(); }", |
| 49 | isSupportedPointerAccessorCall())); |
| 50 | EXPECT_TRUE(matches(Input, "void target(){ C().get_this_in_parens(); }", |
| 51 | isSupportedPointerAccessorCall())); |
| 52 | EXPECT_TRUE(matches(Input, "void target(){ C().get(0); }", |
| 53 | isSupportedPointerAccessorCall())); |
| 54 | EXPECT_TRUE(matches(Input, "void target(){ C().get_nonconst(); }", |
| 55 | isSupportedPointerAccessorCall())); |
Googler | e9a51b5 | 2023-10-25 08:41:19 -0700 | [diff] [blame] | 56 | EXPECT_TRUE(matches(Input, "void target(){ foo().get(); }", |
| 57 | isSupportedPointerAccessorCall())); |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 58 | |
Googler | e9a51b5 | 2023-10-25 08:41:19 -0700 | [diff] [blame] | 59 | EXPECT_FALSE(matches(Input, "void target(){ C().may_mutate(); }", |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 60 | isSupportedPointerAccessorCall())); |
| 61 | EXPECT_FALSE(matches(Input, "void target(){ C().get_external(); }", |
| 62 | isSupportedPointerAccessorCall())); |
| 63 | } |
| 64 | |
Googler | ca74c79 | 2023-11-08 11:27:22 -0800 | [diff] [blame] | 65 | TEST(PointerNullabilityTest, MatchConstMemberFunctions) { |
| 66 | llvm::StringRef Input(R"cc( |
| 67 | class C { |
| 68 | public: |
| 69 | int *_Nullable get() const; |
| 70 | int *_Nullable get(int i) const; |
| 71 | int *_Nullable get_with_default_arg(int i = 0) const; |
| 72 | int *_Nullable get_nonconst(); |
| 73 | }; |
| 74 | C foo() { return C(); } |
| 75 | )cc"); |
| 76 | EXPECT_TRUE(matches(Input, "void target(){ C().get(); }", |
| 77 | isZeroParamConstMemberCall())); |
| 78 | EXPECT_TRUE(matches(Input, "void target(){ foo().get(); }", |
| 79 | isZeroParamConstMemberCall())); |
| 80 | |
| 81 | EXPECT_FALSE(matches(Input, "void target(){ C().get(0); }", |
| 82 | isZeroParamConstMemberCall())); |
| 83 | EXPECT_FALSE(matches(Input, "void target(){ C().get_with_default_arg(); }", |
| 84 | isZeroParamConstMemberCall())); |
| 85 | EXPECT_FALSE(matches(Input, "void target(){ C().get_nonconst(); }", |
| 86 | isZeroParamConstMemberCall())); |
| 87 | } |
Googler | bcfef62 | 2023-10-17 12:13:54 -0700 | [diff] [blame] | 88 | } // namespace |
| 89 | } // namespace clang::tidy::nullability |