rsmith updated this revision to Diff 175791.
rsmith added a comment.

- Do not emit unused discardable vtables.


Repository:
  rC Clang

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

https://reviews.llvm.org/D54986

Files:
  lib/AST/ASTContext.cpp
  lib/AST/RecordLayoutBuilder.cpp
  lib/CodeGen/CGCXX.cpp
  lib/CodeGen/CGCXXABI.h
  lib/CodeGen/CGVTables.cpp
  lib/CodeGen/CodeGenAction.cpp
  lib/CodeGen/CodeGenModule.cpp
  lib/CodeGen/CodeGenModule.h
  lib/CodeGen/ItaniumCXXABI.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/CodeGen/ModuleBuilder.cpp
  lib/Serialization/ASTReaderDecl.cpp
  test/CodeGenCXX/aarch64-cxxabi.cpp
  test/CodeGenCXX/dllimport.cpp
  test/CodeGenCXX/key-function-vtable.cpp
  test/CodeGenCXX/rtti-linkage.cpp
  test/CodeGenCXX/type_visibility.cpp
  test/CodeGenCXX/visibility.cpp
  test/CodeGenCXX/vtable-assume-load.cpp
  test/CodeGenCXX/vtt-layout.cpp

Index: test/CodeGenCXX/vtt-layout.cpp
===================================================================
--- test/CodeGenCXX/vtt-layout.cpp
+++ test/CodeGenCXX/vtt-layout.cpp
@@ -78,12 +78,12 @@
   }
 }
 
-// CHECK: @_ZTTN5Test11BE = unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTVN5Test11BE, i32 0, inrange i32 0, i32 3) to i8*)]
-// CHECK: @_ZTVN5Test51AE = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test51AE to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*), i8* bitcast (void (%"struct.Test5::A"*)* @_ZN5Test51A6anchorEv to i8*)] }
-// CHECK: @_ZTVN5Test61AE = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test61AE to i8*), i8* bitcast (void ()* @__cxa_deleted_virtual to i8*), i8* bitcast (void (%"struct.Test6::A"*)* @_ZN5Test61A6anchorEv to i8*)] }
-// CHECK: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4) to i8*)]
-// CHECK: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 0, i32 5) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 1, i32 3) to i8*)]
-// CHECK: @_ZTVN5Test41DE = linkonce_odr unnamed_addr constant { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] } { [6 x i8*] [i8* inttoptr (i64 72 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 56 to i8*), i8* inttoptr (i64 40 to i8*), i8* null, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)], [8 x i8*] [i8* inttoptr (i64 40 to i8*), i8* inttoptr (i64 24 to i8*), i8* inttoptr (i64 56 to i8*), i8* null, i8* null, i8* inttoptr (i64 -16 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*), i8* bitcast (void (%"class.Test4::V3"*)* @_ZN5Test42V31gEv to i8*)], [3 x i8*] [i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -40 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)], [4 x i8*] [i8* null, i8* inttoptr (i64 -56 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*), i8* bitcast (void (%"class.Test4::A2"*)* @_ZN5Test42A21fEv to i8*)], [4 x i8*] [i8* inttoptr (i64 -16 to i8*), i8* inttoptr (i64 -32 to i8*), i8* inttoptr (i64 -72 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)] }
-// CHECK: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 1, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 4, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 2, i32 3) to i8*)]
+// CHECK-DAG: @_ZTTN5Test11BE = unnamed_addr constant [1 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*] }, { [4 x i8*] }* @_ZTVN5Test11BE, i32 0, inrange i32 0, i32 3) to i8*)]
+// CHECK-DAG: @_ZTVN5Test51AE = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test51AE to i8*), i8* bitcast (void ()* @__cxa_pure_virtual to i8*), i8* bitcast (void (%"struct.Test5::A"*)* @_ZN5Test51A6anchorEv to i8*)] }
+// CHECK-DAG: @_ZTVN5Test61AE = unnamed_addr constant { [4 x i8*] } { [4 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTIN5Test61AE to i8*), i8* bitcast (void ()* @__cxa_deleted_virtual to i8*), i8* bitcast (void (%"struct.Test6::A"*)* @_ZN5Test61A6anchorEv to i8*)] }
+// CHECK-DAG: @_ZTTN5Test21CE = linkonce_odr unnamed_addr constant [2 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*] }, { [5 x i8*] }* @_ZTVN5Test21CE, i32 0, inrange i32 0, i32 4) to i8*)]
+// CHECK-DAG: @_ZTTN5Test31DE = linkonce_odr unnamed_addr constant [13 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 0, i32 5) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE0_NS_2C1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [7 x i8*], [3 x i8*], [4 x i8*] }, { [7 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE16_NS_2C2E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 1, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }, { [5 x i8*], [7 x i8*], [4 x i8*], [3 x i8*] }* @_ZTVN5Test31DE, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test31DE64_NS_2V2E, i32 0, inrange i32 1, i32 3) to i8*)]
+// CHECK-DAG: @_ZTVN5Test41DE = linkonce_odr unnamed_addr constant { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] } { [6 x i8*] [i8* inttoptr (i64 72 to i8*), i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 56 to i8*), i8* inttoptr (i64 40 to i8*), i8* null, i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)], [8 x i8*] [i8* inttoptr (i64 40 to i8*), i8* inttoptr (i64 24 to i8*), i8* inttoptr (i64 56 to i8*), i8* null, i8* null, i8* inttoptr (i64 -16 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*), i8* bitcast (void (%"class.Test4::V3"*)* @_ZN5Test42V31gEv to i8*)], [3 x i8*] [i8* inttoptr (i64 16 to i8*), i8* inttoptr (i64 -40 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)], [4 x i8*] [i8* null, i8* inttoptr (i64 -56 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*), i8* bitcast (void (%"class.Test4::A2"*)* @_ZN5Test42A21fEv to i8*)], [4 x i8*] [i8* inttoptr (i64 -16 to i8*), i8* inttoptr (i64 -32 to i8*), i8* inttoptr (i64 -72 to i8*), i8* bitcast ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64, i8*, i64 }* @_ZTIN5Test41DE to i8*)] }
+// CHECK-DAG: @_ZTTN5Test41DE = linkonce_odr unnamed_addr constant [19 x i8*] [i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 0, i32 6) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE0_NS_2C1E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 0, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 1, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }, { [8 x i8*], [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE16_NS_2C2E, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 2, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 3, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 1, i32 7) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }, { [6 x i8*], [8 x i8*], [3 x i8*], [4 x i8*], [4 x i8*] }* @_ZTVN5Test41DE, i32 0, inrange i32 4, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 0, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [3 x i8*], [4 x i8*] }, { [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE40_NS_2V1E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 0, i32 4) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 1, i32 3) to i8*), i8* bitcast (i8** getelementptr inbounds ({ [4 x i8*], [3 x i8*], [4 x i8*] }, { [4 x i8*], [3 x i8*], [4 x i8*] }* @_ZTCN5Test41DE72_NS_2V2E, i32 0, inrange i32 2, i32 3) to i8*)]
 // CHECK: declare void @__cxa_pure_virtual() unnamed_addr
 // CHECK: declare void @__cxa_deleted_virtual() unnamed_addr
Index: test/CodeGenCXX/vtable-assume-load.cpp
===================================================================
--- test/CodeGenCXX/vtable-assume-load.cpp
+++ test/CodeGenCXX/vtable-assume-load.cpp
@@ -237,7 +237,7 @@
   void bar();
 };
 
-// CHECK8-DAG: @_ZTVN5test81CE = linkonce_odr unnamed_addr constant
+// CHECK8-NOT: @_ZTVN5test81CE
 struct C : A {
   C();
   void bar();
@@ -266,8 +266,8 @@
 }
 
 // FIXME: C has inline virtual functions which prohibits as from generating
-// assumption loads, but because vtable is generated in this TU (key function
-// defined here) it would be correct to refer to it.
+// assumption loads, but because vtable can be generated in this TU (key
+// function defined here) it would be correct to refer to it.
 // CHECK8-LABEL: define void @_ZN5test81cEv()
 // CHECK8-NOT: call void @llvm.assume(
 // CHECK8-LABEL: {{^}}}
Index: test/CodeGenCXX/visibility.cpp
===================================================================
--- test/CodeGenCXX/visibility.cpp
+++ test/CodeGenCXX/visibility.cpp
@@ -101,6 +101,25 @@
   // CHECK-HIDDEN: _ZN6test481yE = hidden global
 }
 
+namespace test27 {
+  template<typename T>
+  class C {
+    class DEFAULT D {
+      void f();
+    };
+  };
+
+  template<>
+  class C<int>::D {
+    virtual void g();
+  };
+
+  void C<int>::D::g() {
+  }
+  // CHECK: _ZTVN6test271CIiE1DE = unnamed_addr constant
+  // CHECK-HIDDEN: _ZTVN6test271CIiE1DE = unnamed_addr constant
+}
+
 // CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10
 // CHECK: @_ZN5Test71aE = hidden global
 // CHECK: @_ZN5Test71bE = global
@@ -119,25 +138,6 @@
 // CHECK: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8]
 // CHECK-HIDDEN: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8]
 
-namespace test27 {
-  template<typename T>
-  class C {
-    class DEFAULT D {
-      void f();
-    };
-  };
-
-  template<>
-  class C<int>::D {
-    virtual void g();
-  };
-
-  void C<int>::D::g() {
-  }
-  // CHECK: _ZTVN6test271CIiE1DE = unnamed_addr constant
-  // CHECK-HIDDEN: _ZTVN6test271CIiE1DE = unnamed_addr constant
-}
-
 // CHECK: @_ZTVN5Test63fooE = linkonce_odr hidden unnamed_addr constant
 
 // CHECK-HIDDEN: @_ZTVN6Test161AIcEE = external unnamed_addr constant
Index: test/CodeGenCXX/type_visibility.cpp
===================================================================
--- test/CodeGenCXX/type_visibility.cpp
+++ test/CodeGenCXX/type_visibility.cpp
@@ -27,13 +27,13 @@
 
   template struct B<A>;
   // FUNS-LABEL:        define weak_odr void @_ZN5temp01BINS_1AEE3fooEv(
-  // VARS:        @_ZTVN5temp01BINS_1AEEE = weak_odr unnamed_addr constant
-  // VARS:        @_ZTSN5temp01BINS_1AEEE = weak_odr constant
-  // VARS:        @_ZTIN5temp01BINS_1AEEE = weak_odr constant
+  // VARS-DAG:          @_ZTVN5temp01BINS_1AEEE = weak_odr unnamed_addr constant
+  // VARS-DAG:          @_ZTSN5temp01BINS_1AEEE = weak_odr constant
+  // VARS-DAG:          @_ZTIN5temp01BINS_1AEEE = weak_odr constant
   // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp01BINS_1AEE3fooEv(
-  // VARS-HIDDEN: @_ZTVN5temp01BINS_1AEEE = weak_odr hidden unnamed_addr constant
-  // VARS-HIDDEN: @_ZTSN5temp01BINS_1AEEE = weak_odr hidden constant
-  // VARS-HIDDEN: @_ZTIN5temp01BINS_1AEEE = weak_odr hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTVN5temp01BINS_1AEEE = weak_odr hidden unnamed_addr constant
+  // VARS-HIDDEN-DAG:   @_ZTSN5temp01BINS_1AEEE = weak_odr hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTIN5temp01BINS_1AEEE = weak_odr hidden constant
 }
 
 namespace temp1 {
@@ -44,13 +44,13 @@
 
   template struct B<A>;
   // FUNS-LABEL:        define weak_odr void @_ZN5temp11BINS_1AEE3fooEv(
-  // VARS:        @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
-  // VARS:        @_ZTSN5temp11BINS_1AEEE = weak_odr constant
-  // VARS:        @_ZTIN5temp11BINS_1AEEE = weak_odr constant
+  // VARS-DAG:          @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
+  // VARS-DAG:          @_ZTSN5temp11BINS_1AEEE = weak_odr constant
+  // VARS-DAG:          @_ZTIN5temp11BINS_1AEEE = weak_odr constant
   // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp11BINS_1AEE3fooEv(
-  // VARS-HIDDEN: @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
-  // VARS-HIDDEN: @_ZTSN5temp11BINS_1AEEE = weak_odr constant
-  // VARS-HIDDEN: @_ZTIN5temp11BINS_1AEEE = weak_odr constant
+  // VARS-HIDDEN-DAG:   @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant
+  // VARS-HIDDEN-DAG:   @_ZTSN5temp11BINS_1AEEE = weak_odr constant
+  // VARS-HIDDEN-DAG:   @_ZTIN5temp11BINS_1AEEE = weak_odr constant
 }
 
 namespace temp2 {
@@ -61,13 +61,13 @@
 
   template struct B<A>;
   // FUNS-LABEL:        define weak_odr void @_ZN5temp21BINS_1AEE3fooEv(
-  // VARS:        @_ZTVN5temp21BINS_1AEEE = weak_odr unnamed_addr constant
-  // VARS:        @_ZTSN5temp21BINS_1AEEE = weak_odr constant
-  // VARS:        @_ZTIN5temp21BINS_1AEEE = weak_odr constant
+  // VARS-DAG:          @_ZTVN5temp21BINS_1AEEE = weak_odr unnamed_addr constant
+  // VARS-DAG:          @_ZTSN5temp21BINS_1AEEE = weak_odr constant
+  // VARS-DAG:          @_ZTIN5temp21BINS_1AEEE = weak_odr constant
   // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp21BINS_1AEE3fooEv(
-  // VARS-HIDDEN: @_ZTVN5temp21BINS_1AEEE = weak_odr hidden unnamed_addr constant
-  // VARS-HIDDEN: @_ZTSN5temp21BINS_1AEEE = weak_odr hidden constant
-  // VARS-HIDDEN: @_ZTIN5temp21BINS_1AEEE = weak_odr hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTVN5temp21BINS_1AEEE = weak_odr hidden unnamed_addr constant
+  // VARS-HIDDEN-DAG:   @_ZTSN5temp21BINS_1AEEE = weak_odr hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTIN5temp21BINS_1AEEE = weak_odr hidden constant
 }
 
 namespace temp3 {
@@ -78,13 +78,13 @@
 
   template struct B<A>;
   // FUNS-LABEL:        define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv(
-  // VARS:        @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
-  // VARS:        @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
-  // VARS:        @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant
+  // VARS-DAG:          @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
+  // VARS-DAG:          @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
+  // VARS-DAG:          @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant
   // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv(
-  // VARS-HIDDEN: @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
-  // VARS-HIDDEN: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
-  // VARS-HIDDEN: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant
+  // VARS-HIDDEN-DAG:   @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant
 }
 
 namespace temp4 {
@@ -95,13 +95,13 @@
 
   template struct B<A>;
   // FUNS-LABEL:        define weak_odr void @_ZN5temp41BINS_1AEE3fooEv(
-  // VARS:        @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
-  // VARS:        @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
-  // VARS:        @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant
+  // VARS-DAG:          @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
+  // VARS-DAG:          @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
+  // VARS-DAG:          @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant
   // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp41BINS_1AEE3fooEv(
-  // VARS-HIDDEN: @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
-  // VARS-HIDDEN: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
-  // VARS-HIDDEN: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant
+  // VARS-HIDDEN-DAG:   @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant
 }
 
 namespace type0 {
@@ -111,13 +111,13 @@
 
   void A::foo() {}
   // FUNS-LABEL:        define void @_ZN5type01A3fooEv(
-  // VARS:        @_ZTVN5type01AE = unnamed_addr constant
-  // VARS:        @_ZTSN5type01AE = constant
-  // VARS:        @_ZTIN5type01AE = constant
+  // VARS-DAG:          @_ZTVN5type01AE = unnamed_addr constant
+  // VARS-DAG:          @_ZTSN5type01AE = constant
+  // VARS-DAG:          @_ZTIN5type01AE = constant
   // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type01A3fooEv(
-  // VARS-HIDDEN: @_ZTVN5type01AE = unnamed_addr constant
-  // VARS-HIDDEN: @_ZTSN5type01AE = constant
-  // VARS-HIDDEN: @_ZTIN5type01AE = constant
+  // VARS-HIDDEN-DAG:   @_ZTVN5type01AE = unnamed_addr constant
+  // VARS-HIDDEN-DAG:   @_ZTSN5type01AE = constant
+  // VARS-HIDDEN-DAG:   @_ZTIN5type01AE = constant
 }
 
 namespace type1 {
@@ -127,13 +127,13 @@
 
   void A::foo() {}
   // FUNS-LABEL:        define hidden void @_ZN5type11A3fooEv(
-  // VARS:        @_ZTVN5type11AE = unnamed_addr constant
-  // VARS:        @_ZTSN5type11AE = constant
-  // VARS:        @_ZTIN5type11AE = constant
+  // VARS-DAG:          @_ZTVN5type11AE = unnamed_addr constant
+  // VARS-DAG:          @_ZTSN5type11AE = constant
+  // VARS-DAG:          @_ZTIN5type11AE = constant
   // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type11A3fooEv(
-  // VARS-HIDDEN: @_ZTVN5type11AE = unnamed_addr constant
-  // VARS-HIDDEN: @_ZTSN5type11AE = constant
-  // VARS-HIDDEN: @_ZTIN5type11AE = constant
+  // VARS-HIDDEN-DAG:   @_ZTVN5type11AE = unnamed_addr constant
+  // VARS-HIDDEN-DAG:   @_ZTSN5type11AE = constant
+  // VARS-HIDDEN-DAG:   @_ZTIN5type11AE = constant
 }
 
 namespace type2 {
@@ -143,13 +143,13 @@
 
   void A::foo() {}
   // FUNS-LABEL:        define void @_ZN5type21A3fooEv(
-  // VARS:        @_ZTVN5type21AE = hidden unnamed_addr constant
-  // VARS:        @_ZTSN5type21AE = hidden constant
-  // VARS:        @_ZTIN5type21AE = hidden constant
+  // VARS-DAG:          @_ZTVN5type21AE = hidden unnamed_addr constant
+  // VARS-DAG:          @_ZTSN5type21AE = hidden constant
+  // VARS-DAG:          @_ZTIN5type21AE = hidden constant
   // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type21A3fooEv(
-  // VARS-HIDDEN: @_ZTVN5type21AE = hidden unnamed_addr constant
-  // VARS-HIDDEN: @_ZTSN5type21AE = hidden constant
-  // VARS-HIDDEN: @_ZTIN5type21AE = hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTVN5type21AE = hidden unnamed_addr constant
+  // VARS-HIDDEN-DAG:   @_ZTSN5type21AE = hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTIN5type21AE = hidden constant
 }
 
 namespace type3 {
@@ -159,12 +159,12 @@
 
   void A::foo() {}
   // FUNS-LABEL:        define void @_ZN5type31A3fooEv(
-  // VARS:        @_ZTVN5type31AE = hidden unnamed_addr constant
-  // VARS:        @_ZTSN5type31AE = hidden constant
-  // VARS:        @_ZTIN5type31AE = hidden constant
+  // VARS-DAG:          @_ZTVN5type31AE = hidden unnamed_addr constant
+  // VARS-DAG:          @_ZTSN5type31AE = hidden constant
+  // VARS-DAG:          @_ZTIN5type31AE = hidden constant
   // FUNS-HIDDEN-LABEL: define void @_ZN5type31A3fooEv(
-  // VARS-HIDDEN: @_ZTVN5type31AE = hidden unnamed_addr constant
-  // VARS-HIDDEN: @_ZTSN5type31AE = hidden constant
-  // VARS-HIDDEN: @_ZTIN5type31AE = hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTVN5type31AE = hidden unnamed_addr constant
+  // VARS-HIDDEN-DAG:   @_ZTSN5type31AE = hidden constant
+  // VARS-HIDDEN-DAG:   @_ZTIN5type31AE = hidden constant
 }
 
Index: test/CodeGenCXX/rtti-linkage.cpp
===================================================================
--- test/CodeGenCXX/rtti-linkage.cpp
+++ test/CodeGenCXX/rtti-linkage.cpp
@@ -115,6 +115,7 @@
 };
 
 inline void F::f() { }
+void *use_vtable() { return new F; }
 const D getD();
 
 const std::type_info &t2() {
Index: test/CodeGenCXX/key-function-vtable.cpp
===================================================================
--- test/CodeGenCXX/key-function-vtable.cpp
+++ test/CodeGenCXX/key-function-vtable.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-none-linux-gnu %s -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 -triple arm-apple-darwin %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-none-linux-gnu %s -emit-llvm -o - | FileCheck %s --implicit-check-not=@_ZTV5testc --implicit-check-not=@_ZTV5testh
+// RUN: %clang_cc1 -triple arm-apple-darwin %s -emit-llvm -o - | FileCheck %s --implicit-check-not=@_ZTV5testc --implicit-check-not=@_ZTV5testh
 
 // Simple key function test
 struct testa { virtual void a(); };
@@ -10,6 +10,7 @@
 testb *testbvar = new testb;
 
 // Key function with out-of-line inline definition
+// vtable is discardable and unused, so is not emitted.
 struct testc { virtual void a(); };
 inline void testc::a() {}
 
@@ -34,6 +35,18 @@
 void testg::a() {}
 testg *testgvar = new testg;
 
+// Key function with out-of-line inline definition
+// vtable is discardable and unused, so is not emitted even though key function is.
+struct testh { virtual void a(); void b(); };
+inline void testh::a() {}
+void testh::b() { testh::a(); }
+
+// Key function with out-of-line inline definition
+// VTable is used, so is emitted.
+struct testi { virtual void a(); };
+inline void testi::a() {}
+void use_i() { testi ti; }
+
 struct X0 { virtual ~X0(); };
 struct X1 : X0 {
   virtual void f();
@@ -45,7 +58,7 @@
 
 // CHECK-DAG: @_ZTV2X1 = linkonce_odr unnamed_addr constant
 // CHECK-DAG: @_ZTV5testa = unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
-// CHECK-DAG: @_ZTV5testc = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
 // CHECK-DAG: @_ZTV5testb = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
 // CHECK-DAG: @_ZTV5teste = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
 // CHECK-DAG: @_ZTVN12_GLOBAL__N_15testgE = internal unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
+// CHECK-DAG: @_ZTV5testi = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null
Index: test/CodeGenCXX/dllimport.cpp
===================================================================
--- test/CodeGenCXX/dllimport.cpp
+++ test/CodeGenCXX/dllimport.cpp
@@ -769,11 +769,20 @@
     virtual ~S();
   };
   S::~S() {}
+  void *use_S_vtable() { return new S; }
 
   // S::~S is a key function, so we would ordinarily emit a strong definition for
-  // the vtable. However, S is imported, so the vtable should be too.
+  // the vtable. However, S is imported, so the vtable should be too (if it's
+  // emitted at all.)
 
   // GNU-DAG: @_ZTVN7PR213551SE = available_externally dllimport unnamed_addr constant { [4 x i8*] }
+
+  // If the vtable isn't needed in this case, it won't be emitted at all.
+  struct __declspec(dllimport) T {
+    virtual ~T();
+  };
+  T::~T() {}
+  // GNU-NOT: @_ZTVN7PR213551TE
 }
 
 namespace PR21366 {
Index: test/CodeGenCXX/aarch64-cxxabi.cpp
===================================================================
--- test/CodeGenCXX/aarch64-cxxabi.cpp
+++ test/CodeGenCXX/aarch64-cxxabi.cpp
@@ -16,16 +16,40 @@
 // (see next section for explanation of guard)
 // CHECK: @_ZGVZ15guard_variablesiE4mine = internal global i64 0
 
-// CHECK: @_ZTV16CheckKeyFunction =
+// An inline key function is not sufficient to trigger vtable emission: the
+// corresponding vtable symbol would be discardable, so we only actually emit
+// it if it would be referenced.
+// CHECK-NOT: @_ZTV22CheckKeyFunctionUnused =
+struct CheckKeyFunctionUnused {
+  virtual void foo();
+};
+inline void CheckKeyFunctionUnused::foo() {
+}
+
+// The same applies even if an inline key function is emitted.
+// CHECK-NOT: @_ZTV16CheckKeyFunction =
 struct CheckKeyFunction {
   virtual void foo();
+  void bar();
 };
-
-// This is not inline when CheckKeyFunction is completed, so
-// CheckKeyFunction::foo is the key function. VTables should be emitted.
 inline void CheckKeyFunction::foo() {
 }
 
+void CheckKeyFunction::bar() {
+  // Explicit use triggers emission of foo, which triggers emission of vtable.
+  CheckKeyFunction::foo();
+}
+
+// CHECK: @_ZTV14CheckVTableUse =
+// Check that using the vtable is enough to trigger emission of the key
+// function and thus the vtable.
+struct CheckVTableUse {
+  virtual void foo();
+};
+inline void CheckVTableUse::foo() {
+}
+void *useVTable() { return new CheckVTableUse; }
+
 ////////////////////////////////////////////////////////////////////////////////
 
 // Guard variables only specify and use the low bit to determine status, rather
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp
+++ lib/Serialization/ASTReaderDecl.cpp
@@ -2771,6 +2771,10 @@
       return false;
   }
 
+  if (auto *ES = D->getASTContext().getExternalSource())
+    if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
+      return true;
+
   if (isa<FileScopeAsmDecl>(D) ||
       isa<ObjCProtocolDecl>(D) ||
       isa<ObjCImplDecl>(D) ||
@@ -2786,10 +2790,9 @@
             OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Var));
   if (const auto *Func = dyn_cast<FunctionDecl>(D))
     return Func->doesThisDeclarationHaveABody() || HasBody;
-
-  if (auto *ES = D->getASTContext().getExternalSource())
-    if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
-      return true;
+  if (const auto *RD = dyn_cast<CXXRecordDecl>(D))
+    return RD->getTemplateSpecializationKind() ==
+           TSK_ExplicitInstantiationDefinition;
 
   return false;
 }
Index: lib/CodeGen/ModuleBuilder.cpp
===================================================================
--- lib/CodeGen/ModuleBuilder.cpp
+++ lib/CodeGen/ModuleBuilder.cpp
@@ -276,13 +276,6 @@
 
       Builder->EmitTentativeDefinition(D);
     }
-
-    void HandleVTable(CXXRecordDecl *RD) override {
-      if (Diags.hasErrorOccurred())
-        return;
-
-      Builder->EmitVTable(RD);
-    }
   };
 }
 
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -292,6 +292,8 @@
   llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
                                         CharUnits VPtrOffset) override;
 
+  void emitVTables(const CXXRecordDecl *RD) override;
+
   CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
                                      Address This, llvm::Type *Ty,
                                      SourceLocation Loc) override;
@@ -1710,23 +1712,7 @@
   MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext();
   const VPtrInfoVector &VFPtrs = VTContext.getVFPtrOffsets(RD);
 
-  if (DeferredVFTables.insert(RD).second) {
-    // We haven't processed this record type before.
-    // Queue up this vtable for possible deferred emission.
-    CGM.addDeferredVTable(RD);
-
-#ifndef NDEBUG
-    // Create all the vftables at once in order to make sure each vftable has
-    // a unique mangled name.
-    llvm::StringSet<> ObservedMangledNames;
-    for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
-      SmallString<256> Name;
-      mangleVFTableName(getMangleContext(), RD, *VFPtrs[J], Name);
-      if (!ObservedMangledNames.insert(Name.str()).second)
-        llvm_unreachable("Already saw this mangling before?");
-    }
-#endif
-  }
+  emitVTables(RD);
 
   const std::unique_ptr<VPtrInfo> *VFPtrI = std::find_if(
       VFPtrs.begin(), VFPtrs.end(), [&](const std::unique_ptr<VPtrInfo>& VPI) {
@@ -1829,6 +1815,29 @@
   return VTable;
 }
 
+void MicrosoftCXXABI::emitVTables(const CXXRecordDecl *RD) {
+  if (DeferredVFTables.insert(RD).second) {
+    // We haven't processed this record type before.
+    // Queue up this vtable for possible deferred emission.
+    CGM.addDeferredVTable(RD);
+
+#ifndef NDEBUG
+    MicrosoftVTableContext &VTContext = CGM.getMicrosoftVTableContext();
+    const VPtrInfoVector &VFPtrs = VTContext.getVFPtrOffsets(RD);
+
+    // Create all the vftables at once in order to make sure each vftable has
+    // a unique mangled name.
+    llvm::StringSet<> ObservedMangledNames;
+    for (size_t J = 0, F = VFPtrs.size(); J != F; ++J) {
+      SmallString<256> Name;
+      mangleVFTableName(getMangleContext(), RD, *VFPtrs[J], Name);
+      assert(ObservedMangledNames.insert(Name.str()).second &&
+             "Already saw this mangling before?");
+    }
+#endif
+  }
+}
+
 CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
                                                     GlobalDecl GD,
                                                     Address This,
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp
+++ lib/CodeGen/ItaniumCXXABI.cpp
@@ -274,6 +274,10 @@
   llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
                                         CharUnits VPtrOffset) override;
 
+  void emitVTables(const CXXRecordDecl *RD) override {
+    (void) getAddrOfVTable(RD, CharUnits());
+  }
+
   CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF, GlobalDecl GD,
                                      Address This, llvm::Type *Ty,
                                      SourceLocation Loc) override;
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -1110,7 +1110,7 @@
 
   void EmitTentativeDefinition(const VarDecl *D);
 
-  void EmitVTable(CXXRecordDecl *Class);
+  void EmitVTable(const CXXRecordDecl *Class);
 
   void RefreshTypeCacheForClass(const CXXRecordDecl *Class);
 
@@ -1312,7 +1312,8 @@
 
   void EmitGlobalDefinition(GlobalDecl D, llvm::GlobalValue *GV = nullptr);
 
-  void EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV);
+  llvm::GlobalValue *
+  EmitGlobalFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV = nullptr);
   void EmitMultiVersionFunctionDefinition(GlobalDecl GD, llvm::GlobalValue *GV);
 
   void EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative = false);
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -2455,7 +2455,8 @@
 
     if (FD->isMultiVersion())
       return EmitMultiVersionFunctionDefinition(GD, GV);
-    return EmitGlobalFunctionDefinition(GD, GV);
+    EmitGlobalFunctionDefinition(GD, GV);
+    return;
   }
 
   if (const auto *VD = dyn_cast<VarDecl>(D))
@@ -3940,7 +3941,7 @@
   EmitTopLevelDecl(VD);
 }
 
-void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
+llvm::GlobalValue *CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
                                                  llvm::GlobalValue *GV) {
   const auto *D = cast<FunctionDecl>(GD.getDecl());
 
@@ -3956,7 +3957,7 @@
 
   // Already emitted.
   if (!GV->isDeclaration())
-    return;
+    return GV;
 
   // We need to set linkage and visibility on the function before
   // generating code for it because various parts of IR generation
@@ -3973,7 +3974,7 @@
 
   maybeSetTrivialComdat(*D, *Fn);
 
-  CodeGenFunction(*this).GenerateCode(D, Fn, FI);
+  CodeGenFunction(*this).GenerateCode(GD, Fn, FI);
 
   setNonAliasAttributes(GD, Fn);
   SetLLVMFunctionAttributesForDefinition(D, Fn);
@@ -3984,6 +3985,14 @@
     AddGlobalDtor(Fn, DA->getPriority());
   if (D->hasAttr<AnnotateAttr>())
     AddGlobalAnnotations(D, Fn);
+
+  // If we emit a key function, also emit the vtable.
+  if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
+    if (declaresSameEntity(Context.getCurrentKeyFunction(MD->getParent()), MD))
+      EmitVTable(MD->getParent());
+  }
+
+  return Fn;
 }
 
 void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
@@ -4797,14 +4806,22 @@
   case Decl::Namespace:
     EmitDeclContext(cast<NamespaceDecl>(D));
     break;
-  case Decl::ClassTemplateSpecialization: {
-    const auto *Spec = cast<ClassTemplateSpecializationDecl>(D);
-    if (DebugInfo &&
-        Spec->getSpecializationKind() == TSK_ExplicitInstantiationDefinition &&
-        Spec->hasDefinition())
-      DebugInfo->completeTemplateDefinition(*Spec);
-  } LLVM_FALLTHROUGH;
-  case Decl::CXXRecord:
+  case Decl::ClassTemplateSpecialization:
+  case Decl::CXXRecord: {
+    auto *RD = cast<CXXRecordDecl>(D);
+    // If this class was explicitly instantiated, emit the accompanying data.
+    if (RD->getTemplateSpecializationKind() ==
+            TSK_ExplicitInstantiationDefinition &&
+        RD->hasDefinition()) {
+      if (DebugInfo) {
+        // FIXME: This should almost certainly apply to explicitly instantiated
+        // member classes of class templates too.
+        if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
+          DebugInfo->completeTemplateDefinition(*CTSD);
+      }
+      if (RD->isDynamicClass())
+        EmitVTable(RD);
+    }
     if (DebugInfo) {
       if (auto *ES = D->getASTContext().getExternalSource())
         if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
@@ -4815,6 +4832,7 @@
       if (isa<VarDecl>(I) || isa<CXXRecordDecl>(I))
         EmitTopLevelDecl(I);
     break;
+  }
     // No code generation needed.
   case Decl::UsingShadow:
   case Decl::ClassTemplate:
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -321,10 +321,6 @@
       Gen->AssignInheritanceModel(RD);
     }
 
-    void HandleVTable(CXXRecordDecl *RD) override {
-      Gen->HandleVTable(RD);
-    }
-
     static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
                                      unsigned LocCookie) {
       SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
Index: lib/CodeGen/CGVTables.cpp
===================================================================
--- lib/CodeGen/CGVTables.cpp
+++ lib/CodeGen/CGVTables.cpp
@@ -876,14 +876,17 @@
   llvm_unreachable("Invalid TemplateSpecializationKind!");
 }
 
-/// This is a callback from Sema to tell us that a particular vtable is
-/// required to be emitted in this translation unit.
+/// This is called when a particular vtable is required to be emitted in this
+/// translation unit.
 ///
-/// This is only called for vtables that _must_ be emitted (mainly due to key
-/// functions).  For weak vtables, CodeGen tracks when they are needed and
-/// emits them as-needed.
-void CodeGenModule::EmitVTable(CXXRecordDecl *theClass) {
-  VTables.GenerateClassData(theClass);
+/// This is only called for vtables that must be emitted due to key functions
+/// or explicit instantiations. For weak vtables, CodeGen tracks when they are
+/// needed and emits them as-needed.
+void CodeGenModule::EmitVTable(const CXXRecordDecl *theClass) {
+  // Skip emitting a vtable that would be discardable. We'll still emit it
+  // if it's actually used.
+  if (!llvm::GlobalValue::isDiscardableIfUnused(getVTableLinkage(theClass)))
+    getCXXABI().emitVTables(theClass);
 }
 
 void
@@ -955,21 +958,15 @@
 /// vtables, and that we are now at the end of the translation unit,
 /// decide whether we should emit them.
 void CodeGenModule::EmitDeferredVTables() {
-#ifndef NDEBUG
-  // Remember the size of DeferredVTables, because we're going to assume
-  // that this entire operation doesn't modify it.
-  size_t savedSize = DeferredVTables.size();
-#endif
-
-  for (const CXXRecordDecl *RD : DeferredVTables)
-    if (shouldEmitVTableAtEndOfTranslationUnit(*this, RD))
-      VTables.GenerateClassData(RD);
-    else if (shouldOpportunisticallyEmitVTables())
-      OpportunisticVTables.push_back(RD);
-
-  assert(savedSize == DeferredVTables.size() &&
-         "deferred extra vtables during vtable emission?");
-  DeferredVTables.clear();
+  while (!DeferredVTables.empty()) {
+    auto WorkList = std::move(DeferredVTables);
+    DeferredVTables.clear();
+    for (const CXXRecordDecl *RD : WorkList)
+      if (shouldEmitVTableAtEndOfTranslationUnit(*this, RD))
+        VTables.GenerateClassData(RD);
+      else if (shouldOpportunisticallyEmitVTables())
+        OpportunisticVTables.push_back(RD);
+  }
 }
 
 bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) {
Index: lib/CodeGen/CGCXXABI.h
===================================================================
--- lib/CodeGen/CGCXXABI.h
+++ lib/CodeGen/CGCXXABI.h
@@ -420,6 +420,9 @@
   virtual llvm::GlobalVariable *getAddrOfVTable(const CXXRecordDecl *RD,
                                                 CharUnits VPtrOffset) = 0;
 
+  /// Ensure that all vtables for the given class are emitted.
+  virtual void emitVTables(const CXXRecordDecl *RD) = 0;
+
   /// Build a virtual function pointer in the ABI-specific way.
   virtual CGCallee getVirtualFunctionPointer(CodeGenFunction &CGF,
                                              GlobalDecl GD, Address This,
Index: lib/CodeGen/CGCXX.cpp
===================================================================
--- lib/CodeGen/CGCXX.cpp
+++ lib/CodeGen/CGCXX.cpp
@@ -206,12 +206,6 @@
 
 llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
                                                   StructorType Type) {
-  const CGFunctionInfo &FnInfo =
-      getTypes().arrangeCXXStructorDeclaration(MD, Type);
-  auto *Fn = cast<llvm::Function>(
-      getAddrOfCXXStructor(MD, Type, &FnInfo, /*FnType=*/nullptr,
-                           /*DontDefer=*/true, ForDefinition));
-
   GlobalDecl GD;
   if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
     GD = GlobalDecl(DD, toCXXDtorType(Type));
@@ -220,12 +214,7 @@
     GD = GlobalDecl(CD, toCXXCtorType(Type));
   }
 
-  setFunctionLinkage(GD, Fn);
-
-  CodeGenFunction(*this).GenerateCode(GD, Fn, FnInfo);
-  setNonAliasAttributes(GD, Fn);
-  SetLLVMFunctionAttributesForDefinition(MD, Fn);
-  return Fn;
+  return cast<llvm::Function>(EmitGlobalFunctionDefinition(GD));
 }
 
 llvm::Constant *CodeGenModule::getAddrOfCXXStructor(
Index: lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- lib/AST/RecordLayoutBuilder.cpp
+++ lib/AST/RecordLayoutBuilder.cpp
@@ -3053,7 +3053,7 @@
 }
 
 const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) {
-  if (!getTargetInfo().getCXXABI().hasKeyFunctions())
+  if (!getTargetInfo().getCXXABI().hasKeyFunctions() || !RD->isDynamicClass())
     return nullptr;
 
   assert(RD->getDefinition() && "Cannot get key function for forward decl!");
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -9793,6 +9793,12 @@
     return !D->getDeclContext()->isDependentContext();
   else if (isa<ImportDecl>(D))
     return true;
+  else if (auto *RD = dyn_cast<CXXRecordDecl>(D))
+    // An explicit instantiation of a dynamic class emits the vtable and
+    // type_info objects, so must be emitted.
+    return RD->hasDefinition() && RD->isDynamicClass() &&
+           RD->getTemplateSpecializationKind() ==
+               TSK_ExplicitInstantiationDefinition;
   else
     return false;
 
@@ -9842,8 +9848,11 @@
   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
     // Multiversioned functions always have to be emitted, because they are used
     // by the resolver.
+    // FIXME: This doesn't appear to be correct. Multiversioned functions should
+    // only be emitted if the resolver is emitted.
     if (FD->isMultiVersion())
       return true;
+
     // Forward declarations aren't required.
     if (!FD->doesThisDeclarationHaveABody())
       return FD->doesDeclarationForceExternallyVisibleDefinition();
@@ -9852,19 +9861,6 @@
     if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
       return true;
 
-    // The key function for a class is required.  This rule only comes
-    // into play when inline functions can be key functions, though.
-    if (getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
-      if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
-        const CXXRecordDecl *RD = MD->getParent();
-        if (MD->isOutOfLine() && RD->isDynamicClass()) {
-          const CXXMethodDecl *KeyFunc = getCurrentKeyFunction(RD);
-          if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl())
-            return true;
-        }
-      }
-    }
-
     GVALinkage Linkage = GetGVALinkageForFunction(FD);
 
     // static, static inline, always_inline, and extern inline functions can
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to