summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Eisentraut2011-06-16 19:39:09 +0000
committerPeter Eisentraut2011-06-16 19:45:38 +0000
commitdbbba5279f66f95805c1e084e6f646d174931e56 (patch)
treeeddb454b3d39b17d2e25491d906a6b05b4ea4e18
parent78475b0ecac4e7793366d2dba0cb875a8fde6bb0 (diff)
Start using flexible array members
Flexible array members are a C99 feature that avoids "cheating" in the declaration of variable-length arrays at the end of structs. With Autoconf support, this should be transparent for older compilers. We start with one use in gist.h because gcc 4.6 started to raise a warning there. Over time, it can be expanded to other places in the source, but they will likely need some review of sizeof and offsetof usage. The current change in gist.h appears to be safe in this regard.
-rwxr-xr-xconfigure71
-rw-r--r--configure.in1
-rw-r--r--src/include/access/gist.h2
-rw-r--r--src/include/pg_config.h.in9
4 files changed, 82 insertions, 1 deletions
diff --git a/configure b/configure
index a2c3aab407..9b8cb48931 100755
--- a/configure
+++ b/configure
@@ -14954,6 +14954,77 @@ _ACEOF
fi
+
+ { $as_echo "$as_me:$LINENO: checking for flexible array members" >&5
+$as_echo_n "checking for flexible array members... " >&6; }
+if test "${ac_cv_c_flexmember+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. */
+#include <stdlib.h>
+ #include <stdio.h>
+ #include <stddef.h>
+ struct s { int n; double d[]; };
+int
+main ()
+{
+int m = getchar ();
+ struct s *p = malloc (offsetof (struct s, d)
+ + m * sizeof (double));
+ p->d[0] = 0.0;
+ return p->d != (double *) NULL;
+ ;
+ 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
+ ac_cv_c_flexmember=yes
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_flexmember=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_flexmember" >&5
+$as_echo "$ac_cv_c_flexmember" >&6; }
+ if test $ac_cv_c_flexmember = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define FLEXIBLE_ARRAY_MEMBER /**/
+_ACEOF
+
+ else
+ cat >>confdefs.h <<\_ACEOF
+#define FLEXIBLE_ARRAY_MEMBER 1
+_ACEOF
+
+ fi
+
{ $as_echo "$as_me:$LINENO: checking for signed types" >&5
$as_echo_n "checking for signed types... " >&6; }
if test "${pgac_cv_c_signed+set}" = set; then
diff --git a/configure.in b/configure.in
index ddc4cc9a16..e873c7b157 100644
--- a/configure.in
+++ b/configure.in
@@ -1110,6 +1110,7 @@ AC_C_BIGENDIAN
AC_C_CONST
PGAC_C_INLINE
AC_C_STRINGIZE
+AC_C_FLEXIBLE_ARRAY_MEMBER
PGAC_C_SIGNED
AC_C_VOLATILE
PGAC_C_FUNCNAME_SUPPORT
diff --git a/src/include/access/gist.h b/src/include/access/gist.h
index df9f39c7b8..5ce7325ff9 100644
--- a/src/include/access/gist.h
+++ b/src/include/access/gist.h
@@ -144,7 +144,7 @@ typedef struct GISTENTRY
typedef struct
{
int32 n; /* number of elements */
- GISTENTRY vector[1]; /* variable-length array */
+ GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER];
} GistEntryVector;
#define GEVHDRSZ (offsetof(GistEntryVector, vector))
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 5d38f25d26..19f38cc0fd 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -61,6 +61,15 @@
(--enable-thread-safety) */
#undef ENABLE_THREAD_SAFETY
+/* Define to nothing if C supports flexible array members, and to 1 if it does
+ not. That way, with a declaration like `struct s { int n; double
+ d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99
+ compilers. When computing the size of such an object, don't use 'sizeof
+ (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)'
+ instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with
+ MSVC and with C++ compilers. */
+#undef FLEXIBLE_ARRAY_MEMBER
+
/* float4 values are passed by value if 'true', by reference if 'false' */
#undef FLOAT4PASSBYVAL