The Oracle Developer Studio 12.6 produces a compilation error when compiling the Gnulib module 'obstack':
cc -m64 -O -DHAVE_CONFIG_H -I. -I../../gllib -I.. -DGNULIB_STRICT_CHECKING=1 -I/home/haible/prefix64/include -g -c -o obstack.o ../../gllib/obstack.c "../../gllib/obstack.c", line 119: internal compiler error: ir_process_arrloc_tree: bad arrloc tree cc: acomp failed for ../../gllib/obstack.c gmake[3]: *** [Makefile:1028: obstack.o] Error 2 The Oracle support determined that the problem is that the compiler gets confused by the conditional expression in the __PTR_ALIGN macro. This patch provides a workaround: Let's evaluate the condition at configure time, rather than at compile time. 2024-03-27 Bruno Haible <br...@clisp.org> obstack: Work around ICE with Oracle cc 12.6 (regr. 2023-12-01). * lib/obstack.in.h (__PTR_ALIGN): Use SMALL_PTRDIFF_T, instead of testing sizeof (ptrdiff_t) < sizeof (void *) at compile time. * m4/obstack.m4 (gl_FUNC_OBSTACK): Set SMALL_PTRDIFF_T. * modules/obstack (Makefile.am): Substitute SMALL_PTRDIFF_T. diff --git a/lib/obstack.in.h b/lib/obstack.in.h index cf149947be..28fb4d8916 100644 --- a/lib/obstack.in.h +++ b/lib/obstack.in.h @@ -133,17 +133,19 @@ # define _OBSTACK_CAST(type, expr) (expr) #endif -/* If B is the base of an object addressed by P, return the result of - aligning P to the next multiple of A + 1. B and P must be of type - char *. A + 1 must be a power of 2. +/* __PTR_ALIGN(B, P, A) returns the result of aligning P to the next multiple + of A + 1. B must be the base of an object addressed by P. B and P must be + of type char *. A + 1 must be a power of 2. If ptrdiff_t is narrower than a pointer (e.g., the AS/400), play it safe and compute the alignment relative to B. Otherwise, use the faster strategy of computing the alignment through uintptr_t. */ - -#define __PTR_ALIGN(B, P, A) \ - (sizeof (ptrdiff_t) < sizeof (void *) \ - ? (B) + (((P) - (B) + (A)) & ~(A)) \ - : (P) + ((- (uintptr_t) (P)) & (A))) +#if @SMALL_PTRDIFF_T@ +# define __PTR_ALIGN(B, P, A) \ + ((B) + (((P) - (B) + (A)) & ~(A))) +#else +# define __PTR_ALIGN(B, P, A) \ + ((P) + ((- (uintptr_t) (P)) & (A))) +#endif #ifndef __attribute_pure__ # define __attribute_pure__ _GL_ATTRIBUTE_PURE diff --git a/m4/obstack.m4 b/m4/obstack.m4 index 196609d7fb..be553cfb78 100644 --- a/m4/obstack.m4 +++ b/m4/obstack.m4 @@ -45,4 +45,25 @@ AC_DEFUN([gl_FUNC_OBSTACK] GL_GENERATE_OBSTACK_H=false fi AC_SUBST([REPLACE_OBSTACK]) + + dnl Test whether a 'ptrdiff_t' has at least as many bits as a pointer. + AC_CACHE_CHECK([whether ptrdiff_t is at least as large as a pointer], + [gl_cv_ptrdiff_t_wide_enough], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <stddef.h> + typedef int check[2 * (sizeof (ptrdiff_t) >= sizeof (void *)) - 1]; + ]], + [[]])], + [gl_cv_ptrdiff_t_wide_enough=yes], + [gl_cv_ptrdiff_t_wide_enough=no]) + ]) + if test $gl_cv_ptrdiff_t_wide_enough = yes; then + SMALL_PTRDIFF_T=0 + else + SMALL_PTRDIFF_T=1 + fi + dnl SMALL_PTRDIFF_T is expected to be 1 only on old / exotic platforms + dnl such as Windows 3.1 and AS/400. + AC_SUBST([SMALL_PTRDIFF_T]) ]) diff --git a/modules/obstack b/modules/obstack index e4db4cdc97..5c94894e8c 100644 --- a/modules/obstack +++ b/modules/obstack @@ -31,6 +31,7 @@ obstack.h: obstack.in.h $(top_builddir)/config.status @NMD@ $(AM_V_GEN)$(MKDIR_P) '%reldir%' $(gl_V_at)$(SED_HEADER_STDOUT) \ -e 's|@''REPLACE_OBSTACK''@|$(REPLACE_OBSTACK)|g' \ + -e 's|@''SMALL_PTRDIFF_T''@|$(SMALL_PTRDIFF_T)|g' \ $(srcdir)/obstack.in.h > $@-t $(AM_V_at)mv $@-t $@ else