summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp18
-rw-r--r--clang/test/CodeGenCXX/destructors.cpp16
2 files changed, 24 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 74f3bbb0459..1f2f4bbde3c 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -181,8 +181,22 @@ void CodeGenModule::applyReplacements() {
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (!Entry)
continue;
- Entry->replaceAllUsesWith(Replacement);
- Entry->eraseFromParent();
+ llvm::Function *OldF = cast<llvm::Function>(Entry);
+ llvm::Function *NewF = dyn_cast<llvm::Function>(Replacement);
+ if (!NewF) {
+ llvm::ConstantExpr *CE = cast<llvm::ConstantExpr>(Replacement);
+ assert(CE->getOpcode() == llvm::Instruction::BitCast ||
+ CE->getOpcode() == llvm::Instruction::GetElementPtr);
+ NewF = dyn_cast<llvm::Function>(CE->getOperand(0));
+ }
+
+ // Replace old with new, but keep the old order.
+ OldF->replaceAllUsesWith(Replacement);
+ if (NewF) {
+ NewF->removeFromParent();
+ OldF->getParent()->getFunctionList().insertAfter(OldF, NewF);
+ }
+ OldF->eraseFromParent();
}
}
diff --git a/clang/test/CodeGenCXX/destructors.cpp b/clang/test/CodeGenCXX/destructors.cpp
index 5b29ce5de4b..59c97b7dca9 100644
--- a/clang/test/CodeGenCXX/destructors.cpp
+++ b/clang/test/CodeGenCXX/destructors.cpp
@@ -36,13 +36,13 @@ namespace PR7526 {
struct allocator_derived : allocator { };
+ // CHECK-LABEL: define void @_ZN6PR75263fooEv()
+ // CHECK: call void {{.*}} @_ZN6PR75269allocatorD2Ev
+
// CHECK-LABEL: define void @_ZN6PR75269allocatorD2Ev(%"struct.PR7526::allocator"* %this) unnamed_addr
// CHECK: call void @__cxa_call_unexpected
allocator::~allocator() throw() { foo(); }
- // CHECK-LABEL: define void @_ZN6PR75263fooEv()
- // CHECK: call void {{.*}} @_ZN6PR75269allocatorD2Ev
-
void foo() {
allocator_derived ad;
}
@@ -393,16 +393,16 @@ namespace test10 {
// CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev(
// CHECK: ret void
- // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
- // CHECK: invoke void @_ZN5test31BD2Ev(
- // CHECK: call void @_ZN5test31AD2Ev(
- // CHECK: ret void
-
// CHECK-LABEL: define internal void @_ZThn8_N5test312_GLOBAL__N_11CD1Ev(
// CHECK: getelementptr inbounds i8* {{.*}}, i64 -8
// CHECK: call void @_ZN5test312_GLOBAL__N_11CD2Ev(
// CHECK: ret void
+ // CHECK-LABEL: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev(%"struct.test3::<anonymous namespace>::C"* %this) unnamed_addr
+ // CHECK: invoke void @_ZN5test31BD2Ev(
+ // CHECK: call void @_ZN5test31AD2Ev(
+ // CHECK: ret void
+
// CHECK: declare void @_ZN5test31BD2Ev(
// CHECK: declare void @_ZN5test31AD2Ev(
OpenPOWER on IntegriCloud