c841db60005a22f87a07709141131d29b46f6efb
[platform/upstream/glibc.git] / math / gen-tgmath-tests.py
1 #!/usr/bin/python3
2 # Generate tests for <tgmath.h> macros.
3 # Copyright (C) 2017-2022 Free Software Foundation, Inc.
4 # This file is part of the GNU C Library.
5 #
6 # The GNU C Library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
10 #
11 # The GNU C Library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with the GNU C Library; if not, see
18 # <https://www.gnu.org/licenses/>.
19
20 # As glibc does not support decimal floating point, the types to
21 # consider for generic parameters are standard and binary
22 # floating-point types, and integer types which are treated as double.
23 # The corresponding complex types may also be used (including complex
24 # integer types, which are a GNU extension, but are currently disabled
25 # here because they do not work properly with tgmath.h).
26
27 # The proposed resolution to TS 18661-1 DR#9
28 # <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2149.htm#dr_9>
29 # makes the <tgmath.h> rules for selecting a function to call
30 # correspond to the usual arithmetic conversions (applied successively
31 # to the arguments for generic parameters in order), which choose the
32 # type whose set of values contains that of the other type (undefined
33 # behavior if neither type's set of values is a superset of the
34 # other), with interchange types being preferred to standard types
35 # (long double, double, float), being preferred to extended types
36 # (_Float128x, _Float64x, _Float32x).
37
38 # For the standard and binary floating-point types supported by GCC 7
39 # on any platform, this means the resulting type is the last of the
40 # given types in one of the following orders, or undefined behavior if
41 # types with both ibm128 and binary128 representation are specified.
42
43 # If double = long double: _Float16, float, _Float32, _Float32x,
44 # double, long double, _Float64, _Float64x, _Float128.
45
46 # Otherwise: _Float16, float, _Float32, _Float32x, double, _Float64,
47 # _Float64x, long double, _Float128.
48
49 # We generate tests to verify the return type is exactly as expected.
50 # We also verify that the function called is real or complex as
51 # expected, and that it is called for the right floating-point format
52 # (but it is OK to call a double function instead of a long double one
53 # if they have the same format, for example).  For all the formats
54 # supported on any given configuration of glibc, the MANT_DIG value
55 # uniquely determines the format.
56
57 import string
58 import sys
59
60 class Type(object):
61     """A type that may be used as an argument for generic parameters."""
62
63     # All possible argument or result types.
64     all_types_list = []
65     # All argument types.
66     argument_types_list = []
67     # All real argument types.
68     real_argument_types_list = []
69     # Real argument types that correspond to a standard floating type
70     # (float, double or long double; not _FloatN or _FloatNx).
71     standard_real_argument_types_list = []
72     # Real argument types other than float, double and long double
73     # (i.e., those that are valid as arguments to narrowing macros
74     # returning _FloatN or _FloatNx).
75     non_standard_real_argument_types_list = []
76     # The real floating types by their order properties (which are
77     # tuples giving the positions in both the possible orders above).
78     real_types_order = {}
79     # The type double.
80     double_type = None
81     # The type long double.
82     long_double_type = None
83     # The type _Complex double.
84     complex_double_type = None
85     # The type _Float64.
86     float64_type = None
87     # The type _Complex _Float64.
88     complex_float64_type = None
89     # The type _Float64x.
90     float64x_type = None
91     # The type _Float64x if available, otherwise _Float64.
92     float32x_ext_type = None
93
94     def __init__(self, name, suffix=None, mant_dig=None, condition='1',
95                  order=None, integer=False, complex=False, real_type=None):
96         """Initialize a Type object, creating any corresponding complex type
97         in the process."""
98         self.name = name
99         self.suffix = suffix
100         self.mant_dig = mant_dig
101         self.condition = condition
102         self.order = order
103         self.integer = integer
104         self.complex = complex
105         if complex:
106             self.complex_type = self
107             self.real_type = real_type
108         else:
109             # complex_type filled in by the caller once created.
110             self.complex_type = None
111             self.real_type = self
112
113     def register_type(self, internal):
114         """Record a type in the lists of all types."""
115         Type.all_types_list.append(self)
116         if not internal:
117             Type.argument_types_list.append(self)
118             if not self.complex:
119                 Type.real_argument_types_list.append(self)
120                 if not self.name.startswith('_Float'):
121                     Type.standard_real_argument_types_list.append(self)
122                 if self.name not in ('float', 'double', 'long double'):
123                     Type.non_standard_real_argument_types_list.append(self)
124         if self.order is not None:
125             Type.real_types_order[self.order] = self
126         if self.name == 'double':
127             Type.double_type = self
128         if self.name == 'long double':
129             Type.long_double_type = self
130         if self.name == '_Complex double':
131             Type.complex_double_type = self
132         if self.name == '_Float64':
133             Type.float64_type = self
134         if self.name == '_Complex _Float64':
135             Type.complex_float64_type = self
136         if self.name == '_Float64x':
137             Type.float64x_type = self
138         if self.name == 'Float32x_ext':
139             Type.float32x_ext_type = self
140
141     @staticmethod
142     def create_type(name, suffix=None, mant_dig=None, condition='1', order=None,
143                     integer=False, complex_name=None, complex_ok=True,
144                     internal=False):
145         """Create and register a Type object for a real type, creating any
146         corresponding complex type in the process."""
147         real_type = Type(name, suffix=suffix, mant_dig=mant_dig,
148                          condition=condition, order=order, integer=integer,
149                          complex=False)
150         if complex_ok:
151             if complex_name is None:
152                 complex_name = '_Complex %s' % name
153             complex_type = Type(complex_name, condition=condition,
154                                 integer=integer, complex=True,
155                                 real_type=real_type)
156         else:
157             complex_type = None
158         real_type.complex_type = complex_type
159         real_type.register_type(internal)
160         if complex_type is not None:
161             complex_type.register_type(internal)
162
163     def floating_type(self, floatn):
164         """Return the corresponding floating type."""
165         if self.integer:
166             if floatn:
167                 return (Type.complex_float64_type
168                         if self.complex
169                         else Type.float64_type)
170             else:
171                 return (Type.complex_double_type
172                         if self.complex
173                         else Type.double_type)
174         else:
175             return self
176
177     def real_floating_type(self, floatn):
178         """Return the corresponding real floating type."""
179         return self.real_type.floating_type(floatn)
180
181     def __str__(self):
182         """Return string representation of a type."""
183         return self.name
184
185     @staticmethod
186     def init_types():
187         """Initialize all the known types."""
188         Type.create_type('_Float16', 'f16', 'FLT16_MANT_DIG',
189                          complex_name='__CFLOAT16',
190                          condition='defined HUGE_VAL_F16', order=(0, 0))
191         Type.create_type('float', 'f', 'FLT_MANT_DIG', order=(1, 1))
192         Type.create_type('_Float32', 'f32', 'FLT32_MANT_DIG',
193                          complex_name='__CFLOAT32',
194                          condition='defined HUGE_VAL_F32', order=(2, 2))
195         Type.create_type('_Float32x', 'f32x', 'FLT32X_MANT_DIG',
196                          complex_name='__CFLOAT32X',
197                          condition='defined HUGE_VAL_F32X', order=(3, 3))
198         Type.create_type('double', '', 'DBL_MANT_DIG', order=(4, 4))
199         Type.create_type('long double', 'l', 'LDBL_MANT_DIG', order=(5, 7))
200         Type.create_type('_Float64', 'f64', 'FLT64_MANT_DIG',
201                          complex_name='__CFLOAT64',
202                          condition='defined HUGE_VAL_F64', order=(6, 5))
203         Type.create_type('_Float64x', 'f64x', 'FLT64X_MANT_DIG',
204                          complex_name='__CFLOAT64X',
205                          condition='defined HUGE_VAL_F64X', order=(7, 6))
206         Type.create_type('_Float128', 'f128', 'FLT128_MANT_DIG',
207                          complex_name='__CFLOAT128',
208                          condition='defined HUGE_VAL_F128', order=(8, 8))
209         Type.create_type('char', integer=True)
210         Type.create_type('signed char', integer=True)
211         Type.create_type('unsigned char', integer=True)
212         Type.create_type('short int', integer=True)
213         Type.create_type('unsigned short int', integer=True)
214         Type.create_type('int', integer=True)
215         Type.create_type('unsigned int', integer=True)
216         Type.create_type('long int', integer=True)
217         Type.create_type('unsigned long int', integer=True)
218         Type.create_type('long long int', integer=True)
219         Type.create_type('unsigned long long int', integer=True)
220         Type.create_type('__int128', integer=True,
221                          condition='defined __SIZEOF_INT128__')
222         Type.create_type('unsigned __int128', integer=True,
223                          condition='defined __SIZEOF_INT128__')
224         Type.create_type('enum e', integer=True, complex_ok=False)
225         Type.create_type('_Bool', integer=True, complex_ok=False)
226         Type.create_type('bit_field', integer=True, complex_ok=False)
227         # Internal types represent the combination of long double with
228         # _Float64 or _Float64x, for which the ordering depends on
229         # whether long double has the same format as double.
230         Type.create_type('long_double_Float64', None, 'LDBL_MANT_DIG',
231                          complex_name='complex_long_double_Float64',
232                          condition='defined HUGE_VAL_F64', order=(6, 7),
233                          internal=True)
234         Type.create_type('long_double_Float64x', None, 'FLT64X_MANT_DIG',
235                          complex_name='complex_long_double_Float64x',
236                          condition='defined HUGE_VAL_F64X', order=(7, 7),
237                          internal=True)
238         # An internal type for the argument type used by f32x*
239         # narrowing macros (_Float64x if available, otherwise
240         # _Float64).
241         Type.create_type('Float32x_ext', None, 'FLT32X_EXT_MANT_DIG',
242                          complex_name='complex_Float32x_ext',
243                          condition='1', internal=True)
244
245     @staticmethod
246     def can_combine_types(types, floatn):
247         """Return a C preprocessor conditional for whether the given list of
248         types can be used together as type-generic macro arguments."""
249         have_long_double = False
250         have_float128 = False
251         for t in types:
252             t = t.real_floating_type(floatn)
253             if t.name == 'long double':
254                 have_long_double = True
255             if t.name == '_Float128' or t.name == '_Float64x':
256                 have_float128 = True
257         if have_long_double and have_float128:
258             # If ibm128 format is in use for long double, both
259             # _Float64x and _Float128 are binary128 and the types
260             # cannot be combined.
261             return '(LDBL_MANT_DIG != 106)'
262         return '1'
263
264     @staticmethod
265     def combine_types(types, floatn):
266         """Return the result of combining a set of types."""
267         have_complex = False
268         combined = None
269         for t in types:
270             if t.complex:
271                 have_complex = True
272             t = t.real_floating_type(floatn)
273             if combined is None:
274                 combined = t
275             else:
276                 order = (max(combined.order[0], t.order[0]),
277                          max(combined.order[1], t.order[1]))
278                 combined = Type.real_types_order[order]
279         return combined.complex_type if have_complex else combined
280
281 def list_product_initial(initial, lists):
282     """Return a list of lists, with an initial sequence from the first
283     argument (a list of lists) followed by each sequence of one
284     element from each successive element of the second argument."""
285     if not lists:
286         return initial
287     return list_product_initial([a + [b] for a in initial for b in lists[0]],
288                                 lists[1:])
289
290 def list_product(lists):
291     """Return a list of lists, with each sequence of one element from each
292     successive element of the argument."""
293     return list_product_initial([[]], lists)
294
295 try:
296     trans_id = str.maketrans(' *', '_p')
297 except AttributeError:
298     trans_id = string.maketrans(' *', '_p')
299 def var_for_type(name):
300     """Return the name of a variable with a given type (name)."""
301     return 'var_%s' % name.translate(trans_id)
302
303 def vol_var_for_type(name):
304     """Return the name of a variable with a given volatile type (name)."""
305     return 'vol_var_%s' % name.translate(trans_id)
306
307 def define_vars_for_type(name):
308     """Return the definitions of variables with a given type (name)."""
309     if name == 'bit_field':
310         struct_vars = define_vars_for_type('struct s');
311         return '%s#define %s %s.bf\n' % (struct_vars,
312                                          vol_var_for_type(name),
313                                          vol_var_for_type('struct s'))
314     return ('%s %s __attribute__ ((unused));\n'
315             '%s volatile %s __attribute__ ((unused));\n'
316             % (name, var_for_type(name), name, vol_var_for_type(name)))
317
318 def if_cond_text(conds, text):
319     """Return the result of making some text conditional under #if.  The
320     text ends with a newline, as does the return value if not empty."""
321     if '0' in conds:
322         return ''
323     conds = [c for c in conds if c != '1']
324     conds = sorted(set(conds))
325     if not conds:
326         return text
327     return '#if %s\n%s#endif\n' % (' && '.join(conds), text)
328
329 class Tests(object):
330     """The state associated with testcase generation."""
331
332     def __init__(self):
333         """Initialize a Tests object."""
334         self.header_list = ['#define __STDC_WANT_IEC_60559_TYPES_EXT__\n'
335                             '#include <float.h>\n'
336                             '#include <stdbool.h>\n'
337                             '#include <stdint.h>\n'
338                             '#include <stdio.h>\n'
339                             '#include <string.h>\n'
340                             '#include <tgmath.h>\n'
341                             '\n'
342                             'struct test\n'
343                             '  {\n'
344                             '    void (*func) (void);\n'
345                             '    const char *func_name;\n'
346                             '    const char *test_name;\n'
347                             '    int mant_dig;\n'
348                             '    int narrow_mant_dig;\n'
349                             '  };\n'
350                             'int num_pass, num_fail;\n'
351                             'volatile int called_mant_dig;\n'
352                             'const char *volatile called_func_name;\n'
353                             'enum e { E, F };\n'
354                             'struct s\n'
355                             '  {\n'
356                             '    int bf:2;\n'
357                             '  };\n']
358         float64_text = ('# if LDBL_MANT_DIG == DBL_MANT_DIG\n'
359                         'typedef _Float64 long_double_Float64;\n'
360                         'typedef __CFLOAT64 complex_long_double_Float64;\n'
361                         '# else\n'
362                         'typedef long double long_double_Float64;\n'
363                         'typedef _Complex long double '
364                         'complex_long_double_Float64;\n'
365                         '# endif\n')
366         float64_text = if_cond_text([Type.float64_type.condition],
367                                     float64_text)
368         float64x_text = ('# if LDBL_MANT_DIG == DBL_MANT_DIG\n'
369                          'typedef _Float64x long_double_Float64x;\n'
370                          'typedef __CFLOAT64X complex_long_double_Float64x;\n'
371                          '# else\n'
372                          'typedef long double long_double_Float64x;\n'
373                          'typedef _Complex long double '
374                          'complex_long_double_Float64x;\n'
375                          '# endif\n')
376         float64x_text = if_cond_text([Type.float64x_type.condition],
377                                      float64x_text)
378         float32x_ext_text = ('#ifdef HUGE_VAL_F64X\n'
379                              'typedef _Float64x Float32x_ext;\n'
380                              'typedef __CFLOAT64X complex_Float32x_ext;\n'
381                              '# define FLT32X_EXT_MANT_DIG FLT64X_MANT_DIG\n'
382                              '#else\n'
383                              'typedef _Float64 Float32x_ext;\n'
384                              'typedef __CFLOAT64 complex_Float32x_ext;\n'
385                              '# define FLT32X_EXT_MANT_DIG FLT64_MANT_DIG\n'
386                              '#endif\n')
387         self.header_list.append(float64_text)
388         self.header_list.append(float64x_text)
389         self.header_list.append(float32x_ext_text)
390         self.types_seen = set()
391         for t in Type.all_types_list:
392             self.add_type_var(t.name, t.condition)
393         self.test_text_list = []
394         self.test_array_list = []
395         self.macros_seen = set()
396
397     def add_type_var(self, name, cond):
398         """Add declarations of variables for a type."""
399         if name in self.types_seen:
400             return
401         t_vars = define_vars_for_type(name)
402         self.header_list.append(if_cond_text([cond], t_vars))
403         self.types_seen.add(name)
404
405     def add_tests(self, macro, ret, args, complex_func=None):
406         """Add tests for a given tgmath.h macro, if that is the macro for
407         which tests are to be generated; otherwise just add it to the
408         list of macros for which test generation is supported."""
409         # 'c' means the function argument or return type is
410         # type-generic and complex only (a complex function argument
411         # may still have a real macro argument).  'g' means it is
412         # type-generic and may be real or complex; 'r' means it is
413         # type-generic and may only be real; 's' means the same as
414         # 'r', but restricted to float, double and long double.
415         self.macros_seen.add(macro)
416         if macro != self.macro:
417             return
418         have_complex = False
419         func = macro
420         narrowing = False
421         narrowing_std = False
422         if ret == 'c' or 'c' in args:
423             # Complex-only.
424             have_complex = True
425             complex_func = func
426             func = None
427         elif ret == 'g' or 'g' in args:
428             # Real and complex.
429             have_complex = True
430             if complex_func == None:
431                 complex_func = 'c%s' % func
432         # For narrowing macros, compute narrow_args, the list of
433         # argument types for which there is an actual corresponding
434         # function.  If none of those types exist, or the return type
435         # does not exist, then the macro is not defined and no tests
436         # of it can be run.
437         if ret == 'float':
438             narrowing = True
439             narrowing_std = True
440             narrow_cond = '1'
441             narrow_args = [Type.double_type, Type.long_double_type]
442             narrow_fallback = Type.double_type
443         elif ret == 'double':
444             narrowing = True
445             narrowing_std = True
446             narrow_cond = '1'
447             narrow_args = [Type.long_double_type]
448             narrow_fallback = Type.long_double_type
449         elif ret.startswith('_Float'):
450             narrowing = True
451             narrow_args = []
452             nret_type = None
453             narrow_fallback = None
454             for order, real_type in sorted(Type.real_types_order.items()):
455                 if real_type.name == ret:
456                     nret_type = real_type
457                 elif nret_type and real_type.name.startswith('_Float'):
458                     narrow_args.append(real_type)
459                     if (narrow_fallback is None
460                         and ret.endswith('x') == real_type.name.endswith('x')):
461                         narrow_fallback = real_type
462             if narrow_args:
463                 narrow_cond = ('(%s && (%s))'
464                                % (nret_type.condition,
465                                   ' || '.join(t.condition
466                                               for t in narrow_args)))
467                 if narrow_fallback is None:
468                     narrow_fallback = narrow_args[0]
469                 if ret == '_Float32x':
470                     narrow_fallback = Type.float32x_ext_type
471             else:
472                 # No possible argument types, even conditionally.
473                 narrow_cond = '0'
474         narrowing_nonstd = narrowing and not narrowing_std
475         types = [ret] + args
476         for t in types:
477             if t != 'c' and t != 'g' and t != 'r' and t != 's':
478                 self.add_type_var(t, '1')
479         for t in Type.argument_types_list:
480             if t.integer:
481                 continue
482             if t.complex and not have_complex:
483                 continue
484             if func == None and not t.complex:
485                 continue
486             if ret == 's' and t.name.startswith('_Float'):
487                 continue
488             if narrowing and t not in narrow_args:
489                 continue
490             if ret == 'c':
491                 ret_name = t.complex_type.name
492             elif ret == 'g':
493                 ret_name = t.name
494             elif ret == 'r' or ret == 's':
495                 ret_name = t.real_type.name
496             else:
497                 ret_name = ret
498             dummy_func_name = complex_func if t.complex else func
499             arg_list = []
500             arg_num = 0
501             for a in args:
502                 if a == 'c':
503                     arg_name = t.complex_type.name
504                 elif a == 'g':
505                     arg_name = t.name
506                 elif a == 'r' or a == 's':
507                     arg_name = t.real_type.name
508                 else:
509                     arg_name = a
510                 arg_list.append('%s arg%d __attribute__ ((unused))'
511                                 % (arg_name, arg_num))
512                 arg_num += 1
513             dummy_func = ('%s\n'
514                           '(%s%s) (%s)\n'
515                           '{\n'
516                           '  called_mant_dig = %s;\n'
517                           '  called_func_name = "%s";\n'
518                           '  return 0;\n'
519                           '}\n' % (ret_name, dummy_func_name,
520                                    t.real_type.suffix, ', '.join(arg_list),
521                                    t.real_type.mant_dig, dummy_func_name))
522             if narrowing:
523                 dummy_cond = [narrow_cond, t.condition]
524             else:
525                 dummy_cond = [t.condition]
526             dummy_func = if_cond_text(dummy_cond, dummy_func)
527             self.test_text_list.append(dummy_func)
528         arg_types = []
529         for t in args:
530             if t == 'g' or t == 'c':
531                 arg_types.append(Type.argument_types_list)
532             elif t == 'r':
533                 if narrowing_std:
534                     arg_types.append(Type.standard_real_argument_types_list)
535                 elif narrowing:
536                     arg_types.append(
537                         Type.non_standard_real_argument_types_list)
538                 else:
539                     arg_types.append(Type.real_argument_types_list)
540             elif t == 's':
541                 arg_types.append(Type.standard_real_argument_types_list)
542         arg_types_product = list_product(arg_types)
543         test_num = 0
544         for this_args in arg_types_product:
545             comb_type = Type.combine_types(this_args, narrowing_nonstd)
546             if narrowing:
547                 # As long as there are no integer arguments, and as
548                 # long as the chosen argument type is as wide as all
549                 # the floating-point arguments passed, the semantics
550                 # of the macro call do not depend on the exact
551                 # function chosen.  In particular, for f32x functions
552                 # when _Float64x exists, the chosen type should differ
553                 # for _Float32x and _Float64 arguments, but it is not
554                 # always possible to distinguish those types before
555                 # GCC 7 and the implementation does not attempt to do
556                 # so before GCC 8.
557                 narrow_mant_dig = comb_type.real_type.mant_dig
558                 for arg_type in this_args:
559                     if arg_type.integer:
560                         narrow_mant_dig = 0
561             else:
562                 narrow_mant_dig = 0
563             if (narrowing
564                 and comb_type not in narrow_args
565                 and narrow_fallback is not None):
566                 comb_type = narrow_fallback
567             can_comb = Type.can_combine_types(this_args, narrowing_nonstd)
568             all_conds = [t.condition for t in this_args]
569             all_conds.append(can_comb)
570             if narrowing:
571                 all_conds.append(narrow_cond)
572             any_complex = func == None
573             for t in this_args:
574                 if t.complex:
575                     any_complex = True
576             func_name = complex_func if any_complex else func
577             test_name = '%s (%s)' % (macro,
578                                      ', '.join([t.name for t in this_args]))
579             test_func_name = 'test_%s_%d' % (macro, test_num)
580             test_num += 1
581             mant_dig = comb_type.real_type.mant_dig
582             test_text = '%s, "%s", "%s", %s, %s' % (test_func_name, func_name,
583                                                     test_name, mant_dig,
584                                                     narrow_mant_dig)
585             test_text = '    { %s },\n' % test_text
586             test_text = if_cond_text(all_conds, test_text)
587             self.test_array_list.append(test_text)
588             call_args = []
589             call_arg_pos = 0
590             for t in args:
591                 if t == 'g' or t == 'c' or t == 'r' or t == 's':
592                     type = this_args[call_arg_pos].name
593                     call_arg_pos += 1
594                 else:
595                     type = t
596                 call_args.append(vol_var_for_type(type))
597             call_args_text = ', '.join(call_args)
598             if ret == 'g':
599                 ret_type = comb_type.name
600             elif ret == 'r' or ret == 's':
601                 ret_type = comb_type.real_type.name
602             elif ret == 'c':
603                 ret_type = comb_type.complex_type.name
604             else:
605                 ret_type = ret
606             call_text = '%s (%s)' % (macro, call_args_text)
607             test_func_text = ('static void\n'
608                               '%s (void)\n'
609                               '{\n'
610                               '  extern typeof (%s) %s '
611                               '__attribute__ ((unused));\n'
612                               '  %s = %s;\n'
613                               '}\n' % (test_func_name, call_text,
614                                        var_for_type(ret_type),
615                                        vol_var_for_type(ret_type), call_text))
616             test_func_text = if_cond_text(all_conds, test_func_text)
617             self.test_text_list.append(test_func_text)
618
619     def add_all_tests(self, macro):
620         """Add tests for the given tgmath.h macro, if any, and generate the
621         list of all supported macros."""
622         self.macro = macro
623         # C99/C11 real-only functions.
624         self.add_tests('atan2', 'r', ['r', 'r'])
625         self.add_tests('cbrt', 'r', ['r'])
626         self.add_tests('ceil', 'r', ['r'])
627         self.add_tests('copysign', 'r', ['r', 'r'])
628         self.add_tests('erf', 'r', ['r'])
629         self.add_tests('erfc', 'r', ['r'])
630         self.add_tests('exp2', 'r', ['r'])
631         self.add_tests('expm1', 'r', ['r'])
632         self.add_tests('fdim', 'r', ['r', 'r'])
633         self.add_tests('floor', 'r', ['r'])
634         self.add_tests('fma', 'r', ['r', 'r', 'r'])
635         self.add_tests('fmax', 'r', ['r', 'r'])
636         self.add_tests('fmin', 'r', ['r', 'r'])
637         self.add_tests('fmod', 'r', ['r', 'r'])
638         self.add_tests('frexp', 'r', ['r', 'int *'])
639         self.add_tests('hypot', 'r', ['r', 'r'])
640         self.add_tests('ilogb', 'int', ['r'])
641         self.add_tests('ldexp', 'r', ['r', 'int'])
642         self.add_tests('lgamma', 'r', ['r'])
643         self.add_tests('llrint', 'long long int', ['r'])
644         self.add_tests('llround', 'long long int', ['r'])
645         # log10 is real-only in ISO C, but supports complex arguments
646         # as a GNU extension.
647         self.add_tests('log10', 'g', ['g'])
648         self.add_tests('log1p', 'r', ['r'])
649         self.add_tests('log2', 'r', ['r'])
650         self.add_tests('logb', 'r', ['r'])
651         self.add_tests('lrint', 'long int', ['r'])
652         self.add_tests('lround', 'long int', ['r'])
653         self.add_tests('nearbyint', 'r', ['r'])
654         self.add_tests('nextafter', 'r', ['r', 'r'])
655         self.add_tests('nexttoward', 's', ['s', 'long double'])
656         self.add_tests('remainder', 'r', ['r', 'r'])
657         self.add_tests('remquo', 'r', ['r', 'r', 'int *'])
658         self.add_tests('rint', 'r', ['r'])
659         self.add_tests('round', 'r', ['r'])
660         self.add_tests('scalbn', 'r', ['r', 'int'])
661         self.add_tests('scalbln', 'r', ['r', 'long int'])
662         self.add_tests('tgamma', 'r', ['r'])
663         self.add_tests('trunc', 'r', ['r'])
664         # C99/C11 real-and-complex functions.
665         self.add_tests('acos', 'g', ['g'])
666         self.add_tests('asin', 'g', ['g'])
667         self.add_tests('atan', 'g', ['g'])
668         self.add_tests('acosh', 'g', ['g'])
669         self.add_tests('asinh', 'g', ['g'])
670         self.add_tests('atanh', 'g', ['g'])
671         self.add_tests('cos', 'g', ['g'])
672         self.add_tests('sin', 'g', ['g'])
673         self.add_tests('tan', 'g', ['g'])
674         self.add_tests('cosh', 'g', ['g'])
675         self.add_tests('sinh', 'g', ['g'])
676         self.add_tests('tanh', 'g', ['g'])
677         self.add_tests('exp', 'g', ['g'])
678         self.add_tests('log', 'g', ['g'])
679         self.add_tests('pow', 'g', ['g', 'g'])
680         self.add_tests('sqrt', 'g', ['g'])
681         self.add_tests('fabs', 'r', ['g'], 'cabs')
682         # C99/C11 complex-only functions.
683         self.add_tests('carg', 'r', ['c'])
684         self.add_tests('cimag', 'r', ['c'])
685         self.add_tests('conj', 'c', ['c'])
686         self.add_tests('cproj', 'c', ['c'])
687         self.add_tests('creal', 'r', ['c'])
688         # TS 18661-1 functions.
689         self.add_tests('roundeven', 'r', ['r'])
690         self.add_tests('nextup', 'r', ['r'])
691         self.add_tests('nextdown', 'r', ['r'])
692         self.add_tests('fminmag', 'r', ['r', 'r'])
693         self.add_tests('fmaxmag', 'r', ['r', 'r'])
694         self.add_tests('llogb', 'long int', ['r'])
695         self.add_tests('fromfp', 'intmax_t', ['r', 'int', 'unsigned int'])
696         self.add_tests('fromfpx', 'intmax_t', ['r', 'int', 'unsigned int'])
697         self.add_tests('ufromfp', 'uintmax_t', ['r', 'int', 'unsigned int'])
698         self.add_tests('ufromfpx', 'uintmax_t', ['r', 'int', 'unsigned int'])
699         for fn, args in (('add', 2), ('div', 2), ('fma', 3), ('mul', 2),
700                          ('sqrt', 1), ('sub', 2)):
701             for ret, prefix in (('float', 'f'),
702                                 ('double', 'd'),
703                                 ('_Float16', 'f16'),
704                                 ('_Float32', 'f32'),
705                                 ('_Float64', 'f64'),
706                                 ('_Float128', 'f128'),
707                                 ('_Float32x', 'f32x'),
708                                 ('_Float64x', 'f64x')):
709                 self.add_tests(prefix + fn, ret, ['r'] * args)
710         # TS 18661-4 functions.
711         self.add_tests('exp10', 'r', ['r'])
712         # C2X functions.
713         self.add_tests('fmaximum', 'r', ['r', 'r'])
714         self.add_tests('fmaximum_mag', 'r', ['r', 'r'])
715         self.add_tests('fmaximum_num', 'r', ['r', 'r'])
716         self.add_tests('fmaximum_mag_num', 'r', ['r', 'r'])
717         self.add_tests('fminimum', 'r', ['r', 'r'])
718         self.add_tests('fminimum_mag', 'r', ['r', 'r'])
719         self.add_tests('fminimum_num', 'r', ['r', 'r'])
720         self.add_tests('fminimum_mag_num', 'r', ['r', 'r'])
721         # Miscellaneous functions.
722         self.add_tests('scalb', 's', ['s', 's'])
723
724     def tests_text(self):
725         """Return the text of the generated testcase."""
726         test_list = [''.join(self.test_text_list),
727                      'static const struct test tests[] =\n'
728                      '  {\n',
729                      ''.join(self.test_array_list),
730                      '  };\n']
731         footer_list = ['static int\n'
732                        'do_test (void)\n'
733                        '{\n'
734                        '  for (size_t i = 0;\n'
735                        '       i < sizeof (tests) / sizeof (tests[0]);\n'
736                        '       i++)\n'
737                        '    {\n'
738                        '      called_mant_dig = 0;\n'
739                        '      called_func_name = "";\n'
740                        '      tests[i].func ();\n'
741                        '      if (called_mant_dig == tests[i].mant_dig\n'
742                        '          && strcmp (called_func_name,\n'
743                        '                     tests[i].func_name) == 0)\n'
744                        '        num_pass++;\n'
745                        '#if !__GNUC_PREREQ (8, 0)\n'
746                        '      else if (tests[i].narrow_mant_dig > 0\n'
747                        '               && (called_mant_dig\n'
748                        '                   >= tests[i].narrow_mant_dig)\n'
749                        '               && strcmp (called_func_name,\n'
750                        '                          tests[i].func_name) == 0)\n'
751                        '        {\n'
752                        '          num_pass++;\n'
753                        '          printf ("Test %zu (%s):\\n"\n'
754                        '                  "  Expected: %s precision %d\\n"\n'
755                        '                  "  Actual: %s precision %d\\n"\n'
756                        '                  "  (OK with old GCC)\\n\\n",\n'
757                        '                  i, tests[i].test_name,\n'
758                        '                  tests[i].func_name,\n'
759                        '                  tests[i].mant_dig,\n'
760                        '                  called_func_name, called_mant_dig);\n'
761                        '        }\n'
762                        '#endif\n'
763                        '      else\n'
764                        '        {\n'
765                        '          num_fail++;\n'
766                        '          printf ("Test %zu (%s):\\n"\n'
767                        '                  "  Expected: %s precision %d\\n"\n'
768                        '                  "  Actual: %s precision %d\\n\\n",\n'
769                        '                  i, tests[i].test_name,\n'
770                        '                  tests[i].func_name,\n'
771                        '                  tests[i].mant_dig,\n'
772                        '                  called_func_name, called_mant_dig);\n'
773                        '        }\n'
774                        '    }\n'
775                        '  printf ("%d pass, %d fail\\n", num_pass, num_fail);\n'
776                        '  return num_fail != 0;\n'
777                        '}\n'
778                        '\n'
779                        '#include <support/test-driver.c>']
780         return ''.join(self.header_list + test_list + footer_list)
781
782     def check_macro_list(self, macro_list):
783         """Check the list of macros that can be tested."""
784         if self.macros_seen != set(macro_list):
785             print('error: macro list mismatch')
786             sys.exit(1)
787
788 def main():
789     """The main entry point."""
790     Type.init_types()
791     t = Tests()
792     if sys.argv[1] == 'check-list':
793         macro = None
794         macro_list = sys.argv[2:]
795     else:
796         macro = sys.argv[1]
797         macro_list = []
798     t.add_all_tests(macro)
799     if macro:
800         print(t.tests_text())
801     else:
802         t.check_macro_list(macro_list)
803
804 if __name__ == '__main__':
805     main()