Introduce string_appendf/string_vappendf
[external/binutils.git] / gdb / unittests / offset-type-selftests.c
1 /* Self tests for offset types for GDB, the GNU debugger.
2
3    Copyright (C) 2017 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "selftest.h"
22 #include "common/offset-type.h"
23 #include "common/underlying.h"
24 #include "common/valid-expr.h"
25
26 namespace selftests {
27 namespace offset_type {
28
29 DEFINE_OFFSET_TYPE (off_A, unsigned int);
30 DEFINE_OFFSET_TYPE (off_B, unsigned int);
31
32 /* First, compile-time tests that:
33
34    - make sure that incorrect operations with mismatching types are
35      caught at compile time.
36
37    - make sure that the same operations but involving the right types
38      do compile and that they return the correct type.
39 */
40
41 #define CHECK_VALID(VALID, EXPR_TYPE, EXPR)             \
42   CHECK_VALID_EXPR_2 (off_A, off_B, VALID, EXPR_TYPE, EXPR)
43
44 off_A lval_a {};
45 off_B lval_b {};
46
47 using undrl = std::underlying_type<off_A>::type;
48
49 /* Offset +/- underlying.  */
50
51 CHECK_VALID (true,  off_A,  off_A {} + undrl {});
52 CHECK_VALID (true,  off_A,  off_A {} - undrl {});
53 CHECK_VALID (true,  off_A,  undrl {} + off_A {});
54 CHECK_VALID (true,  off_A,  undrl {} - off_A {});
55
56 /* Add offset types.  Both same and different.  */
57
58 CHECK_VALID (false, void,   off_A {} + off_A {});
59 CHECK_VALID (false, void,   off_A {} + off_B {});
60
61 /* Subtract offset types.  Both same and different.  */
62
63 CHECK_VALID (false, void,   off_B {} - off_A {});
64 CHECK_VALID (true,  undrl,  off_A {} - off_A {});
65
66 /* Add/assign offset types.  Both same and different.  */
67
68 CHECK_VALID (false, void,   lval_a += off_A {});
69 CHECK_VALID (false, void,   lval_a += off_B {});
70 CHECK_VALID (false, void,   lval_a -= off_A {});
71 CHECK_VALID (false, void,   lval_a -= off_B {});
72
73 /* operator OP+= (offset, underlying), lvalue ref on the lhs. */
74
75 CHECK_VALID (true,  off_A&, lval_a += undrl {});
76 CHECK_VALID (true,  off_A&, lval_a -= undrl {});
77
78 /* operator OP+= (offset, underlying), rvalue ref on the lhs. */
79
80 CHECK_VALID (false, void,   off_A {} += undrl {});
81 CHECK_VALID (false, void,   off_A {} -= undrl {});
82
83 /* Rel ops, with same type.  */
84
85 CHECK_VALID (true,  bool,   off_A {} < off_A {});
86 CHECK_VALID (true,  bool,   off_A {} > off_A {});
87 CHECK_VALID (true,  bool,   off_A {} <= off_A {});
88 CHECK_VALID (true,  bool,   off_A {} >= off_A {});
89
90 /* Rel ops, with unrelated offset types.  */
91
92 CHECK_VALID (false, void,   off_A {} < off_B {});
93 CHECK_VALID (false, void,   off_A {} > off_B {});
94 CHECK_VALID (false, void,   off_A {} <= off_B {});
95 CHECK_VALID (false, void,   off_A {} >= off_B {});
96
97 /* Rel ops, with unrelated types.  */
98
99 CHECK_VALID (false, void,   off_A {} < undrl {});
100 CHECK_VALID (false, void,   off_A {} > undrl {});
101 CHECK_VALID (false, void,   off_A {} <= undrl {});
102 CHECK_VALID (false, void,   off_A {} >= undrl {});
103
104 static void
105 run_tests ()
106 {
107   /* Test op+ and op-.  */
108   {
109     constexpr off_A a {};
110     static_assert (to_underlying (a) == 0, "");
111
112     {
113       constexpr off_A res1 = a + 2;
114       static_assert (to_underlying (res1) == 2, "");
115
116       constexpr off_A res2 = res1 - 1;
117       static_assert (to_underlying (res2) == 1, "");
118     }
119
120     {
121       constexpr off_A res1 = 2 + a;
122       static_assert (to_underlying (res1) == 2, "");
123
124       constexpr off_A res2 = 3 - res1;
125       static_assert (to_underlying (res2) == 1, "");
126     }
127   }
128
129   /* Test op+= and op-=.  */
130   {
131     off_A o {};
132
133     o += 10;
134     SELF_CHECK (to_underlying (o) == 10);
135     o -= 5;
136     SELF_CHECK (to_underlying (o) == 5);
137   }
138
139   /* Test op-.  */
140   {
141     constexpr off_A o1 = (off_A) 10;
142     constexpr off_A o2 = (off_A) 20;
143
144     constexpr unsigned int delta = o2 - o1;
145
146     static_assert (delta == 10, "");
147   }
148
149   /* Test <, <=, >, >=.  */
150   {
151     constexpr off_A o1 = (off_A) 10;
152     constexpr off_A o2 = (off_A) 20;
153
154     static_assert (o1 < o2, "");
155     static_assert (!(o2 < o1), "");
156
157     static_assert (o2 > o1, "");
158     static_assert (!(o1 > o2), "");
159
160     static_assert (o1 <= o2, "");
161     static_assert (!(o2 <= o1), "");
162
163     static_assert (o2 >= o1, "");
164     static_assert (!(o1 >= o2), "");
165
166     static_assert (o1 <= o1, "");
167     static_assert (o1 >= o1, "");
168   }
169 }
170
171 } /* namespace offset_type */
172 } /* namespace selftests */
173
174 void
175 _initialize_offset_type_selftests ()
176 {
177   selftests::register_test ("offset_type", selftests::offset_type::run_tests);
178 }