diff --git a/configure b/configure index d8a7fef102..dff89b0655 100755 --- 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 @@ -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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 to if __STDC__ is defined, since + # 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 +#else +# include +#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 +_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 diff --git a/configure.in b/configure.in index 67c0b462c0..a343fe6e29 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/include/wx/defs.h b/include/wx/defs.h index e787551cce..0a76ab191f 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -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 */ diff --git a/include/wx/strvararg.h b/include/wx/strvararg.h index a39e7b293e..2332ed93f2 100644 --- a/include/wx/strvararg.h +++ b/include/wx/strvararg.h @@ -22,6 +22,16 @@ #include "wx/buffer.h" #include "wx/unichar.h" +#if defined(HAVE_TYPE_TRAITS) + #include +#elif defined(HAVE_TR1_TYPE_TRAITS) + #ifdef __VISUALC__ + #include + #else + #include + #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 // wxArgNormalizer* 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 +struct wxFormatStringSpecifierNonPodType {}; + +template<> +struct wxFormatStringSpecifierNonPodType +{ + enum { value = wxFormatString::Arg_Int }; +}; + +template +struct wxFormatStringSpecifier +{ +#ifdef HAVE_TYPE_TRAITS + typedef std::is_enum is_enum; +#elif defined HAVE_TR1_TYPE_TRAITS + typedef std::tr1::is_enum is_enum; +#endif + enum { value = wxFormatStringSpecifierNonPodType::value }; +}; + +#else // !HAVE_(TR1_)TYPE_TRAITS + +template +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 +struct wxFormatStringSpecifier +{ + enum { value = wxFormatString::Arg_Pointer }; +}; + +template +struct wxFormatStringSpecifier +{ + enum { value = wxFormatString::Arg_Pointer }; +}; +#endif // !HAVE_PARTIAL_SPECIALIZATION + + +#define wxFORMAT_STRING_SPECIFIER(T, arg) \ + template<> struct wxFormatStringSpecifier \ + { \ + 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::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 { 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 { 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 : public wxArgNormalizerWithBuffer { 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 // ---------------------------------------------------------------------------- diff --git a/setup.h.in b/setup.h.in index 770c6fb9c2..667087f1ed 100644 --- a/setup.h.in +++ b/setup.h.in @@ -718,6 +718,16 @@ */ #undef HAVE_TR1_UNORDERED_SET +/* + * Define if your compiler has + */ +#undef HAVE_TR1_TYPE_TRAITS + +/* + * Define if your compiler has + */ +#undef HAVE_TYPE_TRAITS + /* * Define if the compiler supports simple visibility declarations. */ diff --git a/src/common/strvararg.cpp b/src/common/strvararg.cpp index 09b8ca0b98..0e1b1592af 100644 --- a/src/common/strvararg.cpp +++ b/src/common/strvararg.cpp @@ -637,12 +637,12 @@ template 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 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; }