aboutsummaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
authorswarmer <swarmer@yandex-team.com>2023-12-11 21:13:02 +0300
committerswarmer <swarmer@yandex-team.com>2023-12-11 21:41:58 +0300
commit21c0e3877d48d9fe4556aa0556aab7e1d2ff1ebe (patch)
treeed8d85dd5f794ac44a546438d0cff29d2189ca9a /util
parent0f2dee024aa755f1a8e16ecfd1e21c1043ead515 (diff)
downloadydb-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.
Diffstat (limited to 'util')
-rw-r--r--util/string/cast.h14
-rw-r--r--util/string/cast_ut.cpp11
-rw-r--r--util/system/compiler.h14
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