aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.dg/plugin/location_overflow_plugin.cc
blob: f770d35ea518ec7aa247e62b84c40c012309b4bd (plain)
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
/* Plugin for testing how gracefully we degrade in the face of very
   large source files.  */

#include "config.h"
#include "gcc-plugin.h"
#include "system.h"
#include "coretypes.h"
#include "spellcheck.h"
#include "diagnostic.h"
#include "diagnostic-format-text.h"

int plugin_is_GPL_compatible;

static location_t base_location;

/* Callback handler for the PLUGIN_PRAGMAS event; pretend we parsed a
   very large include file.  This is used to set the initial line table
   offset for the preprocessor, to make it appear as if we had parsed a
   very large file.  PRAGMA_START_UNIT is not suitable here as is not
   invoked during the preprocessor stage.  */

static void
on_pragma_registration (void */*gcc_data*/, void */*user_data*/)
{
  /* Act as if we've already parsed a large body of code;
     so that we can simulate various fallbacks in libcpp:

     0x50000001 > LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES:
     this will trigger the creation of line maps with range_bits == 0
     so that all ranges will be stored in the ad-hoc lookaside.

     0x60000001 > LINE_MAP_MAX_LOCATION_WITH_COLS:
     this will trigger the creation of line maps with column_bits == 0
     and hence we will immediately degrade to having locations in which
     column number is 0. */
  line_table->highest_location = base_location;
}

/* We add some extra testing during diagnostics by chaining up
   to the text finalizer.  */

static diagnostic_text_finalizer_fn original_text_finalizer = NULL;

static void
verify_unpacked_ranges  (diagnostic_text_output_format &text_output,
			 const diagnostic_info *diagnostic,
			 diagnostic_t orig_diag_kind)
{
  /* Verify that the locations are ad-hoc, not packed. */
  location_t loc = diagnostic_location (diagnostic);
  gcc_assert (IS_ADHOC_LOC (loc));

  /* We're done testing; chain up to original text finalizer.  */
  gcc_assert (original_text_finalizer);
  original_text_finalizer (text_output, diagnostic, orig_diag_kind);
}

static void
verify_no_columns  (diagnostic_text_output_format &text_output,
		    const diagnostic_info *diagnostic,
		    diagnostic_t orig_diag_kind)
{
  /* Verify that the locations have no columns. */
  location_t loc = diagnostic_location (diagnostic);
  gcc_assert (LOCATION_COLUMN (loc) == 0);

  /* We're done testing; chain up to original text finalizer.  */
  gcc_assert (original_text_finalizer);
  original_text_finalizer (text_output, diagnostic, orig_diag_kind);
}

int
plugin_init (struct plugin_name_args *plugin_info,
	     struct plugin_gcc_version */*version*/)
{
  /* Read VALUE from -fplugin-arg-location_overflow_plugin-value=<VALUE>
     in hexadecimal form into base_location.  */
  for (int i = 0; i < plugin_info->argc; i++)
    {
      if (0 == strcmp (plugin_info->argv[i].key, "value"))
	base_location = strtol (plugin_info->argv[i].value, NULL, 16);
    }

  if (!base_location)
    error_at (UNKNOWN_LOCATION, "missing plugin argument");

  /* With 64-bit locations, the thresholds are larger, so shift the base
     location argument accordingly, basically remap the GCC 14 32-bit
     location_t argument values to 64-bit location_t counterparts.  There
     is one exception for values slightly before the 32-bit location_t
     LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES (0x50000000).  In that case
     remap them to the same amount before the 64-bit location_t
     LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES -
     ((location_t) 0x50000000) << 31.  */
  gcc_assert (sizeof (location_t) == sizeof (uint64_t));
  if (base_location >= 0x4f000000 && base_location <= 0x4fffffff)
    base_location += (((location_t) 0x50000000) << 31) - 0x50000000;
  else
    base_location = 1 + ((base_location - 1) << 31);

  register_callback (plugin_info->base_name,
		     PLUGIN_PRAGMAS,
		     on_pragma_registration,
		     NULL); /* void *user_data */

  /* Hack in additional testing, based on the exact value supplied.  */
  original_text_finalizer = diagnostic_text_finalizer (global_dc);
  switch (base_location)
    {
    case LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES + 1:
      diagnostic_text_finalizer (global_dc) = verify_unpacked_ranges;
      break;

    case LINE_MAP_MAX_LOCATION_WITH_COLS + 1:
      diagnostic_text_finalizer (global_dc) = verify_no_columns;
      break;

    default:
      break;
    }

  return 0;
}