Commit d9b950dd by David Malcolm Committed by David Malcolm

Selftest framework

gcc/ChangeLog:
	* Makefile.in (OBJS): Add function-tests.o,
	hash-map-tests.o, hash-set-tests.o, rtl-tests.o,
	selftest-run-tests.o.
	(OBJS-libcommon): Add selftest.o.
	(OBJS-libcommon-target): Add selftest.o.
	(all.internal): Add "selftest".
	(all.cross): Likewise.
	(selftest): New phony target.
	(s-selftest): New target.
	(selftest-gdb): New phony target.
	(COLLECT2_OBJS): Add selftest.o.
	* bitmap.c: Include "selftest.h".
	(selftest::test_gc_alloc): New function.
	(selftest::test_set_range): New function.
	(selftest::test_clear_bit_in_middle): New function.
	(selftest::test_copying): New function.
	(selftest::test_bitmap_single_bit_set_p): New function.
	(selftest::bitmap_c_tests): New function.
	* common.opt (fself-test): New.
	* diagnostic-show-locus.c: Include "selftest.h".
	(make_range): New function.
	(test_range_contains_point_for_single_point): New function.
	(test_range_contains_point_for_single_line): New function.
	(test_range_contains_point_for_multiple_lines): New function.
	(assert_eq): New function.
	(test_get_line_width_without_trailing_whitespace): New function.
	(selftest::diagnostic_show_locus_c_tests): New function.
	* et-forest.c: Include "selftest.h".
	(selftest::test_single_node): New function.
	(selftest::test_simple_tree): New function.
	(selftest::test_disconnected_nodes): New function.
	(selftest::et_forest_c_tests): New function.
	* fold-const.c: Include "selftest.h".
	(selftest::assert_binop_folds_to_const): New function.
	(selftest::assert_binop_folds_to_nonlvalue): New function.
	(selftest::test_arithmetic_folding): New function.
	(selftest::fold_const_c_tests): New function.
	* function-tests.c: New file.
	* gimple.c: Include "selftest.h".
	Include "gimple-pretty-print.h".
	(selftest::verify_gimple_pp): New function.
	(selftest::test_assign_single): New function.
	(selftest::test_assign_binop): New function.
	(selftest::test_nop_stmt): New function.
	(selftest::test_return_stmt): New function.
	(selftest::test_return_without_value): New function.
	(selftest::gimple_c_tests): New function.
	* hash-map-tests.c: New file.
	* hash-set-tests.c: New file.
	* input.c: Include "selftest.h".
	(selftest::assert_loceq): New function.
	(selftest::test_accessing_ordinary_linemaps): New function.
	(selftest::test_unknown_location): New function.
	(selftest::test_builtins): New function.
	(selftest::test_reading_source_line): New function.
	(selftest::input_c_tests): New function.
	* rtl-tests.c: New file.
	* selftest-run-tests.c: New file.
	* selftest.c: New file.
	* selftest.h: New file.
	* spellcheck.c: Include "selftest.h".
	(selftest::levenshtein_distance_unit_test_oneway): New function,
	adapted from testsuite/gcc.dg/plugin/levenshtein_plugin.c.
	(selftest::levenshtein_distance_unit_test): Likewise.
	(selftest::spellcheck_c_tests): Likewise.
	* toplev.c: Include selftest.h.
	(toplev::run_self_tests): New.
	(toplev::main): Handle -fself-test.
	* toplev.h (toplev::run_self_tests): New.
	* tree.c: Include "selftest.h".
	(selftest::test_integer_constants): New function.
	(selftest::test_identifiers): New function.
	(selftest::test_labels): New function.
	(selftest::tree_c_tests): New function.
	* tree-cfg.c: Include "selftest.h".
	(selftest::push_fndecl): New function.
	(selftest::test_linear_chain): New function.
	(selftest::test_diamond): New function.
	(selftest::test_fully_connected): New function.
	(selftest::tree_cfg_c_tests): New function.
	* vec.c: Include "selftest.h".
	(selftest::safe_push_range): New function.
	(selftest::test_quick_push): New function.
	(selftest::test_safe_push): New function.
	(selftest::test_truncate): New function.
	(selftest::test_safe_grow_cleared): New function.
	(selftest::test_pop): New function.
	(selftest::test_safe_insert): New function.
	(selftest::test_ordered_remove): New function.
	(selftest::test_unordered_remove): New function.
	(selftest::test_block_remove): New function.
	(selftest::reverse_cmp): New function.
	(selftest::test_qsort): New function.
	(selftest::vec_c_tests): New function.c.
	* wide-int.cc: Include selftest.h and wide-int-print.h.
	(selftest::from_int <wide_int>): New function.
	(selftest::from_int <offset_int>): New function.
	(selftest::from_int <widest_int>): New function.
	(selftest::assert_deceq): New function.
	(selftest::assert_hexeq): New function.
	(selftest::test_printing <VALUE_TYPE>): New function template.
	(selftest::test_ops <VALUE_TYPE>): New function template.
	(selftest::test_comparisons <VALUE_TYPE>): New function template.
	(selftest::run_all_wide_int_tests <VALUE_TYPE>): New function
	template.
	(selftest::wide_int_cc_tests): New function.

gcc/testsuite/ChangeLog:
	* gcc.dg/plugin/levenshtein-test-1.c: Delete.
	* gcc.dg/plugin/levenshtein_plugin.c: Delete.
	* gcc.dg/plugin/plugin.exp (plugin_test_list): Remove the
	above.

From-SVN: r237144
parent dbc6221f
2016-06-06 David Malcolm <dmalcolm@redhat.com>
* Makefile.in (OBJS): Add function-tests.o,
hash-map-tests.o, hash-set-tests.o, rtl-tests.o,
selftest-run-tests.o.
(OBJS-libcommon): Add selftest.o.
(OBJS-libcommon-target): Add selftest.o.
(all.internal): Add "selftest".
(all.cross): Likewise.
(selftest): New phony target.
(s-selftest): New target.
(selftest-gdb): New phony target.
(COLLECT2_OBJS): Add selftest.o.
* bitmap.c: Include "selftest.h".
(selftest::test_gc_alloc): New function.
(selftest::test_set_range): New function.
(selftest::test_clear_bit_in_middle): New function.
(selftest::test_copying): New function.
(selftest::test_bitmap_single_bit_set_p): New function.
(selftest::bitmap_c_tests): New function.
* common.opt (fself-test): New.
* diagnostic-show-locus.c: Include "selftest.h".
(make_range): New function.
(test_range_contains_point_for_single_point): New function.
(test_range_contains_point_for_single_line): New function.
(test_range_contains_point_for_multiple_lines): New function.
(assert_eq): New function.
(test_get_line_width_without_trailing_whitespace): New function.
(selftest::diagnostic_show_locus_c_tests): New function.
* et-forest.c: Include "selftest.h".
(selftest::test_single_node): New function.
(selftest::test_simple_tree): New function.
(selftest::test_disconnected_nodes): New function.
(selftest::et_forest_c_tests): New function.
* fold-const.c: Include "selftest.h".
(selftest::assert_binop_folds_to_const): New function.
(selftest::assert_binop_folds_to_nonlvalue): New function.
(selftest::test_arithmetic_folding): New function.
(selftest::fold_const_c_tests): New function.
* function-tests.c: New file.
* gimple.c: Include "selftest.h".
Include "gimple-pretty-print.h".
(selftest::verify_gimple_pp): New function.
(selftest::test_assign_single): New function.
(selftest::test_assign_binop): New function.
(selftest::test_nop_stmt): New function.
(selftest::test_return_stmt): New function.
(selftest::test_return_without_value): New function.
(selftest::gimple_c_tests): New function.
* hash-map-tests.c: New file.
* hash-set-tests.c: New file.
* input.c: Include "selftest.h".
(selftest::assert_loceq): New function.
(selftest::test_accessing_ordinary_linemaps): New function.
(selftest::test_unknown_location): New function.
(selftest::test_builtins): New function.
(selftest::test_reading_source_line): New function.
(selftest::input_c_tests): New function.
* rtl-tests.c: New file.
* selftest-run-tests.c: New file.
* selftest.c: New file.
* selftest.h: New file.
* spellcheck.c: Include "selftest.h".
(selftest::levenshtein_distance_unit_test_oneway): New function,
adapted from testsuite/gcc.dg/plugin/levenshtein_plugin.c.
(selftest::levenshtein_distance_unit_test): Likewise.
(selftest::spellcheck_c_tests): Likewise.
* toplev.c: Include selftest.h.
(toplev::run_self_tests): New.
(toplev::main): Handle -fself-test.
* toplev.h (toplev::run_self_tests): New.
* tree.c: Include "selftest.h".
(selftest::test_integer_constants): New function.
(selftest::test_identifiers): New function.
(selftest::test_labels): New function.
(selftest::tree_c_tests): New function.
* tree-cfg.c: Include "selftest.h".
(selftest::push_fndecl): New function.
(selftest::test_linear_chain): New function.
(selftest::test_diamond): New function.
(selftest::test_fully_connected): New function.
(selftest::tree_cfg_c_tests): New function.
* vec.c: Include "selftest.h".
(selftest::safe_push_range): New function.
(selftest::test_quick_push): New function.
(selftest::test_safe_push): New function.
(selftest::test_truncate): New function.
(selftest::test_safe_grow_cleared): New function.
(selftest::test_pop): New function.
(selftest::test_safe_insert): New function.
(selftest::test_ordered_remove): New function.
(selftest::test_unordered_remove): New function.
(selftest::test_block_remove): New function.
(selftest::reverse_cmp): New function.
(selftest::test_qsort): New function.
(selftest::vec_c_tests): New function.c.
* wide-int.cc: Include selftest.h and wide-int-print.h.
(selftest::from_int <wide_int>): New function.
(selftest::from_int <offset_int>): New function.
(selftest::from_int <widest_int>): New function.
(selftest::assert_deceq): New function.
(selftest::assert_hexeq): New function.
(selftest::test_printing <VALUE_TYPE>): New function template.
(selftest::test_ops <VALUE_TYPE>): New function template.
(selftest::test_comparisons <VALUE_TYPE>): New function template.
(selftest::run_all_wide_int_tests <VALUE_TYPE>): New function
template.
(selftest::wide_int_cc_tests): New function.
2016-06-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR middle-end/37780
......
......@@ -1264,6 +1264,7 @@ OBJS = \
fold-const.o \
fold-const-call.o \
function.o \
function-tests.o \
fwprop.o \
gcc-rich-location.o \
gcse.o \
......@@ -1299,6 +1300,8 @@ OBJS = \
graphite-sese-to-poly.o \
gtype-desc.o \
haifa-sched.o \
hash-map-tests.o \
hash-set-tests.o \
hsa.o \
hsa-gen.o \
hsa-regalloc.o \
......@@ -1399,6 +1402,7 @@ OBJS = \
resource.o \
rtl-chkp.o \
rtl-error.o \
rtl-tests.o \
rtl.o \
rtlhash.o \
rtlanal.o \
......@@ -1411,6 +1415,7 @@ OBJS = \
sel-sched-ir.o \
sel-sched-dump.o \
sel-sched.o \
selftest-run-tests.o \
sese.o \
shrink-wrap.o \
simplify-rtx.o \
......@@ -1543,13 +1548,14 @@ OBJS = \
# no target dependencies.
OBJS-libcommon = diagnostic.o diagnostic-color.o diagnostic-show-locus.o \
pretty-print.o intl.o \
vec.o input.o version.o hash-table.o ggc-none.o memory-block.o
vec.o input.o version.o hash-table.o ggc-none.o memory-block.o \
selftest.o
# Objects in libcommon-target.a, used by drivers and by the core
# compiler and containing target-dependent code.
OBJS-libcommon-target = $(common_out_object_file) prefix.o params.o \
opts.o opts-common.o options.o vec.o hooks.o common/common-targhooks.o \
hash-table.o file-find.o spellcheck.o
hash-table.o file-find.o spellcheck.o selftest.o
# This lists all host objects for the front ends.
ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
......@@ -1816,10 +1822,10 @@ config.status: $(srcdir)/configure $(srcdir)/config.gcc
quickstrap: all
cd $(toplevel_builddir) && $(MAKE) all-target-libgcc
all.internal: start.encap rest.encap doc
all.internal: start.encap rest.encap doc selftest
# This is what to compile if making a cross-compiler.
all.cross: native gcc-cross$(exeext) cpp$(exeext) specs \
libgcc-support lang.all.cross doc @GENINSRC@ srcextra
libgcc-support lang.all.cross doc selftest @GENINSRC@ srcextra
# This is what must be made before installing GCC and converting libraries.
start.encap: native xgcc$(exeext) cpp$(exeext) specs \
libgcc-support lang.start.encap @GENINSRC@ srcextra
......@@ -1839,6 +1845,21 @@ endif
# This does the things that can't be done on the host machine.
rest.cross: specs
# Run the selftests during the build once we have a driver and a cc1,
# so that self-test failures are caught as early as possible.
# Use "s-selftest" to ensure that we only run the selftests if the
# driver or cc1 change.
.PHONY: selftest
selftest: s-selftest
s-selftest: $(GCC_PASSES) cc1$(exeext) stmp-int-hdrs
$(GCC_FOR_TARGET) -xc -S -c /dev/null -fself-test
$(STAMP) $@
# Convenience method for running selftests under gdb:
.PHONY: selftest-gdb
selftest-gdb: $(GCC_PASSES) cc1$(exeext) stmp-int-hdrs
$(GCC_FOR_TARGET) -xc -S -c /dev/null -fself-test -wrapper gdb,--args
# Recompile all the language-independent object files.
# This is used only if the user explicitly asks for it.
compilations: $(BACKEND)
......@@ -1986,7 +2007,7 @@ gcc-nm.c: gcc-ar.c
cp $^ $@
COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o vec.o ggc-none.o \
collect-utils.o file-find.o hash-table.o
collect-utils.o file-find.o hash-table.o selftest.o
COLLECT2_LIBS = @COLLECT2_LIBS@
collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
# Don't try modifying collect2 (aka ld) in place--it might be linking this.
......
......@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "bitmap.h"
#include "selftest.h"
/* Memory allocation statistics purpose instance. */
mem_alloc_description<bitmap_usage> bitmap_mem_desc;
......@@ -2162,5 +2163,117 @@ debug (const bitmap_head *ptr)
fprintf (stderr, "<nil>\n");
}
#if CHECKING_P
namespace selftest {
/* Selftests for bitmaps. */
/* Freshly-created bitmaps ought to be empty. */
static void
test_gc_alloc ()
{
bitmap b = bitmap_gc_alloc ();
ASSERT_TRUE (bitmap_empty_p (b));
}
/* Verify bitmap_set_range. */
static void
test_set_range ()
{
bitmap b = bitmap_gc_alloc ();
ASSERT_TRUE (bitmap_empty_p (b));
bitmap_set_range (b, 7, 5);
ASSERT_FALSE (bitmap_empty_p (b));
ASSERT_EQ (5, bitmap_count_bits (b));
/* Verify bitmap_bit_p at the boundaries. */
ASSERT_FALSE (bitmap_bit_p (b, 6));
ASSERT_TRUE (bitmap_bit_p (b, 7));
ASSERT_TRUE (bitmap_bit_p (b, 11));
ASSERT_FALSE (bitmap_bit_p (b, 12));
}
/* Verify splitting a range into two pieces using bitmap_clear_bit. */
static void
test_clear_bit_in_middle ()
{
bitmap b = bitmap_gc_alloc ();
/* Set b to [100..200]. */
bitmap_set_range (b, 100, 100);
ASSERT_EQ (100, bitmap_count_bits (b));
/* Clear a bit in the middle. */
bool changed = bitmap_clear_bit (b, 150);
ASSERT_TRUE (changed);
ASSERT_EQ (99, bitmap_count_bits (b));
ASSERT_TRUE (bitmap_bit_p (b, 149));
ASSERT_FALSE (bitmap_bit_p (b, 150));
ASSERT_TRUE (bitmap_bit_p (b, 151));
}
/* Verify bitmap_copy. */
static void
test_copying ()
{
bitmap src = bitmap_gc_alloc ();
bitmap_set_range (src, 40, 10);
bitmap dst = bitmap_gc_alloc ();
ASSERT_FALSE (bitmap_equal_p (src, dst));
bitmap_copy (dst, src);
ASSERT_TRUE (bitmap_equal_p (src, dst));
/* Verify that we can make them unequal again... */
bitmap_set_range (src, 70, 5);
ASSERT_FALSE (bitmap_equal_p (src, dst));
/* ...and that changing src after the copy didn't affect
the other: */
ASSERT_FALSE (bitmap_bit_p (dst, 70));
}
/* Verify bitmap_single_bit_set_p. */
static void
test_bitmap_single_bit_set_p ()
{
bitmap b = bitmap_gc_alloc ();
ASSERT_FALSE (bitmap_single_bit_set_p (b));
bitmap_set_range (b, 42, 1);
ASSERT_TRUE (bitmap_single_bit_set_p (b));
ASSERT_EQ (42, bitmap_first_set_bit (b));
bitmap_set_range (b, 1066, 1);
ASSERT_FALSE (bitmap_single_bit_set_p (b));
ASSERT_EQ (42, bitmap_first_set_bit (b));
bitmap_clear_range (b, 0, 100);
ASSERT_TRUE (bitmap_single_bit_set_p (b));
ASSERT_EQ (1066, bitmap_first_set_bit (b));
}
/* Run all of the selftests within this file. */
void
bitmap_c_tests ()
{
test_gc_alloc ();
test_set_range ();
test_clear_bit_in_middle ();
test_copying ();
test_bitmap_single_bit_set_p ();
}
} // namespace selftest
#endif /* CHECKING_P */
#include "gt-bitmap.h"
......@@ -2066,6 +2066,10 @@ fselective-scheduling2
Common Report Var(flag_selective_scheduling2) Optimization
Run selective scheduling after reload.
fself-test
Common Undocumented Var(flag_self_test)
Run self-tests.
fsel-sched-pipelining
Common Report Var(flag_sel_sched_pipelining) Init(0) Optimization
Perform software pipelining of inner loops during selective scheduling.
......
......@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "backtrace.h"
#include "diagnostic.h"
#include "diagnostic-color.h"
#include "selftest.h"
#ifdef HAVE_TERMIOS_H
# include <termios.h>
......@@ -442,6 +443,123 @@ layout_range::contains_point (int row, int column) const
return column <= m_finish.m_column;
}
#if CHECKING_P
/* A helper function for testing layout_range::contains_point. */
static layout_range
make_range (int start_line, int start_col, int end_line, int end_col)
{
const expanded_location start_exploc
= {"test.c", start_line, start_col, NULL, false};
const expanded_location finish_exploc
= {"test.c", end_line, end_col, NULL, false};
return layout_range (&start_exploc, &finish_exploc, false,
&start_exploc);
}
/* Selftests for layout_range::contains_point. */
/* Selftest for layout_range::contains_point where the layout_range
is a range with start==end i.e. a single point. */
static void
test_range_contains_point_for_single_point ()
{
layout_range point = make_range (7, 10, 7, 10);
/* Before the line. */
ASSERT_FALSE (point.contains_point (6, 1));
/* On the line, but before start. */
ASSERT_FALSE (point.contains_point (7, 9));
/* At the point. */
ASSERT_TRUE (point.contains_point (7, 10));
/* On the line, after the point. */
ASSERT_FALSE (point.contains_point (7, 11));
/* After the line. */
ASSERT_FALSE (point.contains_point (8, 1));
}
/* Selftest for layout_range::contains_point where the layout_range
is the single-line range shown as "Example A" above. */
static void
test_range_contains_point_for_single_line ()
{
layout_range example_a = make_range (2, 22, 2, 38);
/* Before the line. */
ASSERT_FALSE (example_a.contains_point (1, 1));
/* On the line, but before start. */
ASSERT_FALSE (example_a.contains_point (2, 21));
/* On the line, at the start. */
ASSERT_TRUE (example_a.contains_point (2, 22));
/* On the line, within the range. */
ASSERT_TRUE (example_a.contains_point (2, 23));
/* On the line, at the end. */
ASSERT_TRUE (example_a.contains_point (2, 38));
/* On the line, after the end. */
ASSERT_FALSE (example_a.contains_point (2, 39));
/* After the line. */
ASSERT_FALSE (example_a.contains_point (2, 39));
}
/* Selftest for layout_range::contains_point where the layout_range
is the multi-line range shown as "Example B" above. */
static void
test_range_contains_point_for_multiple_lines ()
{
layout_range example_b = make_range (3, 14, 5, 8);
/* Before first line. */
ASSERT_FALSE (example_b.contains_point (1, 1));
/* On the first line, but before start. */
ASSERT_FALSE (example_b.contains_point (3, 13));
/* At the start. */
ASSERT_TRUE (example_b.contains_point (3, 14));
/* On the first line, within the range. */
ASSERT_TRUE (example_b.contains_point (3, 15));
/* On an interior line.
The column number should not matter; try various boundary
values. */
ASSERT_TRUE (example_b.contains_point (4, 1));
ASSERT_TRUE (example_b.contains_point (4, 7));
ASSERT_TRUE (example_b.contains_point (4, 8));
ASSERT_TRUE (example_b.contains_point (4, 9));
ASSERT_TRUE (example_b.contains_point (4, 13));
ASSERT_TRUE (example_b.contains_point (4, 14));
ASSERT_TRUE (example_b.contains_point (4, 15));
/* On the final line, before the end. */
ASSERT_TRUE (example_b.contains_point (5, 7));
/* On the final line, at the end. */
ASSERT_TRUE (example_b.contains_point (5, 8));
/* On the final line, after the end. */
ASSERT_FALSE (example_b.contains_point (5, 9));
/* After the line. */
ASSERT_FALSE (example_b.contains_point (6, 1));
}
#endif /* #if CHECKING_P */
/* Given a source line LINE of length LINE_WIDTH, determine the width
without any trailing whitespace. */
......@@ -465,6 +583,34 @@ get_line_width_without_trailing_whitespace (const char *line, int line_width)
return result;
}
#if CHECKING_P
/* A helper function for testing get_line_width_without_trailing_whitespace. */
static void
assert_eq (const char *line, int expected_width)
{
int actual_value
= get_line_width_without_trailing_whitespace (line, strlen (line));
ASSERT_EQ (actual_value, expected_width);
}
/* Verify that get_line_width_without_trailing_whitespace is sane for
various inputs. It is not required to handle newlines. */
static void
test_get_line_width_without_trailing_whitespace ()
{
assert_eq ("", 0);
assert_eq (" ", 0);
assert_eq ("\t", 0);
assert_eq ("hello world", 11);
assert_eq ("hello world ", 11);
assert_eq ("hello world \t\t ", 11);
}
#endif /* #if CHECKING_P */
/* Helper function for layout's ctor, for sanitizing locations relative
to the primary location within a diagnostic.
......@@ -1171,3 +1317,23 @@ diagnostic_show_locus (diagnostic_context * context,
pp_set_prefix (context->printer, saved_prefix);
}
#if CHECKING_P
namespace selftest {
/* Run all of the selftests within this file. */
void
diagnostic_show_locus_c_tests ()
{
test_range_contains_point_for_single_point ();
test_range_contains_point_for_single_line ();
test_range_contains_point_for_multiple_lines ();
test_get_line_width_without_trailing_whitespace ();
}
} // namespace selftest
#endif /* #if CHECKING_P */
......@@ -27,6 +27,7 @@ License along with libiberty; see the file COPYING3. If not see
#include "coretypes.h"
#include "alloc-pool.h"
#include "et-forest.h"
#include "selftest.h"
/* We do not enable this with CHECKING_P, since it is awfully slow. */
#undef DEBUG_ET
......@@ -764,3 +765,120 @@ et_root (struct et_node *node)
return r->of;
}
#if CHECKING_P
namespace selftest {
/* Selftests for et-forest.c. */
/* Perform sanity checks for a tree consisting of a single node. */
static void
test_single_node ()
{
void *test_data = (void *)0xcafebabe;
et_node *n = et_new_tree (test_data);
ASSERT_EQ (n->data, test_data);
ASSERT_EQ (n, et_root (n));
et_free_tree (n);
}
/* Test of this tree:
a
/ \
/ \
b c
/ \ |
d e f. */
static void
test_simple_tree ()
{
et_node *a = et_new_tree (NULL);
et_node *b = et_new_tree (NULL);
et_node *c = et_new_tree (NULL);
et_node *d = et_new_tree (NULL);
et_node *e = et_new_tree (NULL);
et_node *f = et_new_tree (NULL);
et_set_father (b, a);
et_set_father (c, a);
et_set_father (d, b);
et_set_father (e, b);
et_set_father (f, c);
ASSERT_TRUE (et_below (a, a));
ASSERT_TRUE (et_below (b, a));
ASSERT_TRUE (et_below (c, a));
ASSERT_TRUE (et_below (d, a));
ASSERT_TRUE (et_below (e, a));
ASSERT_TRUE (et_below (f, a));
ASSERT_FALSE (et_below (a, b));
ASSERT_TRUE (et_below (b, b));
ASSERT_FALSE (et_below (c, b));
ASSERT_TRUE (et_below (d, b));
ASSERT_TRUE (et_below (e, b));
ASSERT_FALSE (et_below (f, b));
ASSERT_FALSE (et_below (a, c));
ASSERT_FALSE (et_below (b, c));
ASSERT_TRUE (et_below (c, c));
ASSERT_FALSE (et_below (d, c));
ASSERT_FALSE (et_below (e, c));
ASSERT_TRUE (et_below (f, c));
ASSERT_FALSE (et_below (a, d));
ASSERT_FALSE (et_below (b, d));
ASSERT_FALSE (et_below (c, d));
ASSERT_TRUE (et_below (d, d));
ASSERT_FALSE (et_below (e, d));
ASSERT_FALSE (et_below (f, d));
ASSERT_FALSE (et_below (a, e));
ASSERT_FALSE (et_below (b, e));
ASSERT_FALSE (et_below (c, e));
ASSERT_FALSE (et_below (d, e));
ASSERT_TRUE (et_below (e, e));
ASSERT_FALSE (et_below (f, e));
ASSERT_FALSE (et_below (a, f));
ASSERT_FALSE (et_below (b, f));
ASSERT_FALSE (et_below (c, f));
ASSERT_FALSE (et_below (d, f));
ASSERT_FALSE (et_below (e, f));
ASSERT_TRUE (et_below (f, f));
et_free_tree_force (a);
}
/* Verify that two disconnected nodes are unrelated. */
static void
test_disconnected_nodes ()
{
et_node *a = et_new_tree (NULL);
et_node *b = et_new_tree (NULL);
ASSERT_FALSE (et_below (a, b));
ASSERT_FALSE (et_below (b, a));
et_free_tree (a);
et_free_tree (b);
}
/* Run all of the selftests within this file. */
void
et_forest_c_tests ()
{
test_single_node ();
test_simple_tree ();
test_disconnected_nodes ();
}
} // namespace selftest
#endif /* CHECKING_P */
......@@ -76,6 +76,7 @@ along with GCC; see the file COPYING3. If not see
#include "case-cfn-macros.h"
#include "stringpool.h"
#include "tree-ssanames.h"
#include "selftest.h"
#ifndef LOAD_EXTEND_OP
#define LOAD_EXTEND_OP(M) UNKNOWN
......@@ -14496,3 +14497,82 @@ c_getstr (tree src)
return TREE_STRING_POINTER (src) + tree_to_uhwi (offset_node);
}
#if CHECKING_P
namespace selftest {
/* Helper functions for writing tests of folding trees. */
/* Verify that the binary op (LHS CODE RHS) folds to CONSTANT. */
static void
assert_binop_folds_to_const (tree lhs, enum tree_code code, tree rhs,
tree constant)
{
ASSERT_EQ (constant, fold_build2 (code, TREE_TYPE (lhs), lhs, rhs));
}
/* Verify that the binary op (LHS CODE RHS) folds to an NON_LVALUE_EXPR
wrapping WRAPPED_EXPR. */
static void
assert_binop_folds_to_nonlvalue (tree lhs, enum tree_code code, tree rhs,
tree wrapped_expr)
{
tree result = fold_build2 (code, TREE_TYPE (lhs), lhs, rhs);
ASSERT_NE (wrapped_expr, result);
ASSERT_EQ (NON_LVALUE_EXPR, TREE_CODE (result));
ASSERT_EQ (wrapped_expr, TREE_OPERAND (result, 0));
}
/* Verify that various arithmetic binary operations are folded
correctly. */
static void
test_arithmetic_folding ()
{
tree type = integer_type_node;
tree x = create_tmp_var_raw (type, "x");
tree zero = build_zero_cst (type);
tree one = build_int_cst (type, 1);
/* Addition. */
/* 1 <-- (0 + 1) */
assert_binop_folds_to_const (zero, PLUS_EXPR, one,
one);
assert_binop_folds_to_const (one, PLUS_EXPR, zero,
one);
/* (nonlvalue)x <-- (x + 0) */
assert_binop_folds_to_nonlvalue (x, PLUS_EXPR, zero,
x);
/* Subtraction. */
/* 0 <-- (x - x) */
assert_binop_folds_to_const (x, MINUS_EXPR, x,
zero);
assert_binop_folds_to_nonlvalue (x, MINUS_EXPR, zero,
x);
/* Multiplication. */
/* 0 <-- (x * 0) */
assert_binop_folds_to_const (x, MULT_EXPR, zero,
zero);
/* (nonlvalue)x <-- (x * 1) */
assert_binop_folds_to_nonlvalue (x, MULT_EXPR, one,
x);
}
/* Run all of the selftests within this file. */
void
fold_const_c_tests ()
{
test_arithmetic_folding ();
}
} // namespace selftest
#endif /* CHECKING_P */
......@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-walk.h"
#include "gimplify.h"
#include "target.h"
#include "selftest.h"
#include "gimple-pretty-print.h"
/* All the tuples have their operand vector (if present) at the very bottom
......@@ -3022,3 +3024,138 @@ maybe_remove_unused_call_args (struct function *fn, gimple *stmt)
update_stmt_fn (fn, stmt);
}
}
#if CHECKING_P
namespace selftest {
/* Selftests for core gimple structures. */
/* Verify that STMT is pretty-printed as EXPECTED.
Helper function for selftests. */
static void
verify_gimple_pp (const char *expected, gimple *stmt)
{
pretty_printer pp;
pp_gimple_stmt_1 (&pp, stmt, 0 /* spc */, 0 /* flags */);
ASSERT_STREQ (expected, pp_formatted_text (&pp));
}
/* Build a GIMPLE_ASSIGN equivalent to
tmp = 5;
and verify various properties of it. */
static void
test_assign_single ()
{
tree type = integer_type_node;
tree lhs = build_decl (UNKNOWN_LOCATION, VAR_DECL,
get_identifier ("tmp"),
type);
tree rhs = build_int_cst (type, 5);
gassign *stmt = gimple_build_assign (lhs, rhs);
verify_gimple_pp ("tmp = 5;", stmt);
ASSERT_TRUE (is_gimple_assign (stmt));
ASSERT_EQ (lhs, gimple_assign_lhs (stmt));
ASSERT_EQ (lhs, gimple_get_lhs (stmt));
ASSERT_EQ (rhs, gimple_assign_rhs1 (stmt));
ASSERT_EQ (NULL, gimple_assign_rhs2 (stmt));
ASSERT_EQ (NULL, gimple_assign_rhs3 (stmt));
ASSERT_TRUE (gimple_assign_single_p (stmt));
ASSERT_EQ (INTEGER_CST, gimple_assign_rhs_code (stmt));
}
/* Build a GIMPLE_ASSIGN equivalent to
tmp = a * b;
and verify various properties of it. */
static void
test_assign_binop ()
{
tree type = integer_type_node;
tree lhs = build_decl (UNKNOWN_LOCATION, VAR_DECL,
get_identifier ("tmp"),
type);
tree a = build_decl (UNKNOWN_LOCATION, VAR_DECL,
get_identifier ("a"),
type);
tree b = build_decl (UNKNOWN_LOCATION, VAR_DECL,
get_identifier ("b"),
type);
gassign *stmt = gimple_build_assign (lhs, MULT_EXPR, a, b);
verify_gimple_pp ("tmp = a * b;", stmt);
ASSERT_TRUE (is_gimple_assign (stmt));
ASSERT_EQ (lhs, gimple_assign_lhs (stmt));
ASSERT_EQ (lhs, gimple_get_lhs (stmt));
ASSERT_EQ (a, gimple_assign_rhs1 (stmt));
ASSERT_EQ (b, gimple_assign_rhs2 (stmt));
ASSERT_EQ (NULL, gimple_assign_rhs3 (stmt));
ASSERT_FALSE (gimple_assign_single_p (stmt));
ASSERT_EQ (MULT_EXPR, gimple_assign_rhs_code (stmt));
}
/* Build a GIMPLE_NOP and verify various properties of it. */
static void
test_nop_stmt ()
{
gimple *stmt = gimple_build_nop ();
verify_gimple_pp ("GIMPLE_NOP", stmt);
ASSERT_EQ (GIMPLE_NOP, gimple_code (stmt));
ASSERT_EQ (NULL, gimple_get_lhs (stmt));
ASSERT_FALSE (gimple_assign_single_p (stmt));
}
/* Build a GIMPLE_RETURN equivalent to
return 7;
and verify various properties of it. */
static void
test_return_stmt ()
{
tree type = integer_type_node;
tree val = build_int_cst (type, 7);
greturn *stmt = gimple_build_return (val);
verify_gimple_pp ("return 7;", stmt);
ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt));
ASSERT_EQ (NULL, gimple_get_lhs (stmt));
ASSERT_EQ (val, gimple_return_retval (stmt));
ASSERT_FALSE (gimple_assign_single_p (stmt));
}
/* Build a GIMPLE_RETURN equivalent to
return;
and verify various properties of it. */
static void
test_return_without_value ()
{
greturn *stmt = gimple_build_return (NULL);
verify_gimple_pp ("return;", stmt);
ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt));
ASSERT_EQ (NULL, gimple_get_lhs (stmt));
ASSERT_EQ (NULL, gimple_return_retval (stmt));
ASSERT_FALSE (gimple_assign_single_p (stmt));
}
/* Run all of the selftests within this file. */
void
gimple_c_tests ()
{
test_assign_single ();
test_assign_binop ();
test_nop_stmt ();
test_return_stmt ();
test_return_without_value ();
}
} // namespace selftest
#endif /* CHECKING_P */
/* Unit tests for hash-map.h.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "opts.h"
#include "signop.h"
#include "hash-set.h"
#include "fixed-value.h"
#include "alias.h"
#include "flags.h"
#include "symtab.h"
#include "tree-core.h"
#include "stor-layout.h"
#include "tree.h"
#include "stringpool.h"
#include "selftest.h"
#if CHECKING_P
namespace selftest {
/* Construct a hash_map <const char *, int> and verify that
various operations work correctly. */
static void
test_map_of_strings_to_int ()
{
hash_map <const char *, int> m;
const char *ostrich = "ostrich";
const char *elephant = "elephant";
const char *ant = "ant";
const char *spider = "spider";
const char *millipede = "Illacme plenipes";
const char *eric = "half a bee";
/* A fresh hash_map should be empty. */
ASSERT_EQ (0, m.elements ());
ASSERT_EQ (NULL, m.get (ostrich));
/* Populate the hash_map. */
ASSERT_EQ (false, m.put (ostrich, 2));
ASSERT_EQ (false, m.put (elephant, 4));
ASSERT_EQ (false, m.put (ant, 6));
ASSERT_EQ (false, m.put (spider, 8));
ASSERT_EQ (false, m.put (millipede, 750));
ASSERT_EQ (false, m.put (eric, 3));
/* Verify that we can recover the stored values. */
ASSERT_EQ (6, m.elements ());
ASSERT_EQ (2, *m.get (ostrich));
ASSERT_EQ (4, *m.get (elephant));
ASSERT_EQ (6, *m.get (ant));
ASSERT_EQ (8, *m.get (spider));
ASSERT_EQ (750, *m.get (millipede));
ASSERT_EQ (3, *m.get (eric));
/* Verify removing an item. */
m.remove (eric);
ASSERT_EQ (5, m.elements ());
ASSERT_EQ (NULL, m.get (eric));
}
/* Run all of the selftests within this file. */
void
hash_map_tests_c_tests ()
{
test_map_of_strings_to_int ();
}
} // namespace selftest
#endif /* CHECKING_P */
/* Unit tests for hash-set.h.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "opts.h"
#include "signop.h"
#include "hash-set.h"
#include "selftest.h"
#if CHECKING_P
namespace selftest {
/* Construct a hash_set <const char *> and verify that various operations
work correctly. */
static void
test_set_of_strings ()
{
hash_set <const char *> s;
ASSERT_EQ (0, s.elements ());
const char *red = "red";
const char *green = "green";
const char *blue = "blue";
ASSERT_EQ (false, s.contains (red));
/* Populate the hash_set. */
ASSERT_EQ (false, s.add (red));
ASSERT_EQ (false, s.add (green));
ASSERT_EQ (false, s.add (blue));
/* Verify that the values are now within the set. */
ASSERT_EQ (true, s.contains (red));
ASSERT_EQ (true, s.contains (green));
ASSERT_EQ (true, s.contains (blue));
}
/* Run all of the selftests within this file. */
void
hash_set_tests_c_tests ()
{
test_set_of_strings ();
}
} // namespace selftest
#endif /* #if CHECKING_P */
......@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "intl.h"
#include "diagnostic-core.h"
#include "selftest.h"
/* This is a cache used by get_next_line to store the content of a
file to be searched for file lines. */
......@@ -1136,3 +1137,118 @@ dump_location_info (FILE *stream)
dump_labelled_location_range (stream, "AD-HOC LOCATIONS",
MAX_SOURCE_LOCATION + 1, UINT_MAX);
}
#if CHECKING_P
namespace selftest {
/* Selftests of location handling. */
/* Verify the result of LOCATION_FILE/LOCATION_LINE/LOCATION_COLUMN
on LOC. */
static void
assert_loceq (const char *exp_filename, int exp_linenum, int exp_colnum,
location_t loc)
{
ASSERT_STREQ (exp_filename, LOCATION_FILE (loc));
ASSERT_EQ (exp_linenum, LOCATION_LINE (loc));
ASSERT_EQ (exp_colnum, LOCATION_COLUMN (loc));
}
/* Verify basic operation of ordinary linemaps. */
static void
test_accessing_ordinary_linemaps ()
{
/* Build a simple linemap describing some locations. */
linemap_add (line_table, LC_ENTER, false, "foo.c", 0);
linemap_line_start (line_table, 1, 100);
location_t loc_a = linemap_position_for_column (line_table, 1);
location_t loc_b = linemap_position_for_column (line_table, 23);
linemap_line_start (line_table, 2, 100);
location_t loc_c = linemap_position_for_column (line_table, 1);
location_t loc_d = linemap_position_for_column (line_table, 17);
/* Example of a very long line. */
linemap_line_start (line_table, 3, 2000);
location_t loc_e = linemap_position_for_column (line_table, 700);
linemap_add (line_table, LC_LEAVE, false, NULL, 0);
/* Multiple files. */
linemap_add (line_table, LC_ENTER, false, "bar.c", 0);
linemap_line_start (line_table, 1, 200);
location_t loc_f = linemap_position_for_column (line_table, 150);
linemap_add (line_table, LC_LEAVE, false, NULL, 0);
/* Verify that we can recover the location info. */
assert_loceq ("foo.c", 1, 1, loc_a);
assert_loceq ("foo.c", 1, 23, loc_b);
assert_loceq ("foo.c", 2, 1, loc_c);
assert_loceq ("foo.c", 2, 17, loc_d);
assert_loceq ("foo.c", 3, 700, loc_e);
assert_loceq ("bar.c", 1, 150, loc_f);
ASSERT_FALSE (is_location_from_builtin_token (loc_a));
}
/* Verify various properties of UNKNOWN_LOCATION. */
static void
test_unknown_location ()
{
ASSERT_EQ (NULL, LOCATION_FILE (UNKNOWN_LOCATION));
ASSERT_EQ (0, LOCATION_LINE (UNKNOWN_LOCATION));
ASSERT_EQ (0, LOCATION_COLUMN (UNKNOWN_LOCATION));
}
/* Verify various properties of BUILTINS_LOCATION. */
static void
test_builtins ()
{
assert_loceq ("<built-in>", 0, 0, BUILTINS_LOCATION);
ASSERT_PRED1 (is_location_from_builtin_token, BUILTINS_LOCATION);
}
/* Verify reading of input files (e.g. for caret-based diagnostics). */
static void
test_reading_source_line ()
{
/* We will read *this* source file, using __FILE__.
Here is some specific text to read and test for:
The quick brown fox jumps over the lazy dog. */
const int linenum_after_test_message = __LINE__;
const int linenum = linenum_after_test_message - 1;
int line_size;
const char *source_line = location_get_source_line (__FILE__, linenum, &line_size);
ASSERT_TRUE (source_line != NULL);
ASSERT_EQ (53, line_size);
if (!strncmp (" The quick brown fox jumps over the lazy dog. */",
source_line, line_size))
::selftest::pass (__FILE__, __LINE__,
"source_line matched expected value");
else
::selftest::fail (__FILE__, __LINE__,
"source_line did not match expected value");
}
/* Run all of the selftests within this file. */
void
input_c_tests ()
{
test_accessing_ordinary_linemaps ();
test_unknown_location ();
test_builtins ();
test_reading_source_line ();
}
} // namespace selftest
#endif /* CHECKING_P */
/* Unit tests for RTL-handling.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "opts.h"
#include "signop.h"
#include "hash-set.h"
#include "fixed-value.h"
#include "alias.h"
#include "flags.h"
#include "symtab.h"
#include "tree-core.h"
#include "stor-layout.h"
#include "tree.h"
#include "stringpool.h"
#include "stor-layout.h"
#include "rtl.h"
#include "pretty-print.h"
#include "cfgbuild.h"
#include "print-rtl.h"
#include "selftest.h"
#include "function.h"
#include "emit-rtl.h"
#if CHECKING_P
namespace selftest {
/* Verify that PAT is printed as EXPECTED. Helper function for
selftests. */
static void
verify_print_pattern (const char *expected, rtx pat)
{
pretty_printer pp;
print_pattern (&pp, pat, 1);
ASSERT_STREQ (expected, pp_formatted_text (&pp));
}
/* Unit testing of "single_set". */
static void
test_single_set ()
{
/* A label is not a SET. */
ASSERT_EQ (NULL_RTX, single_set (gen_label_rtx ()));
/* An unconditional jump insn is a single SET. */
rtx set_pc = gen_rtx_SET (pc_rtx,
gen_rtx_LABEL_REF (VOIDmode,
gen_label_rtx ()));
rtx_insn *jump_insn = emit_jump_insn (set_pc);
ASSERT_EQ (set_pc, single_set (jump_insn));
/* etc */
}
/* Construct an unconditional jump to a label, and verify that
various properties of it are sane. */
static void
test_uncond_jump ()
{
rtx_insn *label = gen_label_rtx ();
rtx jump_pat = gen_rtx_SET (pc_rtx,
gen_rtx_LABEL_REF (VOIDmode,
label));
ASSERT_EQ (SET, jump_pat->code);
ASSERT_EQ (LABEL_REF, SET_SRC (jump_pat)->code);
ASSERT_EQ (label, LABEL_REF_LABEL (SET_SRC (jump_pat)));
ASSERT_EQ (PC, SET_DEST (jump_pat)->code);
verify_print_pattern ("pc=L0", jump_pat);
rtx_insn *jump_insn = emit_jump_insn (jump_pat);
ASSERT_FALSE (any_condjump_p (jump_insn));
ASSERT_TRUE (any_uncondjump_p (jump_insn));
ASSERT_TRUE (pc_set (jump_insn));
ASSERT_TRUE (simplejump_p (jump_insn));
ASSERT_TRUE (onlyjump_p (jump_insn));
ASSERT_TRUE (control_flow_insn_p (jump_insn));
}
/* Run all of the selftests within this file. */
void
rtl_tests_c_tests ()
{
test_single_set ();
test_uncond_jump ();
/* Purge state. */
set_first_insn (NULL);
set_last_insn (NULL);
}
} // namespace selftest
#endif /* #if CHECKING_P */
/* Implementation of selftests.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "selftest.h"
/* This function needed to be split out from selftest.c as it references
tests from the whole source tree, and so is within
OBJS in Makefile.in, whereas selftest.o is within OBJS-libcommon.
This allows us to embed tests within files in OBJS-libcommon without
introducing a dependency on objects within OBJS. */
#if CHECKING_P
/* Run all tests, aborting if any fail. */
void
selftest::run_tests ()
{
long start_time = get_run_time ();
/* Run all the tests, in hand-coded order of (approximate) dependencies:
run the tests for lowest-level code first. */
/* Low-level data structures. */
bitmap_c_tests ();
et_forest_c_tests ();
hash_map_tests_c_tests ();
hash_set_tests_c_tests ();
vec_c_tests ();
wide_int_cc_tests ();
/* Mid-level data structures. */
input_c_tests ();
tree_c_tests ();
gimple_c_tests ();
rtl_tests_c_tests ();
/* Higher-level tests, or for components that other selftests don't
rely on. */
diagnostic_show_locus_c_tests ();
fold_const_c_tests ();
spellcheck_c_tests ();
tree_cfg_c_tests ();
/* This one relies on most of the above. */
function_tests_c_tests ();
/* Finished running tests. */
long finish_time = get_run_time ();
long elapsed_time = finish_time - start_time;
fprintf (stderr,
"-fself-test: %i pass(es) in %ld.%06ld seconds\n",
num_passes,
elapsed_time / 1000000, elapsed_time % 1000000);
}
#endif /* #if CHECKING_P */
/* A self-testing framework, for use by -fself-test.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "selftest.h"
#if CHECKING_P
int selftest::num_passes;
/* Record the successful outcome of some aspect of a test. */
void
selftest::pass (const char */*file*/, int /*line*/, const char */*msg*/)
{
num_passes++;
}
/* Report the failed outcome of some aspect of a test and abort. */
void
selftest::fail (const char *file, int line, const char *msg)
{
fprintf (stderr,"%s:%i: FAIL: %s\n", file, line, msg);
/* TODO: add calling function name as well? */
abort ();
}
#endif /* #if CHECKING_P */
/* A self-testing framework, for use by -fself-test.
Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_SELFTEST_H
#define GCC_SELFTEST_H
/* The selftest code should entirely disappear in a production
configuration, hence we guard all of it with #if CHECKING_P. */
#if CHECKING_P
namespace selftest {
/* The entrypoint for running all tests. */
extern void run_tests ();
/* Record the successful outcome of some aspect of the test. */
extern void pass (const char *file, int line, const char *msg);
/* Report the failed outcome of some aspect of the test and abort. */
extern void fail (const char *file, int line, const char *msg);
/* Declarations for specific families of tests (by source file), in
alphabetical order. */
extern void bitmap_c_tests ();
extern void diagnostic_show_locus_c_tests ();
extern void et_forest_c_tests ();
extern void fold_const_c_tests ();
extern void function_tests_c_tests ();
extern void gimple_c_tests ();
extern void hash_map_tests_c_tests ();
extern void hash_set_tests_c_tests ();
extern void input_c_tests ();
extern void rtl_tests_c_tests ();
extern void spellcheck_c_tests ();
extern void tree_c_tests ();
extern void tree_cfg_c_tests ();
extern void vec_c_tests ();
extern void wide_int_cc_tests ();
extern int num_passes;
} /* end of namespace selftest. */
/* Macros for writing tests. */
/* Evaluate EXPR and coerce to bool, calling
::selftest::pass if it is true,
::selftest::fail if it false. */
#define ASSERT_TRUE(EXPR) \
SELFTEST_BEGIN_STMT \
const char *desc = "ASSERT_TRUE (" #EXPR ")"; \
bool actual = (EXPR); \
if (actual) \
::selftest::pass (__FILE__, __LINE__, desc); \
else \
::selftest::fail (__FILE__, __LINE__, desc); \
SELFTEST_END_STMT
/* Evaluate EXPR and coerce to bool, calling
::selftest::pass if it is false,
::selftest::fail if it true. */
#define ASSERT_FALSE(EXPR) \
SELFTEST_BEGIN_STMT \
const char *desc = "ASSERT_FALSE (" #EXPR ")"; \
bool actual = (EXPR); \
if (actual) \
::selftest::fail (__FILE__, __LINE__, desc); \
else \
::selftest::pass (__FILE__, __LINE__, desc); \
SELFTEST_END_STMT
/* Evaluate EXPECTED and ACTUAL and compare them with ==, calling
::selftest::pass if they are equal,
::selftest::fail if they are non-equal. */
#define ASSERT_EQ(EXPECTED, ACTUAL) \
SELFTEST_BEGIN_STMT \
const char *desc = "ASSERT_EQ (" #EXPECTED ", " #ACTUAL ")"; \
if ((EXPECTED) == (ACTUAL)) \
::selftest::pass (__FILE__, __LINE__, desc); \
else \
::selftest::fail (__FILE__, __LINE__, desc); \
SELFTEST_END_STMT
/* Evaluate EXPECTED and ACTUAL and compare them with !=, calling
::selftest::pass if they are non-equal,
::selftest::fail if they are equal. */
#define ASSERT_NE(EXPECTED, ACTUAL) \
SELFTEST_BEGIN_STMT \
const char *desc = "ASSERT_NE (" #EXPECTED ", " #ACTUAL ")"; \
if ((EXPECTED) != (ACTUAL)) \
::selftest::pass (__FILE__, __LINE__, desc); \
else \
::selftest::fail (__FILE__, __LINE__, desc); \
SELFTEST_END_STMT
/* Evaluate EXPECTED and ACTUAL and compare them with strcmp, calling
::selftest::pass if they are equal,
::selftest::fail if they are non-equal. */
#define ASSERT_STREQ(EXPECTED, ACTUAL) \
SELFTEST_BEGIN_STMT \
const char *desc = "ASSERT_STREQ (" #EXPECTED ", " #ACTUAL ")"; \
const char *expected_ = (EXPECTED); \
const char *actual_ = (ACTUAL); \
if (0 == strcmp (expected_, actual_)) \
::selftest::pass (__FILE__, __LINE__, desc); \
else \
::selftest::fail (__FILE__, __LINE__, desc); \
SELFTEST_END_STMT
/* Evaluate PRED1 (VAL1), calling ::selftest::pass if it is true,
::selftest::fail if it is false. */
#define ASSERT_PRED1(PRED1, VAL1) \
SELFTEST_BEGIN_STMT \
const char *desc = "ASSERT_PRED1 (" #PRED1 ", " #VAL1 ")"; \
bool actual = (PRED1) (VAL1); \
if (actual) \
::selftest::pass (__FILE__, __LINE__, desc); \
else \
::selftest::fail (__FILE__, __LINE__, desc); \
SELFTEST_END_STMT
#define SELFTEST_BEGIN_STMT do {
#define SELFTEST_END_STMT } while (0)
#endif /* #if CHECKING_P */
#endif /* GCC_SELFTEST_H */
......@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "tree.h"
#include "spellcheck.h"
#include "selftest.h"
/* The Levenshtein distance is an "edit-distance": the minimal
number of one-character insertions, removals or substitutions
......@@ -165,3 +166,60 @@ find_closest_string (const char *target,
return best_candidate;
}
#if CHECKING_P
namespace selftest {
/* Selftests. */
/* Verify that the levenshtein_distance (A, B) equals the expected
value. */
static void
levenshtein_distance_unit_test_oneway (const char *a, const char *b,
edit_distance_t expected)
{
edit_distance_t actual = levenshtein_distance (a, b);
ASSERT_EQ (actual, expected);
}
/* Verify that both
levenshtein_distance (A, B)
and
levenshtein_distance (B, A)
equal the expected value, to ensure that the function is symmetric. */
static void
levenshtein_distance_unit_test (const char *a, const char *b,
edit_distance_t expected)
{
levenshtein_distance_unit_test_oneway (a, b, expected);
levenshtein_distance_unit_test_oneway (b, a, expected);
}
/* Verify levenshtein_distance for a variety of pairs of pre-canned
inputs, comparing against known-good values. */
void
spellcheck_c_tests ()
{
levenshtein_distance_unit_test ("", "nonempty", strlen ("nonempty"));
levenshtein_distance_unit_test ("saturday", "sunday", 3);
levenshtein_distance_unit_test ("foo", "m_foo", 2);
levenshtein_distance_unit_test ("hello_world", "HelloWorld", 3);
levenshtein_distance_unit_test
("the quick brown fox jumps over the lazy dog", "dog", 40);
levenshtein_distance_unit_test
("the quick brown fox jumps over the lazy dog",
"the quick brown dog jumps over the lazy fox",
4);
levenshtein_distance_unit_test
("Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
"All your base are belong to us",
44);
}
} // namespace selftest
#endif /* #if CHECKING_P */
2016-06-06 David Malcolm <dmalcolm@redhat.com>
* gcc.dg/plugin/levenshtein-test-1.c: Delete.
* gcc.dg/plugin/levenshtein_plugin.c: Delete.
* gcc.dg/plugin/plugin.exp (plugin_test_list): Remove the
above.
2016-06-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR middle-end/37780
......
/* Placeholder C source file for unit-testing gcc/spellcheck.c. */
/* { dg-do compile } */
/* { dg-options "-O" } */
int
main (int argc, char **argv)
{
return 0;
}
/* Plugin for unittesting gcc/spellcheck.h. */
#include "config.h"
#include "gcc-plugin.h"
#include "system.h"
#include "coretypes.h"
#include "spellcheck.h"
#include "diagnostic.h"
int plugin_is_GPL_compatible;
static void
levenshtein_distance_unit_test_oneway (const char *a, const char *b,
edit_distance_t expected)
{
edit_distance_t actual = levenshtein_distance (a, b);
if (actual != expected)
error ("levenshtein_distance (\"%s\", \"%s\") : expected: %i got %i",
a, b, expected, actual);
}
static void
levenshtein_distance_unit_test (const char *a, const char *b,
edit_distance_t expected)
{
/* Run every test both ways to ensure it's symmetric. */
levenshtein_distance_unit_test_oneway (a, b, expected);
levenshtein_distance_unit_test_oneway (b, a, expected);
}
/* Callback handler for the PLUGIN_FINISH event; run
levenshtein_distance unit tests here. */
static void
on_finish (void */*gcc_data*/, void */*user_data*/)
{
levenshtein_distance_unit_test ("", "nonempty", strlen ("nonempty"));
levenshtein_distance_unit_test ("saturday", "sunday", 3);
levenshtein_distance_unit_test ("foo", "m_foo", 2);
levenshtein_distance_unit_test ("hello_world", "HelloWorld", 3);
levenshtein_distance_unit_test
("the quick brown fox jumps over the lazy dog", "dog", 40);
levenshtein_distance_unit_test
("the quick brown fox jumps over the lazy dog",
"the quick brown dog jumps over the lazy fox",
4);
levenshtein_distance_unit_test
("Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
"All your base are belong to us",
44);
}
int
plugin_init (struct plugin_name_args *plugin_info,
struct plugin_gcc_version */*version*/)
{
register_callback (plugin_info->base_name,
PLUGIN_FINISH,
on_finish,
NULL); /* void *user_data */
return 0;
}
......@@ -70,7 +70,6 @@ set plugin_test_list [list \
diagnostic-test-expressions-1.c } \
{ diagnostic_plugin_show_trees.c \
diagnostic-test-show-trees-1.c } \
{ levenshtein_plugin.c levenshtein-test-1.c } \
{ location_overflow_plugin.c \
location-overflow-test-1.c \
location-overflow-test-2.c } \
......
......@@ -87,6 +87,8 @@ along with GCC; see the file COPYING3. If not see
#include "xcoffout.h" /* Needed for external data declarations. */
#endif
#include "selftest.h"
static void general_init (const char *, bool);
static void do_compile ();
static void process_options (void);
......@@ -2031,6 +2033,27 @@ toplev::start_timevars ()
timevar_start (TV_TOTAL);
}
/* Handle -fself-test. */
void
toplev::run_self_tests ()
{
#if CHECKING_P
/* Reset some state. */
input_location = UNKNOWN_LOCATION;
bitmap_obstack_initialize (NULL);
/* Run the tests; any failures will lead to an abort of the process.
Use "make selftests-gdb" to run under the debugger. */
::selftest::run_tests ();
/* Cleanup. */
bitmap_obstack_release (NULL);
#else
inform (UNKNOWN_LOCATION, "self-tests are not enabled in this build");
#endif /* #if CHECKING_P */
}
/* Entry point of cc1, cc1plus, jc1, f771, etc.
Exit code is FATAL_EXIT_CODE if can't open files or if there were
any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
......@@ -2098,6 +2121,9 @@ toplev::main (int argc, char **argv)
if (warningcount || errorcount || werrorcount)
print_ignored_options ();
if (flag_self_test)
run_self_tests ();
/* Invoke registered plugin callbacks if any. Some plugins could
emit some diagnostics here. */
invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
......
......@@ -42,6 +42,8 @@ private:
void start_timevars ();
void run_self_tests ();
bool m_use_TV_TOTAL;
bool m_init_signals;
};
......
......@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-cfgcleanup.h"
#include "gimplify.h"
#include "attribs.h"
#include "selftest.h"
/* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */
......@@ -9195,3 +9196,280 @@ gt_pch_nx (edge_def *e, gt_pointer_operator op, void *cookie)
op (&(e->insns.r), cookie);
op (&(block), cookie);
}
#if CHECKING_P
namespace selftest {
/* Helper function for CFG selftests: create a dummy function decl
and push it as cfun. */
static tree
push_fndecl (const char *name)
{
tree fn_type = build_function_type_array (integer_type_node, 0, NULL);
/* FIXME: this uses input_location: */
tree fndecl = build_fn_decl (name, fn_type);
tree retval = build_decl (UNKNOWN_LOCATION, RESULT_DECL,
NULL_TREE, integer_type_node);
DECL_RESULT (fndecl) = retval;
push_struct_function (fndecl);
function *fun = DECL_STRUCT_FUNCTION (fndecl);
ASSERT_TRUE (fun != NULL);
init_empty_tree_cfg_for_function (fun);
ASSERT_EQ (2, n_basic_blocks_for_fn (fun));
ASSERT_EQ (0, n_edges_for_fn (fun));
return fndecl;
}
/* These tests directly create CFGs.
Compare with the static fns within tree-cfg.c:
- build_gimple_cfg
- make_blocks: calls create_basic_block (seq, bb);
- make_edges. */
/* Verify a simple cfg of the form:
ENTRY -> A -> B -> C -> EXIT. */
static void
test_linear_chain ()
{
gimple_register_cfg_hooks ();
tree fndecl = push_fndecl ("cfg_test_linear_chain");
function *fun = DECL_STRUCT_FUNCTION (fndecl);
/* Create some empty blocks. */
basic_block bb_a = create_empty_bb (ENTRY_BLOCK_PTR_FOR_FN (fun));
basic_block bb_b = create_empty_bb (bb_a);
basic_block bb_c = create_empty_bb (bb_b);
ASSERT_EQ (5, n_basic_blocks_for_fn (fun));
ASSERT_EQ (0, n_edges_for_fn (fun));
/* Create some edges: a simple linear chain of BBs. */
make_edge (ENTRY_BLOCK_PTR_FOR_FN (fun), bb_a, EDGE_FALLTHRU);
make_edge (bb_a, bb_b, 0);
make_edge (bb_b, bb_c, 0);
make_edge (bb_c, EXIT_BLOCK_PTR_FOR_FN (fun), 0);
/* Verify the edges. */
ASSERT_EQ (4, n_edges_for_fn (fun));
ASSERT_EQ (NULL, ENTRY_BLOCK_PTR_FOR_FN (fun)->preds);
ASSERT_EQ (1, ENTRY_BLOCK_PTR_FOR_FN (fun)->succs->length ());
ASSERT_EQ (1, bb_a->preds->length ());
ASSERT_EQ (1, bb_a->succs->length ());
ASSERT_EQ (1, bb_b->preds->length ());
ASSERT_EQ (1, bb_b->succs->length ());
ASSERT_EQ (1, bb_c->preds->length ());
ASSERT_EQ (1, bb_c->succs->length ());
ASSERT_EQ (1, EXIT_BLOCK_PTR_FOR_FN (fun)->preds->length ());
ASSERT_EQ (NULL, EXIT_BLOCK_PTR_FOR_FN (fun)->succs);
/* Verify the dominance information
Each BB in our simple chain should be dominated by the one before
it. */
calculate_dominance_info (CDI_DOMINATORS);
ASSERT_EQ (bb_a, get_immediate_dominator (CDI_DOMINATORS, bb_b));
ASSERT_EQ (bb_b, get_immediate_dominator (CDI_DOMINATORS, bb_c));
vec<basic_block> dom_by_b = get_dominated_by (CDI_DOMINATORS, bb_b);
ASSERT_EQ (1, dom_by_b.length ());
ASSERT_EQ (bb_c, dom_by_b[0]);
free_dominance_info (CDI_DOMINATORS);
/* Similarly for post-dominance: each BB in our chain is post-dominated
by the one after it. */
calculate_dominance_info (CDI_POST_DOMINATORS);
ASSERT_EQ (bb_b, get_immediate_dominator (CDI_POST_DOMINATORS, bb_a));
ASSERT_EQ (bb_c, get_immediate_dominator (CDI_POST_DOMINATORS, bb_b));
vec<basic_block> postdom_by_b = get_dominated_by (CDI_POST_DOMINATORS, bb_b);
ASSERT_EQ (1, postdom_by_b.length ());
ASSERT_EQ (bb_a, postdom_by_b[0]);
free_dominance_info (CDI_POST_DOMINATORS);
pop_cfun ();
}
/* Verify a simple CFG of the form:
ENTRY
|
A
/ \
/t \f
B C
\ /
\ /
D
|
EXIT. */
static void
test_diamond ()
{
gimple_register_cfg_hooks ();
tree fndecl = push_fndecl ("cfg_test_diamond");
function *fun = DECL_STRUCT_FUNCTION (fndecl);
/* Create some empty blocks. */
basic_block bb_a = create_empty_bb (ENTRY_BLOCK_PTR_FOR_FN (fun));
basic_block bb_b = create_empty_bb (bb_a);
basic_block bb_c = create_empty_bb (bb_a);
basic_block bb_d = create_empty_bb (bb_b);
ASSERT_EQ (6, n_basic_blocks_for_fn (fun));
ASSERT_EQ (0, n_edges_for_fn (fun));
/* Create the edges. */
make_edge (ENTRY_BLOCK_PTR_FOR_FN (fun), bb_a, EDGE_FALLTHRU);
make_edge (bb_a, bb_b, EDGE_TRUE_VALUE);
make_edge (bb_a, bb_c, EDGE_FALSE_VALUE);
make_edge (bb_b, bb_d, 0);
make_edge (bb_c, bb_d, 0);
make_edge (bb_d, EXIT_BLOCK_PTR_FOR_FN (fun), 0);
/* Verify the edges. */
ASSERT_EQ (6, n_edges_for_fn (fun));
ASSERT_EQ (1, bb_a->preds->length ());
ASSERT_EQ (2, bb_a->succs->length ());
ASSERT_EQ (1, bb_b->preds->length ());
ASSERT_EQ (1, bb_b->succs->length ());
ASSERT_EQ (1, bb_c->preds->length ());
ASSERT_EQ (1, bb_c->succs->length ());
ASSERT_EQ (2, bb_d->preds->length ());
ASSERT_EQ (1, bb_d->succs->length ());
/* Verify the dominance information. */
calculate_dominance_info (CDI_DOMINATORS);
ASSERT_EQ (bb_a, get_immediate_dominator (CDI_DOMINATORS, bb_b));
ASSERT_EQ (bb_a, get_immediate_dominator (CDI_DOMINATORS, bb_c));
ASSERT_EQ (bb_a, get_immediate_dominator (CDI_DOMINATORS, bb_d));
vec<basic_block> dom_by_a = get_dominated_by (CDI_DOMINATORS, bb_a);
ASSERT_EQ (3, dom_by_a.length ()); /* B, C, D, in some order. */
vec<basic_block> dom_by_b = get_dominated_by (CDI_DOMINATORS, bb_b);
ASSERT_EQ (0, dom_by_b.length ());
free_dominance_info (CDI_DOMINATORS);
/* Similarly for post-dominance. */
calculate_dominance_info (CDI_POST_DOMINATORS);
ASSERT_EQ (bb_d, get_immediate_dominator (CDI_POST_DOMINATORS, bb_a));
ASSERT_EQ (bb_d, get_immediate_dominator (CDI_POST_DOMINATORS, bb_b));
ASSERT_EQ (bb_d, get_immediate_dominator (CDI_POST_DOMINATORS, bb_c));
vec<basic_block> postdom_by_d = get_dominated_by (CDI_POST_DOMINATORS, bb_d);
ASSERT_EQ (3, postdom_by_d.length ()); /* A, B, C in some order. */
vec<basic_block> postdom_by_b = get_dominated_by (CDI_POST_DOMINATORS, bb_b);
ASSERT_EQ (0, postdom_by_b.length ());
free_dominance_info (CDI_POST_DOMINATORS);
pop_cfun ();
}
/* Verify that we can handle a CFG containing a "complete" aka
fully-connected subgraph (where A B C D below all have edges
pointing to each other node, also to themselves).
e.g.:
ENTRY EXIT
| ^
| /
| /
| /
V/
A<--->B
^^ ^^
| \ / |
| X |
| / \ |
VV VV
C<--->D
*/
static void
test_fully_connected ()
{
gimple_register_cfg_hooks ();
tree fndecl = push_fndecl ("cfg_fully_connected");
function *fun = DECL_STRUCT_FUNCTION (fndecl);
const int n = 4;
/* Create some empty blocks. */
auto_vec <basic_block> subgraph_nodes;
for (int i = 0; i < n; i++)
subgraph_nodes.safe_push (create_empty_bb (ENTRY_BLOCK_PTR_FOR_FN (fun)));
ASSERT_EQ (n + 2, n_basic_blocks_for_fn (fun));
ASSERT_EQ (0, n_edges_for_fn (fun));
/* Create the edges. */
make_edge (ENTRY_BLOCK_PTR_FOR_FN (fun), subgraph_nodes[0], EDGE_FALLTHRU);
make_edge (subgraph_nodes[0], EXIT_BLOCK_PTR_FOR_FN (fun), 0);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
make_edge (subgraph_nodes[i], subgraph_nodes[j], 0);
/* Verify the edges. */
ASSERT_EQ (2 + (n * n), n_edges_for_fn (fun));
/* The first one is linked to ENTRY/EXIT as well as itself and
everything else. */
ASSERT_EQ (n + 1, subgraph_nodes[0]->preds->length ());
ASSERT_EQ (n + 1, subgraph_nodes[0]->succs->length ());
/* The other ones in the subgraph are linked to everything in
the subgraph (including themselves). */
for (int i = 1; i < n; i++)
{
ASSERT_EQ (n, subgraph_nodes[i]->preds->length ());
ASSERT_EQ (n, subgraph_nodes[i]->succs->length ());
}
/* Verify the dominance information. */
calculate_dominance_info (CDI_DOMINATORS);
/* The initial block in the subgraph should be dominated by ENTRY. */
ASSERT_EQ (ENTRY_BLOCK_PTR_FOR_FN (fun),
get_immediate_dominator (CDI_DOMINATORS,
subgraph_nodes[0]));
/* Every other block in the subgraph should be dominated by the
initial block. */
for (int i = 1; i < n; i++)
ASSERT_EQ (subgraph_nodes[0],
get_immediate_dominator (CDI_DOMINATORS,
subgraph_nodes[i]));
free_dominance_info (CDI_DOMINATORS);
/* Similarly for post-dominance. */
calculate_dominance_info (CDI_POST_DOMINATORS);
/* The initial block in the subgraph should be postdominated by EXIT. */
ASSERT_EQ (EXIT_BLOCK_PTR_FOR_FN (fun),
get_immediate_dominator (CDI_POST_DOMINATORS,
subgraph_nodes[0]));
/* Every other block in the subgraph should be postdominated by the
initial block, since that leads to EXIT. */
for (int i = 1; i < n; i++)
ASSERT_EQ (subgraph_nodes[0],
get_immediate_dominator (CDI_POST_DOMINATORS,
subgraph_nodes[i]));
free_dominance_info (CDI_POST_DOMINATORS);
pop_cfun ();
}
/* Run all of the selftests within this file. */
void
tree_cfg_c_tests ()
{
test_linear_chain ();
test_diamond ();
test_fully_connected ();
}
} // namespace selftest
/* TODO: test the dominator/postdominator logic with various graphs/nodes:
- loop
- nested loops
- switch statement (a block with many out-edges)
- something that jumps to itself
- etc */
#endif /* CHECKING_P */
......@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "print-tree.h"
#include "ipa-utils.h"
#include "selftest.h"
/* Tree code classes. */
......@@ -14203,4 +14204,65 @@ combined_fn_name (combined_fn fn)
return internal_fn_name (as_internal_fn (fn));
}
#if CHECKING_P
namespace selftest {
/* Selftests for tree. */
/* Verify that integer constants are sane. */
static void
test_integer_constants ()
{
ASSERT_TRUE (integer_type_node != NULL);
ASSERT_TRUE (build_int_cst (integer_type_node, 0) != NULL);
tree type = integer_type_node;
tree zero = build_zero_cst (type);
ASSERT_EQ (INTEGER_CST, TREE_CODE (zero));
ASSERT_EQ (type, TREE_TYPE (zero));
tree one = build_int_cst (type, 1);
ASSERT_EQ (INTEGER_CST, TREE_CODE (one));
ASSERT_EQ (type, TREE_TYPE (zero));
}
/* Verify identifiers. */
static void
test_identifiers ()
{
tree identifier = get_identifier ("foo");
ASSERT_EQ (3, IDENTIFIER_LENGTH (identifier));
ASSERT_STREQ ("foo", IDENTIFIER_POINTER (identifier));
}
/* Verify LABEL_DECL. */
static void
test_labels ()
{
tree identifier = get_identifier ("err");
tree label_decl = build_decl (UNKNOWN_LOCATION, LABEL_DECL,
identifier, void_type_node);
ASSERT_EQ (-1, LABEL_DECL_UID (label_decl));
ASSERT_FALSE (FORCED_LABEL (label_decl));
}
/* Run all of the selftests within this file. */
void
tree_c_tests ()
{
test_integer_constants ();
test_identifiers ();
test_labels ();
}
} // namespace selftest
#endif /* CHECKING_P */
#include "gt-tree.h"
......@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "coretypes.h"
#include "hash-table.h"
#include "selftest.h"
/* vNULL is an empty type with a template cast operation that returns
a zero-initialized vec<T, A, L> instance. Use this when you want
......@@ -188,3 +189,194 @@ dump_vec_loc_statistics (void)
{
vec_mem_desc.dump (VEC_ORIGIN);
}
#ifndef GENERATOR_FILE
#if CHECKING_P
namespace selftest {
/* Selftests. */
/* Call V.safe_push for all ints from START up to, but not including LIMIT.
Helper function for selftests. */
static void
safe_push_range (vec <int>&v, int start, int limit)
{
for (int i = start; i < limit; i++)
v.safe_push (i);
}
/* Verify that vec::quick_push works correctly. */
static void
test_quick_push ()
{
auto_vec <int> v;
ASSERT_EQ (0, v.length ());
v.reserve (3);
ASSERT_EQ (0, v.length ());
ASSERT_TRUE (v.space (3));
v.quick_push (5);
v.quick_push (6);
v.quick_push (7);
ASSERT_EQ (3, v.length ());
ASSERT_EQ (5, v[0]);
ASSERT_EQ (6, v[1]);
ASSERT_EQ (7, v[2]);
}
/* Verify that vec::safe_push works correctly. */
static void
test_safe_push ()
{
auto_vec <int> v;
ASSERT_EQ (0, v.length ());
v.safe_push (5);
v.safe_push (6);
v.safe_push (7);
ASSERT_EQ (3, v.length ());
ASSERT_EQ (5, v[0]);
ASSERT_EQ (6, v[1]);
ASSERT_EQ (7, v[2]);
}
/* Verify that vec::truncate works correctly. */
static void
test_truncate ()
{
auto_vec <int> v;
ASSERT_EQ (0, v.length ());
safe_push_range (v, 0, 10);
ASSERT_EQ (10, v.length ());
v.truncate (5);
ASSERT_EQ (5, v.length ());
}
/* Verify that vec::safe_grow_cleared works correctly. */
static void
test_safe_grow_cleared ()
{
auto_vec <int> v;
ASSERT_EQ (0, v.length ());
v.safe_grow_cleared (50);
ASSERT_EQ (50, v.length ());
ASSERT_EQ (0, v[0]);
ASSERT_EQ (0, v[49]);
}
/* Verify that vec::pop works correctly. */
static void
test_pop ()
{
auto_vec <int> v;
safe_push_range (v, 5, 20);
ASSERT_EQ (15, v.length ());
int last = v.pop ();
ASSERT_EQ (19, last);
ASSERT_EQ (14, v.length ());
}
/* Verify that vec::safe_insert works correctly. */
static void
test_safe_insert ()
{
auto_vec <int> v;
safe_push_range (v, 0, 10);
v.safe_insert (5, 42);
ASSERT_EQ (4, v[4]);
ASSERT_EQ (42, v[5]);
ASSERT_EQ (5, v[6]);
ASSERT_EQ (11, v.length ());
}
/* Verify that vec::ordered_remove works correctly. */
static void
test_ordered_remove ()
{
auto_vec <int> v;
safe_push_range (v, 0, 10);
v.ordered_remove (5);
ASSERT_EQ (4, v[4]);
ASSERT_EQ (6, v[5]);
ASSERT_EQ (9, v.length ());
}
/* Verify that vec::unordered_remove works correctly. */
static void
test_unordered_remove ()
{
auto_vec <int> v;
safe_push_range (v, 0, 10);
v.unordered_remove (5);
ASSERT_EQ (9, v.length ());
}
/* Verify that vec::block_remove works correctly. */
static void
test_block_remove ()
{
auto_vec <int> v;
safe_push_range (v, 0, 10);
v.block_remove (5, 3);
ASSERT_EQ (3, v[3]);
ASSERT_EQ (4, v[4]);
ASSERT_EQ (8, v[5]);
ASSERT_EQ (9, v[6]);
ASSERT_EQ (7, v.length ());
}
/* Comparator for use by test_qsort. */
static int
reverse_cmp (const void *p_i, const void *p_j)
{
return *(const int *)p_j - *(const int *)p_i;
}
/* Verify that vec::qsort works correctly. */
static void
test_qsort ()
{
auto_vec <int> v;
safe_push_range (v, 0, 10);
v.qsort (reverse_cmp);
ASSERT_EQ (9, v[0]);
ASSERT_EQ (8, v[1]);
ASSERT_EQ (1, v[8]);
ASSERT_EQ (0, v[9]);
ASSERT_EQ (10, v.length ());
}
/* Run all of the selftests within this file. */
void
vec_c_tests ()
{
test_quick_push ();
test_safe_push ();
test_truncate ();
test_safe_grow_cleared ();
test_pop ();
test_safe_insert ();
test_ordered_remove ();
test_unordered_remove ();
test_block_remove ();
test_qsort ();
}
} // namespace selftest
#endif /* #if CHECKING_P */
#endif /* #ifndef GENERATOR_FILE */
......@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "selftest.h"
#include "wide-int-print.h"
#define HOST_BITS_PER_HALF_WIDE_INT 32
......@@ -2144,3 +2146,171 @@ template void generic_wide_int <wide_int_ref_storage <false> >::dump () const;
template void generic_wide_int <wide_int_ref_storage <true> >::dump () const;
template void offset_int::dump () const;
template void widest_int::dump () const;
#if CHECKING_P
namespace selftest {
/* Selftests for wide ints. We run these multiple times, once per type. */
/* Helper function for building a test value. */
template <class VALUE_TYPE>
static VALUE_TYPE
from_int (int i);
/* Specializations of the fixture for each wide-int type. */
/* Specialization for VALUE_TYPE == wide_int. */
template <>
wide_int
from_int (int i)
{
return wi::shwi (i, 32);
}
/* Specialization for VALUE_TYPE == offset_int. */
template <>
offset_int
from_int (int i)
{
return offset_int (i);
}
/* Specialization for VALUE_TYPE == widest_int. */
template <>
widest_int
from_int (int i)
{
return widest_int (i);
}
/* Verify that print_dec (WI, ..., SGN) gives the expected string
representation (using base 10). */
static void
assert_deceq (const char *expected, const wide_int_ref &wi, signop sgn)
{
char buf[WIDE_INT_PRINT_BUFFER_SIZE];
print_dec (wi, buf, sgn);
ASSERT_STREQ (expected, buf);
}
/* Likewise for base 16. */
static void
assert_hexeq (const char *expected, const wide_int_ref &wi)
{
char buf[WIDE_INT_PRINT_BUFFER_SIZE];
print_hex (wi, buf);
ASSERT_STREQ (expected, buf);
}
/* Test cases. */
/* Verify that print_dec and print_hex work for VALUE_TYPE. */
template <class VALUE_TYPE>
static void
test_printing ()
{
VALUE_TYPE a = from_int<VALUE_TYPE> (42);
assert_deceq ("42", a, SIGNED);
assert_hexeq ("0x2a", a);
}
/* Verify that various operations work correctly for VALUE_TYPE,
unary and binary, using both function syntax, and
overloaded-operators. */
template <class VALUE_TYPE>
static void
test_ops ()
{
VALUE_TYPE a = from_int<VALUE_TYPE> (7);
VALUE_TYPE b = from_int<VALUE_TYPE> (3);
/* Using functions. */
assert_deceq ("-7", wi::neg (a), SIGNED);
assert_deceq ("10", wi::add (a, b), SIGNED);
assert_deceq ("4", wi::sub (a, b), SIGNED);
assert_deceq ("-4", wi::sub (b, a), SIGNED);
assert_deceq ("21", wi::mul (a, b), SIGNED);
/* Using operators. */
assert_deceq ("-7", -a, SIGNED);
assert_deceq ("10", a + b, SIGNED);
assert_deceq ("4", a - b, SIGNED);
assert_deceq ("-4", b - a, SIGNED);
assert_deceq ("21", a * b, SIGNED);
}
/* Verify that various comparisons work correctly for VALUE_TYPE. */
template <class VALUE_TYPE>
static void
test_comparisons ()
{
VALUE_TYPE a = from_int<VALUE_TYPE> (7);
VALUE_TYPE b = from_int<VALUE_TYPE> (3);
/* == */
ASSERT_TRUE (wi::eq_p (a, a));
ASSERT_FALSE (wi::eq_p (a, b));
/* != */
ASSERT_TRUE (wi::ne_p (a, b));
ASSERT_FALSE (wi::ne_p (a, a));
/* < */
ASSERT_FALSE (wi::lts_p (a, a));
ASSERT_FALSE (wi::lts_p (a, b));
ASSERT_TRUE (wi::lts_p (b, a));
/* <= */
ASSERT_TRUE (wi::les_p (a, a));
ASSERT_FALSE (wi::les_p (a, b));
ASSERT_TRUE (wi::les_p (b, a));
/* > */
ASSERT_FALSE (wi::gts_p (a, a));
ASSERT_TRUE (wi::gts_p (a, b));
ASSERT_FALSE (wi::gts_p (b, a));
/* >= */
ASSERT_TRUE (wi::ges_p (a, a));
ASSERT_TRUE (wi::ges_p (a, b));
ASSERT_FALSE (wi::ges_p (b, a));
/* comparison */
ASSERT_EQ (-1, wi::cmps (b, a));
ASSERT_EQ (0, wi::cmps (a, a));
ASSERT_EQ (1, wi::cmps (a, b));
}
/* Run all of the selftests, using the given VALUE_TYPE. */
template <class VALUE_TYPE>
static void run_all_wide_int_tests ()
{
test_printing <VALUE_TYPE> ();
test_ops <VALUE_TYPE> ();
test_comparisons <VALUE_TYPE> ();
}
/* Run all of the selftests within this file, for all value types. */
void
wide_int_cc_tests ()
{
run_all_wide_int_tests <wide_int> ();
run_all_wide_int_tests <offset_int> ();
run_all_wide_int_tests <widest_int> ();
}
} // namespace selftest
#endif /* CHECKING_P */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment