[AMDGPU] Add commute for some VOP3 inst (#121326)
[llvm-project.git] / clang / unittests / Analysis / FlowSensitive / SmartPointerAccessorCachingTest.cpp
blob3f75dff60ee5fca9191720a07b3c2c3a66aec5a9
1 //===- unittests/Analysis/FlowSensitive/SmartPointerAccessorCachingTest.cpp ==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Testing/TestAST.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "gtest/gtest.h"
16 namespace clang::dataflow {
17 namespace {
19 using clang::ast_matchers::match;
21 template <typename MatcherT>
22 bool matches(llvm::StringRef Decls, llvm::StringRef TestInput,
23 MatcherT Matcher) {
24 TestAST InputAST(Decls.str() + TestInput.str());
25 return !match(Matcher, InputAST.context()).empty();
28 TEST(SmartPointerAccessorCachingTest, MatchesClassWithStarArrowGet) {
29 llvm::StringRef Decls(R"cc(
30 namespace std {
31 template <class T>
32 struct unique_ptr {
33 T* operator->() const;
34 T& operator*() const;
35 T* get() const;
37 } // namespace std
39 template <class T>
40 using UniquePtrAlias = std::unique_ptr<T>;
42 struct S { int i; };
43 )cc");
45 EXPECT_TRUE(matches(Decls,
46 "int target(std::unique_ptr<S> P) { return (*P).i; }",
47 isSmartPointerLikeOperatorStar()));
48 EXPECT_TRUE(matches(Decls,
49 "int target(std::unique_ptr<S> P) { return P->i; }",
50 isSmartPointerLikeOperatorArrow()));
51 EXPECT_TRUE(matches(Decls,
52 "int target(std::unique_ptr<S> P) { return P.get()->i; }",
53 isSmartPointerLikeGetMethodCall()));
55 EXPECT_TRUE(matches(Decls, "int target(UniquePtrAlias<S> P) { return P->i; }",
56 isSmartPointerLikeOperatorArrow()));
59 TEST(SmartPointerAccessorCachingTest, NoMatchIfUnexpectedReturnTypes) {
60 llvm::StringRef Decls(R"cc(
61 namespace std {
62 // unique_ptr isn't really like this, but we aren't matching by name
63 template <class T, class U>
64 struct unique_ptr {
65 U* operator->() const;
66 T& operator*() const;
67 T* get() const;
69 } // namespace std
71 struct S { int i; };
72 struct T { int j; };
73 )cc");
75 EXPECT_FALSE(matches(Decls,
76 "int target(std::unique_ptr<S, T> P) { return (*P).i; }",
77 isSmartPointerLikeOperatorStar()));
78 EXPECT_FALSE(matches(Decls,
79 "int target(std::unique_ptr<S, T> P) { return P->j; }",
80 isSmartPointerLikeOperatorArrow()));
81 // The class matching arguably accidentally matches, just because the
82 // instantiation is with S, S. Hopefully doesn't happen too much in real code
83 // with such operator* and operator-> overloads.
84 EXPECT_TRUE(matches(Decls,
85 "int target(std::unique_ptr<S, S> P) { return P->i; }",
86 isSmartPointerLikeOperatorArrow()));
89 TEST(SmartPointerAccessorCachingTest, NoMatchIfBinaryStar) {
90 llvm::StringRef Decls(R"cc(
91 namespace std {
92 template <class T>
93 struct unique_ptr {
94 T* operator->() const;
95 T& operator*(int x) const;
96 T* get() const;
98 } // namespace std
100 struct S { int i; };
101 )cc");
103 EXPECT_FALSE(
104 matches(Decls, "int target(std::unique_ptr<S> P) { return (P * 10).i; }",
105 isSmartPointerLikeOperatorStar()));
108 TEST(SmartPointerAccessorCachingTest, NoMatchIfNoConstOverloads) {
109 llvm::StringRef Decls(R"cc(
110 namespace std {
111 template <class T>
112 struct unique_ptr {
113 T* operator->();
114 T& operator*();
115 T* get();
117 } // namespace std
119 struct S { int i; };
120 )cc");
122 EXPECT_FALSE(matches(Decls,
123 "int target(std::unique_ptr<S> P) { return (*P).i; }",
124 isSmartPointerLikeOperatorStar()));
125 EXPECT_FALSE(matches(Decls,
126 "int target(std::unique_ptr<S> P) { return P->i; }",
127 isSmartPointerLikeOperatorArrow()));
128 EXPECT_FALSE(
129 matches(Decls, "int target(std::unique_ptr<S> P) { return P.get()->i; }",
130 isSmartPointerLikeGetMethodCall()));
133 TEST(SmartPointerAccessorCachingTest, NoMatchIfNoStarMethod) {
134 llvm::StringRef Decls(R"cc(
135 namespace std {
136 template <class T>
137 struct unique_ptr {
138 T* operator->();
139 T* get();
141 } // namespace std
143 struct S { int i; };
144 )cc");
146 EXPECT_FALSE(matches(Decls,
147 "int target(std::unique_ptr<S> P) { return P->i; }",
148 isSmartPointerLikeOperatorArrow()));
149 EXPECT_FALSE(matches(Decls,
150 "int target(std::unique_ptr<S> P) { return P->i; }",
151 isSmartPointerLikeGetMethodCall()));
154 TEST(SmartPointerAccessorCachingTest, MatchesWithValueAndNonConstOverloads) {
155 llvm::StringRef Decls(R"cc(
156 namespace std {
157 template <class T>
158 struct optional {
159 const T* operator->() const;
160 T* operator->();
161 const T& operator*() const;
162 T& operator*();
163 const T& value() const;
164 T& value();
166 } // namespace std
168 struct S { int i; };
169 )cc");
171 EXPECT_TRUE(matches(
172 Decls, "int target(std::optional<S> &NonConst) { return (*NonConst).i; }",
173 isSmartPointerLikeOperatorStar()));
174 EXPECT_TRUE(matches(
175 Decls, "int target(const std::optional<S> &Const) { return (*Const).i; }",
176 isSmartPointerLikeOperatorStar()));
177 EXPECT_TRUE(matches(
178 Decls, "int target(std::optional<S> &NonConst) { return NonConst->i; }",
179 isSmartPointerLikeOperatorArrow()));
180 EXPECT_TRUE(matches(
181 Decls, "int target(const std::optional<S> &Const) { return Const->i; }",
182 isSmartPointerLikeOperatorArrow()));
183 EXPECT_TRUE(matches(
184 Decls,
185 "int target(std::optional<S> &NonConst) { return NonConst.value().i; }",
186 isSmartPointerLikeValueMethodCall()));
187 EXPECT_TRUE(matches(
188 Decls,
189 "int target(const std::optional<S> &Const) { return Const.value().i; }",
190 isSmartPointerLikeValueMethodCall()));
193 } // namespace
194 } // namespace clang::dataflow