Add helper macro to handle printf .* conversion for 32/64

Field width conversion `.*` always takes an `int`.

On Win32, casting `long` to `int` triggers a `-Wuseless-cast` warning.
Omitting the cast works correctly.

On Linux/amd64, casting `long` to `int` works correctly.
Omitting the cast triggers a `-Wformat` warning.

Add a macro that conditionally expands to `static_cast<int>` or to ``,
as necessary for the target platform.
This commit is contained in:
Kp 2016-08-19 03:41:41 +00:00
parent 7f0f269aec
commit bbdecad649
7 changed files with 36 additions and 8 deletions

View file

@ -1875,6 +1875,32 @@ $ x86_64-pc-linux-gnu-g++-5.4.0 -x c++ -S -Wformat -o /dev/null -
return
raise SCons.Errors.StopError("C++ compiler rejects all candidate format strings for std::size_t.")
@_custom_test
def check_compiler_useless_cast(self,context):
context.sconf.Define('DXX_ptrdiff_cast_int', 'static_cast<int>'
if self.Compile(context, text='''
#include <cstdio>
''', main='''
char a[8];
snprintf(a, sizeof(a), "%.*s", static_cast<int>(&argv[0][1] - &argv[0][0]), "0");
''', msg='whether to cast operator-(T*,T*) to int')
else '',
'''
For mingw32-gcc-5.4.0 and x86_64-pc-linux-gnu-gcc-5.4.0, gcc defines
`long operator-(T *, T *)`.
For mingw32, gcc reports a useless cast converting `long` to `int`.
For x86_64-pc-linux-gnu, gcc does not report a useless cast converting
`long` to `int.
Various parts of the code take the difference of two pointers, then cast
it to `int` to be passed as a parameter to `snprintf` field width
conversion `.*`. The field width conversion is defined to take `int`,
so the cast is necessary to avoid a warning from `-Wformat` on
x86_64-pc-linux-gnu, but is not necessary on mingw32. However, the cast
causes a -Wuseless-cast warning on mingw32.
'''
)
@_custom_test
def check_strcasecmp_present(self,context,_successflags={'CPPDEFINES' : ['DXX_HAVE_STRCASECMP']}):
main = '''
return !strcasecmp(argv[0], argv[0] + 1) && !strncasecmp(argv[0] + 1, argv[0], 1);

View file

@ -77,8 +77,10 @@ void decodeFrame16(unsigned char *pFrame, const unsigned char *pMap, int mapRema
FramePtr += 7*g_width;
}
if ((length-(pData-pOrig)) != 0) {
con_printf(CON_CRITICAL, "DEBUG: junk left over: %d,%d,%d", static_cast<int>(pData-pOrig), length, static_cast<int>(length-(pData-pOrig)));
const std::ptrdiff_t remaining = (pData - pOrig);
if (const std::ptrdiff_t difference = length - remaining)
{
con_printf(CON_CRITICAL, "DEBUG: junk left over: %d,%d,%d", DXX_ptrdiff_cast_int(remaining), length, DXX_ptrdiff_cast_int(difference));
}
}

View file

@ -240,7 +240,7 @@ static void ab_load(int skip, const char * filename, array<bitmap_index, MAX_BIT
d_splitpath( filename, &path);
for (i=0; i<MAX_BITMAPS_PER_BRUSH; i++ ) {
snprintf( tempname, sizeof(tempname), "%.*s#%d", static_cast<int>(path.base_end - path.base_start), path.base_start, i );
snprintf( tempname, sizeof(tempname), "%.*s#%d", DXX_ptrdiff_cast_int(path.base_end - path.base_start), path.base_start, i );
bi = piggy_find_bitmap( tempname );
if ( !bi.index )
break;
@ -262,7 +262,7 @@ static void ab_load(int skip, const char * filename, array<bitmap_index, MAX_BIT
}
for (i=0;i< *nframes; i++) {
snprintf( tempname, sizeof(tempname), "%.*s#%d", static_cast<int>(path.base_end - path.base_start), path.base_start, i );
snprintf( tempname, sizeof(tempname), "%.*s#%d", DXX_ptrdiff_cast_int(path.base_end - path.base_start), path.base_start, i );
gr_remap_bitmap_good(*bm[i].get(), newpal, iff_has_transparency ? iff_transparent_color : -1, SuperX);
bm[i]->avg_color = compute_average_pixel(bm[i].get());

View file

@ -69,7 +69,7 @@ int load_palette(const char *name,int used_for_level,int no_change_screen)
struct splitpath_t path;
d_splitpath(name,&path);
snprintf(pigname, sizeof(pigname), "%.*s.pig", static_cast<int>(path.base_end - path.base_start), path.base_start);
snprintf(pigname, sizeof(pigname), "%.*s.pig", DXX_ptrdiff_cast_int(path.base_end - path.base_start), path.base_start);
//if not editor, load pig first so small install message can come
//up in old palette. If editor version, we must load the pig after
//the palette is loaded so we can remap new textures.

View file

@ -189,7 +189,7 @@ static int med_save_situation(char * filename)
// Write mine name.
struct splitpath_t path;
d_splitpath(filename, &path);
PHYSFSX_printf(SaveFile, "%.*s.min\n", static_cast<int>(path.base_end - path.base_start), path.base_start);
PHYSFSX_printf(SaveFile, "%.*s.min\n", DXX_ptrdiff_cast_int(path.base_end - path.base_start), path.base_start);
// Write player position.
PHYSFSX_printf(SaveFile, "%x %x %x\n",(unsigned int) ConsoleObject->pos.x,(unsigned int) ConsoleObject->pos.y,(unsigned int) ConsoleObject->pos.z);

View file

@ -1223,7 +1223,7 @@ int load_level(const char * filename_passed)
auto LoadFile = PHYSFSX_openReadBuffered(filename);
if (!LoadFile)
{
snprintf(filename, sizeof(filename), "%.*s%s", static_cast<int>(std::distance(Current_mission->path.cbegin(), Current_mission->filename)), Current_mission->path.c_str(), filename_passed);
snprintf(filename, sizeof(filename), "%.*s%s", DXX_ptrdiff_cast_int(std::distance(Current_mission->path.cbegin(), Current_mission->filename)), Current_mission->path.c_str(), filename_passed);
LoadFile = PHYSFSX_openReadBuffered(filename);
}

View file

@ -359,7 +359,7 @@ bitmap_index piggy_find_bitmap(const char * name)
if (t) { //extra stuff for ABMs
struct splitpath_t path;
d_splitpath(i.file_name, &path);
snprintf(temp, sizeof(temp), "%.*s%s\n", static_cast<int>(path.base_end - path.base_start), path.base_start, t);
snprintf(temp, sizeof(temp), "%.*s%s\n", DXX_ptrdiff_cast_int(path.base_end - path.base_start), path.base_start, t);
name = temp;
}
else