about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog55
-rw-r--r--math/tgmath.h204
2 files changed, 202 insertions, 57 deletions
diff --git a/ChangeLog b/ChangeLog
index 3930fd1ca4..052db47609 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+2017-11-15  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #21660]
+	* math/tgmath.h (__HAVE_BUILTIN_TGMATH): New macro.
+	[__HAVE_BUILTIN_TGMATH] (__TG_F16_ARG): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TG_F32_ARG): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TG_F64_ARG): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TG_F128_ARG): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TG_F32X_ARG): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TG_F64X_ARG): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TG_F128X_ARG): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_FUNCS): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_RCFUNCS): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_1): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_2): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_2STD): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_3): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_1C): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_2C): Likewise.
+	(__tgml): Make conditional on [!__HAVE_BUILTIN_TGMATH].
+	(__floating_type): Likewise.
+	(__real_integer_type): Likewise.
+	(__complex_integer_type): Likewise.
+	(__expr_is_real): Likewise.
+	(__tgmath_real_type_sub): Likewise.
+	(__tgmath_real_type): Likewise.
+	(__tgmath_complex_type_sub): Likewise.
+	(__tgmath_complex_type): Likewise.
+	(__TGMATH_F128): Likewise.
+	(__TGMATH_CF128): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_UNARY_REAL_ONLY): Define using
+	new macros.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_UNARY_REAL_RET_ONLY): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_BINARY_FIRST_REAL_ONLY):
+	Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_BINARY_FIRST_REAL_STD_ONLY):
+	Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_BINARY_REAL_ONLY): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_BINARY_REAL_STD_ONLY): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_BINARY_REAL_RET_ONLY): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY):
+	Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_TERNARY_REAL_ONLY): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_TERNARY_FIRST_REAL_RET_ONLY):
+	Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_UNARY_REAL_IMAG): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_UNARY_IMAG): Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_UNARY_REAL_IMAG_RET_REAL):
+	Likewise.
+	[__HAVE_BUILTIN_TGMATH] (__TGMATH_BINARY_REAL_IMAG): Likewise.
+	(__TGMATH_UNARY_REAL_IMAG_RET_REAL_SAME): New macro.
+	(carg): Use __TGMATH_UNARY_REAL_IMAG_RET_REAL_SAME.
+	(cimag): Likewise.
+	(creal): Likewise.
+
 2017-11-14  Joseph Myers  <joseph@codesourcery.com>
 
 	* string/tester.c (test_stpncpy): Disable -Wstringop-truncation
diff --git a/math/tgmath.h b/math/tgmath.h
index 108c1a19c7..12161771b1 100644
--- a/math/tgmath.h
+++ b/math/tgmath.h
@@ -31,22 +31,76 @@
 #include <complex.h>
 
 
-/* Since `complex' is currently not really implemented in most C compilers
-   and if it is implemented, the implementations differ.  This makes it
-   quite difficult to write a generic implementation of this header.  We
-   do not try this for now and instead concentrate only on GNU CC.  Once
-   we have more information support for other compilers might follow.  */
+/* There are two variant implementations of type-generic macros in
+   this file: one for GCC 8 and later, using __builtin_tgmath and
+   where each macro expands each of its arguments only once, and one
+   for older GCC, using other compiler extensions but with macros
+   expanding their arguments many times (so resulting in exponential
+   blowup of the size of expansions when calls to such macros are
+   nested inside arguments to such macros).  */
+
+#define __HAVE_BUILTIN_TGMATH __GNUC_PREREQ (8, 0)
 
 #if __GNUC_PREREQ (2, 7)
 
-# ifdef __NO_LONG_DOUBLE_MATH
-#  define __tgml(fct) fct
-# else
-#  define __tgml(fct) fct ## l
-# endif
+# if __HAVE_BUILTIN_TGMATH
 
-/* This is ugly but unless gcc gets appropriate builtins we have to do
-   something like this.  Don't ask how it works.  */
+#  if __HAVE_FLOAT16 && __GLIBC_USE (IEC_60559_TYPES_EXT)
+#   define __TG_F16_ARG(X) X ## f16,
+#  else
+#   define __TG_F16_ARG(X)
+#  endif
+#  if __HAVE_FLOAT32 && __GLIBC_USE (IEC_60559_TYPES_EXT)
+#   define __TG_F32_ARG(X) X ## f32,
+#  else
+#   define __TG_F32_ARG(X)
+#  endif
+#  if __HAVE_FLOAT64 && __GLIBC_USE (IEC_60559_TYPES_EXT)
+#   define __TG_F64_ARG(X) X ## f64,
+#  else
+#   define __TG_F64_ARG(X)
+#  endif
+#  if __HAVE_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)
+#   define __TG_F128_ARG(X) X ## f128,
+#  else
+#   define __TG_F128_ARG(X)
+#  endif
+#  if __HAVE_FLOAT32X && __GLIBC_USE (IEC_60559_TYPES_EXT)
+#   define __TG_F32X_ARG(X) X ## f32x,
+#  else
+#   define __TG_F32X_ARG(X)
+#  endif
+#  if __HAVE_FLOAT64X && __GLIBC_USE (IEC_60559_TYPES_EXT)
+#   define __TG_F64X_ARG(X) X ## f64x,
+#  else
+#   define __TG_F64X_ARG(X)
+#  endif
+#  if __HAVE_FLOAT128X && __GLIBC_USE (IEC_60559_TYPES_EXT)
+#   define __TG_F128X_ARG(X) X ## f128x,
+#  else
+#   define __TG_F128X_ARG(X)
+#  endif
+
+#  define __TGMATH_FUNCS(X) X ## f, X, X ## l,				\
+    __TG_F16_ARG (X) __TG_F32_ARG (X) __TG_F64_ARG (X) __TG_F128_ARG (X) \
+    __TG_F32X_ARG (X) __TG_F64X_ARG (X) __TG_F128X_ARG (X)
+#  define __TGMATH_RCFUNCS(F, C) __TGMATH_FUNCS (F) __TGMATH_FUNCS (C)
+#  define __TGMATH_1(F, X) __builtin_tgmath (__TGMATH_FUNCS (F) (X))
+#  define __TGMATH_2(F, X, Y) __builtin_tgmath (__TGMATH_FUNCS (F) (X), (Y))
+#  define __TGMATH_2STD(F, X, Y) __builtin_tgmath (F ## f, F, F ## l, (X), (Y))
+#  define __TGMATH_3(F, X, Y, Z) __builtin_tgmath (__TGMATH_FUNCS (F)	\
+						   (X), (Y), (Z))
+#  define __TGMATH_1C(F, C, X) __builtin_tgmath (__TGMATH_RCFUNCS (F, C) (X))
+#  define __TGMATH_2C(F, C, X, Y) __builtin_tgmath (__TGMATH_RCFUNCS (F, C) \
+						    (X), (Y))
+
+# else /* !__HAVE_BUILTIN_TGMATH.  */
+
+#  ifdef __NO_LONG_DOUBLE_MATH
+#   define __tgml(fct) fct
+#  else
+#   define __tgml(fct) fct ## l
+#  endif
 
 /* __floating_type expands to 1 if TYPE is a floating type (including
    complex floating types), 0 if TYPE is an integer type (including
@@ -56,48 +110,48 @@
    constant expressions.  All these macros can assume their argument
    has an arithmetic type (not vector, decimal floating-point or
    fixed-point), valid to pass to tgmath.h macros.  */
-# if __GNUC_PREREQ (3, 1)
+#  if __GNUC_PREREQ (3, 1)
 /* __builtin_classify_type expands to an integer constant expression
    in GCC 3.1 and later.  Default conversions applied to the argument
    of __builtin_classify_type mean it always returns 1 for real
    integer types rather than ever returning different values for
    character, boolean or enumerated types.  */
-#  define __floating_type(type)				\
+#   define __floating_type(type)				\
   (__builtin_classify_type (__real__ ((type) 0)) == 8)
-#  define __real_integer_type(type)		\
+#   define __real_integer_type(type)		\
   (__builtin_classify_type ((type) 0) == 1)
-#  define __complex_integer_type(type)				\
+#   define __complex_integer_type(type)				\
   (__builtin_classify_type ((type) 0) == 9			\
    && __builtin_classify_type (__real__ ((type) 0)) == 1)
-# else
+#  else
 /* GCC versions predating __builtin_classify_type are also looser on
    what counts as an integer constant expression.  */
-#  define __floating_type(type) (((type) 1.25) != 1)
-#  define __real_integer_type(type) (((type) (1.25 + _Complex_I)) == 1)
-#  define __complex_integer_type(type)			\
+#   define __floating_type(type) (((type) 1.25) != 1)
+#   define __real_integer_type(type) (((type) (1.25 + _Complex_I)) == 1)
+#   define __complex_integer_type(type)			\
   (((type) (1.25 + _Complex_I)) == (1 + _Complex_I))
-# endif
+#  endif
 
 /* Whether an expression (of arithmetic type) has a real type.  */
-# define __expr_is_real(E) (__builtin_classify_type (E) != 9)
+#  define __expr_is_real(E) (__builtin_classify_type (E) != 9)
 
 /* The tgmath real type for T, where E is 0 if T is an integer type
    and 1 for a floating type.  If T has a complex type, it is
    unspecified whether the return type is real or complex (but it has
    the correct corresponding real type).  */
-# define __tgmath_real_type_sub(T, E) \
+#  define __tgmath_real_type_sub(T, E) \
   __typeof__ (*(0 ? (__typeof__ (0 ? (double *) 0 : (void *) (E))) 0	      \
 		  : (__typeof__ (0 ? (T *) 0 : (void *) (!(E)))) 0))
 
 /* The tgmath real type of EXPR.  */
-# define __tgmath_real_type(expr) \
+#  define __tgmath_real_type(expr) \
   __tgmath_real_type_sub (__typeof__ ((__typeof__ (+(expr))) 0),	      \
 			  __floating_type (__typeof__ (+(expr))))
 
 /* The tgmath complex type for T, where E1 is 1 if T has a floating
    type and 0 otherwise, E2 is 1 if T has a real integer type and 0
    otherwise, and E3 is 1 if T has a complex type and 0 otherwise.  */
-# define __tgmath_complex_type_sub(T, E1, E2, E3)			\
+#  define __tgmath_complex_type_sub(T, E1, E2, E3)			\
   __typeof__ (*(0							\
 		? (__typeof__ (0 ? (T *) 0 : (void *) (!(E1)))) 0	\
 		: (__typeof__ (0					\
@@ -109,61 +163,94 @@
 					      : (void *) (!(E3)))) 0)) 0))
 
 /* The tgmath complex type of EXPR.  */
-# define __tgmath_complex_type(expr)					\
+#  define __tgmath_complex_type(expr)					\
   __tgmath_complex_type_sub (__typeof__ ((__typeof__ (+(expr))) 0),	\
 			     __floating_type (__typeof__ (+(expr))),	\
 			     __real_integer_type (__typeof__ (+(expr))), \
 			     __complex_integer_type (__typeof__ (+(expr))))
 
-# if (__HAVE_DISTINCT_FLOAT16			\
+#  if (__HAVE_DISTINCT_FLOAT16			\
       || __HAVE_DISTINCT_FLOAT32		\
       || __HAVE_DISTINCT_FLOAT64		\
       || __HAVE_DISTINCT_FLOAT32X		\
       || __HAVE_DISTINCT_FLOAT64X		\
       || __HAVE_DISTINCT_FLOAT128X)
-#  error "Unsupported _FloatN or _FloatNx types for <tgmath.h>."
-# endif
+#   error "Unsupported _FloatN or _FloatNx types for <tgmath.h>."
+#  endif
 
 /* Expand to text that checks if ARG_COMB has type _Float128, and if
    so calls the appropriately suffixed FCT (which may include a cast),
    or FCT and CFCT for complex functions, with arguments ARG_CALL.  */
-# if __HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)
-#  if (!__HAVE_FLOAT64X				\
+#  if __HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)
+#   if (!__HAVE_FLOAT64X			\
        || __HAVE_FLOAT64X_LONG_DOUBLE		\
        || !__HAVE_FLOATN_NOT_TYPEDEF)
-#   define __TGMATH_F128(arg_comb, fct, arg_call)			\
+#    define __TGMATH_F128(arg_comb, fct, arg_call)			\
   __builtin_types_compatible_p (__typeof (+(arg_comb)), _Float128)	\
   ? fct ## f128 arg_call :
-#   define __TGMATH_CF128(arg_comb, fct, cfct, arg_call)		\
+#    define __TGMATH_CF128(arg_comb, fct, cfct, arg_call)		\
   __builtin_types_compatible_p (__typeof (+__real__ (arg_comb)), _Float128) \
   ? (__expr_is_real (arg_comb)						\
      ? fct ## f128 arg_call						\
      : cfct ## f128 arg_call) :
-#  else
+#   else
 /* _Float64x is a distinct type at the C language level, which must be
    handled like _Float128.  */
-#   define __TGMATH_F128(arg_comb, fct, arg_call)			\
+#    define __TGMATH_F128(arg_comb, fct, arg_call)			\
   (__builtin_types_compatible_p (__typeof (+(arg_comb)), _Float128)	\
    || __builtin_types_compatible_p (__typeof (+(arg_comb)), _Float64x)) \
   ? fct ## f128 arg_call :
-#   define __TGMATH_CF128(arg_comb, fct, cfct, arg_call)		\
+#    define __TGMATH_CF128(arg_comb, fct, cfct, arg_call)		\
   (__builtin_types_compatible_p (__typeof (+__real__ (arg_comb)), _Float128) \
    || __builtin_types_compatible_p (__typeof (+__real__ (arg_comb)),	\
 				    _Float64x))				\
   ? (__expr_is_real (arg_comb)						\
      ? fct ## f128 arg_call						\
      : cfct ## f128 arg_call) :
+#   endif
+#  else
+#   define __TGMATH_F128(arg_comb, fct, arg_call) /* Nothing.  */
+#   define __TGMATH_CF128(arg_comb, fct, cfct, arg_call) /* Nothing.  */
 #  endif
-# else
-#  define __TGMATH_F128(arg_comb, fct, arg_call) /* Nothing.  */
-#  define __TGMATH_CF128(arg_comb, fct, cfct, arg_call) /* Nothing.  */
-# endif
 
+# endif /* !__HAVE_BUILTIN_TGMATH.  */
 
 /* We have two kinds of generic macros: to support functions which are
    only defined on real valued parameters and those which are defined
    for complex functions as well.  */
-# define __TGMATH_UNARY_REAL_ONLY(Val, Fct) \
+# if __HAVE_BUILTIN_TGMATH
+
+#  define __TGMATH_UNARY_REAL_ONLY(Val, Fct) __TGMATH_1 (Fct, (Val))
+#  define __TGMATH_UNARY_REAL_RET_ONLY(Val, Fct) __TGMATH_1 (Fct, (Val))
+#  define __TGMATH_BINARY_FIRST_REAL_ONLY(Val1, Val2, Fct)	\
+  __TGMATH_2 (Fct, (Val1), (Val2))
+#  define __TGMATH_BINARY_FIRST_REAL_STD_ONLY(Val1, Val2, Fct)	\
+  __TGMATH_2STD (Fct, (Val1), (Val2))
+#  define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct)	\
+  __TGMATH_2 (Fct, (Val1), (Val2))
+#  define __TGMATH_BINARY_REAL_STD_ONLY(Val1, Val2, Fct)	\
+  __TGMATH_2STD (Fct, (Val1), (Val2))
+#  define __TGMATH_BINARY_REAL_RET_ONLY(Val1, Val2, Fct)	\
+  __TGMATH_2 (Fct, (Val1), (Val2))
+#  define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
+  __TGMATH_3 (Fct, (Val1), (Val2), (Val3))
+#  define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct)	\
+  __TGMATH_3 (Fct, (Val1), (Val2), (Val3))
+#  define __TGMATH_TERNARY_FIRST_REAL_RET_ONLY(Val1, Val2, Val3, Fct)	\
+  __TGMATH_3 (Fct, (Val1), (Val2), (Val3))
+#  define __TGMATH_UNARY_REAL_IMAG(Val, Fct, Cfct)	\
+  __TGMATH_1C (Fct, Cfct, (Val))
+#  define __TGMATH_UNARY_IMAG(Val, Cfct) __TGMATH_1 (Cfct, (Val))
+#  define __TGMATH_UNARY_REAL_IMAG_RET_REAL(Val, Fct, Cfct)	\
+  __TGMATH_1C (Fct, Cfct, (Val))
+#  define __TGMATH_UNARY_REAL_IMAG_RET_REAL_SAME(Val, Cfct)	\
+  __TGMATH_1 (Cfct, (Val))
+#  define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct)	\
+  __TGMATH_2C (Fct, Cfct, (Val1), (Val2))
+
+# else /* !__HAVE_BUILTIN_TGMATH.  */
+
+#  define __TGMATH_UNARY_REAL_ONLY(Val, Fct)				\
   (__extension__ ((sizeof (+(Val)) == sizeof (double)			      \
 		      || __builtin_classify_type (Val) != 8)		      \
 		     ? (__tgmath_real_type (Val)) Fct (Val)		      \
@@ -173,7 +260,7 @@
 				      (Val))				      \
 		     (__tgmath_real_type (Val)) __tgml(Fct) (Val)))
 
-# define __TGMATH_UNARY_REAL_RET_ONLY(Val, Fct) \
+#  define __TGMATH_UNARY_REAL_RET_ONLY(Val, Fct) \
      (__extension__ ((sizeof (+(Val)) == sizeof (double)		      \
 		      || __builtin_classify_type (Val) != 8)		      \
 		     ? Fct (Val)					      \
@@ -182,7 +269,7 @@
 		     : __TGMATH_F128 ((Val), Fct, (Val))		      \
 		     __tgml(Fct) (Val)))
 
-# define __TGMATH_BINARY_FIRST_REAL_ONLY(Val1, Val2, Fct) \
+#  define __TGMATH_BINARY_FIRST_REAL_ONLY(Val1, Val2, Fct) \
      (__extension__ ((sizeof (+(Val1)) == sizeof (double)		      \
 		      || __builtin_classify_type (Val1) != 8)		      \
 		     ? (__tgmath_real_type (Val1)) Fct (Val1, Val2)	      \
@@ -192,7 +279,7 @@
 				    (Val1, Val2))			      \
 		     (__tgmath_real_type (Val1)) __tgml(Fct) (Val1, Val2)))
 
-# define __TGMATH_BINARY_FIRST_REAL_STD_ONLY(Val1, Val2, Fct) \
+#  define __TGMATH_BINARY_FIRST_REAL_STD_ONLY(Val1, Val2, Fct) \
      (__extension__ ((sizeof (+(Val1)) == sizeof (double)		      \
 		      || __builtin_classify_type (Val1) != 8)		      \
 		     ? (__tgmath_real_type (Val1)) Fct (Val1, Val2)	      \
@@ -200,7 +287,7 @@
 		     ? (__tgmath_real_type (Val1)) Fct##f (Val1, Val2)	      \
 		     : (__tgmath_real_type (Val1)) __tgml(Fct) (Val1, Val2)))
 
-# define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \
+#  define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \
      (__extension__ ((sizeof ((Val1) + (Val2)) > sizeof (double)	      \
 		      && __builtin_classify_type ((Val1) + (Val2)) == 8)      \
 		     ? __TGMATH_F128 ((Val1) + (Val2),			      \
@@ -222,7 +309,7 @@
 				   + (__tgmath_real_type (Val2)) 0))	      \
 		       Fct##f (Val1, Val2)))
 
-# define __TGMATH_BINARY_REAL_STD_ONLY(Val1, Val2, Fct) \
+#  define __TGMATH_BINARY_REAL_STD_ONLY(Val1, Val2, Fct) \
      (__extension__ ((sizeof ((Val1) + (Val2)) > sizeof (double)	      \
 		      && __builtin_classify_type ((Val1) + (Val2)) == 8)      \
 		     ? (__typeof ((__tgmath_real_type (Val1)) 0		      \
@@ -239,7 +326,7 @@
 				   + (__tgmath_real_type (Val2)) 0))	      \
 		       Fct##f (Val1, Val2)))
 
-# define __TGMATH_BINARY_REAL_RET_ONLY(Val1, Val2, Fct) \
+#  define __TGMATH_BINARY_REAL_RET_ONLY(Val1, Val2, Fct) \
      (__extension__ ((sizeof ((Val1) + (Val2)) > sizeof (double)	      \
 		      && __builtin_classify_type ((Val1) + (Val2)) == 8)      \
 		     ? __TGMATH_F128 ((Val1) + (Val2), Fct, (Val1, Val2))     \
@@ -251,7 +338,7 @@
 		     ? Fct (Val1, Val2)					      \
 		     : Fct##f (Val1, Val2)))
 
-# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
+#  define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
      (__extension__ ((sizeof ((Val1) + (Val2)) > sizeof (double)	      \
 		      && __builtin_classify_type ((Val1) + (Val2)) == 8)      \
 		     ? __TGMATH_F128 ((Val1) + (Val2),			      \
@@ -273,7 +360,7 @@
 				   + (__tgmath_real_type (Val2)) 0))	      \
 		       Fct##f (Val1, Val2, Val3)))
 
-# define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \
+#  define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \
      (__extension__ ((sizeof ((Val1) + (Val2) + (Val3)) > sizeof (double)     \
 		      && __builtin_classify_type ((Val1) + (Val2) + (Val3))   \
 			 == 8)						      \
@@ -302,7 +389,7 @@
 				   + (__tgmath_real_type (Val3)) 0))	      \
 		       Fct##f (Val1, Val2, Val3)))
 
-# define __TGMATH_TERNARY_FIRST_REAL_RET_ONLY(Val1, Val2, Val3, Fct) \
+#  define __TGMATH_TERNARY_FIRST_REAL_RET_ONLY(Val1, Val2, Val3, Fct) \
      (__extension__ ((sizeof (+(Val1)) == sizeof (double)		\
 		      || __builtin_classify_type (Val1) != 8)		\
 		     ? Fct (Val1, Val2, Val3)				\
@@ -313,7 +400,7 @@
 
 /* XXX This definition has to be changed as soon as the compiler understands
    the imaginary keyword.  */
-# define __TGMATH_UNARY_REAL_IMAG(Val, Fct, Cfct) \
+#  define __TGMATH_UNARY_REAL_IMAG(Val, Fct, Cfct) \
      (__extension__ ((sizeof (+__real__ (Val)) == sizeof (double)	      \
 		      || __builtin_classify_type (__real__ (Val)) != 8)	      \
 		     ? (__expr_is_real (Val)				      \
@@ -331,7 +418,7 @@
 		      ? (__tgmath_complex_type (Val)) __tgml(Fct) (Val)	      \
 		      : (__tgmath_complex_type (Val)) __tgml(Cfct) (Val))))
 
-# define __TGMATH_UNARY_IMAG(Val, Cfct) \
+#  define __TGMATH_UNARY_IMAG(Val, Cfct) \
      (__extension__ ((sizeof (+__real__ (Val)) == sizeof (double)	      \
 		      || __builtin_classify_type (__real__ (Val)) != 8)	      \
 		     ? (__typeof__ ((__tgmath_real_type (Val)) 0	      \
@@ -348,7 +435,7 @@
 
 /* XXX This definition has to be changed as soon as the compiler understands
    the imaginary keyword.  */
-# define __TGMATH_UNARY_REAL_IMAG_RET_REAL(Val, Fct, Cfct) \
+#  define __TGMATH_UNARY_REAL_IMAG_RET_REAL(Val, Fct, Cfct) \
      (__extension__ ((sizeof (+__real__ (Val)) == sizeof (double)	      \
 		      || __builtin_classify_type (__real__ (Val)) != 8)	      \
 		     ? (__expr_is_real (Val)				      \
@@ -375,10 +462,12 @@
 		      __tgml(Fct) (Val)					      \
 		      : (__typeof__ (__real__ (__tgmath_real_type (Val)) 0))  \
 		      __tgml(Cfct) (Val))))
+#  define __TGMATH_UNARY_REAL_IMAG_RET_REAL_SAME(Val, Cfct)	\
+  __TGMATH_UNARY_REAL_IMAG_RET_REAL ((Val), Cfct, Cfct)
 
 /* XXX This definition has to be changed as soon as the compiler understands
    the imaginary keyword.  */
-# define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \
+#  define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \
      (__extension__ ((sizeof (__real__ (Val1)				      \
 			      + __real__ (Val2)) > sizeof (double)	      \
 		      && __builtin_classify_type (__real__ (Val1)	      \
@@ -418,6 +507,7 @@
 			: (__typeof ((__tgmath_complex_type (Val1)) 0	      \
 				   + (__tgmath_complex_type (Val2)) 0))	      \
 			  Cfct##f (Val1, Val2))))
+# endif /* !__HAVE_BUILTIN_TGMATH.  */
 #else
 # error "Unsupported compiler; you cannot use <tgmath.h>"
 #endif
@@ -654,7 +744,7 @@
 /* Absolute value, conjugates, and projection.  */
 
 /* Argument value of Z.  */
-#define carg(Val) __TGMATH_UNARY_REAL_IMAG_RET_REAL (Val, carg, carg)
+#define carg(Val) __TGMATH_UNARY_REAL_IMAG_RET_REAL_SAME (Val, carg)
 
 /* Complex conjugate of Z.  */
 #define conj(Val) __TGMATH_UNARY_IMAG (Val, conj)
@@ -666,9 +756,9 @@
 /* Decomposing complex values.  */
 
 /* Imaginary part of Z.  */
-#define cimag(Val) __TGMATH_UNARY_REAL_IMAG_RET_REAL (Val, cimag, cimag)
+#define cimag(Val) __TGMATH_UNARY_REAL_IMAG_RET_REAL_SAME (Val, cimag)
 
 /* Real part of Z.  */
-#define creal(Val) __TGMATH_UNARY_REAL_IMAG_RET_REAL (Val, creal, creal)
+#define creal(Val) __TGMATH_UNARY_REAL_IMAG_RET_REAL_SAME (Val, creal)
 
 #endif /* tgmath.h */