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) // { dg-warning "implicit" }
9 
10 float f;
11 double d;
12 int i;
13 long double ld;
14 _Complex float cf;
15 _Complex double cd;
16 _Complex long double cld;
17 size_t s;
18 
19 extern void varargs_fn (int, ...);
20 extern void double_fn (double);
21 extern float float_fn (void);
22 
23 void
usual_arithmetic_conversions(void)24 usual_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 "implicit" } */
33   local_f = f - d;           /* { dg-warning "implicit" } */
34   local_f = 1.0f * 1.0;      /* { dg-warning "implicit" } */
35   local_f = 1.0f / d;        /* { dg-warning "implicit" } */
36 
37   local_cf = cf + 1.0;       /* { dg-warning "implicit" } */
38   local_cf = cf - d;         /* { dg-warning "implicit" } */
39   local_cf = cf + 1.0 * ID;  /* { dg-message "in expansion of macro 'ID'" } */
40   local_cf = cf - cd;        /* { dg-warning "implicit" } */
41 
42   local_f = i ? f : d;       /* { dg-warning "implicit" } */
43   i = f == d;                /* { dg-warning "implicit" } */
44   i = d != f;                /* { dg-warning "implicit" } */
45 }
46 
47 void
default_argument_promotion(void)48 default_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 
58 void
casts(void)59 casts (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 
82 void
assignments(void)83 assignments (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 
92 void
non_evaluated(void)93 non_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