diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
commit | e252b51ccde010cbd2a146485d8045103cd99533 (patch) | |
tree | e060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/diagnostic.c | |
parent | f10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff) | |
parent | 104c05c5284b7822d770ee51a7d91946c7e56d50 (diff) | |
download | gcc-e252b51ccde010cbd2a146485d8045103cd99533.zip gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2 |
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/diagnostic.c')
-rw-r--r-- | gcc/diagnostic.c | 216 |
1 files changed, 157 insertions, 59 deletions
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 246d752..b3afbea 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -293,6 +293,17 @@ diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */) = determine_url_format ((diagnostic_url_rule_t) value); } +/* Create the file_cache, if not already created, and tell it how to + translate files on input. */ +void diagnostic_initialize_input_context (diagnostic_context *context, + diagnostic_input_charset_callback ccb, + bool should_skip_bom) +{ + if (!context->m_file_cache) + context->m_file_cache = new file_cache; + context->m_file_cache->initialize_input_context (ccb, should_skip_bom); +} + /* Do any cleaning up required after the last diagnostic is emitted. */ void @@ -991,51 +1002,88 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc, pp_set_prefix (pp, saved_prefix); } -/* Update the diag_class of DIAGNOSTIC based on its location - relative to any +/* Update the inlining info in CONTEXT for a DIAGNOSTIC. */ + +static void +get_any_inlining_info (diagnostic_context *context, + diagnostic_info *diagnostic) +{ + auto &ilocs = diagnostic->m_iinfo.m_ilocs; + + if (context->set_locations_cb) + /* Retrieve the locations into which the expression about to be + diagnosed has been inlined, including those of all the callers + all the way down the inlining stack. */ + context->set_locations_cb (context, diagnostic); + else + { + /* When there's no callback use just the one location provided + by the caller of the diagnostic function. */ + location_t loc = diagnostic_location (diagnostic); + ilocs.safe_push (loc); + diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc); + } +} + +/* Update the kind of DIAGNOSTIC based on its location(s), including + any of those in its inlining stack, relative to any #pragma GCC diagnostic directives recorded within CONTEXT. - Return the new diag_class of DIAGNOSTIC if it was updated, or - DK_UNSPECIFIED otherwise. */ + Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED + otherwise. */ static diagnostic_t update_effective_level_from_pragmas (diagnostic_context *context, diagnostic_info *diagnostic) { - diagnostic_t diag_class = DK_UNSPECIFIED; - - if (context->n_classification_history > 0) + if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers) { - location_t location = diagnostic_location (diagnostic); + /* Ignore the diagnostic if all the inlined locations are + in system headers and -Wno-system-headers is in effect. */ + diagnostic->kind = DK_IGNORED; + return DK_IGNORED; + } + + if (context->n_classification_history <= 0) + return DK_UNSPECIFIED; + /* Iterate over the locations, checking the diagnostic disposition + for the diagnostic at each. If it's explicitly set as opposed + to unspecified, update the disposition for this instance of + the diagnostic and return it. */ + for (location_t loc: diagnostic->m_iinfo.m_ilocs) + { /* FIXME: Stupid search. Optimize later. */ for (int i = context->n_classification_history - 1; i >= 0; i --) { - if (linemap_location_before_p - (line_table, - context->classification_history[i].location, - location)) + const diagnostic_classification_change_t &hist + = context->classification_history[i]; + + location_t pragloc = hist.location; + if (!linemap_location_before_p (line_table, pragloc, loc)) + continue; + + if (hist.kind == (int) DK_POP) { - if (context->classification_history[i].kind == (int) DK_POP) - { - i = context->classification_history[i].option; - continue; - } - int option = context->classification_history[i].option; - /* The option 0 is for all the diagnostics. */ - if (option == 0 || option == diagnostic->option_index) - { - diag_class = context->classification_history[i].kind; - if (diag_class != DK_UNSPECIFIED) - diagnostic->kind = diag_class; - break; - } + /* Move on to the next region. */ + i = hist.option; + continue; + } + + int option = hist.option; + /* The option 0 is for all the diagnostics. */ + if (option == 0 || option == diagnostic->option_index) + { + diagnostic_t kind = hist.kind; + if (kind != DK_UNSPECIFIED) + diagnostic->kind = kind; + return kind; } } } - return diag_class; + return DK_UNSPECIFIED; } /* Generate a URL string describing CWE. The caller is responsible for @@ -1122,6 +1170,65 @@ print_option_information (diagnostic_context *context, } } +/* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind + as appropriate for #pragma GCC diagnostic and -Werror=foo. */ + +static bool +diagnostic_enabled (diagnostic_context *context, + diagnostic_info *diagnostic) +{ + /* Update the inlining stack for this diagnostic. */ + get_any_inlining_info (context, diagnostic); + + /* Diagnostics with no option or -fpermissive are always enabled. */ + if (!diagnostic->option_index + || diagnostic->option_index == permissive_error_option (context)) + return true; + + /* This tests if the user provided the appropriate -Wfoo or + -Wno-foo option. */ + if (! context->option_enabled (diagnostic->option_index, + context->lang_mask, + context->option_state)) + return false; + + /* This tests for #pragma diagnostic changes. */ + diagnostic_t diag_class + = update_effective_level_from_pragmas (context, diagnostic); + + /* This tests if the user provided the appropriate -Werror=foo + option. */ + if (diag_class == DK_UNSPECIFIED + && (context->classify_diagnostic[diagnostic->option_index] + != DK_UNSPECIFIED)) + diagnostic->kind + = context->classify_diagnostic[diagnostic->option_index]; + + /* This allows for future extensions, like temporarily disabling + warnings for ranges of source code. */ + if (diagnostic->kind == DK_IGNORED) + return false; + + return true; +} + +/* Returns whether warning OPT is enabled at LOC. */ + +bool +warning_enabled_at (location_t loc, int opt) +{ + if (!diagnostic_report_warnings_p (global_dc, loc)) + return false; + + rich_location richloc (line_table, loc); + diagnostic_info diagnostic = {}; + diagnostic.option_index = opt; + diagnostic.richloc = &richloc; + diagnostic.message.m_richloc = &richloc; + diagnostic.kind = DK_WARNING; + return diagnostic_enabled (global_dc, &diagnostic); +} + /* Report a diagnostic message (an error or a warning) as specified by DC. This function is *the* subroutine in terms of which front-ends should implement their specific diagnostic handling modules. The @@ -1138,9 +1245,17 @@ diagnostic_report_diagnostic (diagnostic_context *context, /* Give preference to being able to inhibit warnings, before they get reclassified to something else. */ - if ((diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN) - && !diagnostic_report_warnings_p (context, location)) - return false; + bool report_warning_p = true; + if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN) + { + if (context->dc_inhibit_warnings) + return false; + /* Remember the result of the overall system header warning setting + but proceed to also check the inlining context. */ + report_warning_p = diagnostic_report_warnings_p (context, location); + if (!report_warning_p && diagnostic->kind == DK_PEDWARN) + return false; + } if (diagnostic->kind == DK_PEDWARN) { @@ -1148,7 +1263,7 @@ diagnostic_report_diagnostic (diagnostic_context *context, /* We do this to avoid giving the message for -pedantic-errors. */ orig_diag_kind = diagnostic->kind; } - + if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p) return false; @@ -1172,33 +1287,18 @@ diagnostic_report_diagnostic (diagnostic_context *context, && diagnostic->kind == DK_WARNING) diagnostic->kind = DK_ERROR; - if (diagnostic->option_index - && diagnostic->option_index != permissive_error_option (context)) - { - /* This tests if the user provided the appropriate -Wfoo or - -Wno-foo option. */ - if (! context->option_enabled (diagnostic->option_index, - context->lang_mask, - context->option_state)) - return false; + diagnostic->message.x_data = &diagnostic->x_data; - /* This tests for #pragma diagnostic changes. */ - diagnostic_t diag_class - = update_effective_level_from_pragmas (context, diagnostic); - - /* This tests if the user provided the appropriate -Werror=foo - option. */ - if (diag_class == DK_UNSPECIFIED - && (context->classify_diagnostic[diagnostic->option_index] - != DK_UNSPECIFIED)) - diagnostic->kind - = context->classify_diagnostic[diagnostic->option_index]; - - /* This allows for future extensions, like temporarily disabling - warnings for ranges of source code. */ - if (diagnostic->kind == DK_IGNORED) - return false; - } + /* Check to see if the diagnostic is enabled at the location and + not disabled by #pragma GCC diagnostic anywhere along the inlining + stack. . */ + if (!diagnostic_enabled (context, diagnostic)) + return false; + + if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs) + /* Bail if the warning is not to be reported because all locations + in the inlining stack (if there is one) are in system headers. */ + return false; if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE) diagnostic_check_max_errors (context); @@ -1239,8 +1339,6 @@ diagnostic_report_diagnostic (diagnostic_context *context, } context->diagnostic_group_emission_count++; - diagnostic->message.x_data = &diagnostic->x_data; - diagnostic->x_data = NULL; pp_format (context->printer, &diagnostic->message); (*diagnostic_starter (context)) (context, diagnostic); pp_output_formatted_text (context->printer); |