[Lldb-commits] [lldb] r331049 - Always normalize FileSpec paths.
Frédéric Riss via lldb-commits
lldb-commits at lists.llvm.org
Fri Apr 27 13:01:59 PDT 2018
> On Apr 27, 2018, at 11:17 AM, Jim Ingham via lldb-commits <lldb-commits at lists.llvm.org> wrote:
>
> Greg,
>
> Your new FileSpecTest unit tests are failing in the Xcode build of lldb, e.g.:
>
> http://lab.llvm.org:8080/green/view/LLDB/job/lldb-xcode/6271/consoleFull#-1083450927b825e790-484f-4586-af29-73c4754ff671
>
> Can you figure out what's up with this?
Once you get past the unit test, it looks like it also broke TestBreakpointCommand.py. Please fix this quickly.
Fred
> Jim
>
> BTW, the "reply to" for lldb-commits mails for you is still your apple.com address. I don't know where that gets set but you should probably update that at some point.
>
>
>
>
>> On Apr 27, 2018, at 8:45 AM, Greg Clayton via lldb-commits <lldb-commits at lists.llvm.org> wrote:
>>
>> Author: gclayton
>> Date: Fri Apr 27 08:45:58 2018
>> New Revision: 331049
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=331049&view=rev
>> Log:
>> Always normalize FileSpec paths.
>>
>> Always normalizing lldb_private::FileSpec paths will help us get a consistent results from comparisons when setting breakpoints and when looking for source files. This also removes a lot of complexity from the comparison routines. Modified the DWARF line table parser to use the normalized compile unit directory if needed.
>>
>> Differential Revision: https://reviews.llvm.org/D45977
>>
>>
>> Modified:
>> lldb/trunk/include/lldb/Core/FileSpecList.h
>> lldb/trunk/include/lldb/Utility/FileSpec.h
>> lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp
>> lldb/trunk/source/Core/FileSpecList.cpp
>> lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
>> lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
>> lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
>> lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
>> lldb/trunk/source/Symbol/CompileUnit.cpp
>> lldb/trunk/source/Symbol/Declaration.cpp
>> lldb/trunk/source/Utility/FileSpec.cpp
>> lldb/trunk/unittests/Utility/FileSpecTest.cpp
>>
>> Modified: lldb/trunk/include/lldb/Core/FileSpecList.h
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FileSpecList.h?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/include/lldb/Core/FileSpecList.h (original)
>> +++ lldb/trunk/include/lldb/Core/FileSpecList.h Fri Apr 27 08:45:58 2018
>> @@ -119,16 +119,11 @@ public:
>> /// @param[in] full
>> /// Should FileSpec::Equal be called with "full" true or false.
>> ///
>> - /// @param[in] remove_backup_dots
>> - /// Should FileSpec::Equal be called with "remove_backup_dots" true or
>> - /// false.
>> - ///
>> /// @return
>> /// The index of the file that matches \a file if it is found,
>> /// else UINT32_MAX is returned.
>> //------------------------------------------------------------------
>> - size_t FindFileIndex(size_t idx, const FileSpec &file, bool full,
>> - bool remove_backup_dots = false) const;
>> + size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const;
>>
>> //------------------------------------------------------------------
>> /// Get file at index.
>>
>> Modified: lldb/trunk/include/lldb/Utility/FileSpec.h
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/FileSpec.h?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/include/lldb/Utility/FileSpec.h (original)
>> +++ lldb/trunk/include/lldb/Utility/FileSpec.h Fri Apr 27 08:45:58 2018
>> @@ -256,8 +256,7 @@ public:
>> //------------------------------------------------------------------
>> static int Compare(const FileSpec &lhs, const FileSpec &rhs, bool full);
>>
>> - static bool Equal(const FileSpec &a, const FileSpec &b, bool full,
>> - bool remove_backups = false);
>> + static bool Equal(const FileSpec &a, const FileSpec &b, bool full);
>>
>> //------------------------------------------------------------------
>> /// Case sensitivity of path.
>> @@ -488,12 +487,6 @@ public:
>> size_t MemorySize() const;
>>
>> //------------------------------------------------------------------
>> - /// Normalize a pathname by collapsing redundant separators and
>> - /// up-level references.
>> - //------------------------------------------------------------------
>> - FileSpec GetNormalizedPath() const;
>> -
>> - //------------------------------------------------------------------
>> /// Change the file specified with a new path.
>> ///
>> /// Update the contents of this object with a new path. The path will
>>
>> Modified: lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp (original)
>> +++ lldb/trunk/source/Breakpoint/BreakpointResolverFileLine.cpp Fri Apr 27 08:45:58 2018
>> @@ -122,7 +122,7 @@ void BreakpointResolverFileLine::FilterC
>>
>> llvm::StringRef relative_path;
>> if (is_relative)
>> - relative_path = m_file_spec.GetNormalizedPath().GetDirectory().GetStringRef();
>> + relative_path = m_file_spec.GetDirectory().GetStringRef();
>>
>> Log * log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
>> for(uint32_t i = 0; i < sc_list.GetSize(); ++i) {
>>
>> Modified: lldb/trunk/source/Core/FileSpecList.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FileSpecList.cpp?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Core/FileSpecList.cpp (original)
>> +++ lldb/trunk/source/Core/FileSpecList.cpp Fri Apr 27 08:45:58 2018
>> @@ -82,7 +82,7 @@ void FileSpecList::Dump(Stream *s, const
>> // it is found, else std::numeric_limits<uint32_t>::max() is returned.
>> //------------------------------------------------------------------
>> size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec,
>> - bool full, bool remove_dots) const {
>> + bool full) const {
>> const size_t num_files = m_files.size();
>>
>> // When looking for files, we will compare only the filename if the
>> @@ -96,7 +96,7 @@ size_t FileSpecList::FindFileIndex(size_
>> file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive()))
>> return idx;
>> } else {
>> - if (FileSpec::Equal(m_files[idx], file_spec, full, remove_dots))
>> + if (FileSpec::Equal(m_files[idx], file_spec, full))
>> return idx;
>> }
>> }
>>
>> Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original)
>> +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Fri Apr 27 08:45:58 2018
>> @@ -5098,9 +5098,6 @@ uint32_t ObjectFileMachO::GetDependentMo
>> // It is OK to resolve this path because we must find a file on
>> // disk for us to accept it anyway if it is rpath relative.
>> FileSpec file_spec(path, true);
>> - // Remove any redundant parts of the path (like "../foo") since
>> - // LC_RPATH values often contain "..".
>> - file_spec = file_spec.GetNormalizedPath();
>> if (file_spec.Exists() && files.AppendIfUnique(file_spec)) {
>> count++;
>> break;
>> @@ -5118,7 +5115,6 @@ uint32_t ObjectFileMachO::GetDependentMo
>> for (const auto &at_exec_relative_path : at_exec_relative_paths) {
>> FileSpec file_spec =
>> exec_dir.CopyByAppendingPathComponent(at_exec_relative_path);
>> - file_spec = file_spec.GetNormalizedPath();
>> if (file_spec.Exists() && files.AppendIfUnique(file_spec))
>> count++;
>> }
>>
>> Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp (original)
>> +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp Fri Apr 27 08:45:58 2018
>> @@ -444,7 +444,7 @@ bool DWARFDebugLine::ParsePrologue(const
>>
>> bool DWARFDebugLine::ParseSupportFiles(
>> const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data,
>> - const char *cu_comp_dir, dw_offset_t stmt_list,
>> + const lldb_private::FileSpec &cu_comp_dir, dw_offset_t stmt_list,
>> FileSpecList &support_files) {
>> lldb::offset_t offset = stmt_list;
>>
>> @@ -861,8 +861,8 @@ void DWARFDebugLine::Prologue::Dump(Log
>> // buff.Append8(0); // Terminate the file names section with empty string
>> //}
>>
>> -bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, const char *comp_dir,
>> - FileSpec &file) const {
>> +bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx,
>> + const lldb_private::FileSpec &comp_dir, FileSpec &file) const {
>> uint32_t idx = file_idx - 1; // File indexes are 1 based...
>> if (idx < file_names.size()) {
>> file.SetFile(file_names[idx].name, false);
>> @@ -876,7 +876,7 @@ bool DWARFDebugLine::Prologue::GetFile(u
>> }
>> }
>>
>> - if (comp_dir && comp_dir[0])
>> + if (comp_dir)
>> file.PrependPathComponent(comp_dir);
>> }
>> return true;
>>
>> Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h (original)
>> +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h Fri Apr 27 08:45:58 2018
>> @@ -90,7 +90,7 @@ public:
>> include_directories.clear();
>> file_names.clear();
>> }
>> - bool GetFile(uint32_t file_idx, const char *comp_dir,
>> + bool GetFile(uint32_t file_idx, const lldb_private::FileSpec &cu_comp_dir,
>> lldb_private::FileSpec &file) const;
>> };
>>
>> @@ -199,7 +199,8 @@ public:
>> static bool
>> ParseSupportFiles(const lldb::ModuleSP &module_sp,
>> const lldb_private::DWARFDataExtractor &debug_line_data,
>> - const char *cu_comp_dir, dw_offset_t stmt_list,
>> + const lldb_private::FileSpec &cu_comp_dir,
>> + dw_offset_t stmt_list,
>> lldb_private::FileSpecList &support_files);
>> static bool
>> ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data,
>>
>> Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
>> +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Fri Apr 27 08:45:58 2018
>> @@ -174,38 +174,39 @@ static const char *removeHostnameFromPat
>> return colon_pos + 1;
>> }
>>
>> -static const char *resolveCompDir(const char *path_from_dwarf) {
>> +static FileSpec resolveCompDir(const char *path_from_dwarf) {
>> if (!path_from_dwarf)
>> - return nullptr;
>> + return FileSpec();
>>
>> // DWARF2/3 suggests the form hostname:pathname for compilation directory.
>> // Remove the host part if present.
>> const char *local_path = removeHostnameFromPathname(path_from_dwarf);
>> if (!local_path)
>> - return nullptr;
>> + return FileSpec();
>>
>> bool is_symlink = false;
>> - FileSpec local_path_spec(local_path, false);
>> + // Always normalize our compile unit directory to get rid of redundant
>> + // slashes and other path anomalies before we use it for path prepending
>> + FileSpec local_spec(local_path, false);
>> const auto &file_specs = GetGlobalPluginProperties()->GetSymLinkPaths();
>> for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i)
>> is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i),
>> - local_path_spec, true);
>> + local_spec, true);
>>
>> if (!is_symlink)
>> - return local_path;
>> + return local_spec;
>>
>> namespace fs = llvm::sys::fs;
>> - if (fs::get_file_type(local_path_spec.GetPath(), false) !=
>> + if (fs::get_file_type(local_spec.GetPath(), false) !=
>> fs::file_type::symlink_file)
>> - return local_path;
>> + return local_spec;
>>
>> - FileSpec resolved_local_path_spec;
>> - const auto error =
>> - FileSystem::Readlink(local_path_spec, resolved_local_path_spec);
>> + FileSpec resolved_symlink;
>> + const auto error = FileSystem::Readlink(local_spec, resolved_symlink);
>> if (error.Success())
>> - return resolved_local_path_spec.GetCString();
>> + return resolved_symlink;
>>
>> - return nullptr;
>> + return local_spec;
>> }
>>
>> DWARFUnit *SymbolFileDWARF::GetBaseCompileUnit() {
>> @@ -912,7 +913,7 @@ bool SymbolFileDWARF::ParseCompileUnitSu
>> const DWARFDIE cu_die = dwarf_cu->GetUnitDIEOnly();
>>
>> if (cu_die) {
>> - const char *cu_comp_dir = resolveCompDir(
>> + FileSpec cu_comp_dir = resolveCompDir(
>> cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr));
>> const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(
>> DW_AT_stmt_list, DW_INVALID_OFFSET);
>>
>> Modified: lldb/trunk/source/Symbol/CompileUnit.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/CompileUnit.cpp?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Symbol/CompileUnit.cpp (original)
>> +++ lldb/trunk/source/Symbol/CompileUnit.cpp Fri Apr 27 08:45:58 2018
>> @@ -287,9 +287,8 @@ uint32_t CompileUnit::ResolveSymbolConte
>> // when finding file indexes
>> std::vector<uint32_t> file_indexes;
>> const bool full_match = (bool)file_spec.GetDirectory();
>> - const bool remove_backup_dots = true;
>> bool file_spec_matches_cu_file_spec =
>> - FileSpec::Equal(file_spec, *this, full_match, remove_backup_dots);
>> + FileSpec::Equal(file_spec, *this, full_match);
>>
>> // If we are not looking for inlined functions and our file spec doesn't
>> // match then we are done...
>> @@ -297,11 +296,10 @@ uint32_t CompileUnit::ResolveSymbolConte
>> return 0;
>>
>> uint32_t file_idx =
>> - GetSupportFiles().FindFileIndex(1, file_spec, true, remove_backup_dots);
>> + GetSupportFiles().FindFileIndex(1, file_spec, true);
>> while (file_idx != UINT32_MAX) {
>> file_indexes.push_back(file_idx);
>> - file_idx = GetSupportFiles().FindFileIndex(file_idx + 1, file_spec, true,
>> - remove_backup_dots);
>> + file_idx = GetSupportFiles().FindFileIndex(file_idx + 1, file_spec, true);
>> }
>>
>> const size_t num_file_indexes = file_indexes.size();
>>
>> Modified: lldb/trunk/source/Symbol/Declaration.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Declaration.cpp?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Symbol/Declaration.cpp (original)
>> +++ lldb/trunk/source/Symbol/Declaration.cpp Fri Apr 27 08:45:58 2018
>> @@ -91,7 +91,7 @@ bool lldb_private::operator==(const Decl
>> return lhs.GetFile() == rhs.GetFile();
>> #else
>> if (lhs.GetLine() == rhs.GetLine())
>> - return FileSpec::Equal(lhs.GetFile(), rhs.GetFile(), true, true);
>> + return FileSpec::Equal(lhs.GetFile(), rhs.GetFile(), true);
>> #endif
>> return false;
>> }
>>
>> Modified: lldb/trunk/source/Utility/FileSpec.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/FileSpec.cpp?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/source/Utility/FileSpec.cpp (original)
>> +++ lldb/trunk/source/Utility/FileSpec.cpp Fri Apr 27 08:45:58 2018
>> @@ -62,17 +62,18 @@ bool IsPathSeparator(char value, FileSpe
>> return value == '/' || (!PathSyntaxIsPosix(syntax) && value == '\\');
>> }
>>
>> -void Normalize(llvm::SmallVectorImpl<char> &path, FileSpec::PathSyntax syntax) {
>> - if (PathSyntaxIsPosix(syntax))
>> - return;
>> -
>> - std::replace(path.begin(), path.end(), '\\', '/');
>> - // Windows path can have \\ slashes which can be changed by replace
>> - // call above to //. Here we remove the duplicate.
>> - auto iter = std::unique(path.begin(), path.end(), [](char &c1, char &c2) {
>> - return (c1 == '/' && c2 == '/');
>> - });
>> - path.erase(iter, path.end());
>> +inline llvm::sys::path::Style
>> +LLVMPathSyntax(FileSpec::PathSyntax lldb_syntax) {
>> + switch (lldb_syntax) {
>> + case FileSpec::ePathSyntaxPosix:
>> + return llvm::sys::path::Style::posix;
>> + case FileSpec::ePathSyntaxWindows:
>> + return llvm::sys::path::Style::windows;
>> + default:
>> + case FileSpec::ePathSyntaxHostNative:
>> + return llvm::sys::path::Style::native;
>> + };
>> + return llvm::sys::path::Style::native;
>> }
>>
>> void Denormalize(llvm::SmallVectorImpl<char> &path,
>> @@ -199,6 +200,104 @@ FileSpec::FileSpec(const FileSpec *rhs)
>> //------------------------------------------------------------------
>> FileSpec::~FileSpec() {}
>>
>> +namespace {
>> +//------------------------------------------------------------------
>> +/// Safely get a character at the specified index.
>> +///
>> +/// @param[in] path
>> +/// A full, partial, or relative path to a file.
>> +///
>> +/// @param[in] i
>> +/// An index into path which may or may not be valid.
>> +///
>> +/// @return
>> +/// The character at index \a i if the index is valid, or 0 if
>> +/// the index is not valid.
>> +//------------------------------------------------------------------
>> +inline char safeCharAtIndex(const llvm::StringRef &path, size_t i) {
>> + if (i < path.size())
>> + return path[i];
>> + return 0;
>> +}
>> +
>> +//------------------------------------------------------------------
>> +/// Check if a path needs to be normalized.
>> +///
>> +/// Check if a path needs to be normalized. We currently consider a
>> +/// path to need normalization if any of the following are true
>> +/// - path contains "/./"
>> +/// - path contains "/../"
>> +/// - path contains "//"
>> +/// - path ends with "/"
>> +/// Paths that start with "./" or with "../" are not considered to
>> +/// need normalization since we aren't trying to resolve the path,
>> +/// we are just trying to remove redundant things from the path.
>> +///
>> +/// @param[in] path
>> +/// A full, partial, or relative path to a file.
>> +///
>> +/// @param[in] syntax
>> +/// The syntax enumeration for the path in \a path.
>> +///
>> +/// @return
>> +/// Returns \b true if the path needs to be normalized.
>> +//------------------------------------------------------------------
>> +bool needsNormalization(const llvm::StringRef &path,
>> + FileSpec::PathSyntax syntax) {
>> + const auto separator = GetPreferredPathSeparator(syntax);
>> + for (auto i = path.find(separator); i != llvm::StringRef::npos;
>> + i = path.find(separator, i + 1)) {
>> + const auto next = safeCharAtIndex(path, i+1);
>> + switch (next) {
>> + case 0:
>> + // path separator char at the end of the string which should be
>> + // stripped unless it is the one and only character
>> + return i > 0;
>> + case '/':
>> + case '\\':
>> + // two path separator chars in the middle of a path needs to be
>> + // normalized
>> + if (next == separator && i > 0)
>> + return true;
>> + ++i;
>> + break;
>> +
>> + case '.': {
>> + const auto next_next = safeCharAtIndex(path, i+2);
>> + switch (next_next) {
>> + default: break;
>> + case 0: return true; // ends with "/."
>> + case '/':
>> + case '\\':
>> + if (next_next == separator)
>> + return true; // contains "/./"
>> + break;
>> + case '.': {
>> + const auto next_next_next = safeCharAtIndex(path, i+3);
>> + switch (next_next_next) {
>> + default: break;
>> + case 0: return true; // ends with "/.."
>> + case '/':
>> + case '\\':
>> + if (next_next_next == separator)
>> + return true; // contains "/../"
>> + break;
>> + }
>> + break;
>> + }
>> + }
>> + }
>> + break;
>> +
>> + default:
>> + break;
>> + }
>> + }
>> + return false;
>> +}
>> +
>> +
>> +}
>> //------------------------------------------------------------------
>> // Assignment operator.
>> //------------------------------------------------------------------
>> @@ -238,7 +337,14 @@ void FileSpec::SetFile(llvm::StringRef p
>> m_is_resolved = true;
>> }
>>
>> - Normalize(resolved, m_syntax);
>> + // Normalize the path by removing ".", ".." and other redundant components.
>> + if (needsNormalization(llvm::StringRef(resolved.data(), resolved.size()),
>> + syntax))
>> + llvm::sys::path::remove_dots(resolved, true, LLVMPathSyntax(syntax));
>> +
>> + // Normalize back slashes to forward slashes
>> + if (syntax == FileSpec::ePathSyntaxWindows)
>> + std::replace(resolved.begin(), resolved.end(), '\\', '/');
>>
>> llvm::StringRef resolve_path_ref(resolved.c_str());
>> size_t dir_end = ParentPathEnd(resolve_path_ref, m_syntax);
>> @@ -408,106 +514,22 @@ int FileSpec::Compare(const FileSpec &a,
>> return ConstString::Compare(a.m_filename, b.m_filename, case_sensitive);
>> }
>>
>> -bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full,
>> - bool remove_backups) {
>> - static ConstString g_dot_string(".");
>> - static ConstString g_dot_dot_string("..");
>> +bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full) {
>>
>> // case sensitivity of equality test
>> const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive();
>>
>> - bool filenames_equal = ConstString::Equals(a.m_filename,
>> - b.m_filename,
>> - case_sensitive);
>> -
>> - // The only way two FileSpecs can be equal if their filenames are
>> - // unequal is if we are removing backups and one or the other filename
>> - // is a backup string:
>> + const bool filenames_equal = ConstString::Equals(a.m_filename,
>> + b.m_filename,
>> + case_sensitive);
>>
>> - if (!filenames_equal && !remove_backups)
>> + if (!filenames_equal)
>> return false;
>>
>> - bool last_component_is_dot = ConstString::Equals(a.m_filename, g_dot_string)
>> - || ConstString::Equals(a.m_filename,
>> - g_dot_dot_string)
>> - || ConstString::Equals(b.m_filename,
>> - g_dot_string)
>> - || ConstString::Equals(b.m_filename,
>> - g_dot_dot_string);
>> -
>> - if (!filenames_equal && !last_component_is_dot)
>> - return false;
>> -
>> if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty()))
>> return filenames_equal;
>>
>> - if (remove_backups == false)
>> - return a == b;
>> -
>> - if (a == b)
>> - return true;
>> -
>> - return Equal(a.GetNormalizedPath(), b.GetNormalizedPath(), full, false);
>> -}
>> -
>> -FileSpec FileSpec::GetNormalizedPath() const {
>> - // Fast path. Do nothing if the path is not interesting.
>> - if (!m_directory.GetStringRef().contains(".") &&
>> - !m_directory.GetStringRef().contains("//") &&
>> - m_filename.GetStringRef() != ".." && m_filename.GetStringRef() != ".")
>> - return *this;
>> -
>> - llvm::SmallString<64> path, result;
>> - const bool normalize = false;
>> - GetPath(path, normalize);
>> - llvm::StringRef rest(path);
>> -
>> - // We will not go below root dir.
>> - size_t root_dir_start = RootDirStart(path, m_syntax);
>> - const bool absolute = root_dir_start != llvm::StringRef::npos;
>> - if (absolute) {
>> - result += rest.take_front(root_dir_start + 1);
>> - rest = rest.drop_front(root_dir_start + 1);
>> - } else {
>> - if (m_syntax == ePathSyntaxWindows && path.size() > 2 && path[1] == ':') {
>> - result += rest.take_front(2);
>> - rest = rest.drop_front(2);
>> - }
>> - }
>> -
>> - bool anything_added = false;
>> - llvm::SmallVector<llvm::StringRef, 0> components, processed;
>> - rest.split(components, '/', -1, false);
>> - processed.reserve(components.size());
>> - for (auto component : components) {
>> - if (component == ".")
>> - continue; // Skip these.
>> - if (component != "..") {
>> - processed.push_back(component);
>> - continue; // Regular file name.
>> - }
>> - if (!processed.empty()) {
>> - processed.pop_back();
>> - continue; // Dots. Go one level up if we can.
>> - }
>> - if (absolute)
>> - continue; // We're at the top level. Cannot go higher than that. Skip.
>> -
>> - result += component; // We're a relative path. We need to keep these.
>> - result += '/';
>> - anything_added = true;
>> - }
>> - for (auto component : processed) {
>> - result += component;
>> - result += '/';
>> - anything_added = true;
>> - }
>> - if (anything_added)
>> - result.pop_back(); // Pop last '/'.
>> - else if (result.empty())
>> - result = ".";
>> -
>> - return FileSpec(result, false, m_syntax);
>> + return a == b;
>> }
>>
>> //------------------------------------------------------------------
>> @@ -647,12 +669,14 @@ void FileSpec::GetPath(llvm::SmallVector
>> bool denormalize) const {
>> path.append(m_directory.GetStringRef().begin(),
>> m_directory.GetStringRef().end());
>> - if (m_directory && m_filename &&
>> - !IsPathSeparator(m_directory.GetStringRef().back(), m_syntax))
>> - path.insert(path.end(), GetPreferredPathSeparator(m_syntax));
>> + // Since the path was normalized and all paths use '/' when stored in these
>> + // objects, we don't need to look for the actual syntax specific path
>> + // separator, we just look for and insert '/'.
>> + if (m_directory && m_filename && m_directory.GetStringRef().back() != '/' &&
>> + m_filename.GetStringRef().back() != '/')
>> + path.insert(path.end(), '/');
>> path.append(m_filename.GetStringRef().begin(),
>> m_filename.GetStringRef().end());
>> - Normalize(path, m_syntax);
>> if (denormalize && !path.empty())
>> Denormalize(path, m_syntax);
>> }
>>
>> Modified: lldb/trunk/unittests/Utility/FileSpecTest.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Utility/FileSpecTest.cpp?rev=331049&r1=331048&r2=331049&view=diff
>> ==============================================================================
>> --- lldb/trunk/unittests/Utility/FileSpecTest.cpp (original)
>> +++ lldb/trunk/unittests/Utility/FileSpecTest.cpp Fri Apr 27 08:45:58 2018
>> @@ -54,17 +54,14 @@ TEST(FileSpecTest, FileAndDirectoryCompo
>>
>> FileSpec fs_posix_trailing_slash("/foo/bar/", false,
>> FileSpec::ePathSyntaxPosix);
>> - EXPECT_STREQ("/foo/bar/.", fs_posix_trailing_slash.GetCString());
>> - EXPECT_STREQ("/foo/bar", fs_posix_trailing_slash.GetDirectory().GetCString());
>> - EXPECT_STREQ(".", fs_posix_trailing_slash.GetFilename().GetCString());
>> + EXPECT_STREQ("/foo/bar", fs_posix_trailing_slash.GetCString());
>> + EXPECT_STREQ("/foo", fs_posix_trailing_slash.GetDirectory().GetCString());
>> + EXPECT_STREQ("bar", fs_posix_trailing_slash.GetFilename().GetCString());
>>
>> FileSpec fs_windows_trailing_slash("F:\\bar\\", false,
>> FileSpec::ePathSyntaxWindows);
>> - EXPECT_STREQ("F:\\bar\\.", fs_windows_trailing_slash.GetCString());
>> - // EXPECT_STREQ("F:\\bar",
>> - // fs_windows_trailing_slash.GetDirectory().GetCString()); // It returns
>> - // "F:/bar"
>> - EXPECT_STREQ(".", fs_windows_trailing_slash.GetFilename().GetCString());
>> + EXPECT_STREQ("F:\\bar", fs_windows_trailing_slash.GetCString());
>> + EXPECT_STREQ("bar", fs_windows_trailing_slash.GetFilename().GetCString());
>> }
>>
>> TEST(FileSpecTest, AppendPathComponent) {
>> @@ -131,32 +128,13 @@ TEST(FileSpecTest, PrependPathComponent)
>> EXPECT_STREQ("F:\\bar", fs_windows_root.GetCString());
>> }
>>
>> -static void Compare(const FileSpec &one, const FileSpec &two, bool full_match,
>> - bool remove_backup_dots, bool result) {
>> - EXPECT_EQ(result, FileSpec::Equal(one, two, full_match, remove_backup_dots))
>> - << "File one: " << one.GetCString() << "\nFile two: " << two.GetCString()
>> - << "\nFull match: " << full_match
>> - << "\nRemove backup dots: " << remove_backup_dots;
>> -}
>> -
>> TEST(FileSpecTest, EqualSeparator) {
>> FileSpec backward("C:\\foo\\bar", false, FileSpec::ePathSyntaxWindows);
>> FileSpec forward("C:/foo/bar", false, FileSpec::ePathSyntaxWindows);
>> EXPECT_EQ(forward, backward);
>> -
>> - const bool full_match = true;
>> - const bool remove_backup_dots = true;
>> - const bool match = true;
>> - Compare(forward, backward, full_match, remove_backup_dots, match);
>> - Compare(forward, backward, full_match, !remove_backup_dots, match);
>> - Compare(forward, backward, !full_match, remove_backup_dots, match);
>> - Compare(forward, backward, !full_match, !remove_backup_dots, match);
>> }
>>
>> TEST(FileSpecTest, EqualDotsWindows) {
>> - const bool full_match = true;
>> - const bool remove_backup_dots = true;
>> - const bool match = true;
>> std::pair<const char *, const char *> tests[] = {
>> {R"(C:\foo\bar\baz)", R"(C:\foo\foo\..\bar\baz)"},
>> {R"(C:\bar\baz)", R"(C:\foo\..\bar\baz)"},
>> @@ -170,18 +148,11 @@ TEST(FileSpecTest, EqualDotsWindows) {
>> for (const auto &test : tests) {
>> FileSpec one(test.first, false, FileSpec::ePathSyntaxWindows);
>> FileSpec two(test.second, false, FileSpec::ePathSyntaxWindows);
>> - EXPECT_NE(one, two);
>> - Compare(one, two, full_match, remove_backup_dots, match);
>> - Compare(one, two, full_match, !remove_backup_dots, !match);
>> - Compare(one, two, !full_match, remove_backup_dots, match);
>> - Compare(one, two, !full_match, !remove_backup_dots, !match);
>> + EXPECT_EQ(one, two);
>> }
>> }
>>
>> TEST(FileSpecTest, EqualDotsPosix) {
>> - const bool full_match = true;
>> - const bool remove_backup_dots = true;
>> - const bool match = true;
>> std::pair<const char *, const char *> tests[] = {
>> {R"(/foo/bar/baz)", R"(/foo/foo/../bar/baz)"},
>> {R"(/bar/baz)", R"(/foo/../bar/baz)"},
>> @@ -193,18 +164,11 @@ TEST(FileSpecTest, EqualDotsPosix) {
>> for (const auto &test : tests) {
>> FileSpec one(test.first, false, FileSpec::ePathSyntaxPosix);
>> FileSpec two(test.second, false, FileSpec::ePathSyntaxPosix);
>> - EXPECT_NE(one, two);
>> - Compare(one, two, full_match, remove_backup_dots, match);
>> - Compare(one, two, full_match, !remove_backup_dots, !match);
>> - Compare(one, two, !full_match, remove_backup_dots, match);
>> - Compare(one, two, !full_match, !remove_backup_dots, !match);
>> + EXPECT_EQ(one, two);
>> }
>> }
>>
>> TEST(FileSpecTest, EqualDotsPosixRoot) {
>> - const bool full_match = true;
>> - const bool remove_backup_dots = true;
>> - const bool match = true;
>> std::pair<const char *, const char *> tests[] = {
>> {R"(/)", R"(/..)"},
>> {R"(/)", R"(/.)"},
>> @@ -214,11 +178,7 @@ TEST(FileSpecTest, EqualDotsPosixRoot) {
>> for (const auto &test : tests) {
>> FileSpec one(test.first, false, FileSpec::ePathSyntaxPosix);
>> FileSpec two(test.second, false, FileSpec::ePathSyntaxPosix);
>> - EXPECT_NE(one, two);
>> - Compare(one, two, full_match, remove_backup_dots, match);
>> - Compare(one, two, full_match, !remove_backup_dots, !match);
>> - Compare(one, two, !full_match, remove_backup_dots, !match);
>> - Compare(one, two, !full_match, !remove_backup_dots, !match);
>> + EXPECT_EQ(one, two);
>> }
>> }
>>
>> @@ -235,22 +195,25 @@ TEST(FileSpecTest, GetNormalizedPath) {
>> {"/foo//bar/./baz", "/foo/bar/baz"},
>> {"/./foo", "/foo"},
>> {"/", "/"},
>> - {"//", "//"},
>> + // TODO: fix llvm::sys::path::remove_dots() to return "//" below.
>> + //{"//", "//"},
>> {"//net", "//net"},
>> {"/..", "/"},
>> {"/.", "/"},
>> {"..", ".."},
>> - {".", "."},
>> + {".", ""},
>> {"../..", "../.."},
>> - {"foo/..", "."},
>> + {"foo/..", ""},
>> {"foo/../bar", "bar"},
>> {"../foo/..", ".."},
>> {"./foo", "foo"},
>> + {"././foo", "foo"},
>> + {"../foo", "../foo"},
>> + {"../../foo", "../../foo"},
>> };
>> for (auto test : posix_tests) {
>> EXPECT_EQ(test.second,
>> FileSpec(test.first, false, FileSpec::ePathSyntaxPosix)
>> - .GetNormalizedPath()
>> .GetPath());
>> }
>>
>> @@ -265,21 +228,25 @@ TEST(FileSpecTest, GetNormalizedPath) {
>> // {R"(\\net)", R"(\\net)"},
>> {R"(c:\..)", R"(c:\)"},
>> {R"(c:\.)", R"(c:\)"},
>> - {R"(\..)", R"(\)"},
>> + // TODO: fix llvm::sys::path::remove_dots() to return "\" below.
>> + {R"(\..)", R"(\..)"},
>> // {R"(c:..)", R"(c:..)"},
>> {R"(..)", R"(..)"},
>> - {R"(.)", R"(.)"},
>> - {R"(c:..\..)", R"(c:..\..)"},
>> + {R"(.)", R"()"},
>> + // TODO: fix llvm::sys::path::remove_dots() to return "c:\" below.
>> + {R"(c:..\..)", R"(c:\..\..)"},
>> {R"(..\..)", R"(..\..)"},
>> - {R"(foo\..)", R"(.)"},
>> + {R"(foo\..)", R"()"},
>> {R"(foo\..\bar)", R"(bar)"},
>> {R"(..\foo\..)", R"(..)"},
>> {R"(.\foo)", R"(foo)"},
>> + {R"(.\.\foo)", R"(foo)"},
>> + {R"(..\foo)", R"(..\foo)"},
>> + {R"(..\..\foo)", R"(..\..\foo)"},
>> };
>> for (auto test : windows_tests) {
>> EXPECT_EQ(test.second,
>> FileSpec(test.first, false, FileSpec::ePathSyntaxWindows)
>> - .GetNormalizedPath()
>> .GetPath())
>> << "Original path: " << test.first;
>> }
>> @@ -308,3 +275,4 @@ TEST(FileSpecTest, FormatFileSpec) {
>> EXPECT_EQ("foo", llvm::formatv("{0:F}", F).str());
>> EXPECT_EQ("(empty)", llvm::formatv("{0:D}", F).str());
>> }
>> +
>>
>>
>> _______________________________________________
>> lldb-commits mailing list
>> lldb-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
More information about the lldb-commits
mailing list