//===- unittest/BinaryFormat/DwarfTest.cpp - Dwarf support tests ----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/FormatVariadic.h" #include "gtest/gtest.h" using namespace llvm; using namespace llvm::dwarf; namespace { TEST(DwarfTest, TagStringOnInvalid) { // This is invalid, so it shouldn't be stringified. EXPECT_EQ(StringRef(), TagString(DW_TAG_invalid)); // These aren't really tags: they describe ranges within tags. They // shouldn't be stringified either. EXPECT_EQ(StringRef(), TagString(DW_TAG_lo_user)); EXPECT_EQ(StringRef(), TagString(DW_TAG_hi_user)); EXPECT_EQ(StringRef(), TagString(DW_TAG_user_base)); } TEST(DwarfTest, getTag) { // A couple of valid tags. EXPECT_EQ(DW_TAG_array_type, getTag("DW_TAG_array_type")); EXPECT_EQ(DW_TAG_module, getTag("DW_TAG_module")); // Invalid tags. EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_invalid")); EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_madeuptag")); EXPECT_EQ(DW_TAG_invalid, getTag("something else")); // Tag range markers should not be recognized. EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_lo_user")); EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_hi_user")); EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_user_base")); } TEST(DwarfTest, getOperationEncoding) { // Some valid ops. EXPECT_EQ(DW_OP_deref, getOperationEncoding("DW_OP_deref")); EXPECT_EQ(DW_OP_bit_piece, getOperationEncoding("DW_OP_bit_piece")); // Invalid ops. EXPECT_EQ(0u, getOperationEncoding("DW_OP_otherthings")); EXPECT_EQ(0u, getOperationEncoding("other")); // Markers shouldn't be recognized. EXPECT_EQ(0u, getOperationEncoding("DW_OP_lo_user")); EXPECT_EQ(0u, getOperationEncoding("DW_OP_hi_user")); } TEST(DwarfTest, LanguageStringOnInvalid) { // This is invalid, so it shouldn't be stringified. EXPECT_EQ(StringRef(), LanguageString(0)); // These aren't really tags: they describe ranges within tags. They // shouldn't be stringified either. EXPECT_EQ(StringRef(), LanguageString(DW_LANG_lo_user)); EXPECT_EQ(StringRef(), LanguageString(DW_LANG_hi_user)); } TEST(DwarfTest, getLanguage) { // A couple of valid languages. EXPECT_EQ(DW_LANG_C89, getLanguage("DW_LANG_C89")); EXPECT_EQ(DW_LANG_C_plus_plus_11, getLanguage("DW_LANG_C_plus_plus_11")); EXPECT_EQ(DW_LANG_OCaml, getLanguage("DW_LANG_OCaml")); EXPECT_EQ(DW_LANG_Mips_Assembler, getLanguage("DW_LANG_Mips_Assembler")); // Invalid languages. EXPECT_EQ(0u, getLanguage("DW_LANG_invalid")); EXPECT_EQ(0u, getLanguage("DW_TAG_array_type")); EXPECT_EQ(0u, getLanguage("something else")); // Language range markers should not be recognized. EXPECT_EQ(0u, getLanguage("DW_LANG_lo_user")); EXPECT_EQ(0u, getLanguage("DW_LANG_hi_user")); } TEST(DwarfTest, AttributeEncodingStringOnInvalid) { // This is invalid, so it shouldn't be stringified. EXPECT_EQ(StringRef(), AttributeEncodingString(0)); // These aren't really tags: they describe ranges within tags. They // shouldn't be stringified either. EXPECT_EQ(StringRef(), AttributeEncodingString(DW_ATE_lo_user)); EXPECT_EQ(StringRef(), AttributeEncodingString(DW_ATE_hi_user)); } TEST(DwarfTest, getAttributeEncoding) { // A couple of valid languages. EXPECT_EQ(DW_ATE_boolean, getAttributeEncoding("DW_ATE_boolean")); EXPECT_EQ(DW_ATE_imaginary_float, getAttributeEncoding("DW_ATE_imaginary_float")); // Invalid languages. EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_invalid")); EXPECT_EQ(0u, getAttributeEncoding("DW_TAG_array_type")); EXPECT_EQ(0u, getAttributeEncoding("something else")); // AttributeEncoding range markers should not be recognized. EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_lo_user")); EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_hi_user")); } TEST(DwarfTest, VirtualityString) { EXPECT_EQ(StringRef("DW_VIRTUALITY_none"), VirtualityString(DW_VIRTUALITY_none)); EXPECT_EQ(StringRef("DW_VIRTUALITY_virtual"), VirtualityString(DW_VIRTUALITY_virtual)); EXPECT_EQ(StringRef("DW_VIRTUALITY_pure_virtual"), VirtualityString(DW_VIRTUALITY_pure_virtual)); // DW_VIRTUALITY_max should be pure virtual. EXPECT_EQ(StringRef("DW_VIRTUALITY_pure_virtual"), VirtualityString(DW_VIRTUALITY_max)); // Invalid numbers shouldn't be stringified. EXPECT_EQ(StringRef(), VirtualityString(DW_VIRTUALITY_max + 1)); EXPECT_EQ(StringRef(), VirtualityString(DW_VIRTUALITY_max + 77)); } TEST(DwarfTest, getVirtuality) { EXPECT_EQ(DW_VIRTUALITY_none, getVirtuality("DW_VIRTUALITY_none")); EXPECT_EQ(DW_VIRTUALITY_virtual, getVirtuality("DW_VIRTUALITY_virtual")); EXPECT_EQ(DW_VIRTUALITY_pure_virtual, getVirtuality("DW_VIRTUALITY_pure_virtual")); // Invalid strings. EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("DW_VIRTUALITY_invalid")); EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("DW_VIRTUALITY_max")); EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("something else")); } TEST(DwarfTest, FixedFormSizes) { std::optional RefSize; std::optional AddrSize; // Test 32 bit DWARF version 2 with 4 byte addresses. FormParams Params_2_4_32 = {2, 4, DWARF32}; RefSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_2_4_32); AddrSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_2_4_32); EXPECT_TRUE(RefSize.has_value()); EXPECT_TRUE(AddrSize.has_value()); EXPECT_EQ(*RefSize, *AddrSize); // Test 32 bit DWARF version 2 with 8 byte addresses. FormParams Params_2_8_32 = {2, 8, DWARF32}; RefSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_2_8_32); AddrSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_2_8_32); EXPECT_TRUE(RefSize.has_value()); EXPECT_TRUE(AddrSize.has_value()); EXPECT_EQ(*RefSize, *AddrSize); // DW_FORM_ref_addr is 4 bytes in DWARF 32 in DWARF version 3 and beyond. FormParams Params_3_4_32 = {3, 4, DWARF32}; RefSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_3_4_32); EXPECT_TRUE(RefSize.has_value()); EXPECT_EQ(*RefSize, 4); FormParams Params_4_4_32 = {4, 4, DWARF32}; RefSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_4_4_32); EXPECT_TRUE(RefSize.has_value()); EXPECT_EQ(*RefSize, 4); FormParams Params_5_4_32 = {5, 4, DWARF32}; RefSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_5_4_32); EXPECT_TRUE(RefSize.has_value()); EXPECT_EQ(*RefSize, 4); // DW_FORM_ref_addr is 8 bytes in DWARF 64 in DWARF version 3 and beyond. FormParams Params_3_8_64 = {3, 8, DWARF64}; RefSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_3_8_64); EXPECT_TRUE(RefSize.has_value()); EXPECT_EQ(*RefSize, 8); FormParams Params_4_8_64 = {4, 8, DWARF64}; RefSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_4_8_64); EXPECT_TRUE(RefSize.has_value()); EXPECT_EQ(*RefSize, 8); FormParams Params_5_8_64 = {5, 8, DWARF64}; RefSize = getFixedFormByteSize(DW_FORM_ref_addr, Params_5_8_64); EXPECT_TRUE(RefSize.has_value()); EXPECT_EQ(*RefSize, 8); } TEST(DwarfTest, format_provider) { EXPECT_EQ("DW_AT_name", formatv("{0}", DW_AT_name).str()); EXPECT_EQ("DW_AT_unknown_3fff", formatv("{0}", DW_AT_hi_user).str()); EXPECT_EQ("DW_FORM_addr", formatv("{0}", DW_FORM_addr).str()); EXPECT_EQ("DW_FORM_unknown_1f00", formatv("{0}", DW_FORM_lo_user).str()); EXPECT_EQ("DW_IDX_compile_unit", formatv("{0}", DW_IDX_compile_unit).str()); EXPECT_EQ("DW_IDX_unknown_3fff", formatv("{0}", DW_IDX_hi_user).str()); EXPECT_EQ("DW_TAG_compile_unit", formatv("{0}", DW_TAG_compile_unit).str()); EXPECT_EQ("DW_TAG_unknown_ffff", formatv("{0}", DW_TAG_hi_user).str()); EXPECT_EQ("DW_OP_lit0", formatv("{0}", DW_OP_lit0).str()); EXPECT_EQ("DW_OP_unknown_ff", formatv("{0}", DW_OP_hi_user).str()); } TEST(DwarfTest, lname) { auto roundtrip = [](llvm::dwarf::SourceLanguage sl) { auto name_version = toDW_LNAME(sl); // Ignore ones without a defined mapping. if (sl == DW_LANG_Mips_Assembler || sl == DW_LANG_GOOGLE_RenderScript || !name_version.has_value()) return sl; return dwarf::toDW_LANG(name_version->first, name_version->second) .value_or(sl); }; #define HANDLE_DW_LANG(ID, NAME, LOWER_BOUND, VERSION, VENDOR) \ EXPECT_EQ(roundtrip(DW_LANG_##NAME), DW_LANG_##NAME); #include "llvm/BinaryFormat/Dwarf.def" } TEST(DwarfTest, lname_getSourceLanguageName) { // Some basics. EXPECT_EQ(getSourceLanguageName("DW_LNAME_Ada"), DW_LNAME_Ada); EXPECT_EQ(getSourceLanguageName("DW_LNAME_Metal"), DW_LNAME_Metal); // Test invalid input. EXPECT_EQ(getSourceLanguageName(""), 0U); EXPECT_EQ(getSourceLanguageName("blah"), 0U); EXPECT_EQ(getSourceLanguageName("DW_LNAME__something_unlikely"), 0U); EXPECT_EQ(getSourceLanguageName("DW_LANG_C"), 0U); // Test that we cover all DW_LNAME_ names. #define xstr(X) #X #define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \ EXPECT_EQ(getSourceLanguageName(xstr(DW_LNAME_##NAME)), DW_LNAME_##NAME); #include "llvm/BinaryFormat/Dwarf.def" } TEST(DwarfTest, lname_SourceLanguageNameString) { // Some basics. EXPECT_EQ(SourceLanguageNameString(DW_LNAME_C_plus_plus), "DW_LNAME_C_plus_plus"); EXPECT_EQ(SourceLanguageNameString(DW_LNAME_CPP_for_OpenCL), "DW_LNAME_CPP_for_OpenCL"); // Test invalid input. EXPECT_EQ(SourceLanguageNameString(static_cast(0)), ""); // Test that we cover all DW_LNAME_ names. #define xstr(X) #X #define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \ EXPECT_EQ(SourceLanguageNameString(DW_LNAME_##NAME), xstr(DW_LNAME_##NAME)); #include "llvm/BinaryFormat/Dwarf.def" } struct LanguageDescriptionTestCase { llvm::dwarf::SourceLanguageName LName; uint32_t LVersion; llvm::StringRef ExpectedDescription; }; LanguageDescriptionTestCase LanguageDescriptionTestCases[] = { {static_cast(0), 0, "Unknown"}, {static_cast(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 {}; 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> 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