Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/include/llvm/BinaryFormat/Dwarf.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ toDW_LNAME(SourceLanguage language) {
case DW_LANG_C11:
return {{DW_LNAME_C, 201112}};
case DW_LANG_C17:
return {{DW_LNAME_C, 201712}};
return {{DW_LNAME_C, 201710}};
case DW_LANG_C_plus_plus:
return {{DW_LNAME_C_plus_plus, 0}};
case DW_LANG_C_plus_plus_03:
Expand Down
217 changes: 181 additions & 36 deletions llvm/unittests/BinaryFormat/DwarfTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,41 +255,186 @@ TEST(DwarfTest, lname_SourceLanguageNameString) {
#include "llvm/BinaryFormat/Dwarf.def"
}

TEST(DWARFDebugInfo, TestLanguageDescription_Versioned) {
// Tests for the llvm::dwarf::LanguageDescription API that
// takes a name *and* a version.

// Unknown language.
EXPECT_EQ(
llvm::dwarf::LanguageDescription(static_cast<SourceLanguageName>(0)),
"Unknown");

EXPECT_EQ(
llvm::dwarf::LanguageDescription(static_cast<SourceLanguageName>(0), 0),
"Unknown");

// Test that specifying an invalid version falls back to a valid language name
// regardless.
EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_ObjC, 0), "Objective C");
EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_Julia, 0), "Julia");

// Check some versions.
EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C_plus_plus, 199711),
"C++98");
EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C_plus_plus, 201402),
"C++14");

// Versions round up.
EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C_plus_plus, 201400),
"C++14");

// Version 0 for C and C++ is an unversioned name.
EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C, 0), "C (K&R and ISO)");
EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_C_plus_plus, 0),
"ISO C++");

// Version 0 for other versioned languages may not be the unversioned name.
EXPECT_EQ(llvm::dwarf::LanguageDescription(DW_LNAME_Fortran, 0),
"FORTRAN 77");
struct LanguageDescriptionTestCase {
llvm::dwarf::SourceLanguageName LName;
uint32_t LVersion;
llvm::StringRef ExpectedDescription;
};

LanguageDescriptionTestCase LanguageDescriptionTestCases[] = {
{static_cast<SourceLanguageName>(0), 0, "Unknown"},
{static_cast<SourceLanguageName>(0), 1, "Unknown"},
{DW_LNAME_Ada, 0, "Ada 83"},
{DW_LNAME_Ada, 1982, "Ada 83"},
{DW_LNAME_Ada, 1983, "Ada 83"},
{DW_LNAME_Ada, 1994, "Ada 95"},
{DW_LNAME_Ada, 1995, "Ada 95"},
{DW_LNAME_Ada, 2004, "Ada 2005"},
{DW_LNAME_Ada, 2005, "Ada 2005"},
{DW_LNAME_Ada, 2011, "Ada 2012"},
{DW_LNAME_Ada, 2012, "Ada 2012"},
{DW_LNAME_Ada, 2013, "ISO Ada"},
{DW_LNAME_Cobol, 0, "COBOL-74"},
{DW_LNAME_Cobol, 1973, "COBOL-74"},
{DW_LNAME_Cobol, 1974, "COBOL-74"},
{DW_LNAME_Cobol, 1984, "COBOL-85"},
{DW_LNAME_Cobol, 1985, "COBOL-85"},
{DW_LNAME_Cobol, 1986, "ISO Cobol"},
{DW_LNAME_Fortran, 0, "FORTRAN 77"},
{DW_LNAME_Fortran, 1976, "FORTRAN 77"},
{DW_LNAME_Fortran, 1977, "FORTRAN 77"},
{DW_LNAME_Fortran, 1989, "FORTRAN 90"},
{DW_LNAME_Fortran, 1990, "FORTRAN 90"},
{DW_LNAME_Fortran, 1994, "Fortran 95"},
{DW_LNAME_Fortran, 1995, "Fortran 95"},
{DW_LNAME_Fortran, 2002, "Fortran 2003"},
{DW_LNAME_Fortran, 2003, "Fortran 2003"},
{DW_LNAME_Fortran, 2007, "Fortran 2008"},
{DW_LNAME_Fortran, 2008, "Fortran 2008"},
{DW_LNAME_Fortran, 2017, "Fortran 2018"},
{DW_LNAME_Fortran, 2018, "Fortran 2018"},
{DW_LNAME_Fortran, 2019, "ISO Fortran"},
{DW_LNAME_C, 0, "C (K&R and ISO)"},
{DW_LNAME_C, 198911, "C89"},
{DW_LNAME_C, 198912, "C89"},
{DW_LNAME_C, 199901, "C99"},
{DW_LNAME_C, 199902, "C11"},
{DW_LNAME_C, 201111, "C11"},
{DW_LNAME_C, 201112, "C11"},
{DW_LNAME_C, 201201, "C17"},
{DW_LNAME_C, 201709, "C17"},
{DW_LNAME_C, 201710, "C17"},
{DW_LNAME_C, 201711, "C (K&R and ISO)"},
{DW_LNAME_C_plus_plus, 0, "ISO C++"},
{DW_LNAME_C_plus_plus, 199710, "C++98"},
{DW_LNAME_C_plus_plus, 199711, "C++98"},
{DW_LNAME_C_plus_plus, 199712, "C++03"},
{DW_LNAME_C_plus_plus, 200310, "C++03"},
{DW_LNAME_C_plus_plus, 200311, "C++11"},
{DW_LNAME_C_plus_plus, 201102, "C++11"},
{DW_LNAME_C_plus_plus, 201103, "C++11"},
{DW_LNAME_C_plus_plus, 201104, "C++14"},
{DW_LNAME_C_plus_plus, 201401, "C++14"},
{DW_LNAME_C_plus_plus, 201402, "C++14"},
{DW_LNAME_C_plus_plus, 201403, "C++17"},
{DW_LNAME_C_plus_plus, 201702, "C++17"},
{DW_LNAME_C_plus_plus, 201703, "C++17"},
{DW_LNAME_C_plus_plus, 201704, "C++20"},
{DW_LNAME_C_plus_plus, 202001, "C++20"},
{DW_LNAME_C_plus_plus, 202002, "C++20"},
{DW_LNAME_C_plus_plus, 202003, "ISO C++"},
{DW_LNAME_ObjC_plus_plus, 0, LanguageDescription(DW_LNAME_ObjC_plus_plus)},
{DW_LNAME_ObjC_plus_plus, 1, LanguageDescription(DW_LNAME_ObjC_plus_plus)},
{DW_LNAME_ObjC, 0, LanguageDescription(DW_LNAME_ObjC)},
{DW_LNAME_ObjC, 1, LanguageDescription(DW_LNAME_ObjC)},
{DW_LNAME_Move, 0, LanguageDescription(DW_LNAME_Move)},
{DW_LNAME_Move, 1, LanguageDescription(DW_LNAME_Move)},
{DW_LNAME_SYCL, 0, LanguageDescription(DW_LNAME_SYCL)},
{DW_LNAME_SYCL, 1, LanguageDescription(DW_LNAME_SYCL)},
{DW_LNAME_BLISS, 0, LanguageDescription(DW_LNAME_BLISS)},
{DW_LNAME_BLISS, 1, LanguageDescription(DW_LNAME_BLISS)},
{DW_LNAME_Crystal, 0, LanguageDescription(DW_LNAME_Crystal)},
{DW_LNAME_Crystal, 1, LanguageDescription(DW_LNAME_Crystal)},
{DW_LNAME_D, 0, LanguageDescription(DW_LNAME_D)},
{DW_LNAME_D, 1, LanguageDescription(DW_LNAME_D)},
{DW_LNAME_Dylan, 0, LanguageDescription(DW_LNAME_Dylan)},
{DW_LNAME_Dylan, 1, LanguageDescription(DW_LNAME_Dylan)},
{DW_LNAME_Go, 0, LanguageDescription(DW_LNAME_Go)},
{DW_LNAME_Go, 1, LanguageDescription(DW_LNAME_Go)},
{DW_LNAME_Haskell, 0, LanguageDescription(DW_LNAME_Haskell)},
{DW_LNAME_Haskell, 1, LanguageDescription(DW_LNAME_Haskell)},
{DW_LNAME_HLSL, 0, LanguageDescription(DW_LNAME_HLSL)},
{DW_LNAME_HLSL, 1, LanguageDescription(DW_LNAME_HLSL)},
{DW_LNAME_Java, 0, LanguageDescription(DW_LNAME_Java)},
{DW_LNAME_Java, 1, LanguageDescription(DW_LNAME_Java)},
{DW_LNAME_Julia, 0, LanguageDescription(DW_LNAME_Julia)},
{DW_LNAME_Julia, 1, LanguageDescription(DW_LNAME_Julia)},
{DW_LNAME_Kotlin, 0, LanguageDescription(DW_LNAME_Kotlin)},
{DW_LNAME_Kotlin, 1, LanguageDescription(DW_LNAME_Kotlin)},
{DW_LNAME_Modula2, 0, LanguageDescription(DW_LNAME_Modula2)},
{DW_LNAME_Modula2, 1, LanguageDescription(DW_LNAME_Modula2)},
{DW_LNAME_Modula3, 0, LanguageDescription(DW_LNAME_Modula3)},
{DW_LNAME_Modula3, 1, LanguageDescription(DW_LNAME_Modula3)},
{DW_LNAME_OCaml, 0, LanguageDescription(DW_LNAME_OCaml)},
{DW_LNAME_OCaml, 1, LanguageDescription(DW_LNAME_OCaml)},
{DW_LNAME_OpenCL_C, 0, LanguageDescription(DW_LNAME_OpenCL_C)},
{DW_LNAME_OpenCL_C, 1, LanguageDescription(DW_LNAME_OpenCL_C)},
{DW_LNAME_Pascal, 0, LanguageDescription(DW_LNAME_Pascal)},
{DW_LNAME_Pascal, 1, LanguageDescription(DW_LNAME_Pascal)},
{DW_LNAME_PLI, 0, LanguageDescription(DW_LNAME_PLI)},
{DW_LNAME_PLI, 1, LanguageDescription(DW_LNAME_PLI)},
{DW_LNAME_Python, 0, LanguageDescription(DW_LNAME_Python)},
{DW_LNAME_Python, 1, LanguageDescription(DW_LNAME_Python)},
{DW_LNAME_RenderScript, 0, LanguageDescription(DW_LNAME_RenderScript)},
{DW_LNAME_RenderScript, 1, LanguageDescription(DW_LNAME_RenderScript)},
{DW_LNAME_Rust, 0, LanguageDescription(DW_LNAME_Rust)},
{DW_LNAME_Rust, 1, LanguageDescription(DW_LNAME_Rust)},
{DW_LNAME_Swift, 0, LanguageDescription(DW_LNAME_Swift)},
{DW_LNAME_Swift, 1, LanguageDescription(DW_LNAME_Swift)},
{DW_LNAME_UPC, 0, LanguageDescription(DW_LNAME_UPC)},
{DW_LNAME_UPC, 1, LanguageDescription(DW_LNAME_UPC)},
{DW_LNAME_Zig, 0, LanguageDescription(DW_LNAME_Zig)},
{DW_LNAME_Zig, 1, LanguageDescription(DW_LNAME_Zig)},
{DW_LNAME_Assembly, 0, LanguageDescription(DW_LNAME_Assembly)},
{DW_LNAME_Assembly, 1, LanguageDescription(DW_LNAME_Assembly)},
{DW_LNAME_C_sharp, 0, LanguageDescription(DW_LNAME_C_sharp)},
{DW_LNAME_C_sharp, 1, LanguageDescription(DW_LNAME_C_sharp)},
{DW_LNAME_Mojo, 0, LanguageDescription(DW_LNAME_Mojo)},
{DW_LNAME_Mojo, 1, LanguageDescription(DW_LNAME_Mojo)},
{DW_LNAME_GLSL, 0, LanguageDescription(DW_LNAME_GLSL)},
{DW_LNAME_GLSL, 1, LanguageDescription(DW_LNAME_GLSL)},
{DW_LNAME_GLSL_ES, 0, LanguageDescription(DW_LNAME_GLSL_ES)},
{DW_LNAME_GLSL_ES, 1, LanguageDescription(DW_LNAME_GLSL_ES)},
{DW_LNAME_OpenCL_CPP, 0, LanguageDescription(DW_LNAME_OpenCL_CPP)},
{DW_LNAME_OpenCL_CPP, 1, LanguageDescription(DW_LNAME_OpenCL_CPP)},
{DW_LNAME_CPP_for_OpenCL, 0, LanguageDescription(DW_LNAME_CPP_for_OpenCL)},
{DW_LNAME_CPP_for_OpenCL, 1, LanguageDescription(DW_LNAME_CPP_for_OpenCL)},
{DW_LNAME_Ruby, 0, LanguageDescription(DW_LNAME_Ruby)},
{DW_LNAME_Ruby, 1, LanguageDescription(DW_LNAME_Ruby)},
{DW_LNAME_Hylo, 0, LanguageDescription(DW_LNAME_Hylo)},
{DW_LNAME_Hylo, 1, LanguageDescription(DW_LNAME_Hylo)},
{DW_LNAME_Metal, 0, LanguageDescription(DW_LNAME_Metal)},
{DW_LNAME_Metal, 1, LanguageDescription(DW_LNAME_Metal)}};

struct LanguageDescriptionTestFixture
: public testing::Test,
public testing::WithParamInterface<LanguageDescriptionTestCase> {};

TEST_P(LanguageDescriptionTestFixture, TestLanguageDescription) {
auto [LName, LVersion, ExpectedDescription] = GetParam();

// Basic test.
EXPECT_EQ(llvm::dwarf::LanguageDescription(LName, LVersion),
ExpectedDescription);

// Now do the same test but roundtrip through the DW_LANG_ <-> DW_LNAME_
// conversion APIs first.

auto DWLang = llvm::dwarf::toDW_LANG(LName, LVersion);
// Some languages are not 1-to-1 mapped. In which case there's nothing else
// to test.
if (!DWLang)
return;

std::optional<std::pair<SourceLanguageName, uint32_t>> DWLName =
llvm::dwarf::toDW_LNAME(*DWLang);

// We are roundtripping, so there definitely should be a mapping back to
// DW_LNAME_.
ASSERT_TRUE(DWLName);

// There is no official DW_LANG_ code for C++98. So the roundtripping turns it
// into a plain DW_LANG_C_plus_plus.
if (DWLang == DW_LANG_C_plus_plus && LVersion <= 199711)
EXPECT_EQ(llvm::dwarf::LanguageDescription(DWLName->first, DWLName->second),
"ISO C++");
else
EXPECT_EQ(llvm::dwarf::LanguageDescription(DWLName->first, DWLName->second),
ExpectedDescription);
}

INSTANTIATE_TEST_SUITE_P(LanguageDescriptionTests,
LanguageDescriptionTestFixture,
::testing::ValuesIn(LanguageDescriptionTestCases));

} // end namespace