]> Git Repo - binutils.git/blob - gdb/unittests/function-view-selftests.c
Automatic date update in version.in
[binutils.git] / gdb / unittests / function-view-selftests.c
1 /* Self tests for function_view for GDB, the GNU debugger.
2
3    Copyright (C) 2017-2022 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 "gdbsupport/selftest.h"
22 #include "gdbsupport/function-view.h"
23
24 namespace selftests {
25 namespace function_view {
26
27 static int
28 plus_one_fn_int (int val)
29 {
30   return ++val;
31 }
32
33 static short
34 plus_one_fn_short (short val)
35 {
36   return ++val;
37 }
38
39 static int
40 call_callback_int (int val, gdb::function_view <int (int)> callback)
41 {
42   return callback (val);
43 }
44
45 static void
46 call_callback_void (int val, gdb::function_view <void (int)> callback)
47 {
48   callback (val);
49 }
50
51 struct plus_one_int_func_obj
52 {
53   int operator () (int val)
54   {
55     ++call_count;
56     return ++val;
57   }
58
59   /* Number of times called.  */
60   int call_count = 0;
61 };
62
63 static void
64 test_function_view ()
65 {
66   /* A simple lambda.  */
67   auto plus_one_lambda = [] (int val) { return ++val; };
68
69   /* A function_view that references the lambda.  */
70   gdb::function_view<int (int)> plus_one_func_view (plus_one_lambda);
71
72   /* Check calling the lambda directly.  */
73   SELF_CHECK (plus_one_lambda (0) == 1);
74   SELF_CHECK (plus_one_lambda (1) == 2);
75
76   /* Check calling lambda via the view.  */
77   SELF_CHECK (plus_one_func_view (2) == 3);
78   SELF_CHECK (plus_one_func_view (3) == 4);
79
80   /* Check calling a function that takes a function_view as argument,
81      by value.  Pass a lambda, making sure a function_view is properly
82      constructed implicitly.  */
83   SELF_CHECK (call_callback_int (1, [] (int val)
84     {
85       return val + 2;
86     }) == 3);
87
88   /* Same, passing a named/lvalue lambda.  */
89   SELF_CHECK (call_callback_int (1, plus_one_lambda) == 2);
90   /* Same, passing a named/lvalue function_view (should copy).  */
91   SELF_CHECK (call_callback_int (1, plus_one_func_view) == 2);
92
93   /* Check constructing a function view over a function-object
94      callable, and calling it.  */
95   plus_one_int_func_obj func_obj;
96   SELF_CHECK (func_obj (0) == 1);
97   SELF_CHECK (call_callback_int (1, func_obj) == 2);
98   /* Check that the callable was referenced, not copied.  */
99   SELF_CHECK (func_obj.call_count == 2);
100
101   /* Check constructing a function_view over a free-function callable,
102      and calling it.  */
103   SELF_CHECK (call_callback_int (1, plus_one_fn_int) == 2);
104
105   /* Check calling a function with a
106      compatible-but-not-exactly-the-same prototype.  */
107   SELF_CHECK (call_callback_int (1, [] (short val) -> short
108     {
109       return val + 2;
110     }) == 3);
111   /* Same, but passing a function pointer.  */
112   SELF_CHECK (call_callback_int (1, plus_one_fn_short) == 2);
113
114   /* Like std::function, a function_view that expects a void return
115      can reference callables with non-void return type.  The result is
116      simply discarded.  Check a lambda, function object and a function
117      pointer.  */
118   call_callback_void (1, [] (int val) -> int
119     {
120       return val + 2;
121     });
122   call_callback_void (1, func_obj);
123   call_callback_void (1, plus_one_fn_int);
124
125   /* Check that the main ctor doesn't hijack the copy ctor.  */
126   auto plus_one_func_view2 (plus_one_func_view);
127   auto plus_one_func_view3 (plus_one_func_view2);
128   static_assert (std::is_same<decltype (plus_one_func_view),
129                  decltype (plus_one_func_view2)>::value, "");
130   static_assert (std::is_same<decltype (plus_one_func_view),
131                  decltype (plus_one_func_view3)>::value, "");
132
133   SELF_CHECK (plus_one_func_view3 (1) == 2);
134
135   /* Likewise, but propagate a NULL callable.  If this calls the main
136      function_view ctor instead of the copy ctor by mistake, then
137      null_func_2 ends up non-NULL (because it'd instead reference
138      null_func_1 as just another callable).  */
139   constexpr gdb::function_view<int (int)> null_func_view_1 = nullptr;
140   constexpr auto null_func_view_2 (null_func_view_1);
141
142   /* While at it, check whether the function_view is bound using
143      various forms, op==, op!= and op bool.  */
144
145   /* op== */
146   static_assert (null_func_view_2 == nullptr, "");
147   static_assert (nullptr == null_func_view_2, "");
148   static_assert (null_func_view_2 == NULL, "");
149   static_assert (NULL == null_func_view_2, "");
150
151   /* op!= */
152   static_assert (!(null_func_view_2 != nullptr), "");
153   static_assert (!(nullptr != null_func_view_2), "");
154   static_assert (!(null_func_view_2 != NULL), "");
155   static_assert (!(NULL != null_func_view_2), "");
156
157   /* op bool */
158   static_assert (!null_func_view_2, "");
159
160   /* Check the nullptr_t ctor.  */
161   constexpr gdb::function_view<int (int)> check_ctor_nullptr (nullptr);
162   static_assert (!check_ctor_nullptr, "");
163
164   /* Check the nullptr_t op= */
165   gdb::function_view<int (int)> check_op_eq_null (plus_one_fn_int);
166   SELF_CHECK (check_op_eq_null);
167   check_op_eq_null = nullptr;
168   SELF_CHECK (!check_op_eq_null);
169 }
170
171 /* A template function where the function_view type is dependent on a
172    template parameter.  */
173
174 template<typename T>
175 static int
176 tmpl_func (T val, gdb::function_view<T (T)> callback)
177 {
178   return callback (val) + 1;
179 }
180
181 static int
182 make_fv_test_func (int val)
183 {
184   return val + 1;
185 }
186
187 /* A function object with const operator().  */
188
189 struct func_obj_const_op
190 {
191   int operator() (int val) const
192   {
193     return val + 1;
194   }
195 };
196
197 /* A function object with non-const operator().  */
198
199 struct func_obj_non_const_op
200 {
201   int operator() (int val)
202   {
203     return val + 1;
204   }
205 };
206
207 static void
208 test_make_function_view ()
209 {
210   /* Function reference.  */
211   SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (make_fv_test_func)));
212
213   /* Function pointer.  */
214   SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (&make_fv_test_func)));
215
216   /* Reference to const and non-const function pointers.  */
217   typedef int (*func_ptr) (int);
218   func_ptr ptr = make_fv_test_func;
219   const func_ptr cptr = make_fv_test_func;
220   SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (ptr)));
221   SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (cptr)));
222
223   /* Lambdas.  */
224
225   auto lambda = [] (int val) -> int { return val + 1; };
226
227   /* This wouldn't compile, since tmpl_func is a template and its
228      function_view argument's callable type is a dependent type.  The
229      passed argument must be of the exact type of the function's
230      parameter.  */
231   // SELF_CHECK (3 == tmpl_func (1, lambda));
232
233   SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (lambda)));
234
235   /* Regular function objects.  */
236
237   func_obj_non_const_op fobj;
238   SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (fobj)));
239
240   func_obj_const_op cfobj;
241   SELF_CHECK (3 == tmpl_func (1, gdb::make_function_view (cfobj)));
242 }
243
244 static void
245 run_tests ()
246 {
247   test_function_view ();
248   test_make_function_view ();
249 }
250
251 } /* namespace function_view */
252 } /* namespace selftests */
253
254 void _initialize_function_view_selftests ();
255 void
256 _initialize_function_view_selftests ()
257 {
258   selftests::register_test ("function_view",
259                             selftests::function_view::run_tests);
260 }
This page took 0.039401 seconds and 4 git commands to generate.