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