diff --git a/mfbt/Char16.h b/mfbt/Char16.h index 40e5cfe3ecc3..b0ba40d0e082 100644 --- a/mfbt/Char16.h +++ b/mfbt/Char16.h @@ -39,14 +39,14 @@ class char16ptr_t { "char16_t and wchar_t sizes differ"); public: - MOZ_IMPLICIT char16ptr_t(const char16_t* aPtr) : mPtr(aPtr) {} + constexpr MOZ_IMPLICIT char16ptr_t(const char16_t* aPtr) : mPtr(aPtr) {} MOZ_IMPLICIT char16ptr_t(const wchar_t* aPtr) : mPtr(reinterpret_cast(aPtr)) {} /* Without this, nullptr assignment would be ambiguous. */ constexpr MOZ_IMPLICIT char16ptr_t(decltype(nullptr)) : mPtr(nullptr) {} - operator const char16_t*() const { return mPtr; } + constexpr operator const char16_t*() const { return mPtr; } operator const wchar_t*() const { return reinterpret_cast(mPtr); } @@ -55,11 +55,13 @@ class char16ptr_t { return const_cast(reinterpret_cast(mPtr)); } - operator const void*() const { return mPtr; } - explicit operator bool() const { return mPtr != nullptr; } + constexpr operator const void*() const { return mPtr; } + constexpr explicit operator bool() const { return mPtr != nullptr; } /* Explicit cast operators to allow things like (char16_t*)str. */ - explicit operator char16_t*() const { return const_cast(mPtr); } + constexpr explicit operator char16_t*() const { + return const_cast(mPtr); + } explicit operator wchar_t*() const { return const_cast(static_cast(*this)); } diff --git a/xpcom/string/nsTStringRepr.h b/xpcom/string/nsTStringRepr.h index 492586d3bcb3..38cef857d6c6 100644 --- a/xpcom/string/nsTStringRepr.h +++ b/xpcom/string/nsTStringRepr.h @@ -124,8 +124,8 @@ class nsTStringRepr { typedef StringClassFlags ClassFlags; // Reading iterators. - const_char_iterator BeginReading() const { return mData; } - const_char_iterator EndReading() const { return mData + mLength; } + constexpr const_char_iterator BeginReading() const { return mData; } + constexpr const_char_iterator EndReading() const { return mData + mLength; } // Deprecated reading iterators. const_iterator& BeginReading(const_iterator& aIter) const { @@ -163,26 +163,32 @@ class nsTStringRepr { #endif // Returns pointer to string data (not necessarily null-terminated) - const typename raw_type::type Data() const { return mData; } + constexpr const typename raw_type::type Data() const { return mData; } - size_type Length() const { return mLength; } + constexpr size_type Length() const { return mLength; } - DataFlags GetDataFlags() const { return mDataFlags; } + constexpr DataFlags GetDataFlags() const { return mDataFlags; } - bool IsEmpty() const { return mLength == 0; } + constexpr bool IsEmpty() const { return mLength == 0; } - bool IsLiteral() const { return !!(mDataFlags & DataFlags::LITERAL); } + constexpr bool IsLiteral() const { + return !!(mDataFlags & DataFlags::LITERAL); + } - bool IsVoid() const { return !!(mDataFlags & DataFlags::VOIDED); } + constexpr bool IsVoid() const { return !!(mDataFlags & DataFlags::VOIDED); } - bool IsTerminated() const { return !!(mDataFlags & DataFlags::TERMINATED); } + constexpr bool IsTerminated() const { + return !!(mDataFlags & DataFlags::TERMINATED); + } - char_type CharAt(index_type aIndex) const { + constexpr char_type CharAt(index_type aIndex) const { NS_ASSERTION(aIndex < mLength, "index exceeds allowable range"); return mData[aIndex]; } - char_type operator[](index_type aIndex) const { return CharAt(aIndex); } + constexpr char_type operator[](index_type aIndex) const { + return CharAt(aIndex); + } char_type First() const; @@ -347,14 +353,15 @@ Compare(const mozilla::detail::nsTStringRepr& aLhs, const nsTStringComparator& = nsTDefaultStringComparator()); template -inline bool operator!=(const mozilla::detail::nsTStringRepr& aLhs, - const mozilla::detail::nsTStringRepr& aRhs) { +inline constexpr bool operator!=( + const mozilla::detail::nsTStringRepr& aLhs, + const mozilla::detail::nsTStringRepr& aRhs) { return !aLhs.Equals(aRhs); } template -inline bool operator!=(const mozilla::detail::nsTStringRepr& aLhs, - const T* aRhs) { +inline constexpr bool operator!=(const mozilla::detail::nsTStringRepr& aLhs, + const T* aRhs) { return !aLhs.Equals(aRhs); } diff --git a/xpcom/tests/gtest/TestStrings.cpp b/xpcom/tests/gtest/TestStrings.cpp index a03da14e0d04..93b8cedec53d 100644 --- a/xpcom/tests/gtest/TestStrings.cpp +++ b/xpcom/tests/gtest/TestStrings.cpp @@ -2446,6 +2446,25 @@ CONVERSION_BENCH(PerfUTF8toUTF16VIHundred, CopyUTF8toUTF16, mViHundredUtf8, CONVERSION_BENCH(PerfUTF8toUTF16VIThousand, CopyUTF8toUTF16, mViThousandUtf8, nsAutoString); +// Tests for usability of nsTLiteralString in constant expressions. +static_assert(NS_LITERAL_STRING("").IsEmpty()); + +constexpr auto testStringA = NS_LITERAL_STRING("a"); +static_assert(!testStringA.IsEmpty()); +static_assert(!testStringA.IsVoid()); +static_assert(testStringA.IsLiteral()); +static_assert(testStringA.IsTerminated()); +static_assert(testStringA.GetDataFlags() == + (nsLiteralString::DataFlags::LITERAL | + nsLiteralString::DataFlags::TERMINATED)); +static_assert(*static_cast(testStringA.Data()) == 'a'); +static_assert(1 == testStringA.Length()); +static_assert(testStringA.CharAt(0) == 'a'); +static_assert(testStringA[0] == 'a'); +static_assert(*testStringA.BeginReading() == 'a'); +static_assert(*testStringA.EndReading() == 0); +static_assert(testStringA.EndReading() - testStringA.BeginReading() == 1); + } // namespace TestStrings #if defined(__clang__) && (__clang_major__ >= 6)