From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-oo1-xc36.google.com (mail-oo1-xc36.google.com [IPv6:2607:f8b0:4864:20::c36]) by sourceware.org (Postfix) with ESMTPS id B8FAC385742F for ; Thu, 10 Jun 2021 23:26:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B8FAC385742F Received: by mail-oo1-xc36.google.com with SMTP id k10-20020a4abd8a0000b0290249ed2f2919so288473oop.4 for ; Thu, 10 Jun 2021 16:26:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language; bh=OANez0neQXZht9Vw3nw4IgfxRswLXcEfMr8xmZ3n22M=; b=s2zV3BMDTYRwT4NruDz7yBB3MYssFgFqsiYBGd2xFXPXZR9ft/FEmJH259x9Ctxnwz 0BgV4GLJqbxXBQRKulOgC2lA9mZAPoNH/rDyvd0R25OlkYX9nIvllez7tszgOWwmNUqd Y9sPOz91sbVFJA4403Cwfj7DjPn6ObWFMyNjeLRLLzT02QAGOsQeVC8MMozo9RmaHUge km+E2vOUROowjzHPLvlFq4AWDEp+RHJo+DYRvNBaNo9i8L7iIeKCvheEFBsk8xnUyCNJ Khpl+aRmq2UxnWpwwDpiPdXAVj62cPKwHjKA/0oJyFDp/a4COPcJODjfO1EBGzWvL13r whbg== X-Gm-Message-State: AOAM530Ld3g6b86BWDAWUMZK/HTjV35ModIg9+5sMbH+MJ2cOv4ITCbm zAd29aO1lV/PS+vjeL10LExPHf3pWhg= X-Google-Smtp-Source: ABdhPJymDTcabf5ASXHkfkHdA52xkH88U/gRQC6uHGLHExWrtxbNsscINthuVYCjgRwIQ2yva9deag== X-Received: by 2002:a4a:d199:: with SMTP id j25mr720388oor.43.1623367590866; Thu, 10 Jun 2021 16:26:30 -0700 (PDT) Received: from [192.168.0.41] (97-118-122-241.hlrn.qwest.net. [97.118.122.241]) by smtp.gmail.com with ESMTPSA id e83sm834448oia.40.2021.06.10.16.26.30 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 10 Jun 2021 16:26:30 -0700 (PDT) Subject: [PATCH 1/4] introduce diagnostic infrastructure changes (PR 98512) To: David Malcolm , gcc-patches References: <2e49b6c6-a403-a207-c41e-58f78df96b84@gmail.com> <945093c7-de5e-0350-6030-e4e79ea41161@gmail.com> <5aff247f-dfcb-cecf-e07e-b5fca877f911@gmail.com> From: Martin Sebor Message-ID: Date: Thu, 10 Jun 2021 17:26:29 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 In-Reply-To: <5aff247f-dfcb-cecf-e07e-b5fca877f911@gmail.com> Content-Type: multipart/mixed; boundary="------------115B854BC79D7CF9B469843E" Content-Language: en-US X-Spam-Status: No, score=-9.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 10 Jun 2021 23:26:35 -0000 This is a multi-part message in MIME format. --------------115B854BC79D7CF9B469843E Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit This diff introduces the diagnostic infrastructure changes to support controlling warnings at any call site in the inlining stack and printing the inlining context without the %K and %G directives. --------------115B854BC79D7CF9B469843E Content-Type: text/x-patch; charset=UTF-8; name="gcc-98512-1.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="gcc-98512-1.diff" Improve warning suppression for inlined functions. Resolves: PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute gcc/ChangeLog: * diagnostic.c (update_inlining_context): New. (update_effective_level_from_pragmas): Handle inlining context. (diagnostic_report_diagnostic): Same. * diagnostic.h (struct diagnostic_info): Add ctor. (struct diagnostic_context): Add members. * tree-diagnostic.c (get_inlining_locations): New. (set_inlining_location): New. (tree_diagnostics_defaults): Set new callback pointers. diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index d58586f2526..d1c8c655f7a 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -991,51 +991,92 @@ 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 inlininig context in CONTEXT for a DIAGNOSTIC. */ + +static void +update_inlining_context (diagnostic_context *context, + diagnostic_info *diagnostic) +{ + context->ictx.reset (); + + auto &ilocs = context->ictx.ilocs; + + if (context->get_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->get_locations_cb (context, diagnostic); + else + { + /* When there's no metadata use just the one location provided + by the caller of the diagnostic function. */ + location_t loc = diagnostic_location (diagnostic); + ilocs.safe_push (loc); + context->ictx.allsyslocs = in_system_header_at (loc); + } +} + +/* Update the kind of DIAGNOSTIC based on its location(s), including + any of those in its inlining context, 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 (context->ictx.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; + + auto &ilocs = context->ictx.ilocs; + /* 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 (unsigned idx = 0; idx < ilocs.length (); ++idx) + { /* 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, ilocs[idx])) + 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 @@ -1129,6 +1170,9 @@ static bool diagnostic_enabled (diagnostic_context *context, diagnostic_info *diagnostic) { + /* Update the inlining context for this diagnostic. */ + update_inlining_context (context, diagnostic); + /* Diagnostics with no option or -fpermissive are always enabled. */ if (!diagnostic->option_index || diagnostic->option_index == permissive_error_option (context)) @@ -1194,9 +1238,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) { @@ -1204,7 +1256,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; @@ -1228,9 +1280,17 @@ diagnostic_report_diagnostic (diagnostic_context *context, && diagnostic->kind == DK_WARNING) diagnostic->kind = DK_ERROR; + /* 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 && context->ictx.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); @@ -1270,8 +1330,14 @@ diagnostic_report_diagnostic (diagnostic_context *context, } context->diagnostic_group_emission_count++; + /* Move X_DATA into DIAGNOSTIC->MESSAGE before setting inlining context + abstract origin and location. It uses X_DATA. */ diagnostic->message.x_data = &diagnostic->x_data; diagnostic->x_data = NULL; + + if (context->set_location_cb) + context->set_location_cb (context, diagnostic); + pp_format (context->printer, &diagnostic->message); (*diagnostic_starter (context)) (context, diagnostic); pp_output_formatted_text (context->printer); diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 1b9d6b1f64d..b95ee23dda0 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -87,6 +87,10 @@ enum diagnostics_extra_output_kind list in diagnostic.def. */ struct diagnostic_info { + diagnostic_info () + : message (), richloc (), metadata (), x_data (), kind (), option_index () + { } + /* Text to be formatted. */ text_info message; @@ -343,6 +347,32 @@ struct diagnostic_context /* Callback for final cleanup. */ void (*final_cb) (diagnostic_context *context); + + /* The inlining context of the diagnostic (may have just one + element if a diagnostic is not for an inlined expression). */ + struct inlining_ctx + { + void reset () + { + ilocs.release (); + loc = UNKNOWN_LOCATION; + ao = NULL; + allsyslocs = false; + } + + /* Locations along the inlining stack. */ + auto_vec ilocs; + /* The locus of the diagnostic. */ + location_t loc; + /* The abstract origin of the location. */ + void *ao; + /* Set of every ILOCS element is in a system header. */ + bool allsyslocs; + } ictx; + + /* Callbacks to get and set the inlining context. */ + void (*get_locations_cb)(diagnostic_context *, diagnostic_info *); + void (*set_location_cb)(const diagnostic_context *, diagnostic_info *); }; static inline void diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c index 95b8ef30070..a8c5484849a 100644 --- a/gcc/tree-diagnostic.c +++ b/gcc/tree-diagnostic.c @@ -305,6 +305,84 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec, return true; } +/* Get the inlining stack corresponding to the DIAGNOSTIC location. */ + +static void +get_inlining_locations (diagnostic_context *context, + diagnostic_info *diagnostic) +{ + context->ictx.reset (); + + location_t loc = diagnostic_location (diagnostic); + tree block = LOCATION_BLOCK (loc); + + /* Count the number of locations in system headers. When all are, + warnings are suppressed by -Wno-system-headers. Otherwise, they + involve some user code, possibly inlined into a function in a system + header, and are not treated as coming from system headers. */ + unsigned nsyslocs = 0; + + while (block && TREE_CODE (block) == BLOCK + && BLOCK_ABSTRACT_ORIGIN (block)) + { + tree ao = BLOCK_ABSTRACT_ORIGIN (block); + if (TREE_CODE (ao) == FUNCTION_DECL) + { + if (!context->ictx.ao) + context->ictx.ao = block; + + location_t loc = BLOCK_SOURCE_LOCATION (block); + context->ictx.ilocs.safe_push (loc); + if (in_system_header_at (loc)) + ++nsyslocs; + } + else if (TREE_CODE (ao) != BLOCK) + break; + + block = BLOCK_SUPERCONTEXT (block); + } + + if (context->ictx.ilocs.length ()) + { + /* When there is an inlining context use the macro expansion + location for the original location and bump up NSYSLOCS if + it's in a system header since it's not counted above. */ + context->ictx.loc = expansion_point_location_if_in_system_header (loc); + if (context->ictx.loc != loc) + ++nsyslocs; + } + else + { + /* When there's no inlining context use the original location + and set NSYSLOCS accordingly. */ + context->ictx.loc = loc; + nsyslocs = in_system_header_at (loc) != 0; + } + + context->ictx.ilocs.safe_push (context->ictx.loc); + + /* Set if all locations are in a system header. */ + context->ictx.allsyslocs = nsyslocs == context->ictx.ilocs.length ();; +} + +/* Set the inlining location for to the DIAGNOSTIC based on the saved + inlining context. */ + +static void +set_inlining_location (const diagnostic_context *context, + diagnostic_info *diagnostic) +{ + if (!pp_ti_abstract_origin (&diagnostic->message) + || !context->ictx.ao + || context->ictx.loc == UNKNOWN_LOCATION) + /* Do nothing when there's no inlining context. */ + return; + + *pp_ti_abstract_origin (&diagnostic->message) = (tree)context->ictx.ao; + diagnostic->message.set_location (0, context->ictx.loc, + SHOW_RANGE_WITH_CARET); +} + /* Sets CONTEXT to use language independent diagnostics. */ void tree_diagnostics_defaults (diagnostic_context *context) @@ -314,4 +392,6 @@ tree_diagnostics_defaults (diagnostic_context *context) diagnostic_format_decoder (context) = default_tree_printer; context->print_path = default_tree_diagnostic_path_printer; context->make_json_for_path = default_tree_make_json_for_path; + context->get_locations_cb = get_inlining_locations; + context->set_location_cb = set_inlining_location; } --------------115B854BC79D7CF9B469843E--