blob: dd90beb4367dcf6e6200303bb5bc3c425ea7fb46 [file] [log] [blame]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// Tests involving function templates.
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "lifetime_analysis/test/lifetime_analysis_test.h"
namespace clang {
namespace tidy {
namespace lifetimes {
namespace {
TEST_F(LifetimeAnalysisTest, FunctionTemplatePtr) {
EXPECT_THAT(GetLifetimesWithPlaceholder(R"(
template <typename T>
T* target(T* t) {
return t;
}
)"),
LifetimesAre({{"target", "a -> a"}}));
}
TEST_F(LifetimeAnalysisTest, FunctionTemplatePtrWithTwoArgs) {
EXPECT_THAT(GetLifetimesWithPlaceholder(R"(
template <typename T, typename U>
T* target(T* t, U* u1, U& u2) {
u1 = &u2;
return t;
}
)"),
LifetimesAre({{"target", "a, b, c -> a"}}));
}
TEST_F(LifetimeAnalysisTest, FunctionTemplatePtrWithTemplatedStruct) {
EXPECT_THAT(GetLifetimesWithPlaceholder(R"(
template <typename T>
struct S {
T t;
};
template <typename T>
T* target(S<T*>* s) {
return s->t;
}
)"),
LifetimesAre({{"target", "(a, b) -> a"}}));
}
TEST_F(LifetimeAnalysisTest, FunctionTemplatePtrWithMultipleFunctions) {
// The code has both template and non-template functions/code.
EXPECT_THAT(GetLifetimesWithPlaceholder(R"(
static int x = 3;
template <typename T>
struct A {
T x;
T y;
};
template <typename T>
T* target(T* t) {
return t;
}
template <typename U>
U* target2(U* u) {
return u;
}
int foo(A<int>* a) {
return a->x + a->y + x;
}
)"),
LifetimesAre(
{{"target", "a -> a"}, {"target2", "a -> a"}, {"foo", "a"}}));
}
TEST_F(LifetimeAnalysisTest, FunctionTemplateCall) {
EXPECT_THAT(GetLifetimes(R"(
template <typename T>
T* t(T* a, T* b) {
if (*a > *b) {
return a;
}
return b;
}
int* target(int* a, int* b) {
return t(a, b);
}
)"),
LifetimesContain({{"target", "a, a -> a"}}));
}
TEST_F(LifetimeAnalysisTest, FunctionTemplateCallIgnoreArg) {
EXPECT_THAT(GetLifetimes(R"(
template <typename T>
T* t(T* a, T* b) {
return a;
}
int* target(int* a, int* b) {
return t(a, b);
}
)"),
LifetimesContain({{"target", "a, b -> a"}}));
}
TEST_F(LifetimeAnalysisTest, FunctionTemplateCallPtrInstantiation) {
EXPECT_THAT(GetLifetimes(R"(
template <typename T>
T* t(T* a, T* b) {
if (*a > *b) {
return a;
}
return b;
}
int** target(int** a, int** b) {
return t(a, b);
}
)"),
LifetimesContain({{"target", "(a, b), (a, b) -> (a, b)"}}));
}
TEST_F(LifetimeAnalysisTest, FunctionTemplateCallIgnoreArgPtrInstantiation) {
EXPECT_THAT(GetLifetimes(R"(
template <typename T>
T* t(T* a, T* b) {
return a;
}
int** target(int** a, int** b) {
return t(a, b);
}
)"),
LifetimesContain({{"target", "(a, b), (c, d) -> (a, b)"}}));
}
TEST_F(LifetimeAnalysisTest, FunctionTemplateInsideClassTemplate) {
EXPECT_THAT(GetLifetimes(R"(
template <typename T>
struct S {
template <typename U>
U f(T t, U u) {
return u;
}
};
int* target(S<int *>& s, int* p1, int* p2) {
return s.f(p1, p2);
}
)"),
LifetimesContain({{"target", "(a, b), c, d -> d"}}));
}
} // namespace
} // namespace lifetimes
} // namespace tidy
} // namespace clang