diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -743,6 +743,12 @@ const NameIndex *getCUNameIndex(uint64_t CUOffset); }; +/// If `Name` is the name of a templated function that includes template +/// parameters, returns a substring of `Name` containing no template +/// parameters. +/// E.g.: StripTemplateParameters("foo") = "foo". +std::optional StripTemplateParameters(StringRef Name); + } // end namespace llvm #endif // LLVM_DEBUGINFO_DWARF_DWARFACCELERATORTABLE_H diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -15,6 +15,7 @@ #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h" #include "llvm/DWARFLinker/DWARFStreamer.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" @@ -140,37 +141,6 @@ DwarfEmitter::~DwarfEmitter() = default; -static std::optional StripTemplateParameters(StringRef Name) { - // We are looking for template parameters to strip from Name. e.g. - // - // operator< - // - // We look for > at the end but if it does not contain any < then we - // have something like operator>>. We check for the operator<=> case. - if (!Name.endswith(">") || Name.count("<") == 0 || Name.endswith("<=>")) - return {}; - - // How many < until we have the start of the template parameters. - size_t NumLeftAnglesToSkip = 1; - - // If we have operator<=> then we need to skip its < as well. - NumLeftAnglesToSkip += Name.count("<=>"); - - size_t RightAngleCount = Name.count('>'); - size_t LeftAngleCount = Name.count('<'); - - // If we have more < than > we have operator< or operator<< - // we to account for their < as well. - if (LeftAngleCount > RightAngleCount) - NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount; - - size_t StartOfTemplate = 0; - while (NumLeftAnglesToSkip--) - StartOfTemplate = Name.find('<', StartOfTemplate) + 1; - - return Name.substr(0, StartOfTemplate - 1); -} - bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die, AttributesInfo &Info, OffsetsStringPool &StringPool, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -969,3 +969,34 @@ } return CUToNameIndex.lookup(CUOffset); } + +std::optional llvm::StripTemplateParameters(StringRef Name) { + // We are looking for template parameters to strip from Name. e.g. + // + // operator< + // + // We look for > at the end but if it does not contain any < then we + // have something like operator>>. We check for the operator<=> case. + if (!Name.endswith(">") || Name.count("<") == 0 || Name.endswith("<=>")) + return {}; + + // How many < until we have the start of the template parameters. + size_t NumLeftAnglesToSkip = 1; + + // If we have operator<=> then we need to skip its < as well. + NumLeftAnglesToSkip += Name.count("<=>"); + + size_t RightAngleCount = Name.count('>'); + size_t LeftAngleCount = Name.count('<'); + + // If we have more < than > we have operator< or operator<< + // we to account for their < as well. + if (LeftAngleCount > RightAngleCount) + NumLeftAnglesToSkip += LeftAngleCount - RightAngleCount; + + size_t StartOfTemplate = 0; + while (NumLeftAnglesToSkip--) + StartOfTemplate = Name.find('<', StartOfTemplate) + 1; + + return Name.substr(0, StartOfTemplate - 1); +} diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -1351,12 +1351,18 @@ return NumErrors; } -static SmallVector getNames(const DWARFDie &DIE, +static SmallVector getNames(const DWARFDie &DIE, + bool IncludeStrippedTemplateNames, bool IncludeLinkageName = true) { SmallVector Result; - if (const char *Str = DIE.getShortName()) + if (const char *Str = DIE.getShortName()) { Result.emplace_back(Str); - else if (DIE.getTag() == dwarf::DW_TAG_namespace) + if (IncludeStrippedTemplateNames) { + if (std::optional StrippedName = + StripTemplateParameters(Result.back())) + Result.push_back(*StrippedName); + } + } else if (DIE.getTag() == dwarf::DW_TAG_namespace) Result.emplace_back("(anonymous namespace)"); if (IncludeLinkageName) { @@ -1423,7 +1429,12 @@ ++NumErrors; } - auto EntryNames = getNames(DIE); + // We allow an extra name for functions: their name without any template + // parameters. + auto IncludeStrippedTemplateNames = + DIE.getTag() == DW_TAG_subprogram || + DIE.getTag() == DW_TAG_inlined_subroutine; + auto EntryNames = getNames(DIE, IncludeStrippedTemplateNames); if (!is_contained(EntryNames, Str)) { error() << formatv("Name Index @ {0:x}: Entry @ {1:x}: mismatched Name " "of DIE @ {2:x}: index - {3}; debug_info - {4}.\n", @@ -1496,7 +1507,11 @@ // the linkage name." auto IncludeLinkageName = Die.getTag() == DW_TAG_subprogram || Die.getTag() == DW_TAG_inlined_subroutine; - auto EntryNames = getNames(Die, IncludeLinkageName); + // We *allow* stripped template names as an extra entry into the template, + // but we don't *require* them to pass the completeness test. + auto IncludeStrippedTemplateNames = false; + auto EntryNames = + getNames(Die, IncludeStrippedTemplateNames, IncludeLinkageName); if (EntryNames.empty()) return 0; diff --git a/llvm/test/tools/dsymutil/X86/dwarf5-accel.test b/llvm/test/tools/dsymutil/X86/dwarf5-accel.test --- a/llvm/test/tools/dsymutil/X86/dwarf5-accel.test +++ b/llvm/test/tools/dsymutil/X86/dwarf5-accel.test @@ -13,12 +13,10 @@ ## $ clang -gdwarf-5 dwarf5-accel.cpp -c -o dwarf5-accel.o #RUN: dsymutil -accelerator=Dwarf -oso-prepend-path %p/Inputs -y %s -o %t.dSYM -#COM: Uncomment next line when dwarfdump will handle stripped template names. -#COM: llvm-dwarfdump --verify %t.dSYM | FileCheck %s --check-prefix VERIFY +#RUN: llvm-dwarfdump --verify %t.dSYM | FileCheck %s --check-prefix VERIFY #RUN: llvm-dwarfdump -a --verbose %t.dSYM | FileCheck %s -#COM: Uncomment next line when dwarfdump will handle stripped template names. -#COM: #VERIFY: No errors. +#VERIFY: No errors. #CHECK: .debug_names #CHECK: "foo"