1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
/* Run expensive selftests. */
/* { dg-options "-O" } */
#include "gcc-plugin.h"
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "diagnostic.h"
#include "edit-context.h"
#include "selftest.h"
#include "selftest-diagnostic.h"
int plugin_is_GPL_compatible;
#if CHECKING_P
namespace selftest {
/* Subroutine of test_fixit_on_very_long_line.
Verify that LOC has the EXPECTED_COLUMN, apart from the various
cases where it can't. */
static void
verify_column (location_t loc,
const line_map_ordinary *ord_map,
int line_width,
int expected_column)
{
ASSERT_TRUE (/* Normal case. */
LOCATION_COLUMN (loc) == expected_column
/* ord_map can't store columns e.g. due to
max_column_hint being too high. */
|| ord_map->m_column_and_range_bits == 0
/* Running out of location_t values. */
|| loc > LINE_MAP_MAX_LOCATION_WITH_COLS
/* column exceeds LINE_MAP_MAX_COLUMN_NUMBER. */
|| expected_column > (int)LINE_MAP_MAX_COLUMN_NUMBER
/* column exceeds max_column_hint for ord_map. */
|| expected_column > line_width);
}
/* Subroutine of test_fixit_on_very_long_line.
Run various things for RICHLOC, but don't check; we just want them
to survive. */
static void
test_richloc (rich_location *richloc)
{
/* Run the diagnostic and fix-it printing code. */
test_diagnostic_context dc;
diagnostic_show_locus (&dc, dc.m_source_printing,
richloc, DK_ERROR, dc.get_reference_printer ());
/* Generate a diff. */
edit_context ec (global_dc->get_file_cache ());
ec.add_fixits (richloc);
char *diff = ec.generate_diff (true);
free (diff);
}
/* Verify that the fix-it-printing code can cope with very long lines
(PR c/82050). */
static void
test_fixit_on_very_long_line (const line_table_case &case_)
{
/* Various interesting column/line-width values, to try to tickle out bugs. In
64-bit location mode, we can't test the max because the maximum supported
column is unreasonably large. */
const int VERY_LONG_LINE = 8192;
const int columns[] = {0,
1,
80,
VERY_LONG_LINE,
VERY_LONG_LINE + 5};
for (unsigned int width_idx = 0; width_idx < ARRAY_SIZE (columns);
width_idx++)
{
int line_width = columns[width_idx];
/* Create a source file with a very long line. */
named_temp_file tmp (".c");
FILE *f = fopen (tmp.get_filename (), "w");
for (int i = 0; i < line_width; i++)
fputc (' ', f);
fputc ('\n', f);
fclose (f);
line_table_test ltt (case_);
const line_map_ordinary *ord_map = linemap_check_ordinary
(linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
linemap_line_start (line_table, 1, line_width);
for (unsigned int start_idx = 0; start_idx < ARRAY_SIZE (columns);
start_idx++)
{
int start_col = columns[start_idx];
location_t start_loc
= linemap_position_for_line_and_column (line_table, ord_map, 1,
start_col);
verify_column (start_loc, ord_map, line_width, start_col);
for (unsigned int finish_idx = 0; finish_idx < ARRAY_SIZE (columns);
finish_idx++)
{
int finish_col = columns[finish_idx];
location_t finish_loc
= linemap_position_for_line_and_column (line_table, ord_map, 1,
finish_col);
verify_column (finish_loc, ord_map, line_width, finish_col);
/* Now use start-finish to exercise the fix-it code.
In each case, run the printing code, but don't check;
we just want it to survive. */
/* Insertion. */
{
rich_location richloc (line_table, start_loc);
richloc.add_fixit_insert_after (start_loc, "insertion");
test_richloc (&richloc);
}
/* Replacement. */
{
rich_location richloc (line_table, start_loc);
source_range range
= source_range::from_locations (start_loc, finish_loc);
richloc.add_fixit_replace (range, "replacement");
test_richloc (&richloc);
}
/* Deletion. */
{
rich_location richloc (line_table, start_loc);
source_range range
= source_range::from_locations (start_loc, finish_loc);
richloc.add_fixit_remove (range);
test_richloc (&richloc);
}
}
}
}
}
/* Callback handler for the PLUGIN_FINISH event.
At this point, all GCC subsystems should be initialized and
"warmed up"; this is where we run our unit tests. */
static void
expensive_tests (void */*gcc_data*/, void */*user_data*/)
{
test_runner r ("expensive_selftests_plugin");
for_each_line_table_case (test_fixit_on_very_long_line);
}
} // namespace selftest
#endif /* #if CHECKING_P */
int
plugin_init (struct plugin_name_args *plugin_info,
struct plugin_gcc_version *version)
{
#if CHECKING_P
const char *plugin_name = plugin_info->base_name;
register_callback (plugin_info->base_name,
PLUGIN_FINISH,
selftest::expensive_tests,
NULL); /* void *user_data */
#else
inform (UNKNOWN_LOCATION, "self-tests are not enabled in this build");
#endif /* #if CHECKING_P */
return 0;
}
|