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
      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
      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
      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
      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  }