| // 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 |