Browse Source

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.
swarmer 1 year ago
parent
commit
21c0e3877d
3 changed files with 32 additions and 7 deletions
  1. 7 7
      util/string/cast.h
  2. 11 0
      util/string/cast_ut.cpp
  3. 14 0
      util/system/compiler.h

+ 7 - 7
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 {
 };

+ 11 - 0
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");
+    }
 }

+ 14 - 0
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