1/* { dg-do compile } */
2/* { dg-options "-Wdouble-promotion" } */
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 unprototyped_fn ();
20extern void varargs_fn (int, ...);
21extern void double_fn (double);
22extern float float_fn (void);
23
24void
25usual_arithmetic_conversions(void)
26{
27  float local_f;
28  _Complex float local_cf;
29
30  /* Values of type "float" are implicitly converted to "double" or
31     "long double" due to use in arithmetic with "double" or "long
32     double" operands.  */
33  local_f = f + 1.0;         /* { dg-warning "implicit" } */
34  local_f = f - d;           /* { dg-warning "implicit" } */
35  local_f = 1.0f * 1.0;      /* { dg-warning "implicit" } */
36  local_f = 1.0f / d;        /* { dg-warning "implicit" } */
37
38  local_cf = cf + 1.0;       /* { dg-warning "implicit" } */
39  local_cf = cf - d;         /* { dg-warning "implicit" } */
40  local_cf = cf + 1.0 * ID;  /* { dg-warning "implicit" } */
41  local_cf = cf - cd;        /* { dg-warning "implicit" } */
42
43  local_f = i ? f : d;       /* { dg-warning "implicit" } */
44  i = f == d;                /* { dg-warning "implicit" } */
45  i = d != f;                /* { dg-warning "implicit" } */
46}
47
48void
49default_argument_promotion (void)
50{
51  /* Because there is no prototype, "f" is promoted to "double".  */
52  unprototyped_fn (f); /* { dg-warning "implicit" } */
53  undeclared_fn (f);   /* { dg-warning "implicit" } */
54  /* Because "f" is part of the variable argument list, it is promoted
55     to "double".  */
56  varargs_fn (1, f);   /* { dg-warning "implicit" } */
57}
58
59/* There is no warning when an explicit cast is used to perform the
60   conversion.  */
61
62void
63casts (void)
64{
65  float local_f;
66  _Complex float local_cf;
67
68  local_f = (double)f + 1.0;                 /* { dg-bogus "implicit" } */
69  local_f = (double)f - d;                   /* { dg-bogus "implicit" } */
70  local_f = (double)1.0f + 1.0;              /* { dg-bogus "implicit" } */
71  local_f = (double)1.0f - d;                /* { dg-bogus "implicit" } */
72
73  local_cf = (_Complex double)cf + 1.0;      /* { dg-bogus "implicit" } */
74  local_cf = (_Complex double)cf - d;        /* { dg-bogus "implicit" } */
75  local_cf = (_Complex double)cf + 1.0 * ID; /* { dg-bogus "implicit" } */
76  local_cf = (_Complex double)cf - cd;       /* { dg-bogus "implicit" } */
77
78  local_f = i ? (double)f : d;               /* { dg-bogus "implicit" } */
79  i = (double)f == d;                        /* { dg-bogus "implicit" } */
80  i = d != (double)f;                        /* { dg-bogus "implicit" } */
81}
82
83/* There is no warning on conversions that occur in assignment (and
84   assignment-like) contexts.  */
85
86void
87assignments (void)
88{
89  d = f;           /* { dg-bogus "implicit" } */
90  double_fn (f);   /* { dg-bogus "implicit" } */
91  d = float_fn (); /* { dg-bogus "implicit" } */
92}
93
94/* There is no warning in non-evaluated contexts.  */
95
96void
97non_evaluated (void)
98{
99  s = sizeof (f + 1.0);             /* { dg-bogus "implicit" } */
100  s = __alignof__ (f + 1.0);        /* { dg-bogus "implicit" } */
101  d = (__typeof__(f + 1.0))f;       /* { dg-bogus "implicit" } */
102  s = sizeof (i ? f : d);           /* { dg-bogus "implicit" } */
103  s = sizeof (unprototyped_fn (f)); /* { dg-bogus "implicit" } */
104}
105