0001-Mark-elog-as-not-returning-if-the-capabilities-of-th.patch
text/x-patch
Filename: 0001-Mark-elog-as-not-returning-if-the-capabilities-of-th.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
Series: patch 0001
| File | + | − |
|---|---|---|
| config/c-compiler.m4 | 41 | 0 |
| configure.in | 2 | 0 |
| src/include/c.h | 10 | 0 |
| src/include/utils/elog.h | 15 | 3 |
>From 94a3f93f4c8a381358a4dc52a43ec60a8f3e33f6 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 11 Jan 2013 16:58:17 +0100
Subject: [PATCH] Mark elog() as not returning if the capabilities of the C
compiler allow it
To do that:
* Add a configure check for __VA_ARGS__ support
* Provide pg_unreachable() macro which expands to__builtin_unreachable() if the
compiler supports it, abort() otherwise
Marking it as such improves code generation and reduces executable size.
---
config/c-compiler.m4 | 41 +++++++++++++++++++++++++++++++++++++++++
configure.in | 2 ++
src/include/c.h | 10 ++++++++++
src/include/utils/elog.h | 18 +++++++++++++++---
4 files changed, 68 insertions(+), 3 deletions(-)
diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 7cbb8ec..f3efe72 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -161,6 +161,47 @@ fi])# PGAC_C_TYPES_COMPATIBLE
+# PGAC_C_VA_ARGS
+# -----------------------
+# Check if the C compiler understands C99 style variadic macros and define
+# HAVE__VA_ARGS if so.
+AC_DEFUN([PGAC_C_VA_ARGS],
+[AC_CACHE_CHECK(for __VA_ARGS__, pgac_cv__va_args,
+[AC_TRY_COMPILE([#include <stdio.h>],
+[#define debug(...) fprintf(stderr, __VA_ARGS__)
+debug("%s", "blarg");
+],
+[pgac_cv__va_args=yes],
+[pgac_cv__va_args=no])])
+if test x"$pgac_cv__va_args" = xyes ; then
+AC_DEFINE(HAVE__VA_ARGS, 1,
+ [Define to 1 if your compiler understands C99 __VA_ARGS__ in macros.])
+fi])# PGAC_C_VA_ARGS
+
+
+
+# PGAC_C_UNREACHABLE
+# -----------------------
+
+# Check if the C compiler understands __builtin_unreachable() and define
+# HAVE__BUILTIN_UNREACHABLE if so.
+#
+# NB: Don't get the idea of putting a for(;;); or such before the
+# __builtin_unreachable() in that case some compilers remove it before linking
+# and only a warning instead of an error will be produced.
+AC_DEFUN([PGAC_C_UNREACHABLE],
+[AC_CACHE_CHECK(for __builtin_unreachable, pgac_cv__builtin_unreachable,
+[AC_TRY_LINK([],
+[__builtin_unreachable();],
+[pgac_cv__builtin_unreachable=yes],
+[pgac_cv__builtin_unreachable=no])])
+if test x"$pgac_cv__builtin_unreachable" = xyes ; then
+AC_DEFINE(HAVE__BUILTIN_UNREACHABLE, 1,
+ [Define to 1 if your compiler understands __builtin_unreachable.])
+fi])# PGAC_C_UNREACHABLE
+
+
+
# PGAC_PROG_CC_CFLAGS_OPT
# -----------------------
# Given a string, check if the compiler supports the string as a
diff --git a/configure.in b/configure.in
index e2682f3..13ac2ab 100644
--- a/configure.in
+++ b/configure.in
@@ -1106,6 +1106,8 @@ AC_C_VOLATILE
PGAC_C_FUNCNAME_SUPPORT
PGAC_C_STATIC_ASSERT
PGAC_C_TYPES_COMPATIBLE
+PGAC_C_VA_ARGS
+PGAC_C_UNREACHABLE
PGAC_STRUCT_TIMEZONE
PGAC_UNION_SEMUN
PGAC_STRUCT_SOCKADDR_UN
diff --git a/src/include/c.h b/src/include/c.h
index c30df8b..77c3319 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -831,6 +831,16 @@ typedef NameData *Name;
#define STATIC_IF_INLINE
#endif /* PG_USE_INLINE */
+/*
+ * Cross Platform support to mark locations as unreachable to avoid warnings
+ * and to aid code generation.
+ */
+#ifdef HAVE__BUILTIN_UNREACHABLE
+#define pg_unreachable() __builtin_unreachable()
+#else
+#define pg_unreachable() abort()
+#endif
+
/* ----------------------------------------------------------------
* Section 7: random stuff
* ----------------------------------------------------------------
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index cbbda04..d6e1054 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -109,7 +109,7 @@
#define ereport_domain(elevel, domain, rest) \
(errstart(elevel, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain) ? \
(errfinish rest) : (void) 0), \
- ((elevel) >= ERROR ? abort() : (void) 0)
+ ((elevel) >= ERROR ? pg_unreachable() : (void) 0)
#define ereport(elevel, rest) \
ereport_domain(elevel, TEXTDOMAIN, rest)
@@ -210,10 +210,22 @@ extern int getinternalerrposition(void);
/*----------
* Old-style error reporting API: to be used in this way:
* elog(ERROR, "portal \"%s\" not found", stmt->portalname);
+ *
+ * If we have support for variadic macros available we can signal that elog
+ * won't return with an elevel >= ERROR which can lead to better code being
+ * generated.
*----------
*/
-#define elog elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO), elog_finish
-
+#ifdef HAVE__VA_ARGS
+#define elog(elevel, ...) \
+ elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO), \
+ elog_finish(elevel, __VA_ARGS__), \
+ ((elevel) >= ERROR ? pg_unreachable() : (void) 0)
+#else
+#define elog \
+ elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO), \
+ elog_finish
+#endif
extern void elog_start(const char *filename, int lineno, const char *funcname);
extern void
elog_finish(int elevel, const char *fmt,...)
--
1.7.12.289.g0ce9864.dirty