1 extern void abort (void);
2 
3 /* { dg-options "-O2" } */
4 /* { dg-do run } */
5 /* { dg-require-effective-target int32plus } */
6 
7 #define TYPE_MAX(type, sign)	\
8   ((!sign) ? ((1 << (sizeof (type) * 8 - 1)) - 1) :	\
9    ((1 << (sizeof (type) * 8)) - 1))
10 #define TYPE_MIN(type, sign)	\
11   ((!sign) ? -(1 << (sizeof (type) * 8 - 1)) : 0)
12 
13 #define TEST_FN(NAME, ARG_TYPE, RET_TYPE, CAST_TYPE, VAL, VR_MIN, VR_MAX)\
14   __attribute__((noinline, noclone)) RET_TYPE				\
15       NAME (ARG_TYPE arg){						\
16       RET_TYPE ret = VAL;						\
17       if (arg + 1 < VR_MIN || arg + 1 > VR_MAX) return ret;		\
18       /* Value Range of arg at this point will be  [VR_min, VR_max].  */\
19       arg = arg + VAL;							\
20       ret = (CAST_TYPE)arg;						\
21       return arg;							\
22   }
23 
24 /* Signed to signed conversion with value in-range.  */
25 TEST_FN (foo1, short, short, char, 1, TYPE_MIN (char, 0), TYPE_MAX (char, 0));
26 TEST_FN (foo2, short, short, char, 1, TYPE_MIN (char, 0) + 1,\
27 	TYPE_MAX (char, 0) - 1);
28 
29 /* Signed to signed conversion with value not in-range.  */
30 TEST_FN (foo3, short, short, char, -1, TYPE_MIN (short, 0) + 1,  100);
31 TEST_FN (foo4, short, short, char, 1, 12, TYPE_MAX (short, 0) + 1);
32 
33 /* Unsigned to unsigned conversion with value in-range.  */
34 TEST_FN (foo5, unsigned short, unsigned short, unsigned char, 1,\
35 	TYPE_MIN (char, 1) + 1, TYPE_MAX (char, 1) - 1);
36 TEST_FN (foo6, unsigned short, unsigned short, unsigned char, 1,\
37 	TYPE_MIN (char, 1), TYPE_MAX (char, 1));
38 
39 /* Unsigned to unsigned conversion with value not in-range.  */
40 TEST_FN (foo7, unsigned short, unsigned short, unsigned char, 1,\
41 	TYPE_MIN (short, 1) + 1, TYPE_MAX (short, 1) - 1);
42 TEST_FN (foo8, unsigned short, unsigned short, unsigned char, 1,\
43 	TYPE_MIN (short, 1), TYPE_MAX (short, 1));
44 
45 /* Signed to unsigned conversion with value range positive.  */
46 TEST_FN (foo9, short, short, unsigned char, -1, 1,\
47 	TYPE_MAX (char, 1) - 1);
48 TEST_FN (foo10, short, short, unsigned char, 1, 0,\
49 	TYPE_MAX (char, 1));
50 
51 /* Signed to unsigned conversion with value range negative.  */
52 TEST_FN (foo11, short, short, unsigned char, 1,\
53 	TYPE_MIN (char, 0) + 1, TYPE_MAX (char, 0) - 1);
54 TEST_FN (foo12, short, short, unsigned char, 1,\
55 	TYPE_MIN (char, 0), TYPE_MAX (char, 0));
56 
57 /* Unsigned to Signed conversion with value range in signed equiv range.  */
58 TEST_FN (foo13, unsigned short, unsigned short, char, 1,\
59 	TYPE_MIN (char, 1) + 1, TYPE_MAX (char, 0) - 1);
60 TEST_FN (foo14, unsigned short, unsigned short, char, 1,\
61 	TYPE_MIN (char, 1), TYPE_MAX (char, 0));
62 
63 /* Unsigned to Signed conversion with value range not-in signed range.  */
64 TEST_FN (foo15, unsigned short, unsigned short, char, 1,\
65 	TYPE_MIN (char, 1) + 1, TYPE_MAX (char, 1) - 1);
66 TEST_FN (foo16, unsigned short, unsigned short, char, 1,\
67 	TYPE_MIN (char, 1), TYPE_MAX (char, 1));
68 
main()69 int main ()
70 {
71   /* Signed to signed conversion with value in-range.  */
72   /* arg + 1.  */
73   if (foo1 (-32) != -31)
74     abort ();
75   /* arg + 1.  */
76   if (foo2 (32) != 33)
77     abort ();
78 
79   /* Signed to signed conversion with value not in-range.  */
80   /* arg - 1.  */
81   if (foo3 (-512) != -513)
82     abort ();
83   /* arg + 1.  */
84   if (foo4 (512) != 513)
85     abort ();
86 
87   /* Unsigned to unsigned conversion with value in-range.  */
88   /* arg + 1.  */
89   if (foo5 (64) != 65)
90     abort ();
91   /* arg + 1.  */
92   if (foo6 (64) != 65)
93     abort ();
94 
95   /* Unsigned to unsigned conversion with value not in-range.  */
96   /* arg + 1.  */
97   if (foo7 (512) != 513)
98     abort ();
99   /* arg + 1.  */
100   if (foo8 (512) != 513)
101     abort ();
102 
103   /* Signed to unsigned conversion with value range positive.  */
104   /* arg - 1.  */
105   if (foo9 (2) != 1)
106     abort ();
107   /* arg + 1.  */
108   if (foo10 (2) != 3)
109     abort ();
110 
111   /* Signed to unsigned conversion with value range negative.  */
112   /* arg + 1.  */
113   if (foo11 (-125) != -124)
114     abort ();
115   /* arg + 1.  */
116   if (foo12 (-125) != -124)
117     abort ();
118 
119   /* Unsigned to Signed conversion with value range in signed equiv range.  */
120   /* arg + 1.  */
121   if (foo13 (125) != 126)
122     abort ();
123   /* arg + 1.  */
124   if (foo14 (125) != 126)
125     abort ();
126 
127   /* Unsigned to Signed conversion with value range not-in signed range.  */
128   /* arg + 1.  */
129   if (foo15 (250) != 251)
130     abort ();
131   /* arg + 1.  */
132   if (foo16 (250) != 251)
133     abort ();
134 
135   return 0;
136 }
137 
138