]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/function-tests.c
c++: Handle multiple aggregate overloads [PR95319].
[thirdparty/gcc.git] / gcc / function-tests.c
1 /* Unit tests for function-handling.
2 Copyright (C) 2015-2020 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "opts.h"
25 #include "hash-set.h"
26 #include "fixed-value.h"
27 #include "alias.h"
28 #include "flags.h"
29 #include "symtab.h"
30 #include "tree-core.h"
31 #include "stor-layout.h"
32 #include "tree.h"
33 #include "stringpool.h"
34 #include "stor-layout.h"
35 #include "rtl.h"
36 #include "predict.h"
37 #include "vec.h"
38 #include "hashtab.h"
39 #include "hash-set.h"
40 #include "hard-reg-set.h"
41 #include "input.h"
42 #include "function.h"
43 #include "dominance.h"
44 #include "cfg.h"
45 #include "cfganal.h"
46 #include "basic-block.h"
47 #include "tree-ssa-alias.h"
48 #include "internal-fn.h"
49 #include "gimple-fold.h"
50 #include "gimple-expr.h"
51 #include "toplev.h"
52 #include "print-tree.h"
53 #include "tree-iterator.h"
54 #include "gimplify.h"
55 #include "tree-cfg.h"
56 #include "basic-block.h"
57 #include "alias.h"
58 #include "symtab.h"
59 #include "inchash.h"
60 #include "tree.h"
61 #include "fold-const.h"
62 #include "stor-layout.h"
63 #include "stmt.h"
64 #include "hash-table.h"
65 #include "tree-ssa-alias.h"
66 #include "internal-fn.h"
67 #include "gimple-expr.h"
68 #include "is-a.h"
69 #include "gimple.h"
70 #include "tree-pass.h"
71 #include "context.h"
72 #include "hash-map.h"
73 #include "plugin-api.h"
74 #include "ipa-ref.h"
75 #include "cgraph.h"
76 #include "selftest.h"
77 #include "print-rtl.h"
78
79 #if CHECKING_P
80
81 namespace selftest {
82
83 /* Helper function for selftests of function-creation. */
84
85 tree
86 make_fndecl (tree return_type,
87 const char *name,
88 vec <tree> &param_types,
89 bool is_variadic)
90 {
91 tree fn_type;
92 if (is_variadic)
93 fn_type = build_varargs_function_type_array (return_type,
94 param_types.length (),
95 param_types.address ());
96 else
97 fn_type = build_function_type_array (return_type,
98 param_types.length (),
99 param_types.address ());
100 /* FIXME: this uses input_location: */
101 tree fndecl = build_fn_decl (name, fn_type);
102
103 return fndecl;
104 }
105
106 /* Verify creating a function declaration equivalent to the following
107 int test_fndecl_int_void (void);
108 C declaration. */
109
110 static void
111 test_fndecl_int_void ()
112 {
113 auto_vec <tree> param_types;
114 const char *name = "test_fndecl_int_void";
115 tree fndecl = make_fndecl (integer_type_node,
116 name,
117 param_types);
118 ASSERT_TRUE (fndecl != NULL);
119
120 /* Verify name of decl. */
121 tree declname = DECL_NAME (fndecl);
122 ASSERT_TRUE (declname != NULL);
123 ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
124 /* We expect it to use a *copy* of the string we passed in. */
125 const char *identifier_ptr = IDENTIFIER_POINTER (declname);
126 ASSERT_NE (name, identifier_ptr);
127 ASSERT_EQ (0, strcmp ("test_fndecl_int_void", identifier_ptr));
128
129 /* Verify type of fndecl. */
130 ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
131 tree fntype = TREE_TYPE (fndecl);
132 ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
133
134 /* Verify return type. */
135 ASSERT_EQ (integer_type_node, TREE_TYPE (fntype));
136
137 /* Verify "void" args. */
138 tree argtypes = TYPE_ARG_TYPES (fntype);
139 ASSERT_EQ (TREE_LIST, TREE_CODE (argtypes));
140 ASSERT_EQ (void_type_node, TREE_VALUE (argtypes));
141 ASSERT_EQ (NULL, TREE_CHAIN (argtypes));
142 }
143
144 /* Verify creating a function declaration equivalent to the following
145 float test_fndecl_float_intchar (int, char);
146 C declaration. */
147
148 static void
149 test_fndecl_float_intchar ()
150 {
151 auto_vec <tree> param_types;
152 param_types.safe_push (integer_type_node);
153 param_types.safe_push (char_type_node);
154 const char *name = "test_fndecl_float_intchar";
155 tree fndecl = make_fndecl (float_type_node,
156 name,
157 param_types);
158 ASSERT_TRUE (fndecl != NULL);
159
160 /* Verify name of decl. */
161 tree declname = DECL_NAME (fndecl);
162 ASSERT_TRUE (declname != NULL);
163 ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
164 /* We expect it to use a *copy* of the string we passed in. */
165 const char *identifier_ptr = IDENTIFIER_POINTER (declname);
166 ASSERT_NE (name, identifier_ptr);
167 ASSERT_EQ (0, strcmp (name, identifier_ptr));
168
169 /* Verify type of fndecl. */
170 ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
171 tree fntype = TREE_TYPE (fndecl);
172 ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
173
174 /* Verify return type. */
175 ASSERT_EQ (float_type_node, TREE_TYPE (fntype));
176
177 /* Verify "(int, char)" args. */
178 tree arg0 = TYPE_ARG_TYPES (fntype);
179 ASSERT_EQ (TREE_LIST, TREE_CODE (arg0));
180 ASSERT_EQ (integer_type_node, TREE_VALUE (arg0));
181 tree arg1 = TREE_CHAIN (arg0);
182 ASSERT_TRUE (arg1 != NULL);
183 ASSERT_EQ (TREE_LIST, TREE_CODE (arg1));
184 ASSERT_EQ (char_type_node, TREE_VALUE (arg1));
185 tree argterm = TREE_CHAIN (arg1);
186 ASSERT_TRUE (argterm != NULL);
187 ASSERT_EQ (TREE_LIST, TREE_CODE (argterm));
188 ASSERT_EQ (void_type_node, TREE_VALUE (argterm));
189 ASSERT_EQ (NULL, TREE_CHAIN (argterm));
190 }
191
192 /* The test cases using these helper functions take a trivial function:
193
194 int test_fn (void) { return 42; }
195
196 and test various conversions done to it:
197
198 - gimplification
199 - construction of the CFG
200 - conversion to SSA form
201 - expansion to RTL form
202
203 In avoid having one overlong test case, this is broken
204 up into separate test cases for each stage, with helper functions
205 to minimize code duplication.
206
207 Another approach would be to attempt to directly construct a function
208 in the appropriate representation at each stage, though presumably
209 that would exhibit different kinds of failure compared to this
210 approach. */
211
212 /* Construct this function:
213 int test_fn (void) { return 42; }
214 in generic tree form. Return the fndecl. */
215
216 static tree
217 build_trivial_generic_function ()
218 {
219 auto_vec <tree> param_types;
220 tree fndecl = make_fndecl (integer_type_node,
221 "test_fn",
222 param_types);
223 ASSERT_TRUE (fndecl != NULL);
224
225 /* Populate the function. */
226 tree retval = build_decl (UNKNOWN_LOCATION, RESULT_DECL,
227 NULL_TREE, integer_type_node);
228 DECL_ARTIFICIAL (retval) = 1;
229 DECL_IGNORED_P (retval) = 1;
230 DECL_RESULT (fndecl) = retval;
231
232 /* Create a BIND_EXPR, and within it, a statement list. */
233 tree stmt_list = alloc_stmt_list ();
234 tree_stmt_iterator stmt_iter = tsi_start (stmt_list);
235 tree block = make_node (BLOCK);
236 tree bind_expr
237 = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, block);
238
239 tree modify_retval = build2 (MODIFY_EXPR,
240 integer_type_node,
241 retval,
242 build_int_cst (integer_type_node, 42));
243 tree return_stmt = build1 (RETURN_EXPR,
244 integer_type_node,
245 modify_retval);
246 tsi_link_after (&stmt_iter, return_stmt, TSI_CONTINUE_LINKING);
247
248 DECL_INITIAL (fndecl) = block;
249 BLOCK_SUPERCONTEXT (block) = fndecl;
250
251 /* how to add to function? the following appears to be how to
252 set the body of a fndecl: */
253 DECL_SAVED_TREE(fndecl) = bind_expr;
254
255 /* Ensure that locals appear in the debuginfo. */
256 BLOCK_VARS (block) = BIND_EXPR_VARS (bind_expr);
257
258 return fndecl;
259 }
260
261 /* Construct this function:
262 int test_fn (void) { return 42; }
263 in "high gimple" form. Return the fndecl. */
264
265 static tree
266 build_trivial_high_gimple_function ()
267 {
268 /* Construct a trivial function, and gimplify it: */
269 tree fndecl = build_trivial_generic_function ();
270 gimplify_function_tree (fndecl);
271 return fndecl;
272 }
273
274 /* Build a CFG for a function in gimple form. */
275
276 static void
277 build_cfg (tree fndecl)
278 {
279 function *fun = DECL_STRUCT_FUNCTION (fndecl);
280 ASSERT_TRUE (fun != NULL);
281 ASSERT_EQ (fndecl, fun->decl);
282
283 /* We first have to lower control flow; for our trivial test function
284 this gives us:
285 test_fn ()
286 {
287 D.56 = 42;
288 goto <D.57>;
289 <D.57>:
290 return D.56;
291 }
292 */
293 gimple_opt_pass *lower_cf_pass = make_pass_lower_cf (g);
294 push_cfun (fun);
295 lower_cf_pass->execute (fun);
296 pop_cfun ();
297 delete lower_cf_pass;
298
299 /* We can now convert to CFG form; for our trivial test function this
300 gives us:
301 test_fn ()
302 {
303 <bb 2>:
304 D.56 = 42;
305 return D.56;
306 }
307 */
308 gimple_opt_pass *build_cfg_pass = make_pass_build_cfg (g);
309 push_cfun (fun);
310 build_cfg_pass->execute (fun);
311 pop_cfun ();
312 delete build_cfg_pass;
313 }
314
315 /* Convert a gimple+CFG function to SSA form. */
316
317 static void
318 convert_to_ssa (tree fndecl)
319 {
320 function *fun = DECL_STRUCT_FUNCTION (fndecl);
321 ASSERT_TRUE (fun != NULL);
322 ASSERT_EQ (fndecl, fun->decl);
323
324 gimple_opt_pass *build_ssa_pass = make_pass_build_ssa (g);
325 push_cfun (fun);
326 build_ssa_pass->execute (fun);
327 pop_cfun ();
328 delete build_ssa_pass;
329 }
330
331 /* Assuming we have a simple 3-block CFG like this:
332 [ENTRY] -> [block2] -> [EXIT]
333 get the "real" basic block (block 2). */
334
335 static basic_block
336 get_real_block (function *fun)
337 {
338 ASSERT_TRUE (fun->cfg != NULL);
339 ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
340 basic_block bb2 = (*fun->cfg->x_basic_block_info)[2];
341 ASSERT_TRUE (bb2 != NULL);
342 return bb2;
343 }
344
345 /* Verify that we have a simple 3-block CFG: the two "fake" ones, and
346 a "real" one:
347 [ENTRY] -> [block2] -> [EXIT]. */
348
349 static void
350 verify_three_block_cfg (function *fun)
351 {
352 ASSERT_TRUE (fun->cfg != NULL);
353 ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
354 ASSERT_EQ (2, n_edges_for_fn (fun));
355
356 /* The "fake" basic blocks. */
357 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
358 ASSERT_TRUE (entry != NULL);
359 ASSERT_EQ (ENTRY_BLOCK, entry->index);
360
361 basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
362 ASSERT_TRUE (exit != NULL);
363 ASSERT_EQ (EXIT_BLOCK, exit->index);
364
365 /* The "real" basic block. */
366 basic_block bb2 = get_real_block (fun);
367 ASSERT_TRUE (bb2 != NULL);
368 ASSERT_EQ (2, bb2->index);
369
370 /* Verify connectivity. */
371 ASSERT_EQ (NULL, entry->preds);
372 ASSERT_EQ (1, entry->succs->length ());
373
374 edge from_entry_to_bb2 = (*entry->succs)[0];
375 ASSERT_EQ (entry, from_entry_to_bb2->src);
376 ASSERT_EQ (bb2, from_entry_to_bb2->dest);
377
378 ASSERT_EQ (1, bb2->preds->length ());
379 ASSERT_EQ (from_entry_to_bb2, (*bb2->preds)[0]);
380 ASSERT_EQ (1, bb2->succs->length ());
381
382 edge from_bb2_to_exit = (*bb2->succs)[0];
383 ASSERT_EQ (bb2, from_bb2_to_exit->src);
384 ASSERT_EQ (exit, from_bb2_to_exit->dest);
385
386 ASSERT_EQ (1, exit->preds->length ());
387 ASSERT_EQ (from_bb2_to_exit, (*exit->preds)[0]);
388 ASSERT_EQ (NULL, exit->succs);
389 }
390
391 /* As above, but additionally verify the gimple statements are sane. */
392
393 static void
394 verify_three_block_gimple_cfg (function *fun)
395 {
396 verify_three_block_cfg (fun);
397
398 /* The "fake" basic blocks should be flagged as gimple, but with have no
399 statements. */
400 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
401 ASSERT_TRUE (entry != NULL);
402 ASSERT_EQ (0, entry->flags & BB_RTL);
403 ASSERT_EQ (NULL, bb_seq (entry));
404
405 basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
406 ASSERT_TRUE (exit != NULL);
407 ASSERT_EQ (0, entry->flags & BB_RTL);
408 ASSERT_EQ (NULL, bb_seq (exit));
409
410 /* The "real" basic block should be flagged as gimple, and have one
411 or more statements. */
412 basic_block bb2 = get_real_block (fun);
413 ASSERT_TRUE (bb2 != NULL);
414 ASSERT_EQ (0, entry->flags & BB_RTL);
415 ASSERT_TRUE (bb_seq (bb2) != NULL);
416 }
417
418 /* As above, but additionally verify the RTL insns are sane. */
419
420 void
421 verify_three_block_rtl_cfg (function *fun)
422 {
423 verify_three_block_cfg (fun);
424
425 /* The "fake" basic blocks should be flagged as RTL, but with no
426 insns. */
427 basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
428 ASSERT_TRUE (entry != NULL);
429 ASSERT_EQ (BB_RTL, entry->flags & BB_RTL);
430 ASSERT_EQ (NULL, BB_HEAD (entry));
431
432 basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
433 ASSERT_TRUE (exit != NULL);
434 ASSERT_EQ (BB_RTL, exit->flags & BB_RTL);
435 ASSERT_EQ (NULL, BB_HEAD (exit));
436
437 /* The "real" basic block should be flagged as RTL, and have one
438 or more insns. */
439 basic_block bb2 = get_real_block (fun);
440 ASSERT_TRUE (bb2 != NULL);
441 ASSERT_EQ (BB_RTL, bb2->flags & BB_RTL);
442 ASSERT_TRUE (BB_HEAD (bb2) != NULL);
443 }
444
445 /* Test converting our trivial function:
446 int test_fn (void) { return 42; }
447 to gimple form. */
448
449 static void
450 test_gimplification ()
451 {
452 tree fndecl = build_trivial_generic_function ();
453
454 /* Convert to gimple: */
455 gimplify_function_tree (fndecl);
456
457 /* Verify that we got gimple out of it. */
458
459 /* The function is now in GIMPLE form but the CFG has not been
460 built yet. */
461
462 /* We should have a struct function for the decl. */
463 function *fun = DECL_STRUCT_FUNCTION (fndecl);
464 ASSERT_TRUE (fun != NULL);
465 ASSERT_EQ (fndecl, fun->decl);
466
467 /* We expect a GIMPLE_BIND, with two gimple statements within it:
468 tmp = 42;
469 return tmp; */
470
471 gimple_seq seq_fn_body = gimple_body (fndecl);
472 ASSERT_TRUE (seq_fn_body != NULL);
473 gimple *bind_stmt = gimple_seq_first_stmt (seq_fn_body);
474 ASSERT_EQ (GIMPLE_BIND, gimple_code (bind_stmt));
475 ASSERT_EQ (NULL, bind_stmt->next);
476
477 gimple_seq seq_bind_body = gimple_bind_body (as_a <gbind *> (bind_stmt));
478
479 /* Verify that we have the 2 statements we expect. */
480 ASSERT_TRUE (seq_bind_body != NULL);
481 gimple *stmt1 = gimple_seq_first_stmt (seq_bind_body);
482 ASSERT_TRUE (stmt1 != NULL);
483 ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt1));
484 gimple *stmt2 = stmt1->next;
485 ASSERT_TRUE (stmt2 != NULL);
486 ASSERT_EQ (stmt1, stmt2->prev);
487 ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt2));
488 }
489
490 /* Test of building a CFG for a function in high gimple form. */
491
492 static void
493 test_building_cfg ()
494 {
495 /* Construct a trivial function, and gimplify it: */
496 tree fndecl = build_trivial_high_gimple_function ();
497 function *fun = DECL_STRUCT_FUNCTION (fndecl);
498 ASSERT_TRUE (fun != NULL);
499
500 /* Build a CFG. */
501 build_cfg (fndecl);
502
503 /* The CFG-building code constructs a 4-block cfg (with
504 ENTRY and EXIT):
505 test_fn ()
506 {
507 <bb 2>:
508 D.65 = 42;
509
510 <bb 3>:
511 return D.65;
512 }
513 and then ought to merge blocks 2 and 3 in cleanup_tree_cfg.
514
515 Hence we should end up with a simple 3-block cfg, the two "fake" ones,
516 and a "real" one:
517 [ENTRY] -> [block2] -> [EXIT]
518 with code like this:
519 test_fn ()
520 {
521 <bb 2>:
522 D.56 = 42;
523 return D.56;
524 }
525 */
526 verify_three_block_gimple_cfg (fun);
527
528 /* Verify the statements within the "real" block. */
529 basic_block bb2 = get_real_block (fun);
530 gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
531 ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
532 gimple *stmt_b = stmt_a->next;
533 ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
534 ASSERT_EQ (NULL, stmt_b->next);
535 }
536
537 /* Test of conversion of gimple to SSA form. */
538
539 static void
540 test_conversion_to_ssa ()
541 {
542 /* As above, construct a trivial function, gimplify it, and build a CFG: */
543 tree fndecl = build_trivial_high_gimple_function ();
544 function *fun = DECL_STRUCT_FUNCTION (fndecl);
545 ASSERT_TRUE (fun != NULL);
546 build_cfg (fndecl);
547
548 convert_to_ssa (fndecl);
549
550 verify_three_block_gimple_cfg (fun);
551
552 /* For out trivial test function we should now have something like
553 this:
554 test_fn ()
555 {
556 <bb 2>:
557 _1 = 42;
558 return _1;
559 }
560 */
561 basic_block bb2 = get_real_block (fun);
562 gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
563 ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
564
565 gimple *stmt_b = stmt_a->next;
566 ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
567 ASSERT_EQ (NULL, stmt_b->next);
568
569 greturn *return_stmt = as_a <greturn *> (stmt_b);
570 ASSERT_EQ (SSA_NAME, TREE_CODE (gimple_return_retval (return_stmt)));
571 }
572
573 /* Test range folding. We must start this here because we need cfun
574 set. */
575
576 static void
577 test_ranges ()
578 {
579 tree fndecl = build_trivial_high_gimple_function ();
580 function *fun = DECL_STRUCT_FUNCTION (fndecl);
581 push_cfun (fun);
582 range_tests ();
583 pop_cfun ();
584 }
585
586 /* Test of expansion from gimple-ssa to RTL. */
587
588 static void
589 test_expansion_to_rtl ()
590 {
591 /* As above, construct a trivial function, gimplify it, build a CFG,
592 and convert to SSA: */
593 tree fndecl = build_trivial_high_gimple_function ();
594 function *fun = DECL_STRUCT_FUNCTION (fndecl);
595 ASSERT_TRUE (fun != NULL);
596 build_cfg (fndecl);
597 convert_to_ssa (fndecl);
598
599 /* We need a cgraph_node for it. */
600 cgraph_node::get_create (fndecl);
601 /* Normally, cgraph_node::expand () would call
602 init_function_start (and a bunch of other stuff),
603 and invoke the expand pass, but it also runs
604 all of the other passes. So just do the minimum
605 needed to get from gimple-SSA to RTL. */
606 rtl_opt_pass *expand_pass = make_pass_expand (g);
607 push_cfun (fun);
608 init_function_start (fndecl);
609 expand_pass->execute (fun);
610 pop_cfun ();
611 delete expand_pass;
612
613 /* On x86_64, I get this:
614 (note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
615 (note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
616 (insn 5 2 6 2 (set (reg:SI 87 [ D.59 ])
617 (const_int 42 [0x2a])) -1 (nil))
618 (insn 6 5 10 2 (set (reg:SI 88 [ <retval> ])
619 (reg:SI 87 [ D.59 ])) -1 (nil))
620 (insn 10 6 11 2 (set (reg/i:SI 0 ax)
621 (reg:SI 88 [ <retval> ])) -1 (nil))
622 (insn 11 10 0 2 (use (reg/i:SI 0 ax)) -1 (nil))
623
624 On cr16-elf I get this:
625 (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
626 (insn 2 4 3 2 (set (reg:SI 24)
627 (reg/f:SI 16 virtual-incoming-args)) -1
628 (nil))
629 (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG)
630 (insn 6 3 7 2 (set (reg:HI 22 [ _1 ])
631 (const_int 42 [0x2a])) -1
632 (nil))
633 (insn 7 6 11 2 (set (reg:HI 23 [ <retval> ])
634 (reg:HI 22 [ _1 ])) -1
635 (nil))
636 (insn 11 7 12 2 (set (reg/i:HI 0 r0)
637 (reg:HI 23 [ <retval> ])) -1
638 (nil))
639 (insn 12 11 0 2 (use (reg/i:HI 0 r0)) -1
640 (nil)). */
641 verify_three_block_rtl_cfg (fun);
642
643 /* Verify as much of the RTL as we can whilst avoiding
644 target-specific behavior. */
645 basic_block bb2 = get_real_block (fun);
646
647 /* Expect a NOTE_INSN_BASIC_BLOCK... */
648 rtx_insn *insn = BB_HEAD (bb2);
649 ASSERT_TRUE (insn != NULL);
650 ASSERT_EQ (NOTE, insn->code);
651 ASSERT_EQ (NOTE_INSN_BASIC_BLOCK, NOTE_KIND (insn));
652 ASSERT_EQ (bb2, NOTE_BASIC_BLOCK (insn));
653
654 /* ...etc; any further checks are likely to over-specify things
655 and run us into target dependencies. */
656
657 /* Verify that print_rtl_function is sane. */
658 named_temp_file tmp_out (".rtl");
659 FILE *outfile = fopen (tmp_out.get_filename (), "w");
660 print_rtx_function (outfile, fun, true);
661 fclose (outfile);
662
663 char *dump = read_file (SELFTEST_LOCATION, tmp_out.get_filename ());
664 ASSERT_STR_CONTAINS (dump, "(function \"test_fn\"\n");
665 ASSERT_STR_CONTAINS (dump, " (insn-chain\n");
666 ASSERT_STR_CONTAINS (dump, " (block 2\n");
667 ASSERT_STR_CONTAINS (dump, " (edge-from entry (flags \"FALLTHRU\"))\n");
668 ASSERT_STR_CONTAINS (dump, " (cinsn "); /* ...etc. */
669 ASSERT_STR_CONTAINS (dump, " (edge-to exit (flags \"FALLTHRU\"))\n");
670 ASSERT_STR_CONTAINS (dump, " ) ;; block 2\n");
671 ASSERT_STR_CONTAINS (dump, " ) ;; insn-chain\n");
672 ASSERT_STR_CONTAINS (dump, " (crtl\n");
673 ASSERT_STR_CONTAINS (dump, " ) ;; crtl\n");
674 ASSERT_STR_CONTAINS (dump, ") ;; function \"test_fn\"\n");
675
676 free (dump);
677 free_after_compilation (fun);
678 }
679
680 /* Run all of the selftests within this file. */
681
682 void
683 function_tests_c_tests ()
684 {
685 test_fndecl_int_void ();
686 test_fndecl_float_intchar ();
687 test_gimplification ();
688 test_building_cfg ();
689 test_conversion_to_ssa ();
690 test_ranges ();
691 test_expansion_to_rtl ();
692 }
693
694 } // namespace selftest
695
696 #endif /* #if CHECKING_P */