blob: dd90beb4367dcf6e6200303bb5bc3c425ea7fb46 [file] [log] [blame]
Luca Versari99fddff2022-05-25 10:22:32 -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
5// Tests involving function templates.
6
7#include "gmock/gmock.h"
8#include "gtest/gtest.h"
9#include "lifetime_analysis/test/lifetime_analysis_test.h"
10
11namespace clang {
12namespace tidy {
13namespace lifetimes {
14namespace {
15
16TEST_F(LifetimeAnalysisTest, FunctionTemplatePtr) {
17 EXPECT_THAT(GetLifetimesWithPlaceholder(R"(
18 template <typename T>
19 T* target(T* t) {
20 return t;
21 }
22 )"),
23 LifetimesAre({{"target", "a -> a"}}));
24}
25
26TEST_F(LifetimeAnalysisTest, FunctionTemplatePtrWithTwoArgs) {
27 EXPECT_THAT(GetLifetimesWithPlaceholder(R"(
28 template <typename T, typename U>
29 T* target(T* t, U* u1, U& u2) {
30 u1 = &u2;
31 return t;
32 }
33 )"),
34 LifetimesAre({{"target", "a, b, c -> a"}}));
35}
36
37TEST_F(LifetimeAnalysisTest, FunctionTemplatePtrWithTemplatedStruct) {
38 EXPECT_THAT(GetLifetimesWithPlaceholder(R"(
39 template <typename T>
40 struct S {
41 T t;
42 };
43
44 template <typename T>
45 T* target(S<T*>* s) {
46 return s->t;
47 }
48 )"),
49 LifetimesAre({{"target", "(a, b) -> a"}}));
50}
51
52TEST_F(LifetimeAnalysisTest, FunctionTemplatePtrWithMultipleFunctions) {
53 // The code has both template and non-template functions/code.
54 EXPECT_THAT(GetLifetimesWithPlaceholder(R"(
55 static int x = 3;
56 template <typename T>
57 struct A {
58 T x;
59 T y;
60 };
61 template <typename T>
62 T* target(T* t) {
63 return t;
64 }
65 template <typename U>
66 U* target2(U* u) {
67 return u;
68 }
69 int foo(A<int>* a) {
70 return a->x + a->y + x;
71 }
72 )"),
73 LifetimesAre(
74 {{"target", "a -> a"}, {"target2", "a -> a"}, {"foo", "a"}}));
75}
76
77TEST_F(LifetimeAnalysisTest, FunctionTemplateCall) {
78 EXPECT_THAT(GetLifetimes(R"(
79 template <typename T>
80 T* t(T* a, T* b) {
81 if (*a > *b) {
82 return a;
83 }
84 return b;
85 }
86 int* target(int* a, int* b) {
87 return t(a, b);
88 }
89 )"),
90 LifetimesContain({{"target", "a, a -> a"}}));
91}
92
93TEST_F(LifetimeAnalysisTest, FunctionTemplateCallIgnoreArg) {
94 EXPECT_THAT(GetLifetimes(R"(
95 template <typename T>
96 T* t(T* a, T* b) {
97 return a;
98 }
99 int* target(int* a, int* b) {
100 return t(a, b);
101 }
102 )"),
103 LifetimesContain({{"target", "a, b -> a"}}));
104}
105
106TEST_F(LifetimeAnalysisTest, FunctionTemplateCallPtrInstantiation) {
107 EXPECT_THAT(GetLifetimes(R"(
108 template <typename T>
109 T* t(T* a, T* b) {
110 if (*a > *b) {
111 return a;
112 }
113 return b;
114 }
115 int** target(int** a, int** b) {
116 return t(a, b);
117 }
118 )"),
119 LifetimesContain({{"target", "(a, b), (a, b) -> (a, b)"}}));
120}
121
122TEST_F(LifetimeAnalysisTest, FunctionTemplateCallIgnoreArgPtrInstantiation) {
123 EXPECT_THAT(GetLifetimes(R"(
124 template <typename T>
125 T* t(T* a, T* b) {
126 return a;
127 }
128 int** target(int** a, int** b) {
129 return t(a, b);
130 }
131 )"),
132 LifetimesContain({{"target", "(a, b), (c, d) -> (a, b)"}}));
133}
134
135TEST_F(LifetimeAnalysisTest, FunctionTemplateInsideClassTemplate) {
136 EXPECT_THAT(GetLifetimes(R"(
137 template <typename T>
138 struct S {
139 template <typename U>
140 U f(T t, U u) {
141 return u;
142 }
143 };
144 int* target(S<int *>& s, int* p1, int* p2) {
145 return s.f(p1, p2);
146 }
147 )"),
148 LifetimesContain({{"target", "(a, b), c, d -> d"}}));
149}
150
151} // namespace
152} // namespace lifetimes
153} // namespace tidy
154} // namespace clang