]> granicus.if.org Git - clang/commitdiff
Keep the old function order in CodeGenModule::applyReplacements.
authorRafael Espindola <rafael.espindola@gmail.com>
Sun, 10 Nov 2013 19:04:30 +0000 (19:04 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sun, 10 Nov 2013 19:04:30 +0000 (19:04 +0000)
The original decls are created when used. The replacements are created at the
end of the TU in reverse order.

This makes the original order far better for testing. This is particularly
important since the replacement logic could be used even when
-mconstructor-aliases is not used, but that would make many tests hard to read.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194357 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenModule.cpp
test/CodeGenCXX/destructors.cpp

index 74f3bbb04598fb0dad0f4547fd105940a5032329..ee700807437678baca026ff86e29af995f623e5b 100644 (file)
@@ -181,8 +181,20 @@ 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 = cast<llvm::Function>(CE->getOperand(0));
+    }
+
+    // Replace old with new, but keep the old order.
+    OldF->replaceAllUsesWith(Replacement);
+    NewF->removeFromParent();
+    OldF->getParent()->getFunctionList().insertAfter(OldF, NewF);
+    OldF->eraseFromParent();
   }
 }
 
index 5b29ce5de4b11834eb92233c243fc91cbfcc4a71..59c97b7dca9117d2e03a3f7450fcbff880d288aa 100644 (file)
@@ -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(