Fortran: Improve file-reading error diagnostic [PR55534] (was: Re: [Patch] Fortran: Improve -Wmissing-include-dirs warnings [PR55534])

Message ID 4312b54b-6fb2-c57c-e102-9474ffd56e7a@codesourcery.com
State New
Headers
Series Fortran: Improve file-reading error diagnostic [PR55534] (was: Re: [Patch] Fortran: Improve -Wmissing-include-dirs warnings [PR55534]) |

Commit Message

Tobias Burnus Sept. 22, 2021, 10:06 p.m. UTC
  Hi Harald,

On 22.09.21 20:29, Harald Anlauf via Gcc-patches wrote:
> What I find a bit confusing - from the viewpoint of a user - is the
> case of using the preprocessor (-cpp), as one gets e.g.
>
> <built-in>: Warning: ./no/such/dir: No such file or directory
> [-Wmissing-include-dirs]
>
> while without -cpp:
>
> f951: Warning: Nonexistent include directory './no/such/dir/'
> [-Wmissing-include-dirs]

C/C++ do something likewise (grep for that string).

The reason for the <built-in> is the code in cpp.c's gfc_cpp_init,
which uses:
   cpp_change_file (cpp_in, LC_RENAME, _("<built-in>"));

It might be possible to reset it by passing NULL to it, at the end
of that function but I don't know whether that causes side effects.
At least linemap_add then uses set->depth--.
It might work just fine, but I do not know.
(Additionally, cb_file_change or print_line needs to be updated
to handle to_file == NULL.)

Feel free to experiment there. Otherwise, I leave it as is.

  * * *

However, this patch now improves the diagnostic printed by
load_file – and uses directly an fatal error instead of
a usual error and then propagating the error through.

Errors are now also properly colored.

Note:
* -fpre-included= is not easily testable. It works when calling
   the compiler itself (f951) but the driver (gfortran) overrides
   it here with:
    -fpre-include=/usr/include/finclude/math-vector-fortran.h
   which exits.

* I did not include the test "include_22.f90" with:
     include "include_22.f90"  ! { dg-error "File 'include_22.f90' is being included recursively" }
   as the error message seemingly confused DejaGNU and causes it
   to enter an endless loop.

OK for mainline?

Tobias

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

Comments

Tobias Burnus Sept. 24, 2021, 8:41 a.m. UTC | #1
On 23.09.21 23:01, Harald Anlauf via Fortran wrote:

> compiled with -cpp gives:
>
> pr55534-play.f90:4:2:
>
>     4 |   type t
>       |  1~~~~~~
> Fatal Error: no/such/file.inc: No such file or directory
> compilation terminated.
>
> If you have an easy solution for that one,

David has an easy but hackish solution, cf. https://gcc.gnu.org/PR100904

That's a GCC 7 regression, which also affects C/C++ but only when
compiling with -traditional-cpp, which gfortran does by default but
gcc/g++ don't.

Tobias

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

Patch

Fortran: Improve file-reading error diagnostic [PR55534]

	PR fortran/55534

gcc/fortran/ChangeLog:

	* scanner.c (load_file): Return void, call (gfc_)fatal_error for
	all errors.
	(include_line, include_stmt, gfc_new_file): Remove exit call
	for failed load_file run.

gcc/testsuite/ChangeLog:

	* gfortran.dg/include_9.f90: Add dg-prune-output.
	* gfortran.dg/include_23.f90: New test.
	* gfortran.dg/include_24.f90: New test.

 gcc/fortran/scanner.c                    | 66 ++++++++++++--------------------
 gcc/testsuite/gfortran.dg/include_23.f90 |  4 ++
 gcc/testsuite/gfortran.dg/include_24.f90 |  4 ++
 gcc/testsuite/gfortran.dg/include_9.f90  |  1 +
 4 files changed, 33 insertions(+), 42 deletions(-)

diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c
index 52124bd5d36..5a450692ba3 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -47,6 +47,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "toplev.h"	/* For set_src_pwd.  */
 #include "debug.h"
 #include "options.h"
+#include "diagnostic-core.h"  /* For fatal_error. */
 #include "cpp.h"
 #include "scanner.h"
 
@@ -2230,7 +2231,7 @@  preprocessor_line (gfc_char_t *c)
 }
 
 
-static bool load_file (const char *, const char *, bool);
+static void load_file (const char *, const char *, bool);
 
 /* include_line()-- Checks a line buffer to see if it is an include
    line.  If so, we call load_file() recursively to load the included
@@ -2396,9 +2397,7 @@  include_line (gfc_char_t *line)
 		   read by anything else.  */
 
   filename = gfc_widechar_to_char (begin, -1);
-  if (!load_file (filename, NULL, false))
-    exit (FATAL_EXIT_CODE);
-
+  load_file (filename, NULL, false);
   free (filename);
   return 1;
 }
@@ -2505,9 +2504,7 @@  include_stmt (gfc_linebuf *b)
       filename[i] = (unsigned char) c;
     }
   filename[length] = '\0';
-  if (!load_file (filename, NULL, false))
-    exit (FATAL_EXIT_CODE);
-
+  load_file (filename, NULL, false);
   free (filename);
 
 do_ret:
@@ -2525,9 +2522,11 @@  do_ret:
   return ret;
 }
 
+
+
 /* Load a file into memory by calling load_line until the file ends.  */
 
-static bool
+static void
 load_file (const char *realfilename, const char *displayedname, bool initial)
 {
   gfc_char_t *line;
@@ -2549,13 +2548,8 @@  load_file (const char *realfilename, const char *displayedname, bool initial)
 
   for (f = current_file; f; f = f->up)
     if (filename_cmp (filename, f->filename) == 0)
-      {
-	fprintf (stderr, "%s:%d: Error: File '%s' is being included "
-		 "recursively\n", current_file->filename, current_file->line,
-		 filename);
-	return false;
-      }
-
+      fatal_error (linemap_line_start (line_table, current_file->line, 0),
+		   "File %qs is being included recursively", filename);
   if (initial)
     {
       if (gfc_src_file)
@@ -2567,10 +2561,7 @@  load_file (const char *realfilename, const char *displayedname, bool initial)
 	input = gfc_open_file (realfilename);
 
       if (input == NULL)
-	{
-	  gfc_error_now ("Cannot open file %qs", filename);
-	  return false;
-	}
+	gfc_fatal_error ("Cannot open file %qs", filename);
     }
   else
     {
@@ -2579,22 +2570,20 @@  load_file (const char *realfilename, const char *displayedname, bool initial)
 	{
 	  /* For -fpre-include file, current_file is NULL.  */
 	  if (current_file)
-	    fprintf (stderr, "%s:%d: Error: Can't open included file '%s'\n",
-		     current_file->filename, current_file->line, filename);
+	    fatal_error (linemap_line_start (line_table, current_file->line, 0),
+			 "Cannot open included file %qs", filename);
 	  else
-	    fprintf (stderr, "Error: Can't open pre-included file '%s'\n",
-		     filename);
-
-	  return false;
+	    gfc_fatal_error ("Cannot open pre-included file %qs", filename);
 	}
       stat_result = stat (realfilename, &st);
-      if (stat_result == 0 && !S_ISREG(st.st_mode))
+      if (stat_result == 0 && !S_ISREG (st.st_mode))
 	{
-	  fprintf (stderr, "%s:%d: Error: Included path '%s'"
-		   " is not a regular file\n",
-		   current_file->filename, current_file->line, filename);
 	  fclose (input);
-	  return false;
+	  if (current_file)
+	    fatal_error (linemap_line_start (line_table, current_file->line, 0),
+			 "Included file %qs is not a regular file", filename);
+	  else
+	    gfc_fatal_error ("Included file %qs is not a regular file", filename);
 	}
     }
 
@@ -2768,7 +2757,6 @@  load_file (const char *realfilename, const char *displayedname, bool initial)
     add_file_change (NULL, current_file->inclusion_line + 1);
   current_file = current_file->up;
   linemap_add (line_table, LC_LEAVE, 0, NULL, 0);
-  return true;
 }
 
 
@@ -2780,23 +2768,17 @@  load_file (const char *realfilename, const char *displayedname, bool initial)
 void
 gfc_new_file (void)
 {
-  bool result;
-
-  if (flag_pre_include != NULL
-      && !load_file (flag_pre_include, NULL, false))
-    exit (FATAL_EXIT_CODE);
+  if (flag_pre_include != NULL)
+    load_file (flag_pre_include, NULL, false);
 
   if (gfc_cpp_enabled ())
     {
-      result = gfc_cpp_preprocess (gfc_source_file);
+      gfc_cpp_preprocess (gfc_source_file);
       if (!gfc_cpp_preprocess_only ())
-        result = load_file (gfc_cpp_temporary_file (), gfc_source_file, true);
+	load_file (gfc_cpp_temporary_file (), gfc_source_file, true);
     }
   else
-    result = load_file (gfc_source_file, NULL, true);
-
-  if (!result)
-    exit (FATAL_EXIT_CODE);
+    load_file (gfc_source_file, NULL, true);
 
   gfc_current_locus.lb = line_head;
   gfc_current_locus.nextc = (line_head == NULL) ? NULL : line_head->line;
diff --git a/gcc/testsuite/gfortran.dg/include_23.f90 b/gcc/testsuite/gfortran.dg/include_23.f90
new file mode 100644
index 00000000000..421ddda87bc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_23.f90
@@ -0,0 +1,4 @@ 
+implicit none
+include "nonexisting/file.f90"  ! { dg-error "Cannot open included file 'nonexisting/file.f90'" }
+end
+! { dg-prune-output "compilation terminated." }
diff --git a/gcc/testsuite/gfortran.dg/include_24.f90 b/gcc/testsuite/gfortran.dg/include_24.f90
new file mode 100644
index 00000000000..1fe9eb57625
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/include_24.f90
@@ -0,0 +1,4 @@ 
+implicit none
+include "."  ! { dg-error "Included file '.' is not a regular file" }
+end
+! { dg-prune-output "compilation terminated." }
diff --git a/gcc/testsuite/gfortran.dg/include_9.f90 b/gcc/testsuite/gfortran.dg/include_9.f90
index c4ef50f6e50..6b0648b3ee5 100644
--- a/gcc/testsuite/gfortran.dg/include_9.f90
+++ b/gcc/testsuite/gfortran.dg/include_9.f90
@@ -4,3 +4,4 @@ 
       program main
       end program
 ! { dg-error "is not a regular file" " " { target *-*-* } 3 }
+! { dg-prune-output "compilation terminated." }