On ons, 2009-12-16 at 10:49 -0500, Tom Lane wrote:
> I think you're way overthinking this.  Where we started was just
> a proposal to try to expand the set of inline-ing compilers beyond
> "gcc only".  I don't see why we need to do anything but that.  The
> code is fine as-is except for the control #ifdefs.

I have found an Autoconf macro that checks whether the compiler properly
supports C99 inline semantics.  This would allow us to replace the
__GNUC__ conditional with HAVE_C99_INLINE, in this case.  Interestingly,
however, this check results in GCC <=4.2 *not* supporting C99 inline,
apparently because it produces redundant copies of static inline
functions.  But GCC 4.2 is currently Debian stable, for example, so
de-supporting that is probably not yet an option.

So, I'm not sure if this would actually solve anyone's problem, but it
does call into question that exact semantics that we are looking for.
Maybe we just replace __GNUC__ by __GNUC__ || __SOMETHING_ELSE_CC__.

Patch attached for entertainment.
diff --git a/aclocal.m4 b/aclocal.m4
index 6d13d0c..1b32d4b 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,6 +1,7 @@
 dnl $PostgreSQL$
 m4_include([config/ac_func_accept_argtypes.m4])
 m4_include([config/acx_pthread.m4])
+m4_include([config/ax_c99_inline.m4])
 m4_include([config/c-compiler.m4])
 m4_include([config/c-library.m4])
 m4_include([config/docbook.m4])
diff --git a/config/ax_c99_inline.m4 b/config/ax_c99_inline.m4
new file mode 100644
index 0000000..b6cbbd8
--- /dev/null
+++ b/config/ax_c99_inline.m4
@@ -0,0 +1,62 @@
+# ===========================================================================
+#          http://www.nongnu.org/autoconf-archive/ax_c99_inline.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_C99_INLINE
+#
+# DESCRIPTION
+#
+#   This macro defines HAVE_C99_INLINE if the C compiler supports "inline"
+#   and "extern inline" correctly. An application may replace "inline" with
+#   "static inline" as a workaround for older compilers.
+#
+# LICENSE
+#
+#   Copyright (c) 2009 Michael McMaster <em...@michaelmcmaster.name>
+#
+#   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.
+
+AC_DEFUN([AX_C99_INLINE], [
+	AC_MSG_CHECKING([whether the compiler supports C99 inline functions])
+	AC_REQUIRE([AC_PROG_CC_C99])
+
+	AC_LANG_PUSH([C])
+
+	dnl In a conforming C99 implementation a function marked "inline" will not
+	dnl	be compiled into the translation unit if the compiler was not able to
+	dnl	inline the function.
+	dnl	GCC versions before 4.3 would output the inline functions into all
+	dnl	translation units that could require the definition.
+	AC_LINK_IFELSE(
+		AC_LANG_SOURCE([
+			inline void* foo() { foo(); return &foo; }
+			int main() { return foo() != 0;}
+			]),
+
+		dnl the invalid source compiled, so the inline keyword does not work
+		dnl correctly.
+		AC_MSG_RESULT([no]),
+
+		dnl Secondary test of valid source.
+		AC_LINK_IFELSE(
+			AC_LANG_SOURCE([
+				extern inline void* foo() { foo(); return &foo; }
+				int main() { return foo() != 0;}
+				]),
+
+			AC_MSG_RESULT([yes])
+			AC_DEFINE([HAVE_C99_INLINE], [1],
+				[Define to 1 if the "extern" keyword controls whether an inline function appears in a translation unit.]),
+
+			dnl Perhaps inline functions aren't supported at all ?
+			AC_MSG_RESULT([no])
+			)
+		)
+
+	AC_LANG_POP([C])
+	]);
diff --git a/configure.in b/configure.in
index 5a27d3a..6d09d48 100644
--- a/configure.in
+++ b/configure.in
@@ -1088,6 +1088,7 @@ m4_defun([AC_PROG_CC_STDC], []) dnl We don't want that.
 AC_C_BIGENDIAN
 AC_C_CONST
 AC_C_INLINE
+AX_C99_INLINE
 AC_C_STRINGIZE
 PGAC_C_SIGNED
 AC_C_VOLATILE
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index 862a083..062459a 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -71,34 +71,34 @@ struct ListCell
 /*
  * These routines are used frequently. However, we can't implement
  * them as macros, since we want to avoid double-evaluation of macro
- * arguments. Therefore, we implement them using GCC inline functions,
- * and as regular functions with non-GCC compilers.
+ * arguments. Therefore, we implement them using inline functions,
+ * if the compiler supports it.
  */
-#ifdef __GNUC__
+#ifdef HAVE_C99_INLINE
 
-static __inline__ ListCell *
+static inline ListCell *
 list_head(List *l)
 {
 	return l ? l->head : NULL;
 }
 
-static __inline__ ListCell *
+static inline ListCell *
 list_tail(List *l)
 {
 	return l ? l->tail : NULL;
 }
 
-static __inline__ int
+static inline int
 list_length(List *l)
 {
 	return l ? l->length : 0;
 }
-#else
+#else /* HAVE_C99_INLINE */
 
 extern ListCell *list_head(List *l);
 extern ListCell *list_tail(List *l);
 extern int	list_length(List *l);
-#endif   /* __GNUC__ */
+#endif /* HAVE_C99_INLINE */
 
 /*
  * NB: There is an unfortunate legacy from a previous incarnation of
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 69799a5..4ee950a 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -84,6 +84,10 @@
 /* Define to 1 if you have the `atexit' function. */
 #undef HAVE_ATEXIT
 
+/* Define to 1 if the "extern" keyword controls whether an inline function
+   appears in a translation unit. */
+#undef HAVE_C99_INLINE
+
 /* Define to 1 if you have the `cbrt' function. */
 #undef HAVE_CBRT
 
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index 93c2cfb..1947efa 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -72,11 +72,11 @@ extern void *repalloc(void *pointer, Size size);
 
 /*
  * MemoryContextSwitchTo can't be a macro in standard C compilers.
- * But we can make it an inline function when using GCC.
+ * But we can make it an inline function if the compiler supports it.
  */
-#ifdef __GNUC__
+#ifdef HAVE_C99_INLINE
 
-static __inline__ MemoryContext
+static inline MemoryContext
 MemoryContextSwitchTo(MemoryContext context)
 {
 	MemoryContext old = CurrentMemoryContext;
@@ -84,10 +84,10 @@ MemoryContextSwitchTo(MemoryContext context)
 	CurrentMemoryContext = context;
 	return old;
 }
-#else
+#else /* not HAVE_C99_INLINE */
 
 extern MemoryContext MemoryContextSwitchTo(MemoryContext context);
-#endif   /* __GNUC__ */
+#endif /* not HAVE_C99_INLINE */
 
 /*
  * These are like standard strdup() except the copied string is
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to