diff --git a/llvm/include/llvm/DebugInfo/DIContext.h b/llvm/include/llvm/DebugInfo/DIContext.h --- a/llvm/include/llvm/DebugInfo/DIContext.h +++ b/llvm/include/llvm/DebugInfo/DIContext.h @@ -133,7 +133,12 @@ /// Controls which fields of DILineInfo container should be filled /// with data. struct DILineInfoSpecifier { - enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; + enum class FileLineInfoKind { + None, + Default, + RelativeFilePath, + AbsoluteFilePath + }; using FunctionNameKind = DINameKind; FileLineInfoKind FLIKind; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -1082,7 +1082,7 @@ if (!Name) return false; StringRef FileName = *Name; - if (Kind != FileLineInfoKind::AbsoluteFilePath || + if (Kind == FileLineInfoKind::None || Kind == FileLineInfoKind::Default || isPathAbsoluteOnWindowsOrPosix(FileName)) { Result = std::string(FileName); return true; @@ -1099,12 +1099,17 @@ IncludeDir = IncludeDirectories[Entry.DirIdx - 1].getAsCString().getValue(); } - // We may still need to append compilation directory of compile unit. - // We know that FileName is not absolute, the only way to have an - // absolute path at this point would be if IncludeDir is absolute. - if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) + // For absolute paths only, include the compilation directory of compile unit. + // We know that FileName is not absolute, the only way to have an absolute + // path at this point would be if IncludeDir is absolute. + if (Kind == FileLineInfoKind::AbsoluteFilePath && !CompDir.empty() && + !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) sys::path::append(FilePath, Style, CompDir); + assert((Kind == FileLineInfoKind::AbsoluteFilePath || + Kind == FileLineInfoKind::RelativeFilePath) && + "invalid FileLineInfo Kind"); + // sys::path::append skips empty strings. sys::path::append(FilePath, Style, IncludeDir, FileName); Result = std::string(FilePath.str()); diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -901,4 +901,63 @@ EXPECT_TRUE(InOutput("0x0000003f: 0c DW_LNS_set_isa (66)\n")) << Output; } +TEST_F(DebugLineBasicFixture, PrintPathsProperly) { + if (!setupGenerator(5)) + return; + + LineTable < = Gen->addLineTable(); + LT.setCustomPrologue({ + {33, LineTable::Long}, // unit length + {5, LineTable::Half}, // version + {8, LineTable::Byte}, // addr size + {0, LineTable::Byte}, // segment selector size + {25, LineTable::Long}, // prologue length + {1, LineTable::Byte}, // min instruction length + {1, LineTable::Byte}, // max ops per instruction + {1, LineTable::Byte}, // default is_stmt + {0, LineTable::Byte}, // line base + {14, LineTable::Byte}, // line range + {2, LineTable::Byte}, // opcode base (small to reduce the amount of + // setup required). + {0, LineTable::Byte}, // standard opcode lengths + {1, LineTable::Byte}, // directory entry format count + {1, LineTable::ULEB}, // directory_entry_format DW_LNCNT_path + {8, LineTable::ULEB}, // directory_entry_format DW_FORM_string + {2, LineTable::ULEB}, // directories count + {'/', LineTable::Byte}, // compilation directory name + {'a', LineTable::Byte}, // compilation directory name continued + {'\0', LineTable::Byte}, // compilation directory name continued + {'b', LineTable::Byte}, // include directory name + {'\0', LineTable::Byte}, // include directory name continued + {2, LineTable::Byte}, // file name entry format count + {1, LineTable::ULEB}, // file name entry format DW_LNCNT_path + {8, LineTable::ULEB}, // file name entry_format DW_FORM_string + {2, LineTable::ULEB}, // file name entry format DW_LNCNT_directory_index + {11, LineTable::ULEB}, // file name entry_format DW_FORM_data1 + {1, LineTable::ULEB}, // file name entry count + {'c', LineTable::Byte}, // file name + {'\0', LineTable::Byte}, // file name continued + {1, LineTable::Byte} // include directory 1 + }); + + generate(); + + auto ExpectedLineTable = Line.getOrParseLineTable(LineData, 0, *Context, + nullptr, RecordRecoverable); + EXPECT_THAT_EXPECTED(ExpectedLineTable, Succeeded()); + std::string Result; + // DWARF 5 stores the comp dir in two places: the Compilation Unit and the + // directory table entry 0, and implementations are free to use one or the + // other. This copy serves as the one stored in the CU. + llvm::StringRef CompDir = "/a"; + EXPECT_TRUE( + (*ExpectedLineTable)->Prologue.getFileNameByIndex( + 0, CompDir, DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Result)); + EXPECT_STREQ(Result.c_str(), "/a/b/c"); + EXPECT_TRUE( + (*ExpectedLineTable)->Prologue.getFileNameByIndex( + 0, CompDir, DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath, Result)); + EXPECT_STREQ(Result.c_str(), "b/c"); +} + } // end anonymous namespace