summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2012-03-13 16:09:25 +0100
committerLuboš Luňák <l.lunak@suse.cz>2012-03-13 16:21:04 +0100
commit3d9f5c856a4a77503695e68ce013ebf859fcb212 (patch)
treeaaa75452b54542a52f746da9782ae6c3d2663453
parent131e5d35a4edb9f8875a197e8e0382c168834f70 (diff)
make OString work even with old gcc that has SFINAE broken
Since OString already has a ctor accepting const char*, I cannot find out a way to distinguish string literals other than using a template, otherwise const char* somehow takes precedence (all of gcc, clang, msvc). But the template requires the Substitution Is Not A Failure Idiom to actually create only wanted instances. And the compiler can try evaluate the OString ctor as a possibility when comparing an int to an anonymous enum, and anonymous enum as a type without linkage cannot be a template argument before C++11. SFINAE should still work, but not with gcc older than 4.0.2 (which we right now use only on macs). So for that case disable the string literal ctors, which means macs will have one extra strlen call, and also that embedded \0's in string literals will be inconsistent. The tiny performance problem shouldn't matter that much and will eventually go away, the \0 problem should not matter, since before string literal ctors were introduced \0's had not been included anyway unless RTL_CONSTASCII_STRINGPARAM was used. So we should be safe and when removing the CONSTASCII macros \0 cases should be handled by explicitly mentioning the length.
-rw-r--r--config_host.mk.in1
-rw-r--r--configure.in35
-rw-r--r--sal/inc/rtl/string.hxx18
-rw-r--r--sal/qa/rtl/strings/test_ostring_stringliterals.cxx12
-rw-r--r--sal/rtl/source/strtmpl.cxx1
-rw-r--r--solenv/gbuild/platform/macosx.mk5
-rw-r--r--solenv/gbuild/platform/unxgcc.mk6
-rw-r--r--solenv/inc/unxgcc.mk4
-rw-r--r--solenv/inc/unxmacx.mk3
-rw-r--r--solenv/inc/unxsogi.mk4
-rw-r--r--solenv/inc/unxsogs.mk4
11 files changed, 88 insertions, 5 deletions
diff --git a/config_host.mk.in b/config_host.mk.in
index 2839b5c83eed..77d149871c11 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -187,6 +187,7 @@ export HAVE_GCC_AVX=@HAVE_GCC_AVX@
export HAVE_GCC_NO_LONG_DOUBLE=@HAVE_GCC_NO_LONG_DOUBLE@
export HAVE_GCC_VISIBILITY_BROKEN=@HAVE_GCC_VISIBILITY_BROKEN@
export HAVE_GCC_VISIBILITY_FEATURE=@HAVE_GCC_VISIBILITY_FEATURE@
+export HAVE_SFINAE_ANONYMOUS_BROKEN=@HAVE_SFINAE_ANONYMOUS_BROKEN@
export HAVE_GETOPT=@HAVE_GETOPT@
export HAVE_LD_BSYMBOLIC_FUNCTIONS=@HAVE_LD_BSYMBOLIC_FUNCTIONS@
export HAVE_LD_HASH_STYLE=@HAVE_LD_HASH_STYLE@
diff --git a/configure.in b/configure.in
index 764b9c00a827..e0bc4ddb2b24 100644
--- a/configure.in
+++ b/configure.in
@@ -4559,6 +4559,41 @@ AC_SUBST(HAVE_GCC_VISIBILITY_FEATURE)
AC_SUBST(HAVE_GCC_VISIBILITY_BROKEN)
dnl ===================================================================
+dnl SFINAE test
+dnl Pre-C++11 does not allow types without linkage as template arguments.
+dnl Substitution Failure Is Not An Error is an idiom that disables
+dnl template instances that would cause an error, without actually
+dnl causing an error. Old gcc (pre-4.0.2) however causes a real error.
+dnl http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21514
+dnl ===================================================================
+HAVE_SFINAE_ANONYMOUS_BROKEN=
+if test \( "$_os" != "WINNT" -o "$WITH_MINGW" = "yes" \); then
+
+ AC_LANG_PUSH([C++])
+ AC_MSG_CHECKING([if SFINAE is broken with anonymous types])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+enum { AnonymousEnumValue };
+template< typename T > class TestPredicate {};
+template<> class TestPredicate< int > { public: typedef bool Type; };
+template< typename T >
+bool test( const T&, typename TestPredicate< T >::Type = false )
+ { return true; };
+void test( ... );
+ ]], [[
+ test( 10 );
+ test( AnonymousEnumValue );
+ ]])],[sfinae_anonymous_broken=no],[sfinae_anonymous_broken=yes
+ ])
+ AC_MSG_RESULT([$sfinae_anonymous_broken])
+ if test "$sfinae_anonymous_broken" = "yes"; then
+ HAVE_SFINAE_ANONYMOUS_BROKEN="TRUE"
+ fi
+ AC_LANG_POP([C++])
+fi
+
+AC_SUBST(HAVE_SFINAE_ANONYMOUS_BROKEN)
+
+dnl ===================================================================
dnl allocator
dnl ===================================================================
AC_MSG_CHECKING([which memory allocator to use])
diff --git a/sal/inc/rtl/string.hxx b/sal/inc/rtl/string.hxx
index 6590677efea0..79b9a15ae94a 100644
--- a/sal/inc/rtl/string.hxx
+++ b/sal/inc/rtl/string.hxx
@@ -85,6 +85,7 @@ namespace rtl
use this class.
*/
+#ifndef HAVE_SFINAE_ANONYMOUS_BROKEN
namespace internal
{
// This template is used for SFINAE (Substitution failure is not an error), to detect that
@@ -107,6 +108,7 @@ struct CharPtrDetector< char* >
typedef Dummy Type;
};
}
+#endif
class OString
{
@@ -184,6 +186,17 @@ public:
@param value a NULL-terminated character array.
*/
+#ifdef HAVE_SFINAE_ANONYMOUS_BROKEN
+ // Old gcc can try to convert anonymous enums to OString and give compile error.
+ // So there's no special-cased handling of string literals.
+ // These are inline functions and technically both variants should work
+ // the same in practice, so there should be no compatibility problem.
+ OString( const sal_Char * value ) SAL_THROW(())
+ {
+ pData = 0;
+ rtl_string_newFromStr( &pData, value );
+ }
+#else
template< typename T >
OString( const T& value, typename internal::CharPtrDetector< T >::Type = internal::Dummy() ) SAL_THROW(())
{
@@ -194,8 +207,8 @@ public:
/**
New string from a string literal.
- Note that embedded \0's are included in the string if explicitly present
- in the string literal.
+ If there are any embedded \0's in the string literal, the result is undefined.
+ Use the overload that explicitly accepts length.
@param literal a string literal
*/
@@ -221,6 +234,7 @@ public:
pData = 0;
rtl_string_newFromStr( &pData, value );
}
+#endif // HAVE_SFINAE_ANONYMOUS_BROKEN
/**
New string from a character buffer array.
diff --git a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
index 22f79ab630a6..8398ae9e63e9 100644
--- a/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
+++ b/sal/qa/rtl/strings/test_ostring_stringliterals.cxx
@@ -62,6 +62,8 @@ CPPUNIT_TEST_SUITE_END();
void test::ostring::StringLiterals::checkCtors()
{
+// string literal ctors do not work with SFINAE broken and are disabled
+#ifndef HAVE_SFINAE_ANONYMOUS_BROKEN
CPPUNIT_ASSERT( CONST_CTOR_USED( "test" ));
const char good1[] = "test";
CPPUNIT_ASSERT( CONST_CTOR_USED( good1 ));
@@ -89,13 +91,19 @@ void test::ostring::StringLiterals::checkCtors()
CPPUNIT_ASSERT( rtl::OString( (const char*)"ab" ) == rtl::OString( "ab" ));
// Check that contents are correct and equal to the case when RTL_CONSTASCII_STRINGPARAM is used.
+ CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "" )) == rtl::OString( "" ));
+ CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "ab" )) == rtl::OString( "ab" ));
+#if 0
+// This is currently disabled because it can't be consistent with HAVE_SFINAE_ANONYMOUS_BROKEN.
+// Since the situation wasn't quite consistent even before, there should be no big harm.
+
// Check also that embedded \0 is included (RTL_CONSTASCII_STRINGPARAM does the same,
// const char* ctor does not, but it seems to make more sense to include it when
// it's explicitly mentioned in the string literal).
- CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "" )) == rtl::OString( "" ));
CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "\0" )) == rtl::OString( "\0" ));
- CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "ab" )) == rtl::OString( "ab" ));
CPPUNIT_ASSERT( rtl::OString( RTL_CONSTASCII_STRINGPARAM( "a\0b" )) == rtl::OString( "a\0b" ));
+#endif
+#endif
}
void test::ostring::StringLiterals::testcall( const char str[] )
diff --git a/sal/rtl/source/strtmpl.cxx b/sal/rtl/source/strtmpl.cxx
index a3ef1facdadf..2d8c44bbe4fa 100644
--- a/sal/rtl/source/strtmpl.cxx
+++ b/sal/rtl/source/strtmpl.cxx
@@ -1189,7 +1189,6 @@ void SAL_CALL IMPL_RTL_STRINGNAME( newFromStr_WithLength )( IMPL_RTL_STRINGDATA*
/* ----------------------------------------------------------------------- */
// Used when creating from string literals.
-// Intentionally copies also embedded \0's if present.
void SAL_CALL IMPL_RTL_STRINGNAME( newFromLiteral)( IMPL_RTL_STRINGDATA** ppThis,
const sal_Char* pCharStr,
sal_Int32 nLen )
diff --git a/solenv/gbuild/platform/macosx.mk b/solenv/gbuild/platform/macosx.mk
index 9a918246f738..22a1fa8e94d9 100644
--- a/solenv/gbuild/platform/macosx.mk
+++ b/solenv/gbuild/platform/macosx.mk
@@ -51,6 +51,11 @@ gb_COMPILERDEFS += \
-DHAVE_GCC_VISIBILITY_FEATURE \
+ifeq ($(HAVE_SFINAE_ANONYMOUS_BROKEN),TRUE)
+gb_COMPILERDEFS += \
+ -DHAVE_SFINAE_ANONYMOUS_BROKEN \
+
+endif
gb_CFLAGS := \
-isysroot $(gb_SDKDIR) \
diff --git a/solenv/gbuild/platform/unxgcc.mk b/solenv/gbuild/platform/unxgcc.mk
index c709fde1e4e8..43f58a7cf0b4 100644
--- a/solenv/gbuild/platform/unxgcc.mk
+++ b/solenv/gbuild/platform/unxgcc.mk
@@ -84,6 +84,12 @@ endif
endif
+ifeq ($(HAVE_SFINAE_ANONYMOUS_BROKEN),TRUE)
+gb_COMPILERDEFS += \
+ -DHAVE_SFINAE_ANONYMOUS_BROKEN \
+
+endif
+
# enable debug STL
ifeq ($(gb_PRODUCT),$(false))
gb_COMPILERDEFS += \
diff --git a/solenv/inc/unxgcc.mk b/solenv/inc/unxgcc.mk
index 3765b2dd6cea..8bfeebc20cf6 100644
--- a/solenv/inc/unxgcc.mk
+++ b/solenv/inc/unxgcc.mk
@@ -51,6 +51,10 @@ CDEFS+=-D_PTHREADS -D_REENTRANT -DNEW_SOLAR -D_USE_NAMESPACE=1
CDEFS += -DHAVE_GCC_VISIBILITY_FEATURE
.ENDIF # "$(HAVE_GCC_VISIBILITY_FEATURE)" == "TRUE"
+.IF "$(HAVE_SFINAE_ANONYMOUS_BROKEN)" == "TRUE"
+CDEFS += -DHAVE_SFINAE_ANONYMOUS_BROKEN
+.ENDIF # "$(HAVE_SFINAE_ANONYMOUS_BROKEN)" == "TRUE"
+
# this is a platform with JAVA support
.IF "$(SOLAR_JAVA)"!=""
JAVADEF=-DSOLAR_JAVA
diff --git a/solenv/inc/unxmacx.mk b/solenv/inc/unxmacx.mk
index 0cb0b62ee02f..8f36772f4d06 100644
--- a/solenv/inc/unxmacx.mk
+++ b/solenv/inc/unxmacx.mk
@@ -60,6 +60,9 @@ EXTRA_CDEFS+:=-isysroot $(MACOSX_SDK_PATH) -DMAC_OS_X_VERSION_MIN_REQUIRED=$(MA
CDEFS += -DHAVE_GCC_VISIBILITY_FEATURE
.ENDIF # "$(HAVE_GCC_VISIBILITY_FEATURE)" == "TRUE"
+.IF "$(HAVE_SFINAE_ANONYMOUS_BROKEN)" == "TRUE"
+CDEFS += -DHAVE_SFINAE_ANONYMOUS_BROKEN
+.ENDIF # "$(HAVE_SFINAE_ANONYMOUS_BROKEN)" == "TRUE"
# MacOS X specific Java compilation/link flags
SOLAR_JAVA*=TRUE
diff --git a/solenv/inc/unxsogi.mk b/solenv/inc/unxsogi.mk
index 2ebcbc468e42..4e811655bfd3 100644
--- a/solenv/inc/unxsogi.mk
+++ b/solenv/inc/unxsogi.mk
@@ -94,6 +94,10 @@ LINKVERSIONMAPFLAG=-Wl,--version-script
CDEFS += -DHAVE_GCC_VISIBILITY_FEATURE
.ENDIF # "$(HAVE_GCC_VISIBILITY_FEATURE)" == "TRUE"
+.IF "$(HAVE_SFINAE_ANONYMOUS_BROKEN)" == "TRUE"
+CDEFS += -DHAVE_SFINAE_ANONYMOUS_BROKEN
+.ENDIF # "$(HAVE_SFINAE_ANONYMOUS_BROKEN)" == "TRUE"
+
# Reihenfolge der libs NICHT egal!
STDLIBCPP=-lstdc++
diff --git a/solenv/inc/unxsogs.mk b/solenv/inc/unxsogs.mk
index 4f80b42c0a4a..e25d690ce49f 100644
--- a/solenv/inc/unxsogs.mk
+++ b/solenv/inc/unxsogs.mk
@@ -93,6 +93,10 @@ LINKVERSIONMAPFLAG=-Wl,--version-script
CDEFS += -DHAVE_GCC_VISIBILITY_FEATURE
.ENDIF # "$(HAVE_GCC_VISIBILITY_FEATURE)" == "TRUE"
+.IF "$(HAVE_SFINAE_ANONYMOUS_BROKEN)" == "TRUE"
+CDEFS += -DHAVE_SFINAE_ANONYMOUS_BROKEN
+.ENDIF # "$(HAVE_SFINAE_ANONYMOUS_BROKEN)" == "TRUE"
+
# Reihenfolge der libs NICHT egal!
STDLIBCPP=-lstdc++