summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--codemaker/source/javamaker/javaoptions.cxx2
-rw-r--r--compilerplugins/clang/compat.hxx24
-rw-r--r--compilerplugins/clang/stringconcatliterals.cxx2
-rw-r--r--compilerplugins/clang/test/stringconcatliterals.cxx2
-rw-r--r--compilerplugins/clang/unusedmember.cxx3
-rw-r--r--config_host/config_global.h.in4
-rw-r--r--configure.ac13
-rw-r--r--i18npool/source/breakiterator/breakiterator_unicode.cxx2
-rw-r--r--include/rtl/string.hxx90
-rw-r--r--sal/qa/rtl/digest/rtl_digest.cxx15
-rw-r--r--sal/qa/rtl/strings/test_ostring_concat.cxx10
-rw-r--r--sal/qa/rtl/textenc/rtl_textcvt.cxx2
12 files changed, 118 insertions, 51 deletions
diff --git a/codemaker/source/javamaker/javaoptions.cxx b/codemaker/source/javamaker/javaoptions.cxx
index 31e43414c68c..c86f35e6cf15 100644
--- a/codemaker/source/javamaker/javaoptions.cxx
+++ b/codemaker/source/javamaker/javaoptions.cxx
@@ -86,7 +86,7 @@ bool JavaOptions::initOptions(int ac, char* av[], bool bCmdFile)
case 'n':
if (av[i][2] != 'D' || av[i][3] != '\0')
{
- OString tmp(OStringLiteral("'-nD', please check your input '") + av[i] + "'");
+ OString tmp(OString::Concat("'-nD', please check your input '") + av[i] + "'");
throw IllegalArgument(tmp);
}
diff --git a/compilerplugins/clang/compat.hxx b/compilerplugins/clang/compat.hxx
index fb8791f978b4..70b462e54e4b 100644
--- a/compilerplugins/clang/compat.hxx
+++ b/compilerplugins/clang/compat.hxx
@@ -215,6 +215,28 @@ inline clang::Expr * getSubExpr(clang::MaterializeTemporaryExpr const * expr) {
// `-MemberExpr 0x2b74e8e656a0 '<bound member function type>' .operator ResString 0x2b74e8dc1f00
// `-DeclRefExpr 0x2b74e8e65648 'struct ErrorResource_Impl' lvalue Var 0x2b74e8e653b0 'aEr' 'struct ErrorResource_Impl'
//
+// Also work around CastExpr::getSubExprAsWritten firing
+//
+// include/llvm/Support/Casting.h:269: typename llvm::cast_retty<X, Y*>::ret_type llvm::cast(Y*)
+// [with X = clang::CXXConstructExpr; Y = clang::Expr;
+// typename llvm::cast_retty<X, Y*>::ret_type = clang::CXXConstructExpr*]: Assertion
+// `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
+//
+// for CastExprs involving ConstantExpr (introduced with
+// <https://github.com/llvm/llvm-project/commit/7c44da279e399d302a685c500e7f802f8adf9762> "Create
+// ConstantExpr class" towards LLVM 8) like
+//
+// CXXFunctionalCastExpr 0xc01c4e8 'class rtl::OStringLiteral<9>':'class rtl::OStringLiteral<9>' functional cast to OStringLiteral <ConstructorConversion>
+// `-ConstantExpr 0xc01c380 'class rtl::OStringLiteral<9>':'class rtl::OStringLiteral<9>'
+// |-value: Struct
+// | |-fields: Int 1073741824, Int 8
+// | `-field: Array size=9
+// | |-elements: Int 46, Int 111, Int 115, Int 108
+// | |-elements: Int 45, Int 116, Int 109, Int 112
+// | `-element: Int 0
+// `-CXXConstructExpr 0xc01c350 'class rtl::OStringLiteral<9>':'class rtl::OStringLiteral<9>' 'void (const char (&)[9])'
+// `-StringLiteral 0xc019ad8 'const char [9]' lvalue ".osl-tmp"
+//
// Copies code from Clang's lib/AST/Expr.cpp:
namespace detail {
inline clang::Expr *skipImplicitTemporary(clang::Expr *expr) {
@@ -240,7 +262,7 @@ inline clang::Expr *getSubExprAsWritten(clang::CastExpr *This) {
// subexpression describing the call; strip it off.
if (E->getCastKind() == clang::CK_ConstructorConversion)
SubExpr =
- detail::skipImplicitTemporary(clang::cast<clang::CXXConstructExpr>(SubExpr)->getArg(0));
+ detail::skipImplicitTemporary(clang::cast<clang::CXXConstructExpr>(SubExpr->IgnoreImplicit())->getArg(0));
else if (E->getCastKind() == clang::CK_UserDefinedConversion) {
assert((clang::isa<clang::CXXMemberCallExpr>(SubExpr) ||
clang::isa<clang::BlockExpr>(SubExpr)) &&
diff --git a/compilerplugins/clang/stringconcatliterals.cxx b/compilerplugins/clang/stringconcatliterals.cxx
index 25872ff6ee32..509a10363c01 100644
--- a/compilerplugins/clang/stringconcatliterals.cxx
+++ b/compilerplugins/clang/stringconcatliterals.cxx
@@ -27,7 +27,7 @@ Expr const * stripCtor(Expr const * expr) {
return expr;
}
auto qt = loplugin::DeclCheck(e2->getConstructor());
- if (qt.MemberFunction().Struct("OStringLiteral").Namespace("rtl").GlobalNamespace()) {
+ if (qt.MemberFunction().Class("OStringLiteral").Namespace("rtl").GlobalNamespace()) {
if (e2->getNumArgs() == 1) {
return e2->getArg(0)->IgnoreParenImpCasts();
}
diff --git a/compilerplugins/clang/test/stringconcatliterals.cxx b/compilerplugins/clang/test/stringconcatliterals.cxx
index 76b82797f77e..348440f0ec4c 100644
--- a/compilerplugins/clang/test/stringconcatliterals.cxx
+++ b/compilerplugins/clang/test/stringconcatliterals.cxx
@@ -19,7 +19,7 @@
void f(std::ostream& s1)
{
- static char const foo[] = "foo";
+ static constexpr char foo[] = "foo";
static char16_t const foou[] = u"foo";
s1 << "foo"
<< "foo";
diff --git a/compilerplugins/clang/unusedmember.cxx b/compilerplugins/clang/unusedmember.cxx
index bcd9a8593a68..a32fd341c665 100644
--- a/compilerplugins/clang/unusedmember.cxx
+++ b/compilerplugins/clang/unusedmember.cxx
@@ -21,6 +21,7 @@
#include "config_clang.h"
#include "check.hxx"
+#include "compat.hxx"
#include "plugin.hxx"
namespace
@@ -289,7 +290,7 @@ public:
return true;
}
auto const t1 = expr->getType();
- auto const t2 = expr->getSubExprAsWritten()->getType();
+ auto const t2 = compat::getSubExprAsWritten(expr)->getType();
if (loplugin::TypeCheck(t1).Pointer().Void())
{
recordCastedRecordDecl(t2);
diff --git a/config_host/config_global.h.in b/config_host/config_global.h.in
index d9a907f4b91f..0df9ac8a47f1 100644
--- a/config_host/config_global.h.in
+++ b/config_host/config_global.h.in
@@ -15,6 +15,10 @@ Any change in this header will cause a rebuild of almost everything.
#define HAVE_GCC_BUILTIN_ATOMIC 0
#define HAVE_SYSLOG_H 0
+// Compiler supports C++20 <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1073r3.html>
+// "Immediate functions":
+#define HAVE_CPP_CONSTEVAL 0
+
// Compiler supports all of C++2a <https://wg21.link/P0202R3> "Add Constexpr Modifiers to Functions
// in <algorithm> and <utility> Headers", <https://wg21.link/P1004R2> "Making std::vector
// constexpr", and <https://wg21.link/P1143R2> "Adding the constinit keyword":
diff --git a/configure.ac b/configure.ac
index d60bfaf425a3..c05f66fd855f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6780,6 +6780,19 @@ if test "$GCC" = yes; then
fi
AC_SUBST([HAVE_GCC_FNO_SIZED_DEALLOCATION])
+AC_MSG_CHECKING([whether $CXX_BASE supports C++20 consteval])
+AC_LANG_PUSH([C++])
+save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS $CXXFLAGS_CXX11"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ consteval int f() { return 0; }
+ ])], [
+ AC_DEFINE([HAVE_CPP_CONSTEVAL],[1])
+ AC_MSG_RESULT([yes])
+ ], [AC_MSG_RESULT([no])])
+CXXFLAGS=$save_CXXFLAGS
+AC_LANG_POP([C++])
+
AC_MSG_CHECKING([whether $CXX_BASE supports C++2a constinit sorted vectors])
AC_LANG_PUSH([C++])
save_CXXFLAGS=$CXXFLAGS
diff --git a/i18npool/source/breakiterator/breakiterator_unicode.cxx b/i18npool/source/breakiterator/breakiterator_unicode.cxx
index bb8d7d9862aa..ca34f91e157b 100644
--- a/i18npool/source/breakiterator/breakiterator_unicode.cxx
+++ b/i18npool/source/breakiterator/breakiterator_unicode.cxx
@@ -214,7 +214,7 @@ void BreakIterator_Unicode::loadICUBreakIterator(const css::lang::Locale& rLocal
rbi.reset();
// ;rule (only)
- const OString aBIMapRuleOnlyKey( OStringLiteral(";") + rule);
+ const OString aBIMapRuleOnlyKey( OString::Concat(";") + rule);
aMapIt = theBIMap.find( aBIMapRuleOnlyKey);
bInMap = (aMapIt != theBIMap.end());
if (bInMap)
diff --git a/include/rtl/string.hxx b/include/rtl/string.hxx
index da75e5eee57c..ca1fd99b7fba 100644
--- a/include/rtl/string.hxx
+++ b/include/rtl/string.hxx
@@ -24,6 +24,7 @@
#include <cassert>
#include <cstddef>
+#include <limits>
#include <new>
#include <ostream>
#include <utility>
@@ -38,6 +39,7 @@
#include "rtl/stringutils.hxx"
#ifdef LIBO_INTERNAL_ONLY // "RTL_FAST_STRING"
+#include "config_global.h"
#include "rtl/stringconcat.hxx"
#endif
@@ -70,34 +72,53 @@ namespace rtl
#ifdef LIBO_INTERNAL_ONLY // "RTL_FAST_STRING"
/**
-A simple wrapper around string literal. It is usually not necessary to use, can
-be mostly used to force OString operator+ working with operands that otherwise would
-not trigger it.
+A wrapper dressing a string literal as a static-refcount rtl_String.
This class is not part of public API and is meant to be used only in LibreOffice code.
@since LibreOffice 4.0
*/
-struct SAL_WARN_UNUSED OStringLiteral
-{
- template< int N >
- explicit OStringLiteral( const char (&str)[ N ] ) : size( N - 1 ), data( str ) { assert( strlen( str ) == N - 1 ); }
+template<std::size_t N> class SAL_WARN_UNUSED OStringLiteral {
+ static_assert(N != 0);
+ static_assert(N - 1 <= std::numeric_limits<sal_Int32>::max(), "literal too long");
+
+public:
+#if HAVE_CPP_CONSTEVAL
+ consteval
+#else
+ constexpr
+#endif
+ explicit OStringLiteral(char const (&literal)[N]) {
+ assert(literal[N - 1] == '\0');
+ //TODO: Use C++20 constexpr std::copy_n (P0202R3):
+ for (std::size_t i = 0; i != N; ++i) {
+ buffer[i] = literal[i];
+ }
+ }
+
#if defined __cpp_char8_t
- template< int N >
- explicit OStringLiteral( const char8_t (&str)[ N ] ) : size( N - 1 ), data( reinterpret_cast<char const *>(str) ) { assert( strlen( data ) == N - 1 ); }
+#if HAVE_CPP_CONSTEVAL
+ consteval
+#else
+ constexpr
+#endif
+ explicit OStringLiteral(char8_t const (&literal)[N]) {
+ assert(literal[N - 1] == '\0');
+ //TODO: Use C++20 constexpr std::copy_n (P0202R3):
+ for (std::size_t i = 0; i != N; ++i) {
+ buffer[i] = literal[i];
+ }
+ }
#endif
- int size;
- const char* data;
+ constexpr sal_Int32 getLength() const { return length; }
- /** So we can use this in some places interchangeably with OUString.
- * @since LibreOffice 7.1
- */
- constexpr sal_Int32 getLength() const { return size; }
+ constexpr char const * getStr() const SAL_RETURNS_NONNULL { return buffer; }
- /** So we can use this in some places interchangeably with OString.
- * @since LibreOffice 7.1
- */
- constexpr const char* getStr() const { return data; }
+private:
+ // Same layout as rtl_String (include/rtl/string.h):
+ oslInterlockedCount refCount = 0x40000000; // SAL_STRING_STATIC_FLAG (sal/rtl/strimp.hxx)
+ sal_Int32 length = N - 1;
+ char buffer[N] = {}; //TODO: drop initialization for C++20 (P1331R2)
};
#endif
@@ -274,23 +295,22 @@ public:
/**
New string from an 8-Bit string literal.
- This constructor is similar to the "direct template" one, but can be
- useful in cases where the latter does not work, like in
-
- OString(flag ? "a" : "bb")
-
- written as
-
- OString(flag ? OStringLiteral("a") : OStringLiteral("bb"))
-
@since LibreOffice 7.1
*/
- OString(OStringLiteral literal): pData(NULL) {
- rtl_string_newFromLiteral(&pData, literal.data, literal.size, 0);
- }
+ template<std::size_t N> OString(OStringLiteral<N> const & literal):
+ pData(const_cast<rtl_String *>(reinterpret_cast<rtl_String const *>(&literal))) {}
/// @endcond
#endif
+#if defined LIBO_INTERNAL_ONLY
+ explicit OString(std::string_view sv) {
+ if (sv.size() > sal_uInt32(std::numeric_limits<sal_Int32>::max())) {
+ throw std::bad_alloc();
+ }
+ pData = nullptr;
+ rtl_string_newFromStr_WithLength(&pData, sv.data(), sv.size());
+ }
+#endif
/**
New string from a Unicode character buffer array.
@@ -1946,11 +1966,11 @@ struct ToStringHelper< OString >
/**
@internal
*/
-template<>
-struct ToStringHelper< OStringLiteral >
+template<std::size_t N>
+struct ToStringHelper< OStringLiteral<N> >
{
- static std::size_t length( const OStringLiteral& str ) { return str.size; }
- static char* addData( char* buffer, const OStringLiteral& str ) { return addDataHelper( buffer, str.data, str.size ); }
+ static constexpr std::size_t length( const OStringLiteral<N>& str ) { return str.getLength(); }
+ static char* addData( char* buffer, const OStringLiteral<N>& str ) { return addDataHelper( buffer, str.getStr(), str.getLength() ); }
static const bool allowOStringConcat = true;
static const bool allowOUStringConcat = false;
};
diff --git a/sal/qa/rtl/digest/rtl_digest.cxx b/sal/qa/rtl/digest/rtl_digest.cxx
index e2392eaadcc8..d948deaf6d6c 100644
--- a/sal/qa/rtl/digest/rtl_digest.cxx
+++ b/sal/qa/rtl/digest/rtl_digest.cxx
@@ -24,6 +24,7 @@
#include <cppunit/plugin/TestPlugIn.h>
#include <memory>
+#include <string_view>
#include <rtl/digest.h>
#include <rtl/string.h>
@@ -61,14 +62,14 @@ const sal_uInt32 constDigestAlgorithmLengths[] =
RTL_DIGEST_LENGTH_HMAC_SHA1,
};
-const OStringLiteral constSampleStringSums[] =
+const std::string_view constSampleStringSums[] =
{
- OStringLiteral("647ee6c9d4aa5fdd374ed9d7a156acbf"),
- OStringLiteral("b16b903e6fc0b62ae389013ed93fe531"),
- OStringLiteral("eab2814429b2613301c8a077b806af3680548914"),
- OStringLiteral("2bc5bdb7506a2cdc2fd27fc8b9889343012d5008"),
- OStringLiteral("0b1b0e1a6f2e4420326354b031063605"),
- OStringLiteral("1998c6a556915be76451bfb587fa7c34d849936e")
+ std::string_view("647ee6c9d4aa5fdd374ed9d7a156acbf"),
+ std::string_view("b16b903e6fc0b62ae389013ed93fe531"),
+ std::string_view("eab2814429b2613301c8a077b806af3680548914"),
+ std::string_view("2bc5bdb7506a2cdc2fd27fc8b9889343012d5008"),
+ std::string_view("0b1b0e1a6f2e4420326354b031063605"),
+ std::string_view("1998c6a556915be76451bfb587fa7c34d849936e")
};
// Create hex-value string from the digest value to keep the string size minimal
diff --git a/sal/qa/rtl/strings/test_ostring_concat.cxx b/sal/qa/rtl/strings/test_ostring_concat.cxx
index e5872654b58d..94f4e8d692cf 100644
--- a/sal/qa/rtl/strings/test_ostring_concat.cxx
+++ b/sal/qa/rtl/strings/test_ostring_concat.cxx
@@ -68,9 +68,15 @@ void test::ostring::StringConcat::checkConcat()
CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OStringBuffer( "foo" ) + "bar" ));
CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringBuffer, const char[ 4 ] > )), typeid( OStringBuffer( "foo" ) + "bar" ));
CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OStringLiteral( "foo" ) + "bar" ));
- CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral, const char[ 4 ] > )), typeid( OStringLiteral( "foo" ) + "bar" ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char[ 4 ] > )), typeid( OStringLiteral<4>( "foo" ) + "bar" ));
+ //TODO: the explicit OUStringLiteral<4> template argument in the unevaluated typeid context
+ // is needed by some GCC versions, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96878>
+ // "Failed class template argument deduction in unevaluated, parenthesized context"
CPPUNIT_ASSERT_EQUAL( OString( "foobar" ), OString( OStringLiteral( "foo" ) + static_cast<const char*>("bar") ));
- CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral, const char* > )), typeid( OStringLiteral( "foo" ) + static_cast<const char*>("bar") ));
+ CPPUNIT_ASSERT_EQUAL(( typeid( OStringConcat< OStringLiteral<4>, const char* > )), typeid( OStringLiteral<4>( "foo" ) + static_cast<const char*>("bar") ));
+ //TODO: the explicit OUStringLiteral<4> template argument in the unevaluated typeid context
+ // is needed by some GCC versions, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96878>
+ // "Failed class template argument deduction in unevaluated, parenthesized context"
const char d1[] = "xyz";
char d2[] = "abc";
const char* d3 = d1;
diff --git a/sal/qa/rtl/textenc/rtl_textcvt.cxx b/sal/qa/rtl/textenc/rtl_textcvt.cxx
index 8e619a23e1ca..6dec034a96ff 100644
--- a/sal/qa/rtl/textenc/rtl_textcvt.cxx
+++ b/sal/qa/rtl/textenc/rtl_textcvt.cxx
@@ -2966,7 +2966,7 @@ void Test::testInvalidUtf8() {
sal_uInt32 info;
sal_Size converted;
auto const size = rtl_convertTextToUnicode(
- converter, nullptr, input.data, input.size, buf,
+ converter, nullptr, input.getStr(), input.getLength(), buf,
TEST_STRING_SIZE,
(RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
| RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR