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
+


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
+
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to