blob: 09bac50d2af44f5caf7fc0c20ce858ef7f3980da [file] [log] [blame]
/* 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"
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 finalizer. */
static diagnostic_finalizer_fn original_finalizer = NULL;
static void
verify_unpacked_ranges (diagnostic_context *context,
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 finalizer. */
gcc_assert (original_finalizer);
original_finalizer (context, diagnostic, orig_diag_kind);
}
static void
verify_no_columns (diagnostic_context *context,
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 finalizer. */
gcc_assert (original_finalizer);
original_finalizer (context, 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");
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_finalizer = diagnostic_finalizer (global_dc);
switch (base_location)
{
case LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES + 1:
diagnostic_finalizer (global_dc) = verify_unpacked_ranges;
break;
case LINE_MAP_MAX_LOCATION_WITH_COLS + 1:
diagnostic_finalizer (global_dc) = verify_no_columns;
break;
default:
error_at (UNKNOWN_LOCATION, "unrecognized value for plugin argument");
}
return 0;
}