diff --git a/CMakeLists.txt b/CMakeLists.txt index cec5009de..1877ff8f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,6 +145,7 @@ INCLUDE(CheckIncludeFile) INCLUDE(CheckTypeSize) INCLUDE(GNUInstallDirs) # for CMAKE_INSTALL_LIBDIR +CHECK_INCLUDE_FILE(assert.h HAVE_ASSERT_H) CHECK_INCLUDE_FILE(dirent.h HAVE_DIRENT_H) CHECK_INCLUDE_FILE(sys/stat.h HAVE_SYS_STAT_H) CHECK_INCLUDE_FILE(sys/types.h HAVE_SYS_TYPES_H) @@ -169,12 +170,22 @@ if(NOT MSVC AND NOT CMAKE_C_COMPILER_ID STREQUAL "XL") set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror") endif() +CHECK_C_SOURCE_COMPILES( + "int main(void) { __builtin_expect(1+1, 2); return 0; }" + HAVE_BUILTIN_EXPECT +) + CHECK_C_SOURCE_COMPILES( "#include int main(void) { int a,b; size_t m; __builtin_mul_overflow(a,b,&m); return 0; }" HAVE_BUILTIN_MUL_OVERFLOW ) +CHECK_C_SOURCE_COMPILES( + "int main(void) { if (0) __builtin_unreachable(); return 0; }" + HAVE_BUILTIN_UNREACHABLE +) + CHECK_C_SOURCE_COMPILES( "int main(void) { char buf[128] __attribute__((uninitialized)); (void)buf; return 0; }" HAVE_ATTRIBUTE_UNINITIALIZED diff --git a/config-cmake.h.in b/config-cmake.h.in index 6539d7735..f0091b225 100644 --- a/config-cmake.h.in +++ b/config-cmake.h.in @@ -1,6 +1,9 @@ /* config.h for CMake builds */ +#cmakedefine HAVE_ASSERT_H 1 +#cmakedefine HAVE_BUILTIN_EXPECT 1 #cmakedefine HAVE_BUILTIN_MUL_OVERFLOW 1 +#cmakedefine HAVE_BUILTIN_UNREACHABLE 1 #cmakedefine HAVE_ATTRIBUTE_UNINITIALIZED 1 #cmakedefine HAVE_DIRENT_H 1 #cmakedefine HAVE_SYS_STAT_H 1 diff --git a/configure.ac b/configure.ac index 5646c5a2b..74aa7de44 100644 --- a/configure.ac +++ b/configure.ac @@ -73,6 +73,20 @@ AC_SYS_LARGEFILE PCRE2_VISIBILITY +# Check for the expect() builtin + +AC_MSG_CHECKING([for __builtin_expect()]) +AC_LANG_PUSH([C]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[__builtin_expect(1+1, 2)]])], + [pcre2_cc_cv_builtin_expect=yes], + [pcre2_cc_cv_builtin_expect=no]) +AC_MSG_RESULT([$pcre2_cc_cv_builtin_expect]) +if test "$pcre2_cc_cv_builtin_expect" = yes; then + AC_DEFINE([HAVE_BUILTIN_EXPECT], 1, + [Define this if your compiler provides __builtin_expect()]) +fi +AC_LANG_POP([C]) + # Check for the mul_overflow() builtin AC_MSG_CHECKING([for __builtin_mul_overflow()]) @@ -95,6 +109,20 @@ if test "$pcre2_cc_cv_builtin_mul_overflow" = yes; then fi AC_LANG_POP([C]) +# Check for the unreachable() builtin + +AC_MSG_CHECKING([for __builtin_unreachable()]) +AC_LANG_PUSH([C]) +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[if (0) __builtin_unreachable()]])], + [pcre2_cc_cv_builtin_unreachable=yes], + [pcre2_cc_cv_builtin_unreachable=no]) +AC_MSG_RESULT([$pcre2_cc_cv_builtin_unreachable]) +if test "$pcre2_cc_cv_builtin_unreachable" = yes; then + AC_DEFINE([HAVE_BUILTIN_UNREACHABLE], 1, + [Define this if your compiler provides __builtin_unreachable()]) +fi +AC_LANG_POP([C]) + # Check for Clang __attribute__((uninitialized)) feature AC_MSG_CHECKING([for __attribute__((uninitialized))]) @@ -521,7 +549,7 @@ HAVE_BCOPY is defined. If your system has neither bcopy() nor memmove(), make sure both macros are undefined; an emulation function will then be used. */]) # Checks for header files. -AC_CHECK_HEADERS(limits.h sys/types.h sys/stat.h dirent.h) +AC_CHECK_HEADERS(assert.h limits.h sys/types.h sys/stat.h dirent.h) AC_CHECK_HEADERS([windows.h], [HAVE_WINDOWS_H=1]) AC_CHECK_HEADERS([sys/wait.h], [HAVE_SYS_WAIT_H=1]) diff --git a/src/config.h.generic b/src/config.h.generic index 009294813..089e1f5ff 100644 --- a/src/config.h.generic +++ b/src/config.h.generic @@ -52,15 +52,24 @@ sure both macros are undefined; an emulation function will then be used. */ LF does in an ASCII/Unicode environment. */ /* #undef EBCDIC_NL25 */ +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASSERT_H */ + /* Define this if your compiler supports __attribute__((uninitialized)) */ /* #undef HAVE_ATTRIBUTE_UNINITIALIZED */ /* Define to 1 if you have the 'bcopy' function. */ /* #undef HAVE_BCOPY */ +/* Define this if your compiler provides __builtin_expect() */ +/* #undef HAVE_BUILTIN_EXPECT */ + /* Define this if your compiler provides __builtin_mul_overflow() */ /* #undef HAVE_BUILTIN_MUL_OVERFLOW */ +/* Define this if your compiler provides __builtin_unreachable() */ +/* #undef HAVE_BUILTIN_UNREACHABLE */ + /* Define to 1 if you have the header file. */ /* #undef HAVE_BZLIB_H */ diff --git a/src/config.h.in b/src/config.h.in index 3bb01c83d..7642d65c7 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -52,15 +52,24 @@ sure both macros are undefined; an emulation function will then be used. */ LF does in an ASCII/Unicode environment. */ #undef EBCDIC_NL25 +/* Define to 1 if you have the header file. */ +#undef HAVE_ASSERT_H + /* Define this if your compiler supports __attribute__((uninitialized)) */ #undef HAVE_ATTRIBUTE_UNINITIALIZED /* Define to 1 if you have the 'bcopy' function. */ #undef HAVE_BCOPY +/* Define this if your compiler provides __builtin_expect() */ +#undef HAVE_BUILTIN_EXPECT + /* Define this if your compiler provides __builtin_mul_overflow() */ #undef HAVE_BUILTIN_MUL_OVERFLOW +/* Define this if your compiler provides __builtin_unreachable() */ +#undef HAVE_BUILTIN_UNREACHABLE + /* Define to 1 if you have the header file. */ #undef HAVE_BZLIB_H diff --git a/src/pcre2.h.generic b/src/pcre2.h.generic index 4ef0793a8..baa709512 100644 --- a/src/pcre2.h.generic +++ b/src/pcre2.h.generic @@ -1002,6 +1002,29 @@ PCRE2_SUFFIX a no-op. Otherwise, generate an error. */ #endif #endif /* PCRE2_CODE_UNIT_WIDTH is defined */ +/* Assertion macros */ + +#ifdef HAVE_BUILTIN_UNREACHABLE +#define PCRE2_UNREACHABLE() __builtin_unreachable() +#else +#define PCRE2_UNREACHABLE() do {} while(0) +#endif + +#ifdef PCRE2_DEBUG +#if defined(HAVE_BUILTIN_EXPECT) && defined(HAVE_BUILTIN_UNREACHABLE) +#define PCRE2_ASSERT(x) do { if (__builtin_expect(!(x), 0)) __builtin_unreachable(); } while (0) +#elif defined(HAVE_ASSERT_H) +#include +#define PCRE2_ASSERT(x) assert(x) +#elif defined(HAVE_STDLIB_H) && defined(HAVE_STDIO_H) +#define PCRE2_ASSERT(x) do { if (!(x)) { fprintf(stderr, "Assertion failed at " __FILE__ ":%d\n", __LINE__); abort(); }} while(0) +#else +#define PCRE2_ASSERT(x) do {} while(0) +#endif +#else +#define PCRE2_ASSERT(x) do {} while(0) +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/pcre2.h.in b/src/pcre2.h.in index a13362daf..2f6b4e866 100644 --- a/src/pcre2.h.in +++ b/src/pcre2.h.in @@ -1003,6 +1003,29 @@ PCRE2_SUFFIX a no-op. Otherwise, generate an error. */ #endif #endif /* PCRE2_CODE_UNIT_WIDTH is defined */ +/* Assertion macros */ + +#ifdef HAVE_BUILTIN_UNREACHABLE +#define PCRE2_UNREACHABLE() __builtin_unreachable() +#else +#define PCRE2_UNREACHABLE() do {} while(0) +#endif + +#ifdef PCRE2_DEBUG +#if defined(HAVE_BUILTIN_EXPECT) && defined(HAVE_BUILTIN_UNREACHABLE) +#define PCRE2_ASSERT(x) do { if (__builtin_expect(!(x), 0)) __builtin_unreachable(); } while (0) +#elif defined(HAVE_ASSERT_H) +#include +#define PCRE2_ASSERT(x) assert(x) +#elif defined(HAVE_STDLIB_H) && defined(HAVE_STDIO_H) +#define PCRE2_ASSERT(x) do { if (!(x)) { fprintf(stderr, "Assertion failed at " __FILE__ ":%d\n", __LINE__); abort(); }} while(0) +#else +#define PCRE2_ASSERT(x) do {} while(0) +#endif +#else +#define PCRE2_ASSERT(x) do {} while(0) +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/vms/configure.com b/vms/configure.com index b50365d4f..c6024e87c 100644 --- a/vms/configure.com +++ b/vms/configure.com @@ -496,12 +496,20 @@ sure both macros are undefined; an emulation function will then be used. */ /* Define this if your compiler supports __attribute__((uninitialized)) */ #undef HAVE_ATTRIBUTE_UNINITIALIZED +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + /* Define to 1 if you have the 'bcopy' function. */ #define HAVE_BCOPY 1 +/* Define this if your compiler provides __builtin_expect() */ +#undef HAVE_BUILTIN_EXPECT + /* Define this if your compiler provides __builtin_mul_overflow() */ #undef HAVE_BUILTIN_MUL_OVERFLOW +/* Define this if your compiler provides __builtin_unreachable() */ +#undef HAVE_BUILTIN_UNREACHABLE /* Define to 1 if you have the header file. */ #define HAVE_DIRENT_H 1