diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /build/clang-plugin/tests/TestTemporaryLifetimeBound.cpp | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'build/clang-plugin/tests/TestTemporaryLifetimeBound.cpp')
-rw-r--r-- | build/clang-plugin/tests/TestTemporaryLifetimeBound.cpp | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/build/clang-plugin/tests/TestTemporaryLifetimeBound.cpp b/build/clang-plugin/tests/TestTemporaryLifetimeBound.cpp new file mode 100644 index 0000000000..0c51182cab --- /dev/null +++ b/build/clang-plugin/tests/TestTemporaryLifetimeBound.cpp @@ -0,0 +1,126 @@ +#define MOZ_LIFETIME_BOUND __attribute__((annotate("moz_lifetime_bound"))) + +struct Foo {}; + +struct Bar { + MOZ_LIFETIME_BOUND const Foo &AsFoo() const; // expected-note {{member function declared here}} expected-note {{member function declared here}} expected-note {{member function declared here}} expected-note {{member function declared here}} expected-note {{member function declared here}} + MOZ_LIFETIME_BOUND operator const Foo &() const; // expected-note {{member function declared here}} expected-note {{member function declared here}} expected-note {{member function declared here}} expected-note {{member function declared here}} expected-note {{member function declared here}} expected-note {{member function declared here}} +}; + +Bar MakeBar() { return Bar(); } + +Bar testReturnsInstance_Constructed() { return Bar(); } + +const Foo &testReturnsReference_Static() { + static constexpr auto bar = Bar{}; + return bar; +} + +/* TODO This is bad as well... but not related to a temporary. +const Foo& testReturnsReference_Local() { + constexpr auto bar = Bar{}; + return bar; +} +*/ + +const Foo &testReturnsReferenceToTemporaryViaLifetimeBound_Constructed() { + return Bar(); // expected-error {{cannot return result of lifetime-bound function 'operator const Foo &' on temporary of type 'Bar'}} +} + +const Foo &testReturnsReferenceToTemporaryViaLifetimeBound2_Constructed() { + return static_cast<const Foo &>(Bar()); // expected-error {{cannot return result of lifetime-bound function 'operator const Foo &' on temporary of type 'Bar'}} +} + +const Foo &testReturnsReferenceToTemporaryViaLifetimeBound3_Constructed() { + return Bar().AsFoo(); // expected-error {{cannot return result of lifetime-bound function 'AsFoo' on temporary of type 'Bar'}} +} + +const Foo & +testReturnsReferenceToTemporaryViaLifetimeBound4_Constructed(bool aCond) { + static constexpr Foo foo; + return aCond ? foo : Bar().AsFoo(); // expected-error {{cannot return result of lifetime-bound function 'AsFoo' on temporary of type 'Bar'}} +} + +Foo testReturnsValueViaLifetimeBoundFunction_Constructed() { return Bar(); } + +Foo testReturnsValueViaLifetimeBoundFunction2_Constructed() { + return static_cast<const Foo &>(Bar()); +} + +Foo testReturnsValueViaLifetimeBoundFunction3_Constructed() { + return Bar().AsFoo(); +} + +Bar testReturnInstance_Returned() { return MakeBar(); } + +const Foo &testReturnsReferenceToTemporaryViaLifetimeBound_Returned() { + return MakeBar(); // expected-error {{cannot return result of lifetime-bound function 'operator const Foo &' on temporary of type 'Bar'}} +} + +const Foo &testReturnsReferenceToTemporaryViaLifetimeBound2_Returned() { + return static_cast<const Foo &>(MakeBar()); // expected-error {{cannot return result of lifetime-bound function 'operator const Foo &' on temporary of type 'Bar'}} +} + +const Foo &testReturnsReferenceToTemporaryViaLifetimeBound3_Returned() { + return MakeBar().AsFoo(); // expected-error {{cannot return result of lifetime-bound function 'AsFoo' on temporary of type 'Bar'}} +} + +Foo testReturnsValueViaLifetimeBoundFunction_Returned() { return MakeBar(); } + +Foo testReturnsValueViaLifetimeBoundFunction2_Returned() { + return static_cast<const Foo &>(MakeBar()); +} + +Foo testReturnsValueViaLifetimeBoundFunction3_Returned() { + return MakeBar().AsFoo(); +} + +void testNoLifetimeExtension() { + const Foo &foo = Bar(); // expected-error {{cannot bind result of lifetime-bound function 'operator const Foo &' on temporary of type 'Bar' to reference, does not extend lifetime}} +} + +void testNoLifetimeExtension2() { + const auto &foo = static_cast<const Foo &>(MakeBar()); // expected-error {{cannot bind result of lifetime-bound function 'operator const Foo &' on temporary of type 'Bar' to reference, does not extend lifetime}} +} + +void testNoLifetimeExtension3() { + const Foo &foo = Bar().AsFoo(); // expected-error {{cannot bind result of lifetime-bound function 'AsFoo' on temporary of type 'Bar' to reference, does not extend lifetime}} +} + +void testNoLifetimeExtension4(bool arg) { + const Foo foo; + const Foo &fooRef = arg ? foo : Bar().AsFoo(); // expected-error {{cannot bind result of lifetime-bound function 'AsFoo' on temporary of type 'Bar' to reference, does not extend lifetime}} +} + +// While this looks similar to testNoLifetimeExtension4, this is actually fine, +// as the coerced type of the conditional operator is `Foo` here rather than +// `const Foo&`, and thus an implicit copy of `Bar().AsFoo()` is created, whose +// lifetime is actually extended. +void testLifetimeExtension(bool arg) { + const Foo &foo = arg ? Foo() : Bar().AsFoo(); +} + +void testConvertToValue() { const Foo foo = Bar(); } + +Foo testReturnConvertToValue() { + return static_cast<Foo>(Bar()); +} + +void FooFunc(const Foo &aFoo); + +// We want to allow binding to parameters of the target reference type though. +// This is the very reason the annotation is required, and the function cannot +// be restricted to lvalues. Lifetime is not an issue here, as the temporary's +// lifetime is until the end of the full expression anyway. + +void testBindToParameter() { + FooFunc(Bar()); + FooFunc(static_cast<const Foo &>(Bar())); + FooFunc(Bar().AsFoo()); + FooFunc(MakeBar()); +} + +// This should be OK, because the return value isn't necessarily coming from the +// argument (and it should be OK for any type). +const Foo &RandomFunctionCall(const Foo &aFoo); +const Foo &testReturnFunctionCall() { return RandomFunctionCall(Bar()); } |