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