]> git.saurik.com Git - wxWidgets.git/commitdiff
Check wxPrintf etc. arguments types.
authorVáclav Slavík <vslavik@fastmail.fm>
Thu, 24 Jun 2010 10:34:18 +0000 (10:34 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Thu, 24 Jun 2010 10:34:18 +0000 (10:34 +0000)
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

configure
configure.in
include/wx/defs.h
include/wx/strvararg.h
setup.h.in
src/common/strvararg.cpp

index d8a7fef1020bcf36be6cdf7cccd1f50aeb25968c..dff89b0655d71de58725e7b3263dbc656ff21d23 100755 (executable)
--- a/configure
+++ b/configure
@@ -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
 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'
 
 
 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'
     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
index 67c0b462c00eb010a3c2289513759308b4456f23..a343fe6e2951896edfd4e5dafd0cb1897a4ab6a7 100644 (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
 
index e787551ccedc70ccb7eae6d607a25845c5400fc3..0a76ab191fd3320364b222a9812f3d1d1dcb2493 100644 (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 */
index a39e7b293e0d3662095623a2aba4353508864d21..2332ed93f226d3c35d76a28abba7492114e74c54 100644 (file)
 #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_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_Other    // something else, for example int for %d
+        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
 // ----------------------------------------------------------------------------
index 770c6fb9c2374c68be1100821a05124d976be1f4..667087f1ed703f9abed5a2c775a8570304df284c 100644 (file)
  */
 #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.
  */
index 09b8ca0b98001033a5b798ff3da7f41e04aa2417..0e1b1592af6bb8874bf83f7c5b468277d8c0f272 100644 (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;
 }