Index: include/lldb/Host/FileSpec.h =================================================================== --- include/lldb/Host/FileSpec.h +++ include/lldb/Host/FileSpec.h @@ -265,7 +265,7 @@ /// will be added. //------------------------------------------------------------------ void - Dump(Stream *s, bool trailing_slash = true) const; + Dump(Stream *s) const; //------------------------------------------------------------------ /// Existence test. @@ -638,6 +638,7 @@ static void Normalize(llvm::SmallVectorImpl &path, PathSyntax syntax = ePathSyntaxHostNative); static void DeNormalize(llvm::SmallVectorImpl &path, PathSyntax syntax = ePathSyntaxHostNative); + char GetPathSeparator() const; //------------------------------------------------------------------ /// Run through the input string, replaying the effect of any ".." and produce Index: source/Host/common/FileSpec.cpp =================================================================== --- source/Host/common/FileSpec.cpp +++ source/Host/common/FileSpec.cpp @@ -276,6 +276,16 @@ std::replace(path.begin(), path.end(), '/', '\\'); } +char +FileSpec::GetPathSeparator() const +{ + if (m_syntax == ePathSyntaxPosix || + (m_syntax == ePathSyntaxHostNative && FileSystem::GetNativePathSyntax() == ePathSyntaxPosix)) + return '/'; + + return '\\'; +} + //------------------------------------------------------------------ // Update the contents of this object with a new path. The path will // be split up into a directory and filename and stored as uniqued @@ -609,15 +619,17 @@ // directory delimiter, and the filename. //------------------------------------------------------------------ void -FileSpec::Dump(Stream *s, bool trailing_slash) const +FileSpec::Dump(Stream *s) const { if (s) { - m_directory.Dump(s); - if ((m_filename || trailing_slash) && m_directory && - !m_directory.GetStringRef().endswith("/")) - s->PutChar('/'); - m_filename.Dump(s); + // Dump guarantees that directory-only paths will have a path separator + // appended. GetPath() guarantees that directory-only paths will not have + // a path separator appended. So it's safe to just append one. + std::string path = GetPath(); + if (!m_filename && !path.empty()) + path.push_back(GetPathSeparator()); + s->PutCString(path.c_str()); } } @@ -816,10 +828,25 @@ void FileSpec::GetPath(llvm::SmallVectorImpl &path, bool denormalize) const { - StreamString stream; - Dump(&stream, false); - path.append(stream.GetString().begin(), stream.GetString().end()); - Normalize(path, m_syntax); + if (m_directory) + { + llvm::StringRef dir = m_directory.GetStringRef(); + // Don't add any trailing slashes, even if `m_directory` has one. This + // will guarantee that GetPath() returns paths with no trailing slash if + // there is no filename. If there is a filename, we will join the directory + // and file with a slash later. + dir = dir.rtrim("/\\"); + path.append(dir.begin(), dir.end()); + } + + if (m_filename) + { + if (m_directory) + path.push_back('/'); + llvm::StringRef file = m_filename.GetStringRef(); + path.append(file.begin(), file.end()); + } + if (denormalize && !path.empty()) DeNormalize(path, m_syntax); }