blob: ba7d59182ea539ba1ac4261560aef807afe0ea3b [file] [log] [blame]
//===- 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<uint8_t> RefSize;
std::optional<uint8_t> 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<SourceLanguageName>(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<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