diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 0e2289d81b7..3424fef99ba 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,72 @@ +2023-06-15 Marek Polacek + + * configure.ac: Also set shared when enable_host_pie. + * configure: Regenerate. + +2023-06-13 Nathan Sidwell + + * cp-demangle.c (d_print_conversion): Remove incorrect + template instantiation handling. + * testsuite/demangle-expected: Add testcases. + +2023-06-07 Costas Argyris + + * argv.c (writeargv): Constant propagate "0" for "status", + simplifying the code slightly. + +2023-06-06 Costas Argyris + + * argv.c (writeargv): Simplify & remove gotos. + +2023-06-05 Costas Argyris + + * pex-win32.c: fix typos. + +2023-06-05 Costas Argyris + + * pex-win32.c (win32_spawn): Check command line length + and generate a response file if necessary. + (spawn_script): Adjust parameters. + (pex_win32_exec_child): Ditto. + +2023-06-03 Patrick Palka + + PR c++/70790 + * cp-demangle.c (cplus_demangle_operators): Add the noexcept + operator. + (d_print_comp_inner) : Always + print parens around the operand of noexcept too. + * testsuite/demangle-expected: Test noexcept operator + demangling. + +2023-04-02 Jakub Jelinek + + PR other/109306 + * strstr.c: Revert the 2020-11-13 changes. + (strstr): Return s1 if len is 0. + +2023-03-30 Gerald Pfeifer + + * obstacks.texi (Preparing for Obstacks): Remove a (broken) + reference to the Glibc manual. + +2023-03-03 Costas Argyris + + * pex-win32.c (win32_spawn): Fix memory leak of cmdline + buffer and refactor to have cleanup code appear once + for all exit cases. + +2023-02-11 niXman + + * lrealpath.c (lrealpath): try to resolve symlink and + use UNC paths where applicable. + +2023-01-07 LIU Hao + + PR middle-end/108300 + * make-temp-file.c: Define `WIN32_LEAN_AND_MEAN` before . + * pex-win32.c: Likewise. + 2022-11-23 Marek Polacek Revert: diff --git a/libiberty/argv.c b/libiberty/argv.c index a95a10e14ff..c2823d3e4ba 100644 --- a/libiberty/argv.c +++ b/libiberty/argv.c @@ -289,8 +289,8 @@ char **buildargv (const char *input) @deftypefn Extension int writeargv (char * const *@var{argv}, FILE *@var{file}) Write each member of ARGV, handling all necessary quoting, to the file -named by FILE, separated by whitespace. Return 0 on success, non-zero -if an error occurred while writing to FILE. +associated with FILE, separated by whitespace. Return 0 on success, +non-zero if an error occurred while writing to FILE. @end deftypefn @@ -299,8 +299,6 @@ if an error occurred while writing to FILE. int writeargv (char * const *argv, FILE *f) { - int status = 0; - if (f == NULL) return 1; @@ -314,37 +312,26 @@ writeargv (char * const *argv, FILE *f) if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"') if (EOF == fputc ('\\', f)) - { - status = 1; - goto done; - } + return 1; if (EOF == fputc (c, f)) - { - status = 1; - goto done; - } + return 1; + arg++; } /* Write out a pair of quotes for an empty argument. */ if (arg == *argv) - if (EOF == fputs ("\"\"", f)) - { - status = 1; - goto done; - } + if (EOF == fputs ("\"\"", f)) + return 1; if (EOF == fputc ('\n', f)) - { - status = 1; - goto done; - } + return 1; + argv++; } - done: - return status; + return 0; } /* diff --git a/libiberty/configure b/libiberty/configure index 1ccfac9fb11..dd896270dc6 100755 --- a/libiberty/configure +++ b/libiberty/configure @@ -5396,8 +5396,8 @@ case "${enable_shared}" in *) shared=yes ;; esac -# ...unless --enable-host-shared was passed from top-level config: -if [ "${enable_host_shared}" = "yes" ]; then +# ...unless --enable-host-{shared,pie} was passed from top-level config: +if [ "${enable_host_shared}" = "yes" ] || [ "${enable_host_pie}" = "yes" ]; then shared=yes fi diff --git a/libiberty/configure.ac b/libiberty/configure.ac index 6c1ff9c6093..0748c592704 100644 --- a/libiberty/configure.ac +++ b/libiberty/configure.ac @@ -245,8 +245,8 @@ case "${enable_shared}" in *) shared=yes ;; esac -# ...unless --enable-host-shared was passed from top-level config: -if [[ "${enable_host_shared}" = "yes" ]]; then +# ...unless --enable-host-{shared,pie} was passed from top-level config: +if [[ "${enable_host_shared}" = "yes" ]] || [[ "${enable_host_pie}" = "yes" ]]; then shared=yes fi diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index f2b36bcad68..3bd303a7544 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -1947,6 +1947,7 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "ng", NL ("-"), 1 }, { "nt", NL ("!"), 1 }, { "nw", NL ("new"), 3 }, + { "nx", NL ("noexcept"), 1 }, { "oR", NL ("|="), 2 }, { "oo", NL ("||"), 2 }, { "or", NL ("|"), 2 }, @@ -5836,8 +5837,8 @@ d_print_comp_inner (struct d_print_info *dpi, int options, if (code && !strcmp (code, "gs")) /* Avoid parens after '::'. */ d_print_comp (dpi, options, operand); - else if (code && !strcmp (code, "st")) - /* Always print parens for sizeof (type). */ + else if (code && (!strcmp (code, "st") || !strcmp (code, "nx"))) + /* Always print parens for sizeof (type) and noexcept(expr). */ { d_append_char (dpi, '('); d_print_comp (dpi, options, operand); @@ -6659,32 +6660,10 @@ d_print_conversion (struct d_print_info *dpi, int options, dpt.template_decl = dpi->current_template; } - if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) - { - d_print_comp (dpi, options, d_left (dc)); - if (dpi->current_template != NULL) - dpi->templates = dpt.next; - } - else - { - d_print_comp (dpi, options, d_left (d_left (dc))); + d_print_comp (dpi, options, d_left (dc)); - /* For a templated cast operator, we need to remove the template - parameters from scope after printing the operator name, - so we need to handle the template printing here. */ - if (dpi->current_template != NULL) - dpi->templates = dpt.next; - - if (d_last_char (dpi) == '<') - d_append_char (dpi, ' '); - d_append_char (dpi, '<'); - d_print_comp (dpi, options, d_right (d_left (dc))); - /* Avoid generating two consecutive '>' characters, to avoid - the C++ syntactic ambiguity. */ - if (d_last_char (dpi) == '>') - d_append_char (dpi, ' '); - d_append_char (dpi, '>'); - } + if (dpi->current_template != NULL) + dpi->templates = dpt.next; } /* Initialize the information structure we use to pass around diff --git a/libiberty/lrealpath.c b/libiberty/lrealpath.c index c662f8fd37e..2578288e8ac 100644 --- a/libiberty/lrealpath.c +++ b/libiberty/lrealpath.c @@ -68,8 +68,135 @@ extern char *canonicalize_file_name (const char *); /* cygwin has realpath, so it won't get here. */ # if defined (_WIN32) # define WIN32_LEAN_AND_MEAN -# include /* for GetFullPathName */ -# endif +# include /* for GetFullPathName/GetFinalPathNameByHandle/ + CreateFile/CloseHandle */ +# define WIN32_REPLACE_SLASHES(_ptr, _len) \ + for (unsigned i = 0; i != (_len); ++i) \ + if ((_ptr)[i] == '\\') (_ptr)[i] = '/'; + +# define WIN32_UNC_PREFIX "//?/UNC/" +# define WIN32_UNC_PREFIX_LEN (sizeof(WIN32_UNC_PREFIX)-1) +# define WIN32_IS_UNC_PREFIX(ptr) \ + (0 == memcmp(ptr, WIN32_UNC_PREFIX, WIN32_UNC_PREFIX_LEN)) + +# define WIN32_NON_UNC_PREFIX "//?/" +# define WIN32_NON_UNC_PREFIX_LEN (sizeof(WIN32_NON_UNC_PREFIX)-1) +# define WIN32_IS_NON_UNC_PREFIX(ptr) \ + (0 == memcmp(ptr, WIN32_NON_UNC_PREFIX, WIN32_NON_UNC_PREFIX_LEN)) + +/* Get full path name without symlinks resolution. + It also converts all forward slashes to back slashes. +*/ +char* get_full_path_name(const char *filename) { + DWORD len; + char *buf, *ptr, *res; + + /* determining the required buffer size. + from the man: `If the lpBuffer buffer is too small to contain + the path, the return value is the size, in TCHARs, of the buffer + that is required to hold the path _and_the_terminating_null_character_` + */ + len = GetFullPathName(filename, 0, NULL, NULL); + + if ( len == 0 ) + return strdup(filename); + + buf = (char *)malloc(len); + + /* no point to check the result again */ + len = GetFullPathName(filename, len, buf, NULL); + buf[len] = 0; + + /* replace slashes */ + WIN32_REPLACE_SLASHES(buf, len); + + /* calculate offset based on prefix type */ + len = WIN32_IS_UNC_PREFIX(buf) + ? (WIN32_UNC_PREFIX_LEN - 2) + : WIN32_IS_NON_UNC_PREFIX(buf) + ? WIN32_NON_UNC_PREFIX_LEN + : 0 + ; + + ptr = buf + len; + if ( WIN32_IS_UNC_PREFIX(buf) ) { + ptr[0] = '/'; + ptr[1] = '/'; + } + + res = strdup(ptr); + + free(buf); + + return res; +} + +# if _WIN32_WINNT >= 0x0600 + +/* Get full path name WITH symlinks resolution. + It also converts all forward slashes to back slashes. +*/ +char* get_final_path_name(HANDLE fh) { + DWORD len; + char *buf, *ptr, *res; + + /* determining the required buffer size. + from the man: `If the function fails because lpszFilePath is too + small to hold the string plus the terminating null character, + the return value is the required buffer size, in TCHARs. This + value _includes_the_size_of_the_terminating_null_character_`. + but in my testcase I have path with 26 chars, the function + returns 26 also, ie without the trailing zero-char... + */ + len = GetFinalPathNameByHandle( + fh + ,NULL + ,0 + ,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS + ); + + if ( len == 0 ) + return NULL; + + len += 1; /* for zero-char */ + buf = (char *)malloc(len); + + /* no point to check the result again */ + len = GetFinalPathNameByHandle( + fh + ,buf + ,len + ,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS + ); + buf[len] = 0; + + /* replace slashes */ + WIN32_REPLACE_SLASHES(buf, len); + + /* calculate offset based on prefix type */ + len = WIN32_IS_UNC_PREFIX(buf) + ? (WIN32_UNC_PREFIX_LEN - 2) + : WIN32_IS_NON_UNC_PREFIX(buf) + ? WIN32_NON_UNC_PREFIX_LEN + : 0 + ; + + ptr = buf + len; + if ( WIN32_IS_UNC_PREFIX(buf) ) { + ptr[0] = '/'; + ptr[1] = '/'; + } + + res = strdup(ptr); + + free(buf); + + return res; +} + +# endif // _WIN32_WINNT >= 0x0600 + +# endif // _WIN32 #endif char * @@ -128,30 +255,52 @@ lrealpath (const char *filename) } #endif - /* The MS Windows method. If we don't have realpath, we assume we - don't have symlinks and just canonicalize to a Windows absolute - path. GetFullPath converts ../ and ./ in relative paths to - absolute paths, filling in current drive if one is not given - or using the current directory of a specified drive (eg, "E:foo"). - It also converts all forward slashes to back slashes. */ + /* The MS Windows method */ #if defined (_WIN32) { - char buf[MAX_PATH]; - char* basename; - DWORD len = GetFullPathName (filename, MAX_PATH, buf, &basename); - if (len == 0 || len > MAX_PATH - 1) - return strdup (filename); - else - { - /* The file system is case-preserving but case-insensitive, - Canonicalize to lowercase, using the codepage associated - with the process locale. */ - CharLowerBuff (buf, len); - return strdup (buf); - } - } -#endif + char *res; - /* This system is a lost cause, just duplicate the filename. */ - return strdup (filename); + /* For Windows Vista and greater */ +#if _WIN32_WINNT >= 0x0600 + + /* For some reason the function receives just empty `filename`, but not NULL. + What should we do in that case? + According to `strdup()` implementation + (https://elixir.bootlin.com/glibc/latest/source/string/strdup.c) + it will alloc 1 byte even for empty but non NULL string. + OK, will use `strdup()` for that case. + */ + if ( 0 == strlen(filename) ) + return strdup(filename); + + HANDLE fh = CreateFile( + filename + ,FILE_READ_ATTRIBUTES + ,FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE + ,NULL + ,OPEN_EXISTING + ,FILE_FLAG_BACKUP_SEMANTICS + ,NULL + ); + + if ( fh == INVALID_HANDLE_VALUE ) { + res = get_full_path_name(filename); + } else { + res = get_final_path_name(fh); + CloseHandle(fh); + + if ( !res ) + res = get_full_path_name(filename); + } + +#else + + /* For Windows XP */ + res = get_full_path_name(filename); + +#endif // _WIN32_WINNT >= 0x0600 + + return res; + } +#endif // _WIN32 } diff --git a/libiberty/make-temp-file.c b/libiberty/make-temp-file.c index fae743f3985..1d2f21d6c5c 100644 --- a/libiberty/make-temp-file.c +++ b/libiberty/make-temp-file.c @@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */ #include /* May get R_OK, etc. on some systems. */ #endif #if defined(_WIN32) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN #include #endif #if HAVE_SYS_STAT_H diff --git a/libiberty/obstacks.texi b/libiberty/obstacks.texi index b2d2403210b..37d26c90f1b 100644 --- a/libiberty/obstacks.texi +++ b/libiberty/obstacks.texi @@ -172,8 +172,8 @@ The value of this variable is a pointer to a function that @code{obstack} uses when @code{obstack_chunk_alloc} fails to allocate memory. The default action is to print a message and abort. You should supply a function that either calls @code{exit} -(@pxref{Program Termination, , , libc, The GNU C Library Reference Manual}) or @code{longjmp} (@pxref{Non-Local -Exits, , , libc, The GNU C Library Reference Manual}) and doesn't return. +(@pxref{Program Termination, , , libc, The GNU C Library Reference Manual}) +or @code{longjmp} and doesn't return. @smallexample void my_obstack_alloc_failed (void) diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c index 5f6b420f7b3..f7fe306036b 100644 --- a/libiberty/pex-win32.c +++ b/libiberty/pex-win32.c @@ -20,6 +20,7 @@ Boston, MA 02110-1301, USA. */ #include "pex-common.h" +#define WIN32_LEAN_AND_MEAN #include #ifdef HAVE_STDLIB_H @@ -350,7 +351,7 @@ argv_to_cmdline (char *const *argv) prevent wasting 2 chars per argument of the CreateProcess 32k char limit. We need only escape embedded double-quotes and immediately preceeding backslash characters. A sequence of backslach characters - that is not follwed by a double quote character will not be + that is not followed by a double quote character will not be escaped. */ needs_quotes = 0; for (j = 0; argv[i][j]; j++) @@ -365,7 +366,7 @@ argv_to_cmdline (char *const *argv) /* Escape preceeding backslashes. */ for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) cmdline_len++; - /* Escape the qote character. */ + /* Escape the quote character. */ cmdline_len++; } } @@ -568,7 +569,8 @@ env_compare (const void *a_ptr, const void *b_ptr) * target is not actually an executable, such as if it is a shell script. */ static pid_t -win32_spawn (const char *executable, +win32_spawn (struct pex_obj *obj, + const char *executable, BOOL search, char *const *argv, char *const *env, /* array of strings of the form: VAR=VALUE */ @@ -576,14 +578,12 @@ win32_spawn (const char *executable, LPSTARTUPINFO si, LPPROCESS_INFORMATION pi) { - char *full_executable; - char *cmdline; + char *full_executable = NULL; + char *cmdline = NULL; + pid_t pid = (pid_t) -1; char **env_copy; char *env_block = NULL; - full_executable = NULL; - cmdline = NULL; - if (env) { int env_size; @@ -621,13 +621,42 @@ win32_spawn (const char *executable, full_executable = find_executable (executable, search); if (!full_executable) - goto error; + goto exit; cmdline = argv_to_cmdline (argv); if (!cmdline) - goto error; - - /* Create the child process. */ - if (!CreateProcess (full_executable, cmdline, + goto exit; + /* If cmdline is too large, CreateProcess will fail with a bad + 'No such file or directory' error. Try passing it through a + temporary response file instead. */ + if (strlen (cmdline) > 32767) + { + char *response_file = make_temp_file (""); + /* Register the file for deletion by pex_free. */ + ++obj->remove_count; + obj->remove = XRESIZEVEC (char *, obj->remove, obj->remove_count); + obj->remove[obj->remove_count - 1] = response_file; + int fd = pex_win32_open_write (obj, response_file, 0, 0); + if (fd == -1) + goto exit; + FILE *f = pex_win32_fdopenw (obj, fd, 0); + /* Don't write argv[0] (program name) to the response file. */ + if (writeargv (&argv[1], f)) + { + fclose (f); + goto exit; + } + fclose (f); /* Also closes fd and the underlying OS handle. */ + char *response_arg = concat ("@", response_file, NULL); + char *response_argv[3] = {argv[0], response_arg, NULL}; + free (cmdline); + cmdline = argv_to_cmdline (response_argv); + free (response_arg); + if (!cmdline) + goto exit; + } + + /* Create the child process. */ + if (CreateProcess (full_executable, cmdline, /*lpProcessAttributes=*/NULL, /*lpThreadAttributes=*/NULL, /*bInheritHandles=*/TRUE, @@ -637,33 +666,25 @@ win32_spawn (const char *executable, si, pi)) { - free (env_block); - - free (full_executable); - - return (pid_t) -1; + CloseHandle (pi->hThread); + pid = (pid_t) pi->hProcess; } + exit: /* Clean up. */ - CloseHandle (pi->hThread); - free (full_executable); - free (env_block); - - return (pid_t) pi->hProcess; - - error: free (env_block); free (cmdline); free (full_executable); - - return (pid_t) -1; + + return pid; } /* Spawn a script. This simulates the Unix script execution mechanism. This function is called as a fallback if win32_spawn fails. */ static pid_t -spawn_script (const char *executable, char *const *argv, +spawn_script (struct pex_obj *obj, + const char *executable, char *const *argv, char* const *env, DWORD dwCreationFlags, LPSTARTUPINFO si, @@ -713,20 +734,20 @@ spawn_script (const char *executable, char *const *argv, executable = strrchr (executable1, '\\') + 1; if (!executable) executable = executable1; - pid = win32_spawn (executable, TRUE, argv, env, + pid = win32_spawn (obj, executable, TRUE, argv, env, dwCreationFlags, si, pi); #else if (strchr (executable1, '\\') == NULL) - pid = win32_spawn (executable1, TRUE, argv, env, + pid = win32_spawn (obj, executable1, TRUE, argv, env, dwCreationFlags, si, pi); else if (executable1[0] != '\\') - pid = win32_spawn (executable1, FALSE, argv, env, + pid = win32_spawn (obj, executable1, FALSE, argv, env, dwCreationFlags, si, pi); else { const char *newex = mingw_rootify (executable1); *avhere = newex; - pid = win32_spawn (newex, FALSE, argv, env, + pid = win32_spawn (obj, newex, FALSE, argv, env, dwCreationFlags, si, pi); if (executable1 != newex) free ((char *) newex); @@ -736,7 +757,7 @@ spawn_script (const char *executable, char *const *argv, if (newex != executable1) { *avhere = newex; - pid = win32_spawn (newex, FALSE, argv, env, + pid = win32_spawn (obj, newex, FALSE, argv, env, dwCreationFlags, si, pi); free ((char *) newex); } @@ -755,7 +776,7 @@ spawn_script (const char *executable, char *const *argv, /* Execute a child. */ static pid_t -pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags, +pex_win32_exec_child (struct pex_obj *obj, int flags, const char *executable, char * const * argv, char* const* env, int in, int out, int errdes, @@ -851,10 +872,10 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags, si.hStdError = stderr_handle; /* Create the child process. */ - pid = win32_spawn (executable, (flags & PEX_SEARCH) != 0, + pid = win32_spawn (obj, executable, (flags & PEX_SEARCH) != 0, argv, env, dwCreationFlags, &si, &pi); if (pid == (pid_t) -1) - pid = spawn_script (executable, argv, env, dwCreationFlags, + pid = spawn_script (obj, executable, argv, env, dwCreationFlags, &si, &pi); if (pid == (pid_t) -1) { diff --git a/libiberty/strstr.c b/libiberty/strstr.c index c6f68495a33..49209e8229f 100644 --- a/libiberty/strstr.c +++ b/libiberty/strstr.c @@ -18,18 +18,23 @@ length, the function returns @var{string}. #include -extern int memcmp (const void *, const void *, size_t); +extern char *strchr (const char *, int); +extern int strncmp (const void *, const void *, size_t); extern size_t strlen (const char *); char * strstr (const char *s1, const char *s2) { + const char *p = s1; const size_t len = strlen (s2); - while (*s1) + + if (!len) + return s1; + + for (; (p = strchr (p, *s2)) != 0; p++) { - if (!memcmp (s1, s2, len)) - return (char *)s1; - ++s1; + if (strncmp (p, s2, len) == 0) + return (char *)p; } return (0); } diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index d9bc7ed4b1f..0acd2d635db 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -1659,3 +1659,33 @@ auto f()::{lambda(X<$T0>*, X*)#1}::operator()(X*, _ZZN1XIiE1FEvENKUliE_clEi X::F()::{lambda(int)#1}::operator()(int) const + +_Z1fIiEv1AIXnxtlT_EEE +void f(A) + +_ZNO1Ycv1XEv +Y::operator X() && + +_ZNO1Ycv1XIT_EIvEEv +Y::operator X() && + +_ZNO1Y3bobEv +Y::bob() && + +_ZNR1Y3bobEv +Y::bob() & + +_ZNKR1YcvRK1XIT_EIvEEv +Y::operator X const&() const & + +_ZZN1XIiEcviEvE1y +X::operator int()::y + +_ZZN1XIiEcv1ZIiEEvE1y +X::operator Z()::y + +_ZZN1Xcv1ZIT_EIiEEvE1y +X::operator Z()::y + +_ZZN1XIfEcv1ZIT_EIiEEvE1y +X::operator Z()::y