diff options
author | swarmer <swarmer@yandex-team.com> | 2023-12-11 21:13:02 +0300 |
---|---|---|
committer | swarmer <swarmer@yandex-team.com> | 2023-12-11 21:41:58 +0300 |
commit | 21c0e3877d48d9fe4556aa0556aab7e1d2ff1ebe (patch) | |
tree | ed8d85dd5f794ac44a546438d0cff29d2189ca9a | |
parent | 0f2dee024aa755f1a8e16ecfd1e21c1043ead515 (diff) | |
download | ydb-21c0e3877d48d9fe4556aa0556aab7e1d2ff1ebe.tar.gz |
add attribute to detect lifetime bound errors
Add wrapper for [[clang::lifetimebound]] attribute.
Mark `ToString(TString)` functions with a new attibute.
Preserve rvalue reference type when ToString applied to a temporary string.
-rw-r--r-- | util/string/cast.h | 14 | ||||
-rw-r--r-- | util/string/cast_ut.cpp | 11 | ||||
-rw-r--r-- | util/system/compiler.h | 14 |
3 files changed, 32 insertions, 7 deletions
diff --git a/util/string/cast.h b/util/string/cast.h index f297cf2e5b..1f28d176fc 100644 --- a/util/string/cast.h +++ b/util/string/cast.h @@ -88,12 +88,12 @@ inline TString ToString(const T& t) { return ::NPrivate::TToString<TR, std::is_arithmetic<TR>::value>::Cvt((const TR&)t); } -inline const TString& ToString(const TString& s) noexcept { +inline const TString& ToString(const TString& s Y_LIFETIME_BOUND) noexcept { return s; } -inline const TString& ToString(TString& s) noexcept { - return s; +inline TString&& ToString(TString&& s Y_LIFETIME_BOUND) noexcept { + return std::move(s); } inline TString ToString(const char* s) { @@ -112,13 +112,13 @@ inline TUtf16String ToWtring(const T& t) { return TUtf16String::FromAscii(ToString(t)); } -inline const TUtf16String& ToWtring(const TUtf16String& w) { +inline const TUtf16String& ToWtring(const TUtf16String& w Y_LIFETIME_BOUND) noexcept { return w; } -inline const TUtf16String& ToWtring(TUtf16String& w) { - return w; -} +inline TUtf16String&& ToWtring(TUtf16String&& w Y_LIFETIME_BOUND) noexcept { + return std::move(w); +}; struct TFromStringException: public TBadCastException { }; diff --git a/util/string/cast_ut.cpp b/util/string/cast_ut.cpp index aef797eddf..443f8a79f8 100644 --- a/util/string/cast_ut.cpp +++ b/util/string/cast_ut.cpp @@ -605,4 +605,15 @@ Y_UNIT_TEST_SUITE(TCastTest) { UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf<i8, 2>(127)), TStringBuf("1111111")); UNIT_ASSERT_VALUES_EQUAL(TStringBuf(TIntStringBuf<i8, 2>(-128)), TStringBuf("-10000000")); } + + Y_UNIT_TEST(TestTrivial) { + UNIT_ASSERT_VALUES_EQUAL(ToString(ToString(ToString("abc"))), TString("abc")); + + // May cause compilation error: + // const TString& ref = ToString(TString{"foo"}); + + const TString ok = ToString(TString{"foo"}); + UNIT_ASSERT_VALUES_EQUAL(ok, "foo"); + UNIT_ASSERT_VALUES_EQUAL(ToString(ToString(ok)), "foo"); + } } diff --git a/util/system/compiler.h b/util/system/compiler.h index 55448c932e..0eac0715a6 100644 --- a/util/system/compiler.h +++ b/util/system/compiler.h @@ -650,3 +650,17 @@ Y_FORCE_INLINE void DoNotOptimizeAway(const T&) = delete; #define Y_DO_NOT_OPTIMIZE_AWAY(X) ::DoNotOptimizeAway(X) #endif + +/** + * @def Y_LIFETIME_BOUND + * + * The attribute on a function parameter can be used to tell the compiler + * that function return value may refer that parameter. + * The compiler may produce compile-time warning if it is able to detect that + * an object or reference refers to another object with a shorter lifetime. + */ +#if defined(__clang__) + #define Y_LIFETIME_BOUND [[clang::lifetimebound]] +#else + #define Y_LIFETIME_BOUND +#endif |