blob: c8ebe2e6673e28c2dc61553597a132b61b6d8149 [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 recursion.
#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, InfiniteDirectRecursion) {
// TODO(danakj): Infinite recursion is UB, so we would like to avoid that we
// call an opaque function that is able to break the recursion (by exiting the
// program, theoretically).
EXPECT_THAT(GetLifetimes(R"(
void opaque();
int* f(int* a) {
// TODO(danakj): opaque();
return f(a);
}
)"),
LifetimesAre({{"f", "a -> b"}}));
}
TEST_F(LifetimeAnalysisTest, FiniteDirectRecursion_1Pointee) {
EXPECT_THAT(GetLifetimes(R"(
int* f(int n, int* a) {
if (n <= 0) return a;
return f(n - 1, a);
}
)"),
LifetimesAre({{"f", "(), a -> a"}}));
}
TEST_F(LifetimeAnalysisTest, FiniteDirectRecursion_2Pointees) {
EXPECT_THAT(GetLifetimes(R"(
int* f(int n, int* a, int* b) {
if (n <= 0) return a;
return f(n - 1, b, a);
}
)"),
LifetimesAre({{"f", "(), a, a -> a"}}));
}
TEST_F(LifetimeAnalysisTest, FiniteDirectRecursion_3Pointees) {
EXPECT_THAT(GetLifetimes(R"(
int* f(int n, int* a, int* b, int *c) {
if (n <= 0) return a;
return f(n - 1, b, c, a);
}
)"),
LifetimesAre({{"f", "(), a, a, a -> a"}}));
}
TEST_F(LifetimeAnalysisTest, MutualFiniteRecursion) {
EXPECT_THAT(GetLifetimes(R"(
int* g(int n, int* a);
int* f(int n, int* a) {
if (n == 0) return a;
return g(n - 1, a);
}
int* g(int n, int* a) {
if (n == 0) return a;
return f(n - 1, a);
}
)"),
LifetimesAre({{"f", "(), a -> a"}, {"g", "(), a -> a"}}));
}
} // namespace
} // namespace lifetimes
} // namespace tidy
} // namespace clang