Index: llvm/lib/DWARFLinker/DWARFLinker.cpp =================================================================== --- llvm/lib/DWARFLinker/DWARFLinker.cpp +++ llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -141,10 +141,33 @@ 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); + auto name = Info.Name.getString(); + + // If the name does not end with > we don't have a template. + if (name.endswith(">")) { + // If we have balanced < and > then we just have to find the first < to + // know where the template parameters start. + size_t num_left_angles_to_count = 1; + + // Unless we have the spaceship operator <=> then we need to skip that < + // as well. + num_left_angles_to_count += name.count("<=>"); + + size_t right_angle_count = name.count('>'); + size_t left_angle_count = name.count('<'); + + // If we are not balanced we either have one of the relational operators + // or shift operators overloaded. + if (left_angle_count > right_angle_count) + num_left_angles_to_count += left_angle_count - right_angle_count; + + size_t start_of_template = 0; + while (num_left_angles_to_count--) + start_of_template = name.find('<', start_of_template) + 1; + + Info.NameWithoutTemplate = + StringPool.getEntry(name.substr(0, start_of_template - 1)); + } } return Info.Name || Info.MangledName; Index: llvm/test/tools/dsymutil/X86/template_operators.test =================================================================== --- /dev/null +++ llvm/test/tools/dsymutil/X86/template_operators.test @@ -0,0 +1,36 @@ +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 +$ clang++ -g template_operators.cpp -c -o template_operators.o +$ clang template_operators.o -o template_operators +template +bool operator<(const T&, const T&){ + return true; +} + +template +bool operator<<(const T&, const T&){ + return true; +} + +template +bool operator==(const T&, const T&){ + return true; +} + +struct B{}; + +int main() { + B b1; + B b2; + + return b1 < b2 && b1 << b2 && b1 == b2; +} + + +NAMES-DAG: "operator<" +NAMES-DAG: "operator<<" +NAMES-DAG: "operator=="