diff --git a/config/c-compiler.m4 b/config/c-compiler.m4
index 9398ca6c4777c0f2aeec3f79f1ea6207563b3c91..069b468daac4de098e89ae81bf7ac9cdd6e59dac 100644
--- a/config/c-compiler.m4
+++ b/config/c-compiler.m4
@@ -121,6 +121,46 @@ fi])# PGAC_C_FUNCNAME_SUPPORT
 
 
 
+# PGAC_C_STATIC_ASSERT
+# -----------------------
+# Check if the C compiler understands _Static_assert(),
+# and define HAVE__STATIC_ASSERT if so.
+#
+# We actually check the syntax ({ _Static_assert(...) }), because we need
+# gcc-style compound expressions to be able to wrap the thing into macros.
+AC_DEFUN([PGAC_C_STATIC_ASSERT],
+[AC_CACHE_CHECK(for _Static_assert, pgac_cv__static_assert,
+[AC_TRY_LINK([],
+[({ _Static_assert(1, "foo"); })],
+[pgac_cv__static_assert=yes],
+[pgac_cv__static_assert=no])])
+if test x"$pgac_cv__static_assert" = xyes ; then
+AC_DEFINE(HAVE__STATIC_ASSERT, 1,
+          [Define to 1 if your compiler understands _Static_assert.])
+fi])# PGAC_C_STATIC_ASSERT
+
+
+
+# PGAC_C_TYPES_COMPATIBLE
+# -----------------------
+# Check if the C compiler understands __builtin_types_compatible_p,
+# and define HAVE__BUILTIN_TYPES_COMPATIBLE_P if so.
+#
+# We check usage with __typeof__, though it's unlikely any compiler would
+# have the former and not the latter.
+AC_DEFUN([PGAC_C_TYPES_COMPATIBLE],
+[AC_CACHE_CHECK(for __builtin_types_compatible_p, pgac_cv__types_compatible,
+[AC_TRY_COMPILE([],
+[ int x; static int y[__builtin_types_compatible_p(__typeof__(x), int)]; ],
+[pgac_cv__types_compatible=yes],
+[pgac_cv__types_compatible=no])])
+if test x"$pgac_cv__types_compatible" = xyes ; then
+AC_DEFINE(HAVE__BUILTIN_TYPES_COMPATIBLE_P, 1,
+          [Define to 1 if your compiler understands __builtin_types_compatible_p.])
+fi])# PGAC_C_TYPES_COMPATIBLE
+
+
+
 # PGAC_PROG_CC_CFLAGS_OPT
 # -----------------------
 # Given a string, check if the compiler supports the string as a
diff --git a/configure b/configure
index 56da7cdc73f3dd8241f3d6cddc094cdd3b347dfa..c6dcc8bfaaf5866ca532aef680f00dfb12cb7ebc 100755
--- a/configure
+++ b/configure
@@ -15524,6 +15524,125 @@ cat >>confdefs.h <<\_ACEOF
 _ACEOF
 
 fi
+fi
+{ $as_echo "$as_me:$LINENO: checking for _Static_assert" >&5
+$as_echo_n "checking for _Static_assert... " >&6; }
+if test "${pgac_cv__static_assert+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+({ _Static_assert(1, "foo"); })
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  pgac_cv__static_assert=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	pgac_cv__static_assert=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $pgac_cv__static_assert" >&5
+$as_echo "$pgac_cv__static_assert" >&6; }
+if test x"$pgac_cv__static_assert" = xyes ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE__STATIC_ASSERT 1
+_ACEOF
+
+fi
+{ $as_echo "$as_me:$LINENO: checking for __builtin_types_compatible_p" >&5
+$as_echo_n "checking for __builtin_types_compatible_p... " >&6; }
+if test "${pgac_cv__types_compatible+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+ int x; static int y[__builtin_types_compatible_p(__typeof__(x), int)];
+  ;
+  return 0;
+}
+_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 ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$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
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  pgac_cv__types_compatible=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	pgac_cv__types_compatible=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $pgac_cv__types_compatible" >&5
+$as_echo "$pgac_cv__types_compatible" >&6; }
+if test x"$pgac_cv__types_compatible" = xyes ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1
+_ACEOF
+
 fi
 { $as_echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
diff --git a/configure.in b/configure.in
index 8d02abb4cca6538b8b16d30bc8589ca9febe9902..fef8e7f013a9020576d9f2d22b7c2aa112282632 100644
--- a/configure.in
+++ b/configure.in
@@ -1104,6 +1104,8 @@ AC_C_FLEXIBLE_ARRAY_MEMBER
 PGAC_C_SIGNED
 AC_C_VOLATILE
 PGAC_C_FUNCNAME_SUPPORT
+PGAC_C_STATIC_ASSERT
+PGAC_C_TYPES_COMPATIBLE
 PGAC_STRUCT_TIMEZONE
 PGAC_UNION_SEMUN
 PGAC_STRUCT_SOCKADDR_UN
diff --git a/src/include/c.h b/src/include/c.h
index 50e1ecfde4da66899eb294f9b51a8b49bc7c297e..06f689d35937b13178f263a6d5db6752e8b96a07 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -689,6 +689,47 @@ typedef NameData *Name;
 	} while (0)
 
 
+/*
+ * Macros to support compile-time assertion checks, if the compiler has them.
+ *
+ * If the "condition" (a compile-time-constant expression) evaluates to false,
+ * throw a compile error using the "errmessage" (a string literal).
+ *
+ * gcc 4.6 and up supports _Static_assert(), but it has bizarre syntactic
+ * placement restrictions.  These macros make it safe to use as a statement
+ * or in an expression, respectively.
+ */
+#ifdef HAVE__STATIC_ASSERT
+#define StaticAssertStmt(condition, errmessage) \
+	do { _Static_assert(condition, errmessage); } while(0)
+#define StaticAssertExpr(condition, errmessage) \
+	({ StaticAssertStmt(condition, errmessage); true; })
+#else /* !HAVE__STATIC_ASSERT */
+#define StaticAssertStmt(condition, errmessage)
+#define StaticAssertExpr(condition, errmessage) ((void) true)
+#endif /* HAVE__STATIC_ASSERT */
+
+
+/*
+ * Compile-time checks that a variable (or expression) has the specified type.
+ *
+ * AssertVariableIsOfType() can be used as a statement.
+ * AssertVariableIsOfTypeMacro() is intended for use in macros, eg
+ *		#define foo(x) (AssertVariableIsOfTypeMacro(x, int), bar(x))
+ */
+#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+#define AssertVariableIsOfType(varname, typename) \
+	StaticAssertStmt(__builtin_types_compatible_p(__typeof__(varname), typename), \
+	CppAsString(varname) " does not have type " CppAsString(typename))
+#define AssertVariableIsOfTypeMacro(varname, typename) \
+	StaticAssertExpr(__builtin_types_compatible_p(__typeof__(varname), typename), \
+	CppAsString(varname) " does not have type " CppAsString(typename))
+#else /* !HAVE__BUILTIN_TYPES_COMPATIBLE_P */
+#define AssertVariableIsOfType(varname, typename)
+#define AssertVariableIsOfTypeMacro(varname, typename) ((void) true)
+#endif /* HAVE__BUILTIN_TYPES_COMPATIBLE_P */
+
+
 /* ----------------------------------------------------------------
  *				Section 7:	random stuff
  * ----------------------------------------------------------------
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 1ffb032835f1fa324fda404647551d8529040269..58cd5907dd4c487a6e556a79754109822c40334e 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -635,6 +635,12 @@
 /* Define to 1 if you have the <winldap.h> header file. */
 #undef HAVE_WINLDAP_H
 
+/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
+#undef HAVE__BUILTIN_TYPES_COMPATIBLE_P
+
+/* Define to 1 if your compiler understands _Static_assert. */
+#undef HAVE__STATIC_ASSERT
+
 /* Define to the appropriate snprintf format for 64-bit ints. */
 #undef INT64_FORMAT
 
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index b7b7c641d3af10c10c377bfce5f29cd2c138f942..4d9cc55c69908e34c6ffc3cbebbc1be6ff2f96f9 100644
--- a/src/include/pg_config.h.win32
+++ b/src/include/pg_config.h.win32
@@ -526,6 +526,12 @@
 /* Define to 1 if you have the <winldap.h> header file. */
 /* #undef HAVE_WINLDAP_H */
 
+/* Define to 1 if your compiler understands __builtin_types_compatible_p. */
+/* #undef HAVE__BUILTIN_TYPES_COMPATIBLE_P */
+
+/* Define to 1 if your compiler understands _Static_assert. */
+/* #undef HAVE__STATIC_ASSERT */
+
 /* Define to the appropriate snprintf format for 64-bit ints, if any. */
 #define INT64_FORMAT "%lld"