Kaydet (Commit) 1fc79c34 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

Avoid using O[U]StringConcat lvalues containing dangling refs to temporaries

...in code accidentally using auto like

> auto const aURL = uri->getUriReference() + "/"
>     + INetURLObject::encode(
>         m_sEmbeddedName, INetURLObject::PART_FPATH,
>         INetURLObject::EncodeMechanism::All);
>
> uno::Reference<uno::XInterface> xDataSource(xDatabaseContext->getByName(aURL), uno::UNO_QUERY);

in <https://gerrit.libreoffice.org/#/c/44569/1> "Properly construct
vnd.sun.star.pkg URL" did (causing hard to debug test failures there).

So make functions taking O[U]StringConcat take those by rvalue reference.
Unfortunately, that also needed adaption of various functions that just forward
their arguments.  And some code in sc/qa/unit/ucalc_formula.cxx used
CPPUNIT_ASSERT_EQUAL on OUStringConcat arguments in cases where that happened to
actually compile (because the structure of the two OUStringConcats was
identical), which needed adaption too (but which would arguably better use
CPPUNIT_ASSERT_EQUAL_MESSAGE, anyway).

Change-Id: I8994d932aaedb2a491c7c81c167e93379d4fb6e3
Reviewed-on: https://gerrit.libreoffice.org/44608Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarStephan Bergmann <sbergman@redhat.com>
üst f697d06b
......@@ -79,7 +79,9 @@ public:
#if defined LIBO_INTERNAL_ONLY
template<typename T1, typename T2>
explicit inline Any(rtl::OUStringConcat<T1, T2> const & value);
explicit inline Any(rtl::OUStringConcat<T1, T2> && value);
template<typename T1, typename T2>
explicit Any(rtl::OUStringConcat<T1, T2> const &) = delete;
#endif
/** Copy constructor: Sets value of the given any.
......
......@@ -26,6 +26,7 @@
#include <cstddef>
#include <iomanip>
#include <ostream>
#include <utility>
#include "com/sun/star/uno/Any.h"
#include "uno/data.h"
......@@ -76,7 +77,8 @@ inline Any::Any( bool value )
#if defined LIBO_INTERNAL_ONLY
template<typename T1, typename T2>
Any::Any(rtl::OUStringConcat<T1, T2> const & value): Any(rtl::OUString(value))
Any::Any(rtl::OUStringConcat<T1, T2> && value):
Any(rtl::OUString(std::move(value)))
{}
#endif
......@@ -239,6 +241,14 @@ template<> Any toAny(Any const & value) { return value; }
#if defined LIBO_INTERNAL_ONLY
template<typename T1, typename T2>
Any makeAny(rtl::OUStringConcat<T1, T2> && value)
{ return Any(std::move(value)); }
template<typename T1, typename T2>
Any toAny(rtl::OUStringConcat<T1, T2> && value)
{ return makeAny(std::move(value)); }
template<typename T> bool fromAny(Any const & any, T * value) {
assert(value != nullptr);
return any >>= *value;
......@@ -275,14 +285,16 @@ inline void SAL_CALL operator <<= ( Any & rAny, bool const & value )
#ifdef LIBO_INTERNAL_ONLY // "RTL_FAST_STRING"
template< class C1, class C2 >
inline void SAL_CALL operator <<= ( Any & rAny, const rtl::OUStringConcat< C1, C2 >& value )
inline void SAL_CALL operator <<= ( Any & rAny, rtl::OUStringConcat< C1, C2 >&& value )
{
const rtl::OUString str( value );
const rtl::OUString str( std::move(value) );
const Type & rType = ::cppu::getTypeFavourUnsigned(&str);
::uno_type_any_assign(
&rAny, const_cast< rtl::OUString * >( &str ), rType.getTypeLibType(),
cpp_acquire, cpp_release );
}
template<typename T1, typename T2>
void operator <<=(Any &, rtl::OUStringConcat<T1, T2> const &) = delete;
#endif
#if defined LIBO_INTERNAL_ONLY
......
......@@ -10,6 +10,10 @@
#ifndef INCLUDED_COMPHELPER_PROPERTYVALUE_HXX
#define INCLUDED_COMPHELPER_PROPERTYVALUE_HXX
#include <sal/config.h>
#include <utility>
#include <com/sun/star/beans/PropertyValue.hpp>
namespace comphelper
......@@ -22,11 +26,11 @@ namespace comphelper
*
* instead of writing 3 extra lines to set the name and value of the beans::PropertyValue.
*/
template<typename T> css::beans::PropertyValue makePropertyValue(const OUString& rName, const T& rValue)
template<typename T> css::beans::PropertyValue makePropertyValue(const OUString& rName, T&& rValue)
{
css::beans::PropertyValue aValue;
aValue.Name = rName;
aValue.Value = css::uno::toAny(rValue);
aValue.Value = css::uno::toAny(std::forward<T>(rValue));
return aValue;
}
......
......@@ -21,6 +21,7 @@
#define INCLUDED_OOX_HELPER_PROPERTYMAP_HXX
#include <map>
#include <utility>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Reference.hxx>
......@@ -67,12 +68,12 @@ public:
/** Sets the specified property to the passed value. Does nothing, if the
identifier is invalid. */
template< typename Type >
bool setProperty( sal_Int32 nPropId, const Type& rValue )
bool setProperty( sal_Int32 nPropId, Type&& rValue )
{
if( nPropId < 0 )
return false;
maProperties[ nPropId ] <<= rValue;
maProperties[ nPropId ] <<= std::forward<Type>(rValue);
return true;
}
......
......@@ -214,7 +214,7 @@ public:
@internal
*/
template< typename T1, typename T2 >
OStringBuffer( const OStringConcat< T1, T2 >& c )
OStringBuffer( OStringConcat< T1, T2 >&& c )
{
const sal_Int32 l = c.length();
nCapacity = l + 16;
......@@ -279,7 +279,7 @@ public:
#if defined LIBO_INTERNAL_ONLY
/** @overload @since LibreOffice 5.3 */
template<typename T1, typename T2>
OStringBuffer & operator =(OStringConcat<T1, T2> const & concat) {
OStringBuffer & operator =(OStringConcat<T1, T2> && concat) {
sal_Int32 const n = concat.length();
if (n >= nCapacity) {
ensureCapacity(n + 16); //TODO: check for overflow
......@@ -549,7 +549,7 @@ public:
@internal
*/
template< typename T1, typename T2 >
OStringBuffer& append( const OStringConcat< T1, T2 >& c )
OStringBuffer& append( OStringConcat< T1, T2 >&& c )
{
sal_Int32 l = c.length();
if( l == 0 )
......
......@@ -26,6 +26,7 @@
#include <cstddef>
#include <new>
#include <ostream>
#include <utility>
#include <string.h>
#include "rtl/textenc.h"
......@@ -266,7 +267,7 @@ public:
@internal
*/
template< typename T1, typename T2 >
OString( const OStringConcat< T1, T2 >& c )
OString( OStringConcat< T1, T2 >&& c )
{
const sal_Int32 l = c.length();
pData = rtl_string_alloc( l );
......@@ -367,7 +368,7 @@ public:
@internal
*/
template< typename T1, typename T2 >
OString& operator+=( const OStringConcat< T1, T2 >& c ) & {
OString& operator+=( OStringConcat< T1, T2 >&& c ) & {
sal_Int32 l = c.length();
if( l == 0 )
return *this;
......@@ -379,7 +380,7 @@ public:
return *this;
}
template<typename T1, typename T2> void operator +=(
OStringConcat<T1, T2> const &) && = delete;
OStringConcat<T1, T2> &&) && = delete;
#endif
/**
......@@ -1839,9 +1840,9 @@ struct ToStringHelper< OStringLiteral >
*/
template< typename charT, typename traits, typename T1, typename T2 >
inline std::basic_ostream<charT, traits> & operator <<(
std::basic_ostream<charT, traits> & stream, const OStringConcat< T1, T2 >& concat)
std::basic_ostream<charT, traits> & stream, OStringConcat< T1, T2 >&& concat)
{
return stream << OString( concat );
return stream << OString( std::move(concat) );
}
#endif
......
......@@ -208,7 +208,7 @@ public:
@internal
*/
template< typename T1, typename T2 >
OUStringBuffer( const OUStringConcat< T1, T2 >& c )
OUStringBuffer( OUStringConcat< T1, T2 >&& c )
{
const sal_Int32 l = c.length();
nCapacity = l + 16;
......@@ -313,7 +313,7 @@ public:
#if defined LIBO_INTERNAL_ONLY
/** @overload @since LibreOffice 5.3 */
template<typename T1, typename T2>
OUStringBuffer & operator =(OUStringConcat<T1, T2> const & concat) {
OUStringBuffer & operator =(OUStringConcat<T1, T2> && concat) {
sal_Int32 const n = concat.length();
if (n >= nCapacity) {
ensureCapacity(n + 16); //TODO: check for overflow
......@@ -631,7 +631,7 @@ public:
@internal
*/
template< typename T1, typename T2 >
OUStringBuffer& append( const OUStringConcat< T1, T2 >& c )
OUStringBuffer& append( OUStringConcat< T1, T2 >&& c )
{
sal_Int32 l = c.length();
if( l == 0 )
......
......@@ -26,6 +26,7 @@
#include <cstddef>
#include <new>
#include <ostream>
#include <utility>
#include <string.h>
#include "rtl/ustring.h"
......@@ -391,7 +392,7 @@ public:
@internal
*/
template< typename T1, typename T2 >
OUString( const OUStringConcat< T1, T2 >& c )
OUString( OUStringConcat< T1, T2 >&& c )
{
const sal_Int32 l = c.length();
pData = rtl_uString_alloc( l );
......@@ -598,7 +599,7 @@ public:
@internal
*/
template< typename T1, typename T2 >
OUString& operator+=( const OUStringConcat< T1, T2 >& c ) & {
OUString& operator+=( OUStringConcat< T1, T2 >&& c ) & {
sal_Int32 l = c.length();
if( l == 0 )
return *this;
......@@ -610,7 +611,7 @@ public:
return *this;
}
template<typename T1, typename T2> void operator +=(
OUStringConcat<T1, T2> const &) && = delete;
OUStringConcat<T1, T2> &&) && = delete;
#endif
/**
......@@ -3584,9 +3585,9 @@ struct ToStringHelper< OUStringLiteral >
*/
template< typename charT, typename traits, typename T1, typename T2 >
inline std::basic_ostream<charT, traits> & operator <<(
std::basic_ostream<charT, traits> & stream, const OUStringConcat< T1, T2 >& concat)
std::basic_ostream<charT, traits> & stream, OUStringConcat< T1, T2 >&& concat)
{
return stream << OUString( concat );
return stream << OUString( std::move(concat) );
}
/// @endcond
......
......@@ -24,6 +24,7 @@
#include <sax/fastattribs.hxx>
#include <stdarg.h>
#include <memory>
#include <utility>
#define FSNS(namespc, element) ((namespc << 16) | element)
// Backwards compatibility for code that used FSEND to terminate the vararg.
......@@ -76,11 +77,11 @@ public:
/// Start an element. After the first argument there can be a number of (attribute, value) pairs.
template<typename... Args>
void startElement(sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, Args... args)
void startElement(sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, Args &&... args)
{
if (value)
pushAttributeValue(attribute, value);
startElement(elementTokenId, args...);
startElement(elementTokenId, std::forward<Args>(args)...);
}
void startElement(sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, FSEND_t)
{
......@@ -89,10 +90,10 @@ public:
startElement(elementTokenId, FSEND);
}
template<typename... Args>
void startElement(sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, Args... args)
void startElement(sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, Args &&... args)
{
pushAttributeValue(attribute, value);
startElement(elementTokenId, args...);
startElement(elementTokenId, std::forward<Args>(args)...);
}
void startElement(sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, FSEND_t)
{
......@@ -103,11 +104,11 @@ public:
/// Start an element. After the first two arguments there can be a number of (attribute, value) pairs.
template<typename... Args>
void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, Args... args)
void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, Args &&... args)
{
if (value)
pushAttributeValue(attribute, value);
startElementNS(namespaceTokenId, elementTokenId, args...);
startElementNS(namespaceTokenId, elementTokenId, std::forward<Args>(args)...);
}
void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, FSEND_t)
{
......@@ -116,10 +117,10 @@ public:
startElementNS(namespaceTokenId, elementTokenId, FSEND);
}
template<typename... Args>
void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, Args... args)
void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, Args &&... args)
{
pushAttributeValue(attribute, value);
startElementNS(namespaceTokenId, elementTokenId, args...);
startElementNS(namespaceTokenId, elementTokenId, std::forward<Args>(args)...);
}
void startElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, FSEND_t)
{
......@@ -133,11 +134,11 @@ public:
/// Create a single element. After the first argument there can be a number of (attribute, value) pairs.
template<typename... Args>
void singleElement(sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, Args... args)
void singleElement(sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, Args &&... args)
{
if (value)
pushAttributeValue(attribute, value);
singleElement(elementTokenId, args...);
singleElement(elementTokenId, std::forward<Args>(args)...);
}
void singleElement(sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, FSEND_t)
{
......@@ -146,10 +147,10 @@ public:
singleElement(elementTokenId, FSEND);
}
template<typename... Args>
void singleElement(sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, Args... args)
void singleElement(sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, Args &&... args)
{
pushAttributeValue(attribute, value);
singleElement(elementTokenId, args...);
singleElement(elementTokenId, std::forward<Args>(args)...);
}
void singleElement(sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, FSEND_t)
{
......@@ -160,11 +161,11 @@ public:
/// Create a single element. After the first two arguments there can be a number of (attribute, value) pairs.
template<typename... Args>
void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, Args... args)
void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, Args &&... args)
{
if (value)
pushAttributeValue(attribute, value);
singleElementNS(namespaceTokenId, elementTokenId, args...);
singleElementNS(namespaceTokenId, elementTokenId, std::forward<Args>(args)...);
}
void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const char* value, FSEND_t)
{
......@@ -173,10 +174,10 @@ public:
singleElementNS(namespaceTokenId, elementTokenId, FSEND);
}
template<typename... Args>
void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, Args... args)
void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, Args &&... args)
{
pushAttributeValue(attribute, value);
singleElementNS(namespaceTokenId, elementTokenId, args...);
singleElementNS(namespaceTokenId, elementTokenId, std::forward<Args>(args)...);
}
void singleElementNS(sal_Int32 namespaceTokenId, sal_Int32 elementTokenId, sal_Int32 attribute, const OString& value, FSEND_t)
{
......
......@@ -147,6 +147,13 @@ void test::ostring::StringConcat::checkInvalid()
rtl_uString* rus = nullptr;
CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rs ));
CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rus ));
#if 0
// Should fail to compile, to avoid use of OStringConcat lvalues that
// contain dangling references to temporaries:
auto const conc = OStringLiteral("foo") + "bar";
(void) OString(conc);
#endif
}
}} // namespace
......
......@@ -157,6 +157,13 @@ void test::oustring::StringConcat::checkInvalid()
rtl_uString* rus = nullptr;
CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rs ));
CPPUNIT_ASSERT( INVALID_CONCAT( OUString( "b" ) + rus ));
#if 0
// Should fail to compile, to avoid use of OUStringConcat lvalues that
// contain dangling references to temporaries:
auto const conc = OUStringLiteral("foo") + "bar";
(void) OUString(conc);
#endif
}
}} // namespace
......
......@@ -6488,8 +6488,8 @@ void Test::testFuncTableRef()
m_pDoc->SetString( aPos, aFormula);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aNames[i].pCounta),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aNames[i].pCounta)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
// Use the named expressions in SUM() formulas, on row 3 that intersects.
......@@ -6500,8 +6500,8 @@ void Test::testFuncTableRef()
m_pDoc->SetString( aPos, aFormula);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aNames[i].pSum3),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aNames[i].pSum3)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
// Use the named expressions in SUM() formulas, on row 4 that intersects.
......@@ -6512,8 +6512,8 @@ void Test::testFuncTableRef()
m_pDoc->SetString( aPos, aFormula);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aNames[i].pSum4),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aNames[i].pSum4)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
// Use the named expressions in SUM() formulas, on row 5 that does not intersect.
......@@ -6524,8 +6524,8 @@ void Test::testFuncTableRef()
m_pDoc->SetString( aPos, aFormula);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aNames[i].pSumX),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aNames[i].pSumX)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
// Insert a column at column B to extend database range from column A,B to
......@@ -6541,8 +6541,8 @@ void Test::testFuncTableRef()
ScAddress aPos(4+i,3,0);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aNames[i].pSum4),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aNames[i].pSum4)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
const char* pColumn2Formula = "=SUM(table[[#Data];[Column2]])";
......@@ -6662,8 +6662,8 @@ void Test::testFuncTableRef()
m_pDoc->SetString( aPos, aFormula);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aHlNames[i].pCounta),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aHlNames[i].pCounta)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
// Use the named expressions in SUM() formulas, on row 11 that intersects.
......@@ -6674,8 +6674,8 @@ void Test::testFuncTableRef()
m_pDoc->SetString( aPos, aFormula);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aHlNames[i].pSum3),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aHlNames[i].pSum3)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
// Use the named expressions in SUM() formulas, on row 12 that intersects.
......@@ -6686,8 +6686,8 @@ void Test::testFuncTableRef()
m_pDoc->SetString( aPos, aFormula);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aHlNames[i].pSum4),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aHlNames[i].pSum4)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
// Use the named expressions in SUM() formulas, on row 13 that does not intersect.
......@@ -6698,8 +6698,8 @@ void Test::testFuncTableRef()
m_pDoc->SetString( aPos, aFormula);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aHlNames[i].pSumX),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aHlNames[i].pSumX)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
// Insert a column at column F to extend database range from column E,F to
......@@ -6715,8 +6715,8 @@ void Test::testFuncTableRef()
ScAddress aPos(8+i,11,0);
// For easier "debugability" have position and formula in assertion.
OUString aPrefix( aPos.Format(ScRefFlags::VALID) + " " + aFormula + " : ");
CPPUNIT_ASSERT_EQUAL( aPrefix + OUString::createFromAscii( aHlNames[i].pSum4),
aPrefix + m_pDoc->GetString( aPos));
CPPUNIT_ASSERT_EQUAL( OUString(aPrefix + OUString::createFromAscii( aHlNames[i].pSum4)),
OUString(aPrefix + m_pDoc->GetString( aPos)));
}
const char* pColumn3Formula = "=SUM(hltable[[#Data];[Column3]])";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment