diff mbox series

[RFC/PATCH] gcc.c: access does not work in new msvcr for nul file

Message ID 20190103105453.6105-1-johannespfau@gmail.com
State New
Headers show
Series [RFC/PATCH] gcc.c: access does not work in new msvcr for nul file | expand

Commit Message

Johannes Pfau Jan. 3, 2019, 10:54 a.m. UTC
Hello list,

I'm currently adding D support to the MinGW targets. As the libphobos
upstream only targets newer msvcr runtime libraries, I tried building
GCC against libmsvcr120. When doing that, the build fails when building 
s-selftest-c++:

/home/jpfau/mingw-gcc-trunk/x86_64-trunk-win32-seh-rt_v6/build/gcc-trunk/./gcc/xgcc \
    -B/home/jpfau/mingw-gcc-trunk/x86_64-trunk-win32-seh-rt_v6/build/gcc-trunk/./gcc/ \
    -xc++ -nostdinc nul -S -o nul -fself-test=../../../../src/gcc-trunk/gcc/testsuite/selftests
xgcc.exe: error: nul: Invalid argument
xgcc.exe: warning: '-x c' after last input file has no effect
xgcc.exe: fatal error: no input files
compilation terminated.
make[2]: *** [../../../../src/gcc-trunk/gcc/cp/Make-lang.in:178: s-selftest-c++] Error 1

Debugging shows that the access function used to check
if the input files exist has different behavior in newer msvcr libraries:
It does return proper results for the 'nul' file in the old msvcrt.dll
but in newer libraries it returns EINVAL for the nul file.

I can think of at least two possible solutions:
1) Manually strcmp the input to find nul files. As far as I know there
   are many paths which count as nul files on windows, so it might be
   difficult to actually properly support all valid paths.
2) Use the windows API to check if the file exists.

A RFC patch for 2) is attached. I guess we don't want such platform
specific code in GCC, so any recommendation how to proceed? Should
this be placed in libiberty as a generic
int file_exists(const char *path, **error) instead?

Best regards,
Johannes

---
 gcc/gcc.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

Comments

Alexander Monakov Jan. 3, 2019, 12:34 p.m. UTC | #1
On Thu, 3 Jan 2019, Johannes Pfau wrote:
> 
> Debugging shows that the access function used to check
> if the input files exist has different behavior in newer msvcr libraries:
> It does return proper results for the 'nul' file in the old msvcrt.dll
> but in newer libraries it returns EINVAL for the nul file.

I would recommend to consult with MinGW-W64 maintainers first: it may be
appropriate to handle this in mingw's wrapper for the access function.
In any case, they should be informed about this weird regression.

Cheers.
Alexander
Johannes Pfau Jan. 13, 2019, 10:13 p.m. UTC | #2
Am 03.01.19 um 13:34 schrieb Alexander Monakov:
> On Thu, 3 Jan 2019, Johannes Pfau wrote:
>>
>> Debugging shows that the access function used to check
>> if the input files exist has different behavior in newer msvcr libraries:
>> It does return proper results for the 'nul' file in the old msvcrt.dll
>> but in newer libraries it returns EINVAL for the nul file.
> 
> I would recommend to consult with MinGW-W64 maintainers first: it may be
> appropriate to handle this in mingw's wrapper for the access function.
> In any case, they should be informed about this weird regression.
> 
> Cheers.
> Alexander
> 

Thanks for your help Alexander. I've reported this to MinGW-W64 and the 
problem has now been solved in MinGW-W64, commit 
df15931c0d2c250218c68d71ec35bac61f84e1be.

Best regards,
Johannes
diff mbox series

Patch

diff --git a/gcc/gcc.c b/gcc/gcc.c
index 955a08cc8e8..674313facf1 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -45,6 +45,10 @@  compilation is specified by a string called a "spec".  */
 #include "filenames.h"
 #include "spellcheck.h"
 
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
 
 
 /* Manage the manipulation of env vars.
@@ -4552,12 +4556,26 @@  process_command (unsigned int decoded_options_count,
 	  else
 	    fname = xstrdup (arg);
 
-          if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
+#ifdef _WIN32
+	  // _access does not work for the nul file on newer msvc versions
+	  if (strcmp (fname, "-") != 0 && GetFileAttributes(fname) == INVALID_FILE_ATTRIBUTES)
+	    {
+	      bool resp = fname[0] == '@'
+		  && GetFileAttributes(fname + 1) == INVALID_FILE_ATTRIBUTES;
+
+	      char error_msg[256] = "\0";
+	      FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
+		(LPSTR)&error_msg, 256, NULL);
+	      error ("%s: %s", fname + resp, error_msg);
+	    }
+#else
+	  if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
 	    {
 	      bool resp = fname[0] == '@' && access (fname + 1, F_OK) < 0;
 	      error ("%s: %m", fname + resp);
 	    }
-          else
+#endif
+	  else
 	    add_infile (arg, spec_lang);
 
           free (fname);