elf: Fix use-after-free in ldconfig [BZ #26779]
[glibc.git] / math / gen-tgmath-tests.py
blobc841db60005a22f87a07709141131d29b46f6efb
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.
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.
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.
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/>.
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).
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).
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.
43 # If double = long double: _Float16, float, _Float32, _Float32x,
44 # double, long double, _Float64, _Float64x, _Float128.
46 # Otherwise: _Float16, float, _Float32, _Float32x, double, _Float64,
47 # _Float64x, long double, _Float128.
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.
57 import string
58 import sys
60 class Type(object):
61 """A type that may be used as an argument for generic parameters."""
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
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
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
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)
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
177 def real_floating_type(self, floatn):
178 """Return the corresponding real floating type."""
179 return self.real_type.floating_type(floatn)
181 def __str__(self):
182 """Return string representation of a type."""
183 return self.name
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)
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'
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
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:])
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)
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)
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)
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)))
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)
329 class Tests(object):
330 """The state associated with testcase generation."""
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()
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)
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)
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'])
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)
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)
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)
804 if __name__ == '__main__':
805 main()