From: Amos Jeffries Date: Tue, 2 Aug 2011 07:31:53 +0000 (+1200) Subject: Support C++0x features where possible X-Git-Tag: take08~55^2~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a203dec7313a5b60a79d7158dc1c161da5080ec6;p=thirdparty%2Fsquid.git Support C++0x features where possible This tests for and enables -std=c++0x compiler support on build. Due to auto_ptr deprecation pieces of the code and a hack to work around incompatible cppunit code, are converted to use unique_ptr. When C++0x is available it also tests and uses the nullptr definition for extra type safety. --- diff --git a/acinclude/ax_cxx_0x_types.m4 b/acinclude/ax_cxx_0x_types.m4 new file mode 100644 index 0000000000..615a7de0ac --- /dev/null +++ b/acinclude/ax_cxx_0x_types.m4 @@ -0,0 +1,41 @@ +## Shamelessly copied from the DUNE sources under GPL version 2 +## +AC_DEFUN([AX_CXX_TYPE_NULLPTR],[ + AC_REQUIRE([AC_PROG_CXX]) + AC_LANG_PUSH([C++]) + AC_MSG_CHECKING([whether nullptr is supported]) + AC_TRY_COMPILE([],[char* ch = nullptr;], [ + HAVE_NULLPTR=yes + AC_MSG_RESULT(yes)], [ + HAVE_NULLPTR=no + AC_MSG_RESULT(no)]) + if test "x$HAVE_NULLPTR" = xyes; then + AC_DEFINE(HAVE_NULLPTR, 1, [Define to 1 if nullptr is supported]) + fi + AC_MSG_CHECKING([whether nullptr_t is supported]) + AC_TRY_COMPILE([#include ],[typedef nullptr_t peng;], [ + HAVE_NULLPTR_T=yes + AC_MSG_RESULT(yes)], [ + HAVE_NULLPTR_T=no + AC_MSG_RESULT(no)]) + if test "x$HAVE_NULLPTR_T" = xyes; then + AC_DEFINE(HAVE_NULLPTR_T, 1, [Define to 1 if nullptr_t is supported]) + fi + AC_LANG_POP +]) + +## Hand crafted for Squid under GPL version 2 +AC_DEFUN([AX_CXX_TYPE_UNIQUE_PTR],[ + AC_REQUIRE([AC_PROG_CXX]) + AC_LANG_PUSH([C++]) + AC_MSG_CHECKING([whether std::unique_ptr is supported]) + AC_TRY_COMPILE([#include ],[std::unique_ptr c;], [ + HAVE_UNIQUE_PTR=yes + AC_MSG_RESULT(yes)], [ + HAVE_UNIQUE_PTR=no + AC_MSG_RESULT(no)]) + if test "x$HAVE_UNIQUE_PTR" = xyes; then + AC_DEFINE(HAVE_UNIQUE_PTR, 1, [Define to 1 if std::unique_ptr is supported]) + fi + AC_LANG_POP +]) diff --git a/acinclude/ax_cxx_compile_stdcxx_0x.m4 b/acinclude/ax_cxx_compile_stdcxx_0x.m4 new file mode 100644 index 0000000000..a4e556ff90 --- /dev/null +++ b/acinclude/ax_cxx_compile_stdcxx_0x.m4 @@ -0,0 +1,107 @@ +# ============================================================================ +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_0x.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_0X +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++0x +# standard. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 7 + +AU_ALIAS([AC_CXX_COMPILE_STDCXX_0X], [AX_CXX_COMPILE_STDCXX_0X]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX_0X], [ + AC_CACHE_CHECK(if g++ supports C++0x features without additional flags, + ax_cv_cxx_compile_cxx0x_native, + [AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c);],, + ax_cv_cxx_compile_cxx0x_native=yes, ax_cv_cxx_compile_cxx0x_native=no) + AC_LANG_RESTORE + ]) + + AC_CACHE_CHECK(if g++ supports C++0x features with -std=c++0x, + ax_cv_cxx_compile_cxx0x_cxx, + [AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -std=c++0x" + AC_TRY_COMPILE([ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c);],, + ax_cv_cxx_compile_cxx0x_cxx=yes, ax_cv_cxx_compile_cxx0x_cxx=no) + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE + ]) + + AC_CACHE_CHECK(if g++ supports C++0x features with -std=gnu++0x, + ax_cv_cxx_compile_cxx0x_gxx, + [AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -std=gnu++0x" + AC_TRY_COMPILE([ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c);],, + ax_cv_cxx_compile_cxx0x_gxx=yes, ax_cv_cxx_compile_cxx0x_gxx=no) + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE + ]) + + if test "$ax_cv_cxx_compile_cxx0x_native" = yes || + test "$ax_cv_cxx_compile_cxx0x_cxx" = yes || + test "$ax_cv_cxx_compile_cxx0x_gxx" = yes; then + AC_DEFINE(HAVE_STDCXX_0X,,[Define if g++ supports C++0x features. ]) + fi +]) diff --git a/compat/GnuRegex.c b/compat/GnuRegex.c index 33e3616b8d..2717975b06 100644 --- a/compat/GnuRegex.c +++ b/compat/GnuRegex.c @@ -158,10 +158,6 @@ static int re_match_2(struct re_pattern_buffer * buffer, const char *string1, #define ISUPPER(c) (isascii ((unsigned char)c) && isupper ((unsigned char)c)) #define ISXDIGIT(c) (isascii ((unsigned char)c) && isxdigit ((unsigned char)c)) -#ifndef NULL -#define NULL 0 -#endif - /* We remove any previous definition of `SIGN_EXTEND_CHAR', * since ours (we hope) works properly with all combinations of * machines, compilers, `char' and `unsigned char' argument types. diff --git a/compat/Makefile.am b/compat/Makefile.am index fc8238350e..f3e11fb387 100644 --- a/compat/Makefile.am +++ b/compat/Makefile.am @@ -17,6 +17,7 @@ libcompat_squid_a_SOURCES = \ compat.h \ compat_shared.h \ cpu.h \ + cppunit.h \ debug.cc \ debug.h \ drand48.h \ diff --git a/compat/compat.h b/compat/compat.h index e1de846f5b..b964509f34 100644 --- a/compat/compat.h +++ b/compat/compat.h @@ -113,4 +113,7 @@ /* some functions are unsafe to be used in Squid. */ #include "compat/unsafe.h" +/* cppunit is not quite C++0x compatible yet */ +#include "compat/cppunit.h" + #endif /* _SQUID_COMPAT_H */ diff --git a/compat/cppunit.h b/compat/cppunit.h new file mode 100644 index 0000000000..4ae60b66e4 --- /dev/null +++ b/compat/cppunit.h @@ -0,0 +1,33 @@ +#ifndef SQUID_COMPAT_CPPUNIT_H +#define SQUID_COMPAT_CPPUNIT_H + +// CPPUNIT test suite uses auto_ptr which is deprecated in C++0x + +#if defined(__cplusplus) && HAVE_UNIQUE_PTR +#include + +#undef CPPUNIT_TEST_SUITE_END + +// Clone from cppunit 1.12.1 +#define CPPUNIT_TEST_SUITE_END() \ + } \ + \ + static CPPUNIT_NS::TestSuite *suite() \ + { \ + const CPPUNIT_NS::TestNamer &namer = getTestNamer__(); \ + std::unique_ptr suite( \ + new CPPUNIT_NS::TestSuite( namer.getFixtureName() )); \ + CPPUNIT_NS::ConcretTestFixtureFactory factory; \ + CPPUNIT_NS::TestSuiteBuilderContextBase context( *suite.get(), \ + namer, \ + factory ); \ + TestFixtureType::addTestsToSuite( context ); \ + return suite.release(); \ + } \ + private: /* dummy typedef so that the macro can still end with ';'*/ \ + typedef int CppUnitDummyTypedefForSemiColonEnding__ + + +#endif /* HAVE_UNIQUE_PTR */ + +#endif /* SQUID_COMPAT_CPPUNIT_H */ diff --git a/compat/types.h b/compat/types.h index 707a45191f..318ae10849 100644 --- a/compat/types.h +++ b/compat/types.h @@ -138,4 +138,12 @@ typedef int socklen_t; typedef long mtyp_t; #endif +#ifndef NULL +#if defined(__cplusplus) && HAVE_NULLPTR +#define NULL nullptr +#else +#define NULL 0 +#endif +#endif + #endif /* SQUID_TYPES_H */ diff --git a/configure.ac b/configure.ac index 17d09c03de..5babed5700 100644 --- a/configure.ac +++ b/configure.ac @@ -21,8 +21,11 @@ m4_include([acinclude/krb5.m4]) m4_include([acinclude/pam.m4]) m4_include([acinclude/pkg.m4]) m4_include([acinclude/lib-checks.m4]) +m4_include([acinclude/ax_cxx_compile_stdcxx_0x.m4]) +m4_include([acinclude/ax_cxx_0x_types.m4]) PRESET_CFLAGS="$CFLAGS" +PRESET_CXXFLAGS="$CXXFLAGS" PRESET_LDFLAGS="$LDFLAGS" dnl Set default LDFLAGS @@ -54,6 +57,12 @@ if test "x$squid_host_os" = "solaris" -a "x$GCC" != "x" ; then AC_USE_SYSTEM_EXTENSIONS fi +# Check for C++0x compiler support +AX_CXX_COMPILE_STDCXX_0X +if test "x$ax_cv_cxx_compile_cxx0x_cxx" = "xyes"; then + CXXFLAGS="$CXXFLAGS -std=c++0x" +fi + # test for programs AC_PROG_RANLIB AC_PROG_CPP @@ -2431,6 +2440,10 @@ AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(off_t) AC_CHECK_SIZEOF(size_t) +dnl Some C++0x types we try to use +AX_CXX_TYPE_NULLPTR +AX_CXX_TYPE_UNIQUE_PTR + dnl On Solaris 9 x86, gcc may includes a "fixed" set of old system include files dnl that is incompatible with the updated Solaris header files. dnl For this reason, we must check if pad128_t and upad128_t are defined. diff --git a/include/snmp_impl.h b/include/snmp_impl.h index c3c89d411e..4350d6dc1d 100644 --- a/include/snmp_impl.h +++ b/include/snmp_impl.h @@ -47,20 +47,6 @@ SOFTWARE. #define SID_MAX_LEN 64 -#if 0 /* defines performed globally by config.h */ - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif -#endif /* dead code. */ - #define READ 1 #define WRITE 0 diff --git a/src/StoreEntryStream.h b/src/StoreEntryStream.h index fb9b715759..97511f38ee 100644 --- a/src/StoreEntryStream.h +++ b/src/StoreEntryStream.h @@ -70,7 +70,10 @@ protected: return traits_type::eof(); if (aChar != traits_type::eof()) { - char chars[1] = {aChar}; + // NP: cast because GCC promotes int_type to 32-bit type + // std::basic_streambuf::int_type {aka int} + // despite the definition with 8-bit type value. + char chars[1] = {char(aChar)}; if (aChar != traits_type::eof()) theEntry->append(chars, 1); diff --git a/src/mgr/Inquirer.cc b/src/mgr/Inquirer.cc index 9c7432cc73..769bd4e7b6 100644 --- a/src/mgr/Inquirer.cc +++ b/src/mgr/Inquirer.cc @@ -70,17 +70,29 @@ Mgr::Inquirer::start() Must(Comm::IsConnOpen(conn)); Must(aggrAction != NULL); +#if HAVE_UNIQUE_PTR + std::unique_ptr replyBuf; +#else std::auto_ptr replyBuf; +#endif if (strands.empty()) { LOCAL_ARRAY(char, url, MAX_URL); snprintf(url, MAX_URL, "%s", aggrAction->command().params.httpUri.termedBuf()); HttpRequest *req = HttpRequest::CreateFromUrl(url); ErrorState *err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND, req); +#if HAVE_UNIQUE_PTR + std::unique_ptr reply(err->BuildHttpReply()); +#else std::auto_ptr reply(err->BuildHttpReply()); +#endif replyBuf.reset(reply->pack()); errorStateFree(err); } else { +#if HAVE_UNIQUE_PTR + std::unique_ptr reply(new HttpReply); +#else std::auto_ptr reply(new HttpReply); +#endif reply->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime); reply->header.putStr(HDR_CONNECTION, "close"); // until we chunk response replyBuf.reset(reply->pack());