blob: f9affdc1260c53be10bb8836dcb528af95c81143 [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 that defaulted functions are analyzed correctly.
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "lifetime_analysis/test/lifetime_analysis_test.h"
namespace clang {
namespace tidy {
namespace lifetimes {
namespace {
class DefaultedFunctions : public LifetimeAnalysisTest {};
TEST_F(DefaultedFunctions, DefaultConstrutor_NoRecordTypeFieldsNoBases) {
GetLifetimesOptions options;
options.include_implicit_methods = true;
EXPECT_THAT(GetLifetimes(R"(
struct S {
int i;
};
void target() {
S();
}
)",
options),
// Test is successful if we can call the default constructor.
LifetimesAre({{"S::S", "a:"}, {"target", ""}}));
}
TEST_F(DefaultedFunctions, DefaultConstrutor_LifetimeParam) {
GetLifetimesOptions options;
options.include_implicit_methods = true;
EXPECT_THAT(GetLifetimes(R"(
struct [[clang::annotate("lifetime_params", "a")]] S {
[[clang::annotate("member_lifetimes", "a")]]
int* p;
};
void target() {
S();
}
)",
options),
LifetimesAre({{"S::S", "(a, b):"}, {"target", ""}}));
}
TEST_F(DefaultedFunctions, DefaultConstrutor_RecordTypeFields) {
// To check that we synthesize defaulted default constructors correctly,
// we create a class `T` with a field of a type whose default constructor
// takes a `this` pointer with static lifetime. We verify that this causes
// the default constructor of `T` to also take a `this` pointer with static
// lifetime.
GetLifetimesOptions options;
options.include_implicit_methods = true;
EXPECT_THAT(
GetLifetimes(R"(
struct S {
S() {
static S* last_constructed = nullptr;
last_constructed = this;
}
};
struct T {
S s;
};
void f() {
static T t;
}
)",
options),
LifetimesAre({{"S::S", "static:"}, {"T::T", "static:"}, {"f", ""}}));
}
TEST_F(DefaultedFunctions, DefaultConstrutor_BaseClass) {
// See DefaultConstrutor_RecordTypeField for an exaplanation of hwo this
// test works.
GetLifetimesOptions options;
options.include_implicit_methods = true;
EXPECT_THAT(
GetLifetimes(R"(
struct S {
S() {
static S* last_constructed = nullptr;
last_constructed = this;
}
};
struct T : public S {};
void f() {
static T t;
}
)",
options),
LifetimesAre({{"S::S", "static:"}, {"T::T", "static:"}, {"f", ""}}));
}
} // namespace
} // namespace lifetimes
} // namespace tidy
} // namespace clang