From patchwork Fri Sep 17 13:02:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tobias Burnus X-Patchwork-Id: 45126 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A3C7A385480A for ; Fri, 17 Sep 2021 13:02:43 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) by sourceware.org (Postfix) with ESMTPS id 2F68B3857C5B; Fri, 17 Sep 2021 13:02:16 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2F68B3857C5B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com IronPort-SDR: J3d3Uwl67cclkyPRfbIhIVm0paCzj8ypan/xsk+kh+HSyykWg30Rk2BFKLCumu0L2XLKKoOjIJ j2t5pVHxhXKufm8CLFMraOjju56Iteea0RQz4VDuLBRAbSWIGntt1GH/LN+hv6uJmROEWMsVPd 8U2c4FFTxNficooiRwsgytNBrGTJExJNtUVpYUVxU7s6azLAc4Upu/3m8Zd5dOLTUDIMvKY1SI EqAFjmhMyPEnG+wGURW6VLaIErqPhwocb0J+3Hzz+TECyhurxC9BQNSgLEzJ5heKECNnckpHM2 cFCR9EI+78YXuPy0dUjzG7fY X-IronPort-AV: E=Sophos;i="5.85,301,1624348800"; d="diff'?scan'208";a="65978146" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 17 Sep 2021 05:02:15 -0800 IronPort-SDR: 1erL6M5nDMDxHim4tgio4pc/mOBseTyVP4IGt7tsZmKxR2rkEk5LmQrOS6PdLGwZOw72zy56l7 QmtHy5rMwEKlt/oB0G6rGiSsXZ1lbJOIDKvEGAR8VQfq+YTvAXgT8DCGBS06udXmv0HeZi5EtH Ryv8C558LFdVMedowHV9ybANXvhwac60a1+6KOQgEX/bxHfegzP7FPpig8ihGMrVpUdaIJgIo2 O/2QI92RRfblnNxvh8VzxK4ttemKLr3vsVDipygambG3VRvX6/nceOsdMTx4bzMMej1xcHpERU 6jk= To: gcc-patches , fortran From: Tobias Burnus Subject: [Patch] Fortran: Fix -Wno-missing-include-dirs handling [PR55534] Message-ID: <7d444f75-620a-fdd4-6edd-6a1969b1ac7b@codesourcery.com> Date: Fri, 17 Sep 2021 15:02:09 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 MIME-Version: 1.0 Content-Language: en-US X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-02.mgc.mentorg.com (139.181.222.2) To svr-ies-mbx-01.mgc.mentorg.com (139.181.222.1) X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, KAM_SHORT, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Short version: * -Wno-missing-include-dirs had no effect as the warning was always on * For CPP-only options like -idirafter, no warning was shown. This patch tries to address both, i.e. cpp's include-dir diagnostics are shown as well – and silencing the diagnostic works as well. OK for mainline? Tobias PS: BACKGROUND and LONG DESCRIPTION C/C++ by default have disabled the -Wmissing-include-dirs warning. Fortran by default has that warning enabled. The value is actually stored at two places (cf. c-family/c.opt): Wmissing-include-dirs ... CPP(warn_missing_include_dirs) Var(cpp_warn_missing_include_dirs) Init(0) For CPP, that value always needs to initialized – and it is used in gcc/incpath.c as cpp_options *opts = cpp_get_options (pfile); if (opts->warn_missing_include_dirs && cur->user_supplied_p) cpp_warning (pfile, CPP_W_MISSING_INCLUDE_DIRS, "%s: %s", Additionally, there is cpp_warn_missing_include_dirs which is used by Fortran – and which consists of global_options.x_cpp_warn_missing_include_dirs global_options_set._cpp_warn_missing_include_dirs The flag processing happens as described in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55534#c11 in short: - First gfc_init_options is called - Then for reach command-line option gfc_handle_option - Finally gfc_post_options Currently: - gfc_init_options: Sets cpp_warn_missing_include_dirs (unconditionally as unset) - gfc_handle_option: Always warns about the missing include dir - before gfc_post_options: set_option is called, which sets cpp_warn_missing_include_dirs – but that's too late. Additionally, as mentioned above – pfile's warn_missing_include_dirs is never properly set. * * * This patch fixes those issues: * Now -Wno-missing-include-dirs does silence the warnings * CPP now also properly does warn. Example (initial version): $ gfortran-trunk ../empty.f90 -c -cpp -idirafter /fdaf/ -I bar/ -Wmissing-include-dirs f951: Warning: Nonexistent include directory ‘bar//’ [-Wmissing-include-dirs] : Warning: /fdaf/: No such file or directory : Warning: bar/: No such file or directory In order to avoid the double output for -I, I disabled the Fortran output if CPP is enabled. Additionally, I had to use the cpp_reason_option_codes to print the flag in brackets. Fixed/final output is: : Warning: /fdaf/: No such file or directory [-Wmissing-include-dirs] : Warning: bar/: No such file or directory [-Wmissing-include-dirs] ----------------- Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955 Fortran: Fix -Wno-missing-include-dirs handling [PR55534] gcc/fortran/ChangeLog: PR fortran/55534 * cpp.c: Define GCC_C_COMMON_C for #include "options.h" to make cpp_reason_option_codes available. (gfc_cpp_register_include_paths): Make static, set pfile's warn_missing_include_dirs and move before caller. (gfc_cpp_init_cb): New, cb code moved from ... (gfc_cpp_init_0): ... here. (gfc_cpp_post_options): Call gfc_cpp_init_cb. (cb_cpp_diagnostic_cpp_option): New. As implemented in c-family to match CppReason flags to -W... names. (cb_cpp_diagnostic): Use it to replace single special case. * cpp.h (gfc_cpp_register_include_paths): Remove as now static. * gfortran.h (gfc_check_include_dirs): New prototype. * options.c (gfc_init_options): Don't set -Wmissing-include-dirs. (gfc_post_options): Set it here after commandline processing. * scanner.c (gfc_do_check_include_dirs, gfc_check_include_dirs): New. Diagnostic moved from ... (add_path_to_list): ... here, which came before cmdline processing. * scanner.h (struct gfc_directorylist): Reorder for alignment issues, add new 'bool warn'. gcc/fortran/cpp.c | 106 ++++++++++++++++++++++++++++++------------------- gcc/fortran/cpp.h | 2 - gcc/fortran/gfortran.h | 1 + gcc/fortran/options.c | 14 +++---- gcc/fortran/scanner.c | 58 +++++++++++++++++++-------- gcc/fortran/scanner.h | 2 +- 6 files changed, 116 insertions(+), 67 deletions(-) diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c index 83c4517acdb..3ff895455e9 100644 --- a/gcc/fortran/cpp.c +++ b/gcc/fortran/cpp.c @@ -19,11 +19,15 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" + +#define GCC_C_COMMON_C +#include "options.h" /* For cpp_reason_option_codes. */ +#undef GCC_C_COMMON_C + #include "target.h" #include "gfortran.h" #include "diagnostic.h" - #include "toplev.h" #include "../../libcpp/internal.h" @@ -240,6 +244,18 @@ gfc_cpp_temporary_file (void) return gfc_cpp_option.temporary_filename; } +static void +gfc_cpp_register_include_paths (void) +{ + int cxx_stdinc = 0; + cpp_get_options (cpp_in)->warn_missing_include_dirs + = global_options.x_cpp_warn_missing_include_dirs; + register_include_chains (cpp_in, gfc_cpp_option.sysroot, + gfc_cpp_option.prefix, gfc_cpp_option.multilib, + gfc_cpp_option.standard_include_paths, cxx_stdinc, + gfc_cpp_option.verbose); +} + void gfc_cpp_init_options (unsigned int decoded_options_count, struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED) @@ -435,6 +451,37 @@ gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED return result; } +/* This function needs to be called before gfc_cpp_register_include_paths + as the latter may diagnose missing include directories. */ +static void +gfc_cpp_init_cb (void) +{ + struct cpp_callbacks *cb; + + cb = cpp_get_callbacks (cpp_in); + cb->file_change = cb_file_change; + cb->line_change = cb_line_change; + cb->ident = cb_ident; + cb->def_pragma = cb_def_pragma; + cb->diagnostic = cb_cpp_diagnostic; + + if (gfc_cpp_option.dump_includes) + cb->include = cb_include; + + if ((gfc_cpp_option.dump_macros == 'D') + || (gfc_cpp_option.dump_macros == 'N')) + { + cb->define = cb_define; + cb->undef = cb_undef; + } + + if (gfc_cpp_option.dump_macros == 'U') + { + cb->before_define = dump_queued_macros; + cb->used_define = cb_used_define; + cb->used_undef = cb_used_undef; + } +} void gfc_cpp_post_options (void) @@ -498,6 +545,7 @@ gfc_cpp_post_options (void) way libcpp will do it, namely, with no charset conversion but with skipping of a UTF-8 BOM if present. */ diagnostic_initialize_input_context (global_dc, nullptr, true); + gfc_cpp_init_cb (); gfc_cpp_register_include_paths (); } @@ -506,32 +554,6 @@ gfc_cpp_post_options (void) void gfc_cpp_init_0 (void) { - struct cpp_callbacks *cb; - - cb = cpp_get_callbacks (cpp_in); - cb->file_change = cb_file_change; - cb->line_change = cb_line_change; - cb->ident = cb_ident; - cb->def_pragma = cb_def_pragma; - cb->diagnostic = cb_cpp_diagnostic; - - if (gfc_cpp_option.dump_includes) - cb->include = cb_include; - - if ((gfc_cpp_option.dump_macros == 'D') - || (gfc_cpp_option.dump_macros == 'N')) - { - cb->define = cb_define; - cb->undef = cb_undef; - } - - if (gfc_cpp_option.dump_macros == 'U') - { - cb->before_define = dump_queued_macros; - cb->used_define = cb_used_define; - cb->used_undef = cb_used_undef; - } - /* Initialize the print structure. Setting print.src_line to -1 here is a trick to guarantee that the first token of the file will cause a linemarker to be output by maybe_print_line. */ @@ -723,17 +745,6 @@ gfc_cpp_add_include_path_after (char *path, bool user_supplied) add_path (path, INC_AFTER, cxx_aware, user_supplied); } -void -gfc_cpp_register_include_paths (void) -{ - int cxx_stdinc = 0; - register_include_chains (cpp_in, gfc_cpp_option.sysroot, - gfc_cpp_option.prefix, gfc_cpp_option.multilib, - gfc_cpp_option.standard_include_paths, cxx_stdinc, - gfc_cpp_option.verbose); -} - - static void scan_translation_unit_trad (cpp_reader *); static void account_for_newlines (const unsigned char *, size_t); @@ -1043,6 +1054,21 @@ cb_used_define (cpp_reader *pfile, location_t line ATTRIBUTE_UNUSED, cpp_define_queue = q; } +/* Return the gcc option code associated with the reason for a cpp + message, or 0 if none. */ + +static int +cb_cpp_diagnostic_cpp_option (enum cpp_warning_reason reason) +{ + const struct cpp_reason_option_codes_t *entry; + + for (entry = cpp_reason_option_codes; entry->reason != CPP_W_NONE; entry++) + if (entry->reason == reason) + return entry->option_code; + return 0; +} + + /* Callback from cpp_error for PFILE to print diagnostics from the preprocessor. The diagnostic is of type LEVEL, with REASON set to the reason code if LEVEL is represents a warning, at location @@ -1089,8 +1115,8 @@ cb_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED, } diagnostic_set_info_translated (&diagnostic, msg, ap, richloc, dlevel); - if (reason == CPP_W_WARNING_DIRECTIVE) - diagnostic_override_option_index (&diagnostic, OPT_Wcpp); + diagnostic_override_option_index (&diagnostic, + cb_cpp_diagnostic_cpp_option (reason)); ret = diagnostic_report_diagnostic (global_dc, &diagnostic); if (level == CPP_DL_WARNING_SYSHDR) global_dc->dc_warn_system_headers = save_warn_system_headers; diff --git a/gcc/fortran/cpp.h b/gcc/fortran/cpp.h index f642c7745f7..5cb7e5a9c34 100644 --- a/gcc/fortran/cpp.h +++ b/gcc/fortran/cpp.h @@ -50,6 +50,4 @@ void gfc_cpp_done (void); void gfc_cpp_add_include_path (char *path, bool user_supplied); void gfc_cpp_add_include_path_after (char *path, bool user_supplied); -void gfc_cpp_register_include_paths (void); - #endif /* GFC_CPP_H */ diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index fdf556eef3d..b02c434295c 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -3031,6 +3031,7 @@ void gfc_scanner_init_1 (void); void gfc_add_include_path (const char *, bool, bool, bool); void gfc_add_intrinsic_modules_path (const char *); void gfc_release_include_path (void); +void gfc_check_include_dirs (void); FILE *gfc_open_included_file (const char *, bool, bool); int gfc_at_end (void); diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c index 847e20e8829..a1ac760dd96 100644 --- a/gcc/fortran/options.c +++ b/gcc/fortran/options.c @@ -159,14 +159,7 @@ gfc_init_options (unsigned int decoded_options_count, | GFC_FPE_UNDERFLOW; gfc_option.rtcheck = 0; - /* ??? Wmissing-include-dirs is disabled by default in C/C++ but - enabled by default in Fortran. Ideally, we should express this - in .opt, but that is not supported yet. */ - SET_OPTION_IF_UNSET (&global_options, &global_options_set, - cpp_warn_missing_include_dirs, 1); - set_dec_flags (0); - set_default_std_flags (); /* Initialize cpp-related options. */ @@ -260,6 +253,13 @@ gfc_post_options (const char **pfilename) char *source_path; int i; + /* This needs to be after the commandline has been processed. + In Fortran, the options is by default enabled, in C/C++ + by default disabled. */ + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + cpp_warn_missing_include_dirs, 1); + gfc_check_include_dirs (); + /* Finalize DEC flags. */ post_dec_flags (flag_dec); diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c index 39db0994b62..93446c90b0e 100644 --- a/gcc/fortran/scanner.c +++ b/gcc/fortran/scanner.c @@ -298,6 +298,46 @@ gfc_scanner_done_1 (void) } } +/* In order that -W(no-)missing-include-dirs works, the diagnostic can only be + run after processing the commandline. */ +static void +gfc_do_check_include_dirs (gfc_directorylist **list) +{ + struct stat st; + gfc_directorylist *prev, *q, *n; + prev = NULL; + n = *list; + while (n) + { + q = n; n = n->next; + if (stat (q->path, &st)) + { + if (errno != ENOENT) + gfc_warning_now (0, "Include directory %qs: %s", q->path, + xstrerror(errno)); + else if (q->warn && !gfc_cpp_enabled ()) + gfc_warning_now (OPT_Wmissing_include_dirs, + "Nonexistent include directory %qs", q->path); + } + else if (!S_ISDIR (st.st_mode)) + gfc_fatal_error ("%qs is not a directory", q->path); + else + continue; + if (prev == NULL) + *list = n; + else + prev->next = n; + free (q->path); + free (q); + } +} + +void +gfc_check_include_dirs () +{ + gfc_do_check_include_dirs (&include_dirs); + gfc_do_check_include_dirs (&intrinsic_modules_dirs); +} /* Adds path to the list pointed to by list. */ @@ -308,7 +348,6 @@ add_path_to_list (gfc_directorylist **list, const char *path, gfc_directorylist *dir; const char *p; char *q; - struct stat st; size_t len; int i; @@ -326,22 +365,6 @@ add_path_to_list (gfc_directorylist **list, const char *path, while (i >=0 && IS_DIR_SEPARATOR (q[i])) q[i--] = '\0'; - if (stat (q, &st)) - { - if (errno != ENOENT) - gfc_warning_now (0, "Include directory %qs: %s", path, - xstrerror(errno)); - else if (warn) - gfc_warning_now (OPT_Wmissing_include_dirs, - "Nonexistent include directory %qs", path); - return; - } - else if (!S_ISDIR (st.st_mode)) - { - gfc_fatal_error ("%qs is not a directory", path); - return; - } - if (head || *list == NULL) { dir = XCNEW (gfc_directorylist); @@ -362,6 +385,7 @@ add_path_to_list (gfc_directorylist **list, const char *path, if (head) *list = dir; dir->use_for_modules = use_for_modules; + dir->warn = warn; dir->path = XCNEWVEC (char, strlen (p) + 2); strcpy (dir->path, p); strcat (dir->path, "/"); /* make '/' last character */ diff --git a/gcc/fortran/scanner.h b/gcc/fortran/scanner.h index 0bad63f4ffb..8782fe6ccc5 100644 --- a/gcc/fortran/scanner.h +++ b/gcc/fortran/scanner.h @@ -23,8 +23,8 @@ along with GCC; see the file COPYING3. If not see typedef struct gfc_directorylist { char *path; - bool use_for_modules; struct gfc_directorylist *next; + bool use_for_modules, warn; } gfc_directorylist;