aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGCXX.cpp6
-rw-r--r--lib/CodeGen/CGVTables.cpp4
-rw-r--r--lib/CodeGen/CodeGenModule.cpp23
-rw-r--r--lib/CodeGen/CodeGenModule.h6
-rw-r--r--lib/Sema/SemaDeclCXX.cpp7
-rw-r--r--test/CodeGenCXX/vtable-available-externally.cpp48
6 files changed, 73 insertions, 21 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index a4145675b3..f2128792f8 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -227,7 +227,8 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D,
const llvm::FunctionType *FTy =
getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type),
FPT->isVariadic());
- return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, GD));
+ return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, GD,
+ /*ForVTable=*/false));
}
void CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) {
@@ -284,7 +285,8 @@ CodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
const llvm::FunctionType *FTy =
getTypes().GetFunctionType(getTypes().getFunctionInfo(D, Type), false);
- return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, GD));
+ return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FTy, GD,
+ /*ForVTable=*/false));
}
static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VTableIndex,
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index de6cbf52f3..eadfe9f146 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -2463,7 +2463,7 @@ llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
getCXXABI().getMangleContext().mangleThunk(MD, Thunk, Name);
const llvm::Type *Ty = getTypes().GetFunctionTypeForVTable(GD);
- return GetOrCreateLLVMFunction(Name, Ty, GD);
+ return GetOrCreateLLVMFunction(Name, Ty, GD, /*ForVTable=*/false);
}
static llvm::Value *PerformTypeAdjustment(CodeGenFunction &CGF,
@@ -2918,7 +2918,7 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
} else {
const llvm::Type *Ty = CGM.getTypes().GetFunctionTypeForVTable(GD);
- Init = CGM.GetAddrOfFunction(GD, Ty);
+ Init = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
}
Init = llvm::ConstantExpr::getBitCast(Init, Int8PtrTy);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index b8f91b464d..0c541b9670 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -650,7 +650,8 @@ llvm::Constant *CodeGenModule::GetWeakRefReference(const ValueDecl *VD) {
llvm::Constant *Aliasee;
if (isa<llvm::FunctionType>(DeclTy))
- Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GlobalDecl());
+ Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GlobalDecl(),
+ /*ForVTable=*/false);
else
Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
llvm::PointerType::getUnqual(DeclTy), 0);
@@ -782,7 +783,7 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
llvm::Constant *
CodeGenModule::GetOrCreateLLVMFunction(llvm::StringRef MangledName,
const llvm::Type *Ty,
- GlobalDecl D) {
+ GlobalDecl D, bool ForVTable) {
// Lookup the entry, lazily creating it if necessary.
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry) {
@@ -840,7 +841,11 @@ CodeGenModule::GetOrCreateLLVMFunction(llvm::StringRef MangledName,
// - special member functions with implicit definitions
// If we ever change our AST traversal to walk into class methods,
// this will be unnecessary.
- } else if (getLangOptions().CPlusPlus && D.getDecl()) {
+ //
+ // We also don't emit a definition for a function if it's going to be an entry
+ // in a vtable, unless it's already marked as used.
+ } else if (getLangOptions().CPlusPlus && D.getDecl() &&
+ !(ForVTable && !D.getDecl()->isUsed())) {
// Look for a declaration that's lexically in a record.
const FunctionDecl *FD = cast<FunctionDecl>(D.getDecl());
do {
@@ -872,13 +877,14 @@ CodeGenModule::GetOrCreateLLVMFunction(llvm::StringRef MangledName,
/// non-null, then this function will use the specified type if it has to
/// create it (this occurs when we see a definition of the function).
llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
- const llvm::Type *Ty) {
+ const llvm::Type *Ty,
+ bool ForVTable) {
// If there was no specific requested type, just convert it now.
if (!Ty)
Ty = getTypes().ConvertType(cast<ValueDecl>(GD.getDecl())->getType());
llvm::StringRef MangledName = getMangledName(GD);
- return GetOrCreateLLVMFunction(MangledName, Ty, GD);
+ return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable);
}
/// CreateRuntimeFunction - Create a new runtime function with the specified
@@ -886,7 +892,7 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
llvm::Constant *
CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
llvm::StringRef Name) {
- return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl());
+ return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false);
}
static bool DeclIsConstantGlobal(ASTContext &Context, const VarDecl *D) {
@@ -1445,7 +1451,8 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
// if a deferred decl.
llvm::Constant *Aliasee;
if (isa<llvm::FunctionType>(DeclTy))
- Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GlobalDecl());
+ Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GlobalDecl(),
+ /*ForVTable=*/false);
else
Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(),
llvm::PointerType::getUnqual(DeclTy), 0);
@@ -1511,7 +1518,7 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,
const llvm::FunctionType *Ty =
cast<llvm::FunctionType>(getTypes().ConvertType(FD->getType()));
- return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl(FD));
+ return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl(FD), /*ForVTable=*/false);
}
llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys,
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 7652b88fdc..00f88f6f5a 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -317,7 +317,8 @@ public:
/// non-null, then this function will use the specified type if it has to
/// create it.
llvm::Constant *GetAddrOfFunction(GlobalDecl GD,
- const llvm::Type *Ty = 0);
+ const llvm::Type *Ty = 0,
+ bool ForVTable = false);
/// GetAddrOfRTTIDescriptor - Get the address of the RTTI descriptor
/// for the given type.
@@ -541,7 +542,8 @@ private:
llvm::Constant *GetOrCreateLLVMFunction(llvm::StringRef MangledName,
const llvm::Type *Ty,
- GlobalDecl D);
+ GlobalDecl D,
+ bool ForVTable);
llvm::Constant *GetOrCreateLLVMGlobal(llvm::StringRef MangledName,
const llvm::PointerType *PTy,
const VarDecl *D,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b4c375d638..0565a7fef9 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -7118,13 +7118,6 @@ bool Sema::DefineUsedVTables() {
switch (KeyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
- // The key function is in another translation unit. Mark all of the
- // virtual members of this class as referenced so that we can build a
- // vtable anyway (in order to do devirtualization when optimizations
- // are turned on for example.
- MarkVirtualMembersReferenced(Loc, Class);
- continue;
-
case TSK_ExplicitInstantiationDeclaration:
// The key function is in another translation unit.
continue;
diff --git a/test/CodeGenCXX/vtable-available-externally.cpp b/test/CodeGenCXX/vtable-available-externally.cpp
index b6e48c8f8c..11c1abda4b 100644
--- a/test/CodeGenCXX/vtable-available-externally.cpp
+++ b/test/CodeGenCXX/vtable-available-externally.cpp
@@ -53,3 +53,51 @@ namespace Test2 {
void A::f() { }
}
+
+// Test that we don't assert on this test.
+namespace Test3 {
+
+struct A {
+ virtual void f();
+ virtual ~A() { }
+};
+
+struct B : A {
+ B();
+ virtual void f();
+};
+
+B::B() { }
+
+void g(A* a) {
+ a->f();
+};
+
+}
+
+// PR9114, test that we don't try to emit a definition of
+namespace Test4 {
+
+template <class T> struct RefPtr {
+ T* p;
+ ~RefPtr() {
+ p->deref();
+ }
+};
+
+struct A {
+ virtual ~A();
+};
+
+struct Node;
+
+struct B : A {
+ virtual void deref();
+ RefPtr<Node> m;
+};
+
+void f() {
+ RefPtr<B> b;
+}
+
+}