Check wxPrintf etc. arguments types.

Implements checks similar to gcc's compile-time checks: verify that the
arguments are of correct types. This works partially at compile time
(e.g. passing an object as argument fails to compile) and partially at
runtime (assert if the specifier doesn't match the type).

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64710 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík 2010-06-24 10:34:18 +00:00
parent 2fe2d3de6b
commit 0f895b0cf5
6 changed files with 652 additions and 34 deletions

406
configure vendored
View File

@ -677,6 +677,7 @@ CXXFLAGS
ac_ct_CXX
AR
OSX_SW_VERS
CXXCPP
subdirs
PKG_CONFIG
GTK_CFLAGS
@ -1067,6 +1068,7 @@ CPP
CXX
CXXFLAGS
CCC
CXXCPP
PKG_CONFIG
DIRECTFB_CFLAGS
DIRECTFB_LIBS
@ -1977,6 +1979,7 @@ Some influential environment variables:
CPP C preprocessor
CXX C++ compiler command
CXXFLAGS C++ compiler flags
CXXCPP C++ preprocessor
PKG_CONFIG path to pkg-config utility
DIRECTFB_CFLAGS
C compiler flags for DIRECTFB, overriding pkg-config
@ -14401,10 +14404,7 @@ fi
rm -f confcache
CFLAGS=${CFLAGS:=}
ac_ext=c
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
@ -15326,6 +15326,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@ -16869,10 +16873,7 @@ fi
CXXFLAGS=${CXXFLAGS:=}
ac_ext=cpp
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
@ -17239,6 +17240,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@ -25844,6 +25849,380 @@ fi
fi
fi
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; }
if test -z "$CXXCPP"; then
if test "${ac_cv_prog_CXXCPP+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
# Double quotes because CXXCPP needs to be expanded
for CXXCPP in "$CXX -E" "/lib/cpp"
do
ac_preproc_ok=false
for ac_cxx_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
# <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
Syntax error
_ACEOF
if { (ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null && {
test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
test ! -s conftest.err
}; then
:
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
if { (ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null && {
test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
test ! -s conftest.err
}; then
# Broken: success on invalid input.
continue
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
# Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.err conftest.$ac_ext
if $ac_preproc_ok; then
break
fi
done
ac_cv_prog_CXXCPP=$CXXCPP
fi
CXXCPP=$ac_cv_prog_CXXCPP
else
ac_cv_prog_CXXCPP=$CXXCPP
fi
{ echo "$as_me:$LINENO: result: $CXXCPP" >&5
echo "${ECHO_T}$CXXCPP" >&6; }
ac_preproc_ok=false
for ac_cxx_preproc_warn_flag in '' yes
do
# Use a header file that comes with gcc, so configuring glibc
# with a fresh cross-compiler works.
# Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
# <limits.h> exists even on freestanding compilers.
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. "Syntax error" is here to catch this case.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#ifdef __STDC__
# include <limits.h>
#else
# include <assert.h>
#endif
Syntax error
_ACEOF
if { (ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null && {
test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
test ! -s conftest.err
}; then
:
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
# Broken: fails on valid input.
continue
fi
rm -f conftest.err conftest.$ac_ext
# OK, works on sane cases. Now check whether nonexistent headers
# can be detected and how.
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <ac_nonexistent.h>
_ACEOF
if { (ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null && {
test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
test ! -s conftest.err
}; then
# Broken: success on invalid input.
continue
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
# Passes both tests.
ac_preproc_ok=:
break
fi
rm -f conftest.err conftest.$ac_ext
done
# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
rm -f conftest.err conftest.$ac_ext
if $ac_preproc_ok; then
:
else
{ { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
See \`config.log' for more details." >&5
echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
See \`config.log' for more details." >&2;}
{ (exit 1); exit 1; }; }
fi
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
for ac_header in type_traits tr1/type_traits
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
echo $ECHO_N "(cached) $ECHO_C" >&6
fi
ac_res=`eval echo '${'$as_ac_Header'}'`
{ echo "$as_me:$LINENO: result: $ac_res" >&5
echo "${ECHO_T}$ac_res" >&6; }
else
# Is the header compilable?
{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
#include <$ac_header>
_ACEOF
rm -f conftest.$ac_objext
if { (ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_compile") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_cxx_werror_flag" ||
test ! -s conftest.err
} && test -s conftest.$ac_objext; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_compiler=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6; }
# Is the header present?
{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <$ac_header>
_ACEOF
if { (ac_try="$ac_cpp conftest.$ac_ext"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null && {
test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
test ! -s conftest.err
}; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6; }
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
yes:no: )
{ echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
ac_header_preproc=yes
;;
no:yes:* )
{ echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
{ echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
( cat <<\_ASBOX
## ----------------------------------------- ##
## Report this to wx-dev@lists.wxwidgets.org ##
## ----------------------------------------- ##
_ASBOX
) | sed "s/^/$as_me: WARNING: /" >&2
;;
esac
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
eval "$as_ac_Header=\$ac_header_preproc"
fi
ac_res=`eval echo '${'$as_ac_Header'}'`
{ echo "$as_me:$LINENO: result: $ac_res" >&5
echo "${ECHO_T}$ac_res" >&6; }
fi
if test `eval echo '${'$as_ac_Header'}'` = yes; then
cat >>confdefs.h <<_ACEOF
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
fi
done
if test -n "$GCC"; then
@ -52781,6 +53160,7 @@ CXXFLAGS!$CXXFLAGS$ac_delim
ac_ct_CXX!$ac_ct_CXX$ac_delim
AR!$AR$ac_delim
OSX_SW_VERS!$OSX_SW_VERS$ac_delim
CXXCPP!$CXXCPP$ac_delim
subdirs!$subdirs$ac_delim
PKG_CONFIG!$PKG_CONFIG$ac_delim
GTK_CFLAGS!$GTK_CFLAGS$ac_delim
@ -52816,7 +53196,6 @@ HILDON_CFLAGS!$HILDON_CFLAGS$ac_delim
HILDON_LIBS!$HILDON_LIBS$ac_delim
HILDON2_CFLAGS!$HILDON2_CFLAGS$ac_delim
HILDON2_LIBS!$HILDON2_LIBS$ac_delim
PYTHON!$PYTHON$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@ -52858,6 +53237,7 @@ _ACEOF
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
PYTHON!$PYTHON$ac_delim
COND_PYTHON!$COND_PYTHON$ac_delim
CAIRO_CFLAGS!$CAIRO_CFLAGS$ac_delim
CAIRO_LIBS!$CAIRO_LIBS$ac_delim
@ -52954,7 +53334,6 @@ BK_DEPS!$BK_DEPS$ac_delim
WINDRES!$WINDRES$ac_delim
REZ!$REZ$ac_delim
SETFILE!$SETFILE$ac_delim
OBJCXXFLAGS!$OBJCXXFLAGS$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@ -52996,6 +53375,7 @@ _ACEOF
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
OBJCXXFLAGS!$OBJCXXFLAGS$ac_delim
GCC_PCH!$GCC_PCH$ac_delim
ICC_PCH!$ICC_PCH$ac_delim
ICC_PCH_CREATE_SWITCH!$ICC_PCH_CREATE_SWITCH$ac_delim
@ -53092,7 +53472,6 @@ COND_PLATFORM_UNIX_1_TOOLKIT_MGL!$COND_PLATFORM_UNIX_1_TOOLKIT_MGL$ac_delim
COND_PLATFORM_UNIX_1_TOOLKIT_MGL_USE_GUI_1!$COND_PLATFORM_UNIX_1_TOOLKIT_MGL_USE_GUI_1$ac_delim
COND_PLATFORM_UNIX_1_USE_GUI_1!$COND_PLATFORM_UNIX_1_USE_GUI_1$ac_delim
COND_PLATFORM_UNIX_1_USE_PLUGINS_0!$COND_PLATFORM_UNIX_1_USE_PLUGINS_0$ac_delim
COND_PLATFORM_WIN32_0!$COND_PLATFORM_WIN32_0$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@ -53134,6 +53513,7 @@ _ACEOF
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
COND_PLATFORM_WIN32_0!$COND_PLATFORM_WIN32_0$ac_delim
COND_PLATFORM_WIN32_1!$COND_PLATFORM_WIN32_1$ac_delim
COND_PLATFORM_WIN32_1_SHARED_0!$COND_PLATFORM_WIN32_1_SHARED_0$ac_delim
COND_SHARED_0!$COND_SHARED_0$ac_delim
@ -53230,7 +53610,6 @@ COND_WXUSE_LIBPNG_BUILTIN!$COND_WXUSE_LIBPNG_BUILTIN$ac_delim
COND_WXUSE_LIBTIFF_BUILTIN!$COND_WXUSE_LIBTIFF_BUILTIN$ac_delim
COND_WXUSE_REGEX_BUILTIN!$COND_WXUSE_REGEX_BUILTIN$ac_delim
COND_WXUSE_ZLIB_BUILTIN!$COND_WXUSE_ZLIB_BUILTIN$ac_delim
COND_wxUSE_EXPAT_builtin!$COND_wxUSE_EXPAT_builtin$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@ -53272,6 +53651,7 @@ _ACEOF
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
COND_wxUSE_EXPAT_builtin!$COND_wxUSE_EXPAT_builtin$ac_delim
COND_wxUSE_LIBJPEG_builtin!$COND_wxUSE_LIBJPEG_builtin$ac_delim
COND_wxUSE_LIBPNG_builtin!$COND_wxUSE_LIBPNG_builtin$ac_delim
COND_wxUSE_LIBTIFF_builtin!$COND_wxUSE_LIBTIFF_builtin$ac_delim
@ -53324,7 +53704,7 @@ LIBOBJS!$LIBOBJS$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 50; then
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 51; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5

View File

@ -2133,6 +2133,8 @@ if test "$wxUSE_STL" = "yes"; then
fi
fi
AC_CHECK_HEADERS([type_traits tr1/type_traits])
dnl check for atomic operations builtins for wx/atomic.h:
WX_ATOMIC_BUILTINS

View File

@ -325,6 +325,12 @@ typedef short int WXTYPE;
#endif
#endif
#ifndef HAVE_TR1_TYPE_TRAITS
#if defined(__VISUALC__) && (_MSC_FULL_VER >= 150030729)
#define HAVE_TR1_TYPE_TRAITS
#endif
#endif
/* provide replacement for C99 va_copy() if the compiler doesn't have it */
/* could be already defined by configure or the user */

View File

@ -22,6 +22,16 @@
#include "wx/buffer.h"
#include "wx/unichar.h"
#if defined(HAVE_TYPE_TRAITS)
#include <type_traits>
#elif defined(HAVE_TR1_TYPE_TRAITS)
#ifdef __VISUALC__
#include <type_traits>
#else
#include <tr1/type_traits>
#endif
#endif
class WXDLLIMPEXP_FWD_BASE wxCStrData;
class WXDLLIMPEXP_FWD_BASE wxString;
@ -140,12 +150,41 @@ public:
wxFormatString(const wxScopedWCharBuffer& str)
: m_wchar(str), m_str(NULL), m_cstr(NULL) {}
// Possible argument types. These are or-combinable for wxASSERT_ARG_TYPE
// convenience.
enum ArgumentType
{
Arg_Char, // character as char
Arg_Char = 0x0001, // character as char %c
Arg_Pointer = 0x0002, // %p
Arg_String = 0x0004, // any form of string
Arg_Other // something else, for example int for %d
Arg_Int = 0x0008,
#if SIZEOF_INT == SIZEOF_LONG
Arg_LongInt = Arg_Int,
#else
Arg_LongInt = 0x0010,
#endif
#if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == SIZEOF_LONG
Arg_LongLongInt = Arg_LongInt,
#elif defined(wxLongLong_t)
Arg_LongLongInt = 0x0020,
#endif
Arg_Double = 0x0040,
Arg_LongDouble = 0x0080,
#ifdef wxSIZE_T_IS_UINT
Arg_Size_t = Arg_Int,
#endif
#ifdef wxSIZE_T_IS_ULONG
Arg_Size_t = Arg_LongInt,
#endif
Arg_IntPtr = 0x0100, // %n -- store # of chars written
Arg_ShortIntPtr = 0x0200,
Arg_LongIntPtr = 0x0400,
Arg_Unknown = 0x8000 // unrecognized specifier (likely error)
};
// returns the type of format specifier for n-th variadic argument (this is
@ -260,6 +299,126 @@ struct wxFormatStringArgumentFinder<wxWCharBuffer>
// wxArgNormalizer*<T> converters
// ----------------------------------------------------------------------------
#if wxDEBUG_LEVEL
// Check that the format specifier for index-th argument in 'fmt' has
// the correct type (one of wxFormatString::Arg_XXX or-combination in
// 'expected_mask').
#define wxASSERT_ARG_TYPE(fmt, index, expected_mask) \
do \
{ \
if ( !fmt ) \
break; \
const int argtype = fmt->GetArgumentType(index); \
wxASSERT_MSG( (argtype & (expected_mask)) == argtype, \
"format specifier doesn't match argument type" ); \
} while ( wxFalse )
#else
#define wxASSERT_ARG_TYPE(fmt, index, expected_mask)
#endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
#if defined(HAVE_TYPE_TRAITS) || defined(HAVE_TR1_TYPE_TRAITS)
// Note: this type is misnamed, so that the error message is easier to
// understand (no error happens for enums, because the IsEnum=true case is
// specialized).
template<bool IsEnum>
struct wxFormatStringSpecifierNonPodType {};
template<>
struct wxFormatStringSpecifierNonPodType<true>
{
enum { value = wxFormatString::Arg_Int };
};
template<typename T>
struct wxFormatStringSpecifier
{
#ifdef HAVE_TYPE_TRAITS
typedef std::is_enum<T> is_enum;
#elif defined HAVE_TR1_TYPE_TRAITS
typedef std::tr1::is_enum<T> is_enum;
#endif
enum { value = wxFormatStringSpecifierNonPodType<is_enum::value>::value };
};
#else // !HAVE_(TR1_)TYPE_TRAITS
template<typename T>
struct wxFormatStringSpecifier
{
// We can't detect enums without is_enum, so the only thing we can
// do is to accept unknown types. However, the only acceptable unknown
// types still are enums, which are promoted to ints, so return Arg_Int
// here. This will at least catch passing of non-POD types through ... at
// runtime.
//
// Furthermore, if the compiler doesn't have partial template
// specialization, we didn't cover pointers either.
#ifdef HAVE_PARTIAL_SPECIALIZATION
enum { value = wxFormatString::Arg_Int };
#else
enum { value = wxFormatString::Arg_Int | wxFormatString::Arg_Pointer };
#endif
};
#endif // HAVE_TR1_TYPE_TRAITS/!HAVE_TR1_TYPE_TRAITS
#ifdef HAVE_PARTIAL_SPECIALIZATION
template<typename T>
struct wxFormatStringSpecifier<T*>
{
enum { value = wxFormatString::Arg_Pointer };
};
template<typename T>
struct wxFormatStringSpecifier<const T*>
{
enum { value = wxFormatString::Arg_Pointer };
};
#endif // !HAVE_PARTIAL_SPECIALIZATION
#define wxFORMAT_STRING_SPECIFIER(T, arg) \
template<> struct wxFormatStringSpecifier<T> \
{ \
enum { value = arg }; \
};
wxFORMAT_STRING_SPECIFIER(bool, wxFormatString::Arg_Int)
wxFORMAT_STRING_SPECIFIER(int, wxFormatString::Arg_Int)
wxFORMAT_STRING_SPECIFIER(unsigned int, wxFormatString::Arg_Int)
wxFORMAT_STRING_SPECIFIER(short int, wxFormatString::Arg_Int)
wxFORMAT_STRING_SPECIFIER(short unsigned int, wxFormatString::Arg_Int)
wxFORMAT_STRING_SPECIFIER(long int, wxFormatString::Arg_LongInt)
wxFORMAT_STRING_SPECIFIER(long unsigned int, wxFormatString::Arg_LongInt)
#ifdef wxLongLong_t
wxFORMAT_STRING_SPECIFIER(wxLongLong_t, wxFormatString::Arg_LongLongInt)
wxFORMAT_STRING_SPECIFIER(wxULongLong_t, wxFormatString::Arg_LongLongInt)
#endif
wxFORMAT_STRING_SPECIFIER(float, wxFormatString::Arg_Double)
wxFORMAT_STRING_SPECIFIER(double, wxFormatString::Arg_Double)
wxFORMAT_STRING_SPECIFIER(long double, wxFormatString::Arg_LongDouble)
wxFORMAT_STRING_SPECIFIER(wchar_t, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
wxFORMAT_STRING_SPECIFIER(char*, wxFormatString::Arg_String | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(unsigned char*, wxFormatString::Arg_String | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(signed char*, wxFormatString::Arg_String | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(const char*, wxFormatString::Arg_String | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(const unsigned char*, wxFormatString::Arg_String | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(const signed char*, wxFormatString::Arg_String | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(wchar_t*, wxFormatString::Arg_String | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(const wchar_t*, wxFormatString::Arg_String | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(int*, wxFormatString::Arg_IntPtr | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(short int*, wxFormatString::Arg_ShortIntPtr | wxFormatString::Arg_Pointer)
wxFORMAT_STRING_SPECIFIER(long int*, wxFormatString::Arg_LongIntPtr | wxFormatString::Arg_Pointer)
#undef wxFORMAT_STRING_SPECIFIER
// Converts an argument passed to wxPrint etc. into standard form expected,
// by wxXXX functions, e.g. all strings (wxString, char*, wchar_t*) are
// converted into wchar_t* or char* depending on the build.
@ -271,8 +430,11 @@ struct wxArgNormalizer
// use format string and 'index' is index of 'value' in variadic arguments
// list (starting at 1)
wxArgNormalizer(T value,
const wxFormatString *WXUNUSED(fmt), unsigned WXUNUSED(index))
: m_value(value) {}
const wxFormatString *fmt, unsigned index)
: m_value(value)
{
wxASSERT_ARG_TYPE( fmt, index, wxFormatStringSpecifier<T>::value );
}
// Returns the value in a form that can be safely passed to real vararg
// functions. In case of strings, this is char* in ANSI build and wchar_t*
@ -326,9 +488,13 @@ struct wxArgNormalizerWithBuffer
wxArgNormalizerWithBuffer() {}
wxArgNormalizerWithBuffer(const CharBuffer& buf,
const wxFormatString *WXUNUSED(fmt),
unsigned WXUNUSED(index))
: m_value(buf) {}
const wxFormatString *fmt,
unsigned index)
: m_value(buf)
{
wxASSERT_ARG_TYPE( fmt, index,
wxFormatString::Arg_String | wxFormatString::Arg_Pointer );
}
const CharType *get() const { return m_value; }
@ -340,9 +506,12 @@ template<>
struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxString&>
{
wxArgNormalizerNative(const wxString& s,
const wxFormatString *WXUNUSED(fmt),
unsigned WXUNUSED(index))
: m_value(s) {}
const wxFormatString *fmt,
unsigned index)
: m_value(s)
{
wxASSERT_ARG_TYPE( fmt, index, wxFormatString::Arg_String );
}
const wxStringCharType *get() const;
@ -354,9 +523,13 @@ template<>
struct WXDLLIMPEXP_BASE wxArgNormalizerNative<const wxCStrData&>
{
wxArgNormalizerNative(const wxCStrData& value,
const wxFormatString *WXUNUSED(fmt),
unsigned WXUNUSED(index))
: m_value(value) {}
const wxFormatString *fmt,
unsigned index)
: m_value(value)
{
wxASSERT_ARG_TYPE( fmt, index,
wxFormatString::Arg_String | wxFormatString::Arg_Pointer );
}
const wxStringCharType *get() const;
@ -412,9 +585,12 @@ struct wxArgNormalizerUtf8<const char*>
: public wxArgNormalizerWithBuffer<char>
{
wxArgNormalizerUtf8(const char* s,
const wxFormatString *WXUNUSED(fmt),
unsigned WXUNUSED(index))
const wxFormatString *fmt,
unsigned index)
{
wxASSERT_ARG_TYPE( fmt, index,
wxFormatString::Arg_String | wxFormatString::Arg_Pointer );
if ( wxLocaleIsUtf8 )
{
m_value = wxScopedCharBuffer::CreateNonOwned(s);
@ -577,6 +753,9 @@ struct wxArgNormalizerNarrowChar
wxArgNormalizerNarrowChar(T value,
const wxFormatString *fmt, unsigned index)
{
wxASSERT_ARG_TYPE( fmt, index,
wxFormatString::Arg_Char | wxFormatString::Arg_Int );
// FIXME-UTF8: which one is better default in absence of fmt string
// (i.e. when used like e.g. Foo("foo", "bar", 'c', NULL)?
if ( !fmt || fmt->GetArgumentType(index) == wxFormatString::Arg_Char )
@ -632,6 +811,8 @@ WX_ARG_NORMALIZER_FORWARD(const signed char&, signed char);
#undef WX_ARG_NORMALIZER_FORWARD
#undef _WX_ARG_NORMALIZER_FORWARD_IMPL
#undef wxASSERT_ARG_TYPE
// ----------------------------------------------------------------------------
// WX_VA_ARG_STRING
// ----------------------------------------------------------------------------

View File

@ -718,6 +718,16 @@
*/
#undef HAVE_TR1_UNORDERED_SET
/*
* Define if your compiler has <tr1/type_traits>
*/
#undef HAVE_TR1_TYPE_TRAITS
/*
* Define if your compiler has <type_traits>
*/
#undef HAVE_TYPE_TRAITS
/*
* Define if the compiler supports simple visibility declarations.
*/

View File

@ -637,12 +637,12 @@ template<typename CharType>
wxFormatString::ArgumentType DoGetArgumentType(const CharType *format,
unsigned n)
{
wxCHECK_MSG( format, wxFormatString::Arg_Other,
wxCHECK_MSG( format, wxFormatString::Arg_Unknown,
"empty format string not allowed here" );
wxPrintfConvSpecParser<CharType> parser(format);
wxCHECK_MSG( parser.pspec[n-1] != NULL, wxFormatString::Arg_Other,
wxCHECK_MSG( parser.pspec[n-1] != NULL, wxFormatString::Arg_Unknown,
"requested argument not found - invalid format string?" );
switch ( parser.pspec[n-1]->m_type )
@ -651,9 +651,48 @@ wxFormatString::ArgumentType DoGetArgumentType(const CharType *format,
case wxPAT_WCHAR:
return wxFormatString::Arg_Char;
default:
return wxFormatString::Arg_Other;
case wxPAT_PCHAR:
case wxPAT_PWCHAR:
return wxFormatString::Arg_String;
case wxPAT_INT:
return wxFormatString::Arg_Int;
case wxPAT_LONGINT:
return wxFormatString::Arg_LongInt;
#ifdef wxLongLong_t
case wxPAT_LONGLONGINT:
return wxFormatString::Arg_LongLongInt;
#endif
case wxPAT_SIZET:
return wxFormatString::Arg_Size_t;
case wxPAT_DOUBLE:
return wxFormatString::Arg_Double;
case wxPAT_LONGDOUBLE:
return wxFormatString::Arg_LongDouble;
case wxPAT_POINTER:
return wxFormatString::Arg_Pointer;
case wxPAT_NINT:
return wxFormatString::Arg_IntPtr;
case wxPAT_NSHORTINT:
return wxFormatString::Arg_ShortIntPtr;
case wxPAT_NLONGINT:
return wxFormatString::Arg_LongIntPtr;
case wxPAT_STAR:
// "*" requires argument of type int
return wxFormatString::Arg_Int;
case wxPAT_INVALID:
// (handled after the switch statement)
break;
}
// silence warning
wxFAIL_MSG( "unexpected argument type" );
return wxFormatString::Arg_Unknown;
}
} // anonymous namespace
@ -670,5 +709,5 @@ wxFormatString::ArgumentType wxFormatString::GetArgumentType(unsigned n) const
return DoGetArgumentType(m_cstr->AsInternal(), n);
wxFAIL_MSG( "unreachable code" );
return Arg_Other;
return Arg_Unknown;
}