1 //===- unittests/Analysis/FlowSensitive/SmartPointerAccessorCachingTest.cpp ==//
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
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
{
19 using clang::ast_matchers::match
;
21 template <typename MatcherT
>
22 bool matches(llvm::StringRef Decls
, llvm::StringRef TestInput
,
24 TestAST
InputAST(Decls
.str() + TestInput
.str());
25 return !match(Matcher
, InputAST
.context()).empty();
28 TEST(SmartPointerAccessorCachingTest
, MatchesClassWithStarArrowGet
) {
29 llvm::StringRef
Decls(R
"cc(
33 T* operator->() const;
40 using UniquePtrAlias = std::unique_ptr<T>;
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(
62 // unique_ptr isn't really like this, but we aren't matching by name
63 template <class T, class U>
65 U* operator->() const;
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(
94 T* operator->() const;
95 T& operator*(int x) const;
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(
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()));
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(
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(
159 const T* operator->() const;
161 const T& operator*() const;
163 const T& value() const;
172 Decls
, "int target(std::optional<S> &NonConst) { return (*NonConst).i; }",
173 isSmartPointerLikeOperatorStar()));
175 Decls
, "int target(const std::optional<S> &Const) { return (*Const).i; }",
176 isSmartPointerLikeOperatorStar()));
178 Decls
, "int target(std::optional<S> &NonConst) { return NonConst->i; }",
179 isSmartPointerLikeOperatorArrow()));
181 Decls
, "int target(const std::optional<S> &Const) { return Const->i; }",
182 isSmartPointerLikeOperatorArrow()));
185 "int target(std::optional<S> &NonConst) { return NonConst.value().i; }",
186 isSmartPointerLikeValueMethodCall()));
189 "int target(const std::optional<S> &Const) { return Const.value().i; }",
190 isSmartPointerLikeValueMethodCall()));
194 } // namespace clang::dataflow