[PATCH] D11297: PR17829: Functions declared extern "C" with a name matching a mangled C++ function are allowed

Andrey Bokhanko andreybokhanko at gmail.com
Fri Jul 17 07:26:48 PDT 2015


andreybokhanko created this revision.
andreybokhanko added reviewers: rjmccall, rsmith.
andreybokhanko added a subscriber: cfe-commits.

This patch fixes compiler crash described in the following thread: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2015-July/thread.html#43852. It also fixes incorrect behavior described in PR17829.

In essence, I inserted a check in GetAddrOfFunction that verifies that no two different declarations correspond to the same mangled name. Given that clang defers everything, this is the best suitable place I managed to find for the check. Also, the check makes sense only if one of declarations is a C++ method, as there are some kinds of non-C++ declarations that can correctly have the same mangled name (inline assembly inserts is an example).

Yours,
Andrey Bokhanko
============
Software Engineer
Intel Compiler Team
Intel


http://reviews.llvm.org/D11297

Files:
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CodeGenModule.cpp
  test/CodeGenCXX/duplicate-mangled-name.cpp

Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1666,6 +1666,21 @@
     Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType());
   
   StringRef MangledName = getMangledName(GD);
+
+  // Check that there are no declarations with the same mangled name. This check
+  // is valid only if one of declarations is a C++ method.
+  GlobalDecl OldGD;
+  if (lookupRepresentativeDecl(MangledName, OldGD) &&
+      (isa<CXXMethodDecl>(GD.getDecl()) ||
+       isa<CXXMethodDecl>(OldGD.getDecl())) &&
+      GD.getCanonicalDecl().getDecl() != OldGD.getCanonicalDecl().getDecl()) {
+    getDiags().Report(GD.getDecl()->getLocation(),
+                      diag::err_duplicate_mangled_name);
+    getDiags().Report(OldGD.getDecl()->getLocation(),
+                      diag::note_previous_definition);
+    return llvm::UndefValue::get(VoidPtrTy);
+  }
+
   return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer);
 }
 
@@ -2401,6 +2416,9 @@
     llvm::Constant *C =
         GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, /*DontDefer*/ true);
 
+    if (isa<llvm::UndefValue>(C))
+      return;
+
     // Strip off a bitcast if we got one back.
     if (auto *CE = dyn_cast<llvm::ConstantExpr>(C)) {
       assert(CE->getOpcode() == llvm::Instruction::BitCast);
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -3181,6 +3181,10 @@
   }
 
   llvm::Value *Callee = EmitScalarExpr(E->getCallee());
+
+  if (isa<llvm::UndefValue>(Callee))
+    return RValue::get(Callee);
+
   return EmitCall(E->getCallee()->getType(), Callee, E, ReturnValue,
                   TargetDecl);
 }
Index: test/CodeGenCXX/duplicate-mangled-name.cpp
===================================================================
--- test/CodeGenCXX/duplicate-mangled-name.cpp
+++ test/CodeGenCXX/duplicate-mangled-name.cpp
@@ -1,10 +1,31 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only %s -verify
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -DTEST1 %s -verify
+// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm-only -DTEST2 %s -verify
 
 // rdar://15522601
+#ifdef TEST1
 class MyClass {
  static void meth();
 };
 void MyClass::meth() { } // expected-note {{previous}}
 extern "C" {
   void _ZN7MyClass4methEv() { } // expected-error {{definition with same mangled name as another definition}}
 }
+
+#elif TEST2
+
+extern "C" void _ZN1TD1Ev(); // expected-error {{definition with same mangled name as another definition}}
+struct T {
+    ~T() {} // expected-note {{previous}}
+};
+
+int main() {
+  _ZN1TD1Ev();
+  T t;
+}
+
+#else
+
+#error Unknown test mode
+
+#endif
+


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D11297.30000.patch
Type: text/x-patch
Size: 2844 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150717/2e2cefe8/attachment.bin>


More information about the cfe-commits mailing list