1/* { dg-do compile } */
2/* { dg-options "-Wdouble-promotion -ftrack-macro-expansion=2" } */
3
4#include <stddef.h>
5
6/* Some targets do not provide <complex.h> so we define I ourselves.  */
7#define I 1.0iF
8#define ID ((_Complex double)I)
9
10float f;
11double d;
12int i;
13long double ld;
14_Complex float cf;
15_Complex double cd;
16_Complex long double cld;
17size_t s;
18
19extern void varargs_fn (int, ...);
20extern void double_fn (double);
21extern float float_fn (void);
22
23void
24usual_arithmetic_conversions(void)
25{
26  float local_f;
27  _Complex float local_cf;
28
29  /* Values of type "float" are implicitly converted to "double" or
30     "long double" due to use in arithmetic with "double" or "long
31     double" operands.  */
32  local_f = f + 1.0;         /* { dg-warning "15:implicit" } */
33  local_f = f - d;           /* { dg-warning "15:implicit" } */
34  local_f = 1.0f * 1.0;      /* { dg-warning "18:implicit" } */
35  local_f = 1.0f / d;        /* { dg-warning "18:implicit" } */
36
37  local_cf = cf + 1.0;       /* { dg-warning "17:implicit" } */
38  local_cf = cf - d;         /* { dg-warning "17:implicit" } */
39  local_cf = cf + 1.0 * ID;  /* { dg-warning "17:implicit" } */
40  local_cf = cf - cd;        /* { dg-warning "17:implicit" } */
41
42  local_f = i ? f : d;       /* { dg-warning "15:implicit" } */
43  i = f == d;                /* { dg-warning "9:implicit" } */
44  i = d != f;                /* { dg-warning "9:implicit" } */
45}
46
47void
48default_argument_promotion (void)
49{
50  /* Because "f" is part of the variable argument list, it is promoted
51     to "double".  */
52  varargs_fn (1, f);   /* { dg-warning "implicit" } */
53}
54
55/* There is no warning when an explicit cast is used to perform the
56   conversion.  */
57
58void
59casts (void)
60{
61  float local_f;
62  _Complex float local_cf;
63
64  local_f = (double)f + 1.0;                 /* { dg-bogus "implicit" } */
65  local_f = (double)f - d;                   /* { dg-bogus "implicit" } */
66  local_f = (double)1.0f + 1.0;              /* { dg-bogus "implicit" } */
67  local_f = (double)1.0f - d;                /* { dg-bogus "implicit" } */
68
69  local_cf = (_Complex double)cf + 1.0;      /* { dg-bogus "implicit" } */
70  local_cf = (_Complex double)cf - d;        /* { dg-bogus "implicit" } */
71  local_cf = (_Complex double)cf + 1.0 * ID; /* { dg-bogus "implicit" } */
72  local_cf = (_Complex double)cf - cd;       /* { dg-bogus "implicit" } */
73
74  local_f = i ? (double)f : d;               /* { dg-bogus "implicit" } */
75  i = (double)f == d;                        /* { dg-bogus "implicit" } */
76  i = d != (double)f;                        /* { dg-bogus "implicit" } */
77}
78
79/* There is no warning on conversions that occur in assignment (and
80   assignment-like) contexts.  */
81
82void
83assignments (void)
84{
85  d = f;           /* { dg-bogus "implicit" } */
86  double_fn (f);   /* { dg-bogus "implicit" } */
87  d = float_fn (); /* { dg-bogus "implicit" } */
88}
89
90/* There is no warning in non-evaluated contexts.  */
91
92void
93non_evaluated (void)
94{
95  s = sizeof (f + 1.0);             /* { dg-bogus "implicit" } */
96  s = __alignof__ (f + 1.0);        /* { dg-bogus "implicit" } */
97  d = (__typeof__(f + 1.0))f;       /* { dg-bogus "implicit" } */
98  s = sizeof (i ? f : d);           /* { dg-bogus "implicit" } */
99}
100