>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

