diff options
Diffstat (limited to 'llvm/lib/Support/Path.cpp')
-rw-r--r-- | llvm/lib/Support/Path.cpp | 103 |
1 files changed, 62 insertions, 41 deletions
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp index a724ba2faf93..3957547dfaaa 100644 --- a/llvm/lib/Support/Path.cpp +++ b/llvm/lib/Support/Path.cpp @@ -12,6 +12,7 @@ #include "llvm/Support/Path.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Config/config.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Errc.h" @@ -37,15 +38,16 @@ namespace { using llvm::sys::path::Style; inline Style real_style(Style style) { -#ifdef _WIN32 - return (style == Style::posix) ? Style::posix : Style::windows; -#else - return (style == Style::windows) ? Style::windows : Style::posix; -#endif + if (style != Style::native) + return style; + if (is_style_posix(style)) + return Style::posix; + return LLVM_WINDOWS_PREFER_FORWARD_SLASH ? Style::windows_slash + : Style::windows_backslash; } inline const char *separators(Style style) { - if (real_style(style) == Style::windows) + if (is_style_windows(style)) return "\\/"; return "/"; } @@ -66,7 +68,7 @@ namespace { if (path.empty()) return path; - if (real_style(style) == Style::windows) { + if (is_style_windows(style)) { // C: if (path.size() >= 2 && std::isalpha(static_cast<unsigned char>(path[0])) && path[1] == ':') @@ -98,7 +100,7 @@ namespace { size_t pos = str.find_last_of(separators(style), str.size() - 1); - if (real_style(style) == Style::windows) { + if (is_style_windows(style)) { if (pos == StringRef::npos) pos = str.find_last_of(':', str.size() - 2); } @@ -113,7 +115,7 @@ namespace { // directory in str, it returns StringRef::npos. size_t root_dir_start(StringRef str, Style style) { // case "c:/" - if (real_style(style) == Style::windows) { + if (is_style_windows(style)) { if (str.size() > 2 && str[1] == ':' && is_separator(str[2], style)) return 2; } @@ -259,7 +261,7 @@ const_iterator &const_iterator::operator++() { // Root dir. if (was_net || // c:/ - (real_style(S) == Style::windows && Component.endswith(":"))) { + (is_style_windows(S) && Component.endswith(":"))) { Component = Path.substr(Position, 1); return *this; } @@ -348,7 +350,7 @@ StringRef root_path(StringRef path, Style style) { if (b != e) { bool has_net = b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0]; - bool has_drive = (real_style(style) == Style::windows) && b->endswith(":"); + bool has_drive = is_style_windows(style) && b->endswith(":"); if (has_net || has_drive) { if ((++pos != e) && is_separator((*pos)[0], style)) { @@ -373,7 +375,7 @@ StringRef root_name(StringRef path, Style style) { if (b != e) { bool has_net = b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0]; - bool has_drive = (real_style(style) == Style::windows) && b->endswith(":"); + bool has_drive = is_style_windows(style) && b->endswith(":"); if (has_net || has_drive) { // just {C:,//net}, return the first component. @@ -390,7 +392,7 @@ StringRef root_directory(StringRef path, Style style) { if (b != e) { bool has_net = b->size() > 2 && is_separator((*b)[0], style) && (*b)[1] == (*b)[0]; - bool has_drive = (real_style(style) == Style::windows) && b->endswith(":"); + bool has_drive = is_style_windows(style) && b->endswith(":"); if ((has_net || has_drive) && // {C:,//net}, skip to the next component. @@ -497,7 +499,7 @@ void replace_extension(SmallVectorImpl<char> &path, const Twine &extension, static bool starts_with(StringRef Path, StringRef Prefix, Style style = Style::native) { // Windows prefix matching : case and separator insensitive - if (real_style(style) == Style::windows) { + if (is_style_windows(style)) { if (Path.size() < Prefix.size()) return false; for (size_t I = 0, E = Prefix.size(); I != E; ++I) { @@ -548,8 +550,10 @@ void native(const Twine &path, SmallVectorImpl<char> &result, Style style) { void native(SmallVectorImpl<char> &Path, Style style) { if (Path.empty()) return; - if (real_style(style) == Style::windows) { - std::replace(Path.begin(), Path.end(), '/', '\\'); + if (is_style_windows(style)) { + for (char &Ch : Path) + if (is_separator(Ch, style)) + Ch = preferred_separator(style); if (Path[0] == '~' && (Path.size() == 1 || is_separator(Path[1], style))) { SmallString<128> PathHome; home_directory(PathHome); @@ -557,14 +561,12 @@ void native(SmallVectorImpl<char> &Path, Style style) { Path = PathHome; } } else { - for (auto PI = Path.begin(), PE = Path.end(); PI < PE; ++PI) - if (*PI == '\\') - *PI = '/'; + std::replace(Path.begin(), Path.end(), '\\', '/'); } } std::string convert_to_slash(StringRef path, Style style) { - if (real_style(style) != Style::windows) + if (is_style_posix(style)) return std::string(path); std::string s = path.str(); @@ -599,7 +601,7 @@ StringRef extension(StringRef path, Style style) { bool is_separator(char value, Style style) { if (value == '/') return true; - if (real_style(style) == Style::windows) + if (is_style_windows(style)) return value == '\\'; return false; } @@ -671,8 +673,7 @@ bool is_absolute(const Twine &path, Style style) { StringRef p = path.toStringRef(path_storage); bool rootDir = has_root_directory(p, style); - bool rootName = - (real_style(style) != Style::windows) || has_root_name(p, style); + bool rootName = is_style_posix(style) || has_root_name(p, style); return rootDir && rootName; } @@ -686,7 +687,7 @@ bool is_absolute_gnu(const Twine &path, Style style) { if (!p.empty() && is_separator(p.front(), style)) return true; - if (real_style(style) == Style::windows) { + if (is_style_windows(style)) { // Handle drive letter pattern (a character followed by ':') on Windows. if (p.size() >= 2 && (p[0] && p[1] == ':')) return true; @@ -906,8 +907,7 @@ void make_absolute(const Twine ¤t_directory, bool rootName = path::has_root_name(p); // Already absolute. - if ((rootName || real_style(Style::native) != Style::windows) && - rootDirectory) + if ((rootName || is_style_posix(Style::native)) && rootDirectory) return; // All of the following conditions will need the current directory. @@ -1190,6 +1190,10 @@ TempFile &TempFile::operator=(TempFile &&Other) { FD = Other.FD; Other.Done = true; Other.FD = -1; +#ifdef _WIN32 + RemoveOnClose = Other.RemoveOnClose; + Other.RemoveOnClose = false; +#endif return *this; } @@ -1204,20 +1208,23 @@ Error TempFile::discard() { FD = -1; #ifdef _WIN32 - // On windows closing will remove the file. - TmpName = ""; - return Error::success(); + // On Windows, closing will remove the file, if we set the delete + // disposition. If not, remove it manually. + bool Remove = RemoveOnClose; #else - // Always try to close and remove. + // Always try to remove the file. + bool Remove = true; +#endif std::error_code RemoveEC; - if (!TmpName.empty()) { + if (Remove && !TmpName.empty()) { RemoveEC = fs::remove(TmpName); sys::DontRemoveFileOnSignal(TmpName); if (!RemoveEC) TmpName = ""; + } else { + TmpName = ""; } return errorCodeToError(RemoveEC); -#endif } Error TempFile::keep(const Twine &Name) { @@ -1228,19 +1235,26 @@ Error TempFile::keep(const Twine &Name) { // If we can't cancel the delete don't rename. auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); std::error_code RenameEC = setDeleteDisposition(H, false); + bool ShouldDelete = false; if (!RenameEC) { RenameEC = rename_handle(H, Name); // If rename failed because it's cross-device, copy instead if (RenameEC == std::error_code(ERROR_NOT_SAME_DEVICE, std::system_category())) { RenameEC = copy_file(TmpName, Name); - setDeleteDisposition(H, true); + ShouldDelete = true; } } - // If we can't rename, discard the temporary file. + // If we can't rename or copy, discard the temporary file. if (RenameEC) - setDeleteDisposition(H, true); + ShouldDelete = true; + if (ShouldDelete) { + if (!RemoveOnClose) + setDeleteDisposition(H, true); + else + remove(TmpName); + } #else std::error_code RenameEC = fs::rename(TmpName, Name); if (RenameEC) { @@ -1250,8 +1264,8 @@ Error TempFile::keep(const Twine &Name) { if (RenameEC) remove(TmpName); } - sys::DontRemoveFileOnSignal(TmpName); #endif + sys::DontRemoveFileOnSignal(TmpName); if (!RenameEC) TmpName = ""; @@ -1273,9 +1287,8 @@ Error TempFile::keep() { auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); if (std::error_code EC = setDeleteDisposition(H, false)) return errorCodeToError(EC); -#else - sys::DontRemoveFileOnSignal(TmpName); #endif + sys::DontRemoveFileOnSignal(TmpName); TmpName = ""; @@ -1297,14 +1310,22 @@ Expected<TempFile> TempFile::create(const Twine &Model, unsigned Mode, return errorCodeToError(EC); TempFile Ret(ResultPath, FD); -#ifndef _WIN32 - if (sys::RemoveFileOnSignal(ResultPath)) { +#ifdef _WIN32 + auto H = reinterpret_cast<HANDLE>(_get_osfhandle(FD)); + bool SetSignalHandler = false; + if (std::error_code EC = setDeleteDisposition(H, true)) { + Ret.RemoveOnClose = true; + SetSignalHandler = true; + } +#else + bool SetSignalHandler = true; +#endif + if (SetSignalHandler && sys::RemoveFileOnSignal(ResultPath)) { // Make sure we delete the file when RemoveFileOnSignal fails. consumeError(Ret.discard()); std::error_code EC(errc::operation_not_permitted); return errorCodeToError(EC); } -#endif return std::move(Ret); } } // namespace fs |