1 /* Plugin for testing how gracefully we degrade in the face of very
2 large source files. */
3
4 #include "config.h"
5 #include "gcc-plugin.h"
6 #include "system.h"
7 #include "coretypes.h"
8 #include "spellcheck.h"
9 #include "diagnostic.h"
10
11 int plugin_is_GPL_compatible;
12
13 static location_t base_location;
14
15 /* Callback handler for the PLUGIN_PRAGMAS event; pretend we parsed a
16 very large include file. This is used to set the initial line table
17 offset for the preprocessor, to make it appear as if we had parsed a
18 very large file. PRAGMA_START_UNIT is not suitable here as is not
19 invoked during the preprocessor stage. */
20
21 static void
on_pragma_registration(void *,void *)22 on_pragma_registration (void */*gcc_data*/, void */*user_data*/)
23 {
24 /* Act as if we've already parsed a large body of code;
25 so that we can simulate various fallbacks in libcpp:
26
27 0x50000001 > LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES:
28 this will trigger the creation of line maps with range_bits == 0
29 so that all ranges will be stored in the ad-hoc lookaside.
30
31 0x60000001 > LINE_MAP_MAX_LOCATION_WITH_COLS:
32 this will trigger the creation of line maps with column_bits == 0
33 and hence we will immediately degrade to having locations in which
34 column number is 0. */
35 line_table->highest_location = base_location;
36 }
37
38 /* We add some extra testing during diagnostics by chaining up
39 to the finalizer. */
40
41 static diagnostic_finalizer_fn original_finalizer = NULL;
42
43 static void
verify_unpacked_ranges(diagnostic_context * context,diagnostic_info * diagnostic,diagnostic_t orig_diag_kind)44 verify_unpacked_ranges (diagnostic_context *context,
45 diagnostic_info *diagnostic,
46 diagnostic_t orig_diag_kind)
47 {
48 /* Verify that the locations are ad-hoc, not packed. */
49 location_t loc = diagnostic_location (diagnostic);
50 gcc_assert (IS_ADHOC_LOC (loc));
51
52 /* We're done testing; chain up to original finalizer. */
53 gcc_assert (original_finalizer);
54 original_finalizer (context, diagnostic, orig_diag_kind);
55 }
56
57 static void
verify_no_columns(diagnostic_context * context,diagnostic_info * diagnostic,diagnostic_t orig_diag_kind)58 verify_no_columns (diagnostic_context *context,
59 diagnostic_info *diagnostic,
60 diagnostic_t orig_diag_kind)
61 {
62 /* Verify that the locations have no columns. */
63 location_t loc = diagnostic_location (diagnostic);
64 gcc_assert (LOCATION_COLUMN (loc) == 0);
65
66 /* We're done testing; chain up to original finalizer. */
67 gcc_assert (original_finalizer);
68 original_finalizer (context, diagnostic, orig_diag_kind);
69 }
70
71 int
plugin_init(struct plugin_name_args * plugin_info,struct plugin_gcc_version *)72 plugin_init (struct plugin_name_args *plugin_info,
73 struct plugin_gcc_version */*version*/)
74 {
75 /* Read VALUE from -fplugin-arg-location_overflow_plugin-value=<VALUE>
76 in hexadecimal form into base_location. */
77 for (int i = 0; i < plugin_info->argc; i++)
78 {
79 if (0 == strcmp (plugin_info->argv[i].key, "value"))
80 base_location = strtol (plugin_info->argv[i].value, NULL, 16);
81 }
82
83 if (!base_location)
84 error_at (UNKNOWN_LOCATION, "missing plugin argument");
85
86 register_callback (plugin_info->base_name,
87 PLUGIN_PRAGMAS,
88 on_pragma_registration,
89 NULL); /* void *user_data */
90
91 /* Hack in additional testing, based on the exact value supplied. */
92 original_finalizer = diagnostic_finalizer (global_dc);
93 switch (base_location)
94 {
95 case LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES + 1:
96 diagnostic_finalizer (global_dc) = verify_unpacked_ranges;
97 break;
98
99 case LINE_MAP_MAX_LOCATION_WITH_COLS + 1:
100 diagnostic_finalizer (global_dc) = verify_no_columns;
101 break;
102
103 default:
104 error_at (UNKNOWN_LOCATION, "unrecognized value for plugin argument");
105 }
106
107 return 0;
108 }
109