[llvm] 3754946 - [dsymutil] Fix template stripping in getDIENames(...) to account for overloaded operators

via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 4 14:55:18 PST 2020


Author: shafik
Date: 2020-03-04T14:54:31-08:00
New Revision: 37549464c13e5f059925b9d8be1ea8e87711537e

URL: https://github.com/llvm/llvm-project/commit/37549464c13e5f059925b9d8be1ea8e87711537e
DIFF: https://github.com/llvm/llvm-project/commit/37549464c13e5f059925b9d8be1ea8e87711537e.diff

LOG: [dsymutil] Fix template stripping in getDIENames(...) to account for 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

Added: 
    llvm/test/tools/dsymutil/Inputs/private/tmp/templated_operators/template_operators
    llvm/test/tools/dsymutil/Inputs/private/tmp/templated_operators/template_operators.o
    llvm/test/tools/dsymutil/X86/template_operators.test

Modified: 
    llvm/lib/DWARFLinker/DWARFLinker.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index 2a957a2f82f1..66da6265ca53 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -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,
@@ -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;

diff  --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/templated_operators/template_operators b/llvm/test/tools/dsymutil/Inputs/private/tmp/templated_operators/template_operators
new file mode 100755
index 000000000000..caaf1c139412
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/templated_operators/template_operators 
diff er

diff  --git a/llvm/test/tools/dsymutil/Inputs/private/tmp/templated_operators/template_operators.o b/llvm/test/tools/dsymutil/Inputs/private/tmp/templated_operators/template_operators.o
new file mode 100644
index 000000000000..34fac2b84309
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/private/tmp/templated_operators/template_operators.o 
diff er

diff  --git a/llvm/test/tools/dsymutil/X86/template_operators.test b/llvm/test/tools/dsymutil/X86/template_operators.test
new file mode 100644
index 000000000000..339713612543
--- /dev/null
+++ b/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>"


        


More information about the llvm-commits mailing list