[libpng15] Fixes for C++ compilation using g++ When libpng source is compiled

    using g++. The compiler imposes C++ rules on the C source; thus it
    is desireable to make the source work with either C or C++ rules
    without throwing away useful error information.  This change adds
    png_voidcast to allow C semantic (void*) cases or the corresponding
    C++ static_cast operation, as appropriate.
diff --git a/ANNOUNCE b/ANNOUNCE
index 83fb03a..661151a 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -78,6 +78,12 @@
     libpng transform code. This check-in also contains fixes to various bugs
     in the simplified APIs themselves and to some bugs in compose and rgb to
     gray (on palette) itself.
+  Fixes for C++ compilation using g++ When libpng source is compiled
+    using g++. The compiler imposes C++ rules on the C source; thus it
+    is desireable to make the source work with either C or C++ rules
+    without throwing away useful error information.  This change adds
+    png_voidcast to allow C semantic (void*) cases or the corresponding
+    C++ static_cast operation, as appropriate.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net:
 (subscription required; visit
diff --git a/png.c b/png.c
index b55eae9..14ab048 100644
--- a/png.c
+++ b/png.c
@@ -3028,7 +3028,7 @@
 static int
 png_image_free_function(png_voidp argument)
 {
-   png_imagep image = argument;
+   png_imagep image = png_voidcast(png_imagep, argument);
    png_controlp cp = image->opaque;
    png_control c;
 
@@ -3042,7 +3042,7 @@
 #  ifdef PNG_STDIO_SUPPORTED
       if (cp->owned_file)
       {
-         FILE *fp = cp->png_ptr->io_ptr;
+         FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr);
          cp->owned_file = 0;
 
          /* Ignore errors here. */
diff --git a/pngerror.c b/pngerror.c
index 74f8cc8..d09bcba 100644
--- a/pngerror.c
+++ b/pngerror.c
@@ -684,7 +684,7 @@
 png_safe_error,(png_structp png_ptr, png_const_charp error_message),
    PNG_NORETURN)
 {
-   png_imagep image = png_ptr->error_ptr;
+   png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
 
    /* An error is always logged here, overwriting anything (typically a warning)
     * that is already there:
@@ -694,9 +694,12 @@
       png_safecat(image->message, sizeof image->message, 0, error_message);
       image->warning_or_error = 1;
 
-      /* Retrieve the jmp_buf from within the png_control */
+      /* Retrieve the jmp_buf from within the png_control, making this work for
+       * C++ compilation too is pretty tricky: C++ wants a pointer to the first
+       * element of a jmp_buf, but C doesn't tell us the type of that.
+       */
       if (image->opaque != NULL && image->opaque->error_buf != NULL)
-         longjmp(image->opaque->error_buf, 1);
+         longjmp(png_control_jmp_buf(image->opaque), 1);
 
       /* Missing longjmp buffer, the following is to help debugging: */
       {
@@ -714,7 +717,7 @@
 void /* PRIVATE */
 png_safe_warning(png_structp png_ptr, png_const_charp warning_message)
 {
-   png_imagep image = png_ptr->error_ptr;
+   png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
 
    /* A warning is only logged if there is no prior warning or error. */
    if (image->warning_or_error == 0)
diff --git a/pngpriv.h b/pngpriv.h
index 04cf552..6f6a85a 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -234,15 +234,28 @@
 #  define png_fixed_error(s1,s2) png_err(s1)
 #endif
 
+/* C allows up-casts from (void*) to any pointer and (const void*) to any
+ * pointer to a const object.  C++ regards this as a type error and requires an
+ * explicit, static, cast and provides the static_cast<> rune to ensure that
+ * const is not cast away.
+ */
+#ifdef __cplusplus
+#  define png_voidcast(type, value) static_cast<type>(value)
+#else
+#  define png_voidcast(type, value) (value)
+#endif /* __cplusplus */
+
 #ifndef PNG_EXTERN
 /* The functions exported by PNG_EXTERN are internal functions, which
  * aren't usually used outside the library (as far as I know), so it is
  * debatable if they should be exported at all.  In the future, when it
  * is possible to have run-time registry of chunk-handling functions,
  * some of these might be made available again.
-#  define PNG_EXTERN extern
+ *
+ * 1.5.7: turned the use of 'extern' back on, since it is localized to pngpriv.h
+ * it should be safe now (it is unclear why it was turned off.)
  */
-#  define PNG_EXTERN
+#  define PNG_EXTERN extern
 #endif
 
 /* Some fixed point APIs are still required even if not exported because
@@ -1642,6 +1655,15 @@
    unsigned int owned_file :1; /* We own the file in io_ptr */
 } png_control;
 
+/* Return the pointer to the jmp_buf from a png_control: necessary because C
+ * does not reveal the type of the elements of jmp_buf.
+ */
+#ifdef __cplusplus
+#  define png_control_jmp_buf(pc) (((jmp_buf*)((pc)->error_buf))[0])
+#else
+#  define png_control_jmp_buf(pc) ((pc)->error_buf)
+#endif
+
 /* Utility to safely execute a piece of libpng code catching and logging any
  * errors that might occur.  Returns true on success, false on failure (either
  * of the function or as a result of a png_error.)
diff --git a/pngread.c b/pngread.c
index 01dc752..e55ec73 100644
--- a/pngread.c
+++ b/pngread.c
@@ -1332,7 +1332,8 @@
 
       if (info_ptr != NULL)
       {
-         png_controlp control = png_malloc_warn(png_ptr, sizeof *control);
+         png_controlp control = png_voidcast(png_controlp,
+            png_malloc_warn(png_ptr, sizeof *control));
 
          if (control != NULL)
          {
@@ -1384,7 +1385,7 @@
 static int
 png_image_read_header(png_voidp argument)
 {
-   png_imagep image = argument;
+   png_imagep image = png_voidcast(png_imagep, argument);
    png_structp png_ptr = image->opaque->png_ptr;
    png_infop info_ptr = image->opaque->info_ptr;
 
@@ -1508,7 +1509,7 @@
 {
    if (png_ptr != NULL)
    {
-      png_imagep image = png_ptr->io_ptr;
+      png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);
       if (image != NULL)
       {
          png_controlp cp = image->opaque;
@@ -1546,7 +1547,7 @@
              * store it into io_ptr.  Again do this in-place to avoid calling a
              * libpng function that requires error handling.
              */
-            image->opaque->memory = memory;
+            image->opaque->memory = png_voidcast(png_const_bytep, memory);
             image->opaque->size = size;
             image->opaque->png_ptr->io_ptr = image;
             image->opaque->png_ptr->read_data_fn = png_image_memory_read;
@@ -1581,7 +1582,8 @@
 static int
 png_image_read_composite(png_voidp argument)
 {
-   png_image_read_control *display = argument;
+   png_image_read_control *display = png_voidcast(png_image_read_control*,
+      argument);
    png_imagep image = display->image;
    png_structp png_ptr = image->opaque->png_ptr;
    png_byte interlace_type = png_ptr->interlaced;
@@ -1707,7 +1709,8 @@
 static int
 png_image_read_background(png_voidp argument)
 {
-   png_image_read_control *display = argument;
+   png_image_read_control *display = png_voidcast(png_image_read_control*,
+      argument);
    png_imagep image = display->image;
    png_structp png_ptr = image->opaque->png_ptr;
    png_infop info_ptr = image->opaque->info_ptr;
@@ -1965,7 +1968,8 @@
 static int
 png_image_read_end(png_voidp argument)
 {
-   png_image_read_control *display = argument;
+   png_image_read_control *display = png_voidcast(png_image_read_control*,
+      argument);
    png_imagep image = display->image;
    png_structp png_ptr = image->opaque->png_ptr;
    png_infop info_ptr = image->opaque->info_ptr;
@@ -2347,7 +2351,7 @@
     * display acts as a flag.
     */
    {
-      png_bytep first_row = display->buffer;
+      png_bytep first_row = png_voidcast(png_bytep, display->buffer);
       ptrdiff_t row_bytes = display->row_stride;
 
       if (linear)
@@ -2366,7 +2370,8 @@
    if (do_local_compose)
    {
       int result;
-      png_bytep row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+      png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
+         png_get_rowbytes(png_ptr, info_ptr)));
 
       display->local_row = row;
       result = png_safe_execute(image, png_image_read_composite, display);
@@ -2379,7 +2384,8 @@
    else if (do_local_background == 2)
    {
       int result;
-      png_bytep row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+      png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
+         png_get_rowbytes(png_ptr, info_ptr)));
 
       display->local_row = row;
       result = png_safe_execute(image, png_image_read_background, display);
diff --git a/pngwrite.c b/pngwrite.c
index fad6cc6..41cba81 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -1672,7 +1672,8 @@
 
       if (info_ptr != NULL)
       {
-         png_controlp control = png_malloc_warn(png_ptr, sizeof *control);
+         png_controlp control = png_voidcast(png_controlp,
+            png_malloc_warn(png_ptr, sizeof *control));
 
          if (control != NULL)
          {
@@ -1717,12 +1718,14 @@
 static int
 png_write_image_16bit(png_voidp argument)
 {
-   png_image_write_control *display = argument;
+   png_image_write_control *display = png_voidcast(png_image_write_control*,
+      argument);
    png_imagep image = display->image;
    png_structp png_ptr = image->opaque->png_ptr;
 
-   png_const_uint_16p input_row = display->first_row;
-   png_uint_16p output_row = display->local_row;
+   png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
+      display->first_row);
+   png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
    png_uint_16p row_end;
    int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
    int aindex = 0;
@@ -1805,7 +1808,7 @@
          ++out_ptr;
       }
 
-      png_write_row(png_ptr, display->local_row);
+      png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
       input_row += display->row_bytes/(sizeof (png_uint_16));
    }
 
@@ -1819,12 +1822,14 @@
 static int
 png_write_image_8bit(png_voidp argument)
 {
-   png_image_write_control *display = argument;
+   png_image_write_control *display = png_voidcast(png_image_write_control*,
+      argument);
    png_imagep image = display->image;
    png_structp png_ptr = image->opaque->png_ptr;
 
-   png_const_uint_16p input_row = display->first_row;
-   png_bytep output_row = display->local_row;
+   png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
+      display->first_row);
+   png_bytep output_row = png_voidcast(png_bytep, display->local_row);
    png_uint_32 y = image->height;
    int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
 
@@ -1917,7 +1922,8 @@
             ++out_ptr;
          } /* while out_ptr < row_end */
 
-         png_write_row(png_ptr, display->local_row);
+         png_write_row(png_ptr, png_voidcast(png_const_bytep,
+            display->local_row));
          input_row += display->row_bytes/(sizeof (png_uint_16));
       } /* while y */
    }
@@ -1953,7 +1959,8 @@
 static int
 png_image_write_main(png_voidp argument)
 {
-   png_image_write_control *display = argument;
+   png_image_write_control *display = png_voidcast(png_image_write_control*,
+      argument);
    png_imagep image = display->image;
    png_structp png_ptr = image->opaque->png_ptr;
    png_infop info_ptr = image->opaque->info_ptr;
@@ -2039,7 +2046,7 @@
       png_error(png_ptr, "png_write_image: unsupported transformation");
 
    {
-      png_const_bytep row = display->buffer;
+      png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
       ptrdiff_t row_bytes = display->row_stride;
 
       if (linear)
@@ -2058,7 +2065,8 @@
     */
    if ((linear && alpha) || display->convert_to_8bit)
    {
-      png_bytep row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+      png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
+         png_get_rowbytes(png_ptr, info_ptr)));
       int result;
 
       display->local_row = row;
@@ -2080,7 +2088,7 @@
     */
    else
    {
-      png_const_bytep row = display->first_row;
+      png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
       ptrdiff_t row_bytes = display->row_bytes;
       png_uint_32 y = image->height;