Browse Source

Disallow conversion of const {Image,Trade::ImageData}&& to ImageReference.

The conversion is done implicitly, thus this seemingly innocent code
would be allowed:

    ImageReference2D reference = Image2D(...);
    foo(reference.data()); // crash on access, data already deleted
pull/34/head
Vladimír Vondruš 13 years ago
parent
commit
fb1a8490ea
  1. 26
      src/Image.h
  2. 11
      src/Test/ImageTest.cpp
  3. 26
      src/Trade/ImageData.h
  4. 11
      src/Trade/Test/ImageDataTest.cpp

26
src/Image.h

@ -80,12 +80,18 @@ template<UnsignedInt dimensions> class Image: public AbstractImage {
/** @brief Destructor */ /** @brief Destructor */
~Image() { delete[] _data; } ~Image() { delete[] _data; }
/** /** @brief Conversion to reference */
* @brief Conversion to reference /*implicit*/ operator ImageReference<dimensions>()
* #ifndef CORRADE_GCC47_COMPATIBILITY
* @todo GCC 4.8: don't allow this on rvalue-ref const &;
*/ #else
/*implicit*/ operator ImageReference<dimensions>() const; const;
#endif
#ifndef CORRADE_GCC47_COMPATIBILITY
/** @overload */
/*implicit*/ operator ImageReference<dimensions>() const && = delete;
#endif
/** @brief %Image size */ /** @brief %Image size */
typename DimensionTraits<Dimensions, Int>::VectorType size() const { return _size; } typename DimensionTraits<Dimensions, Int>::VectorType size() const { return _size; }
@ -132,7 +138,13 @@ template<UnsignedInt dimensions> inline Image<dimensions>& Image<dimensions>::op
return *this; return *this;
} }
template<UnsignedInt dimensions> inline Image<dimensions>::operator ImageReference<dimensions>() const { template<UnsignedInt dimensions> inline Image<dimensions>::operator ImageReference<dimensions>()
#ifndef CORRADE_GCC47_COMPATIBILITY
const &
#else
const
#endif
{
return ImageReference<dimensions>(AbstractImage::format(), AbstractImage::type(), _size, _data); return ImageReference<dimensions>(AbstractImage::format(), AbstractImage::type(), _size, _data);
} }

11
src/Test/ImageTest.cpp

@ -71,13 +71,22 @@ void ImageTest::moveAssignment() {
void ImageTest::toReference() { void ImageTest::toReference() {
unsigned char* data = new unsigned char[3]; unsigned char* data = new unsigned char[3];
Image2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data); const Image2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data);
ImageReference2D b = a; ImageReference2D b = a;
CORRADE_COMPARE(b.format(), ColorFormat::Red); CORRADE_COMPARE(b.format(), ColorFormat::Red);
CORRADE_COMPARE(b.type(), ColorType::UnsignedByte); CORRADE_COMPARE(b.type(), ColorType::UnsignedByte);
CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.size(), Vector2i(1, 3));
CORRADE_VERIFY(b.data() == data); CORRADE_VERIFY(b.data() == data);
CORRADE_VERIFY((std::is_convertible<const Image2D&, ImageReference2D>::value));
{
#ifdef CORRADE_GCC47_COMPATIBILITY
CORRADE_EXPECT_FAIL("Rvalue references for *this are not supported in GCC < 4.8.1.");
#endif
CORRADE_VERIFY(!(std::is_convertible<const Image2D, ImageReference2D>::value));
CORRADE_VERIFY(!(std::is_convertible<const Image2D&&, ImageReference2D>::value));
}
} }
}} }}

26
src/Trade/ImageData.h

@ -70,12 +70,18 @@ template<UnsignedInt dimensions> class ImageData: public AbstractImage {
/** @brief Destructor */ /** @brief Destructor */
~ImageData() { delete[] _data; } ~ImageData() { delete[] _data; }
/** /** @brief Conversion to reference */
* @brief Conversion to reference /*implicit*/ operator ImageReference<dimensions>()
* #ifndef CORRADE_GCC47_COMPATIBILITY
* @todo GCC 4.8: don't allow this on rvalue-ref const &;
*/ #else
/*implicit*/ operator ImageReference<dimensions>() const; const;
#endif
#ifndef CORRADE_GCC47_COMPATIBILITY
/** @overload */
/*implicit*/ operator ImageReference<dimensions>() const && = delete;
#endif
/** @brief %Image size */ /** @brief %Image size */
typename DimensionTraits<Dimensions, Int>::VectorType size() const { return _size; } typename DimensionTraits<Dimensions, Int>::VectorType size() const { return _size; }
@ -110,7 +116,13 @@ template<UnsignedInt dimensions> inline ImageData<dimensions>& ImageData<dimensi
return *this; return *this;
} }
template<UnsignedInt dimensions> inline ImageData<dimensions>::operator ImageReference<dimensions>() const { template<UnsignedInt dimensions> inline ImageData<dimensions>::operator ImageReference<dimensions>()
#ifndef CORRADE_GCC47_COMPATIBILITY
const &
#else
const
#endif
{
return ImageReference<dimensions>(AbstractImage::format(), AbstractImage::type(), _size, _data); return ImageReference<dimensions>(AbstractImage::format(), AbstractImage::type(), _size, _data);
} }

11
src/Trade/Test/ImageDataTest.cpp

@ -71,13 +71,22 @@ void ImageDataTest::moveAssignment() {
void ImageDataTest::toReference() { void ImageDataTest::toReference() {
unsigned char* data = new unsigned char[3]; unsigned char* data = new unsigned char[3];
Trade::ImageData2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data); const Trade::ImageData2D a(ColorFormat::Red, ColorType::UnsignedByte, {1, 3}, data);
ImageReference2D b = a; ImageReference2D b = a;
CORRADE_COMPARE(b.format(), ColorFormat::Red); CORRADE_COMPARE(b.format(), ColorFormat::Red);
CORRADE_COMPARE(b.type(), ColorType::UnsignedByte); CORRADE_COMPARE(b.type(), ColorType::UnsignedByte);
CORRADE_COMPARE(b.size(), Vector2i(1, 3)); CORRADE_COMPARE(b.size(), Vector2i(1, 3));
CORRADE_COMPARE(b.data(), data); CORRADE_COMPARE(b.data(), data);
CORRADE_VERIFY((std::is_convertible<const Trade::ImageData2D&, ImageReference2D>::value));
{
#ifdef CORRADE_GCC47_COMPATIBILITY
CORRADE_EXPECT_FAIL("Rvalue references for *this are not supported in GCC < 4.8.1.");
#endif
CORRADE_VERIFY(!(std::is_convertible<const Trade::ImageData2D, ImageReference2D>::value));
CORRADE_VERIFY(!(std::is_convertible<const Trade::ImageData2D&&, ImageReference2D>::value));
}
} }
}}} }}}

Loading…
Cancel
Save