[PATCH] D69650: [ELF] Suggest extern "C" when the definition is mangled while an undefined reference is not

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 8 09:49:48 PST 2019


This revision was automatically updated to reflect the committed changes.
Closed by commit rG59d3fbc227cc: [ELF] Suggest extern "C" when the definition is mangled while an undefined… (authored by MaskRay).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69650/new/

https://reviews.llvm.org/D69650

Files:
  lld/ELF/Relocations.cpp
  lld/test/ELF/undef-suggest-extern-c2.s


Index: lld/test/ELF/undef-suggest-extern-c2.s
===================================================================
--- /dev/null
+++ lld/test/ELF/undef-suggest-extern-c2.s
@@ -0,0 +1,21 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+
+## The definition is mangled while the reference is not, suggest an arbitrary
+## C++ overload.
+# RUN: echo '.globl _Z3fooi; _Z3fooi:' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o
+# RUN: not ld.lld %t.o %t1.o -o /dev/null 2>&1 | FileCheck %s
+
+## Check that we can suggest a local definition.
+# RUN: echo '_Z3fooi: call foo' | llvm-mc -filetype=obj -triple=x86_64 - -o %t2.o
+# RUN: not ld.lld %t2.o -o /dev/null 2>&1 | FileCheck %s
+
+# CHECK:      error: undefined symbol: foo
+# CHECK-NEXT: >>> referenced by {{.*}}
+# CHECK-NEXT: >>> did you mean to declare foo(int) as extern "C"?
+
+## Don't suggest nested names whose base name is "foo", e.g. F::foo().
+# RUN: echo '.globl _ZN1F3fooEv; _ZN1F3fooEv:' | llvm-mc -filetype=obj -triple=x86_64 - -o %t3.o
+# RUN: not ld.lld %t.o %t3.o -o /dev/null 2>&1 | FileCheck /dev/null --implicit-check-not='did you mean'
+
+call foo
Index: lld/ELF/Relocations.cpp
===================================================================
--- lld/ELF/Relocations.cpp
+++ lld/ELF/Relocations.cpp
@@ -697,11 +697,26 @@
 
 static std::vector<UndefinedDiag> undefs;
 
+// Check whether the definition name def is a mangled function name that matches
+// the reference name ref.
+static bool canSuggestExternCForCXX(StringRef ref, StringRef def) {
+  llvm::ItaniumPartialDemangler d;
+  if (d.partialDemangle(def.str().c_str()))
+    return false;
+  char *buf = d.getFunctionName(nullptr, nullptr);
+  if (!buf)
+    return false;
+  bool ret = ref == buf;
+  free(buf);
+  return ret;
+}
+
 // Suggest an alternative spelling of an "undefined symbol" diagnostic. Returns
 // the suggested symbol, which is either in the symbol table, or in the same
 // file of sym.
 static const Symbol *getAlternativeSpelling(const Undefined &sym,
-                                            std::string &pre_hint) {
+                                            std::string &pre_hint,
+                                            std::string &post_hint) {
   // Build a map of local defined symbols.
   DenseMap<StringRef, const Symbol *> map;
   if (sym.file && !isa<SharedFile>(sym.file)) {
@@ -774,6 +789,23 @@
           return s;
         }
       }
+  } else {
+    const Symbol *s = nullptr;
+    for (auto &it : map)
+      if (canSuggestExternCForCXX(name, it.first)) {
+        s = it.second;
+        break;
+      }
+    if (!s)
+      symtab->forEachSymbol([&](Symbol *sym) {
+        if (!s && canSuggestExternCForCXX(name, sym->getName()))
+          s = sym;
+      });
+    if (s) {
+      pre_hint = " to declare ";
+      post_hint = " as extern \"C\"?";
+      return s;
+    }
   }
 
   return nullptr;
@@ -822,10 +854,10 @@
                .str();
 
   if (correctSpelling) {
-    std::string pre_hint = ": ";
+    std::string pre_hint = ": ", post_hint;
     if (const Symbol *corrected =
-            getAlternativeSpelling(cast<Undefined>(sym), pre_hint)) {
-      msg += "\n>>> did you mean" + pre_hint + toString(*corrected);
+            getAlternativeSpelling(cast<Undefined>(sym), pre_hint, post_hint)) {
+      msg += "\n>>> did you mean" + pre_hint + toString(*corrected) + post_hint;
       if (corrected->file)
         msg += "\n>>> defined in: " + toString(corrected->file);
     }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D69650.228480.patch
Type: text/x-patch
Size: 3510 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191108/1ed48c29/attachment.bin>


More information about the llvm-commits mailing list