Skip to content

Commit

Permalink
[dsymutil] Fix template stripping in getDIENames(...) to account for …
Browse files Browse the repository at this point in the history
…overloaded operators

Currently dsymutil when generating accelerator tables will attempt to strip the template parameters from names for subroutines.
For some overload operators which contain < in their names e.g. operator< the current method ends up stripping the operator name as well,
we just end up with the name operator in the table for each case.

Differential Revision: https://reviews.llvm.org/D75545
  • Loading branch information
shafik committed Mar 4, 2020
1 parent b019c5c commit 3754946
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 4 deletions.
38 changes: 34 additions & 4 deletions llvm/lib/DWARFLinker/DWARFLinker.cpp
Expand Up @@ -119,6 +119,37 @@ AddressesMap::~AddressesMap() {}

DwarfEmitter::~DwarfEmitter() {}

static Optional<StringRef> StripTemplateParameters(StringRef Name) {
// We are looking for template parameters to strip from Name. e.g.
//
// operator<<B>
//
// 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,
Expand All @@ -140,10 +171,9 @@ bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die,
Info.Name = StringPool.getEntry(Name);

if (StripTemplate && Info.Name && Info.MangledName != Info.Name) {
// FIXME: dsymutil compatibility. This is wrong for operator<
auto Split = Info.Name.getString().split('<');
if (!Split.second.empty())
Info.NameWithoutTemplate = StringPool.getEntry(Split.first);
StringRef Name = Info.Name.getString();
if (Optional<StringRef> StrippedName = StripTemplateParameters(Name))
Info.NameWithoutTemplate = StringPool.getEntry(*StrippedName);
}

return Info.Name || Info.MangledName;
Expand Down
Binary file not shown.
Binary file not shown.
62 changes: 62 additions & 0 deletions llvm/test/tools/dsymutil/X86/template_operators.test
@@ -0,0 +1,62 @@
RUN: dsymutil -oso-prepend-path %p/../Inputs %p/../Inputs/private/tmp/templated_operators/template_operators -o %t.apple.dSYM

RUN: llvm-dwarfdump -apple-names %t.apple.dSYM | FileCheck %s -check-prefix=NAMES

The test was compiled from a single source:
$ cat template_operators.cpp
template <typename T>
bool operator<(const T&, const T&){
return true;
}

template <typename T>
bool operator>(const T&, const T&){
return true;
}

template <typename T>
bool operator<<(const T&, const T&){
return true;
}

template <typename T>
bool operator>>(const T&, const T&){
return true;
}

template <typename T>
bool operator==(const T&, const T&){
return true;
}

struct B{};

struct D{};

template <typename T>
bool operator<=>(const T&,const T&){ return true;}

int main() {
B b1;
B b2;
D d1;
D d2;

return b1 < b2 && b1 > b2 && b1 << b2 && b1 >> b2 && b1 == b2 && d1 <=> d2;
}
$ clang++ -std=c++2a -g template_operators.cpp -c -o template_operators.o
$ clang template_operators.o -o template_operators


NAMES-DAG: "operator<"
NAMES-DAG: "operator<<B>"
NAMES-DAG: "operator>"
NAMES-DAG: "operator><B>"
NAMES-DAG: "operator<<"
NAMES-DAG: "operator<<<B>"
NAMES-DAG: "operator>>"
NAMES-DAG: "operator>><B>"
NAMES-DAG: "operator<=>"
NAMES-DAG: "operator<=><D>"
NAMES-DAG: "operator=="
NAMES-DAG: "operator==<B>"

0 comments on commit 3754946

Please sign in to comment.