aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/Path.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support/Path.cpp')
-rw-r--r--llvm/lib/Support/Path.cpp103
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 &current_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