Have ASTRecordLayout keep track of the key function, in preparation of fixing a synthetic ctor/dtor bug.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90168 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp
index edf19f7..1a9bc39 100644
--- a/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -330,32 +330,6 @@
}
-static const CXXMethodDecl *GetKeyFunction(const RecordDecl *D) {
- const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
- if (!RD || !RD->isDynamicClass())
- return 0;
-
- for (CXXRecordDecl::method_iterator I = RD->method_begin(),
- E = RD->method_end(); I != E; ++I) {
- const CXXMethodDecl *MD = *I;
-
- if (!MD->isVirtual())
- continue;
-
- if (MD->isPure())
- continue;
-
- const FunctionDecl *fn;
- if (MD->getBody(fn) && !fn->isOutOfLine())
- continue;
-
- // We found it.
- return MD;
- }
-
- return 0;
-}
-
CGRecordLayout *
CGRecordLayoutBuilder::ComputeLayout(CodeGenTypes &Types,
const RecordDecl *D) {
@@ -385,7 +359,5 @@
Types.addBitFieldInfo(Info.FD, Info.FieldNo, Info.Start, Info.Size);
}
- const CXXMethodDecl *KeyFunction = GetKeyFunction(D);
-
- return new CGRecordLayout(Ty, Builder.ContainsMemberPointer, KeyFunction);
+ return new CGRecordLayout(Ty, Builder.ContainsMemberPointer);
}
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 224c829..715aa4c 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -1060,10 +1060,10 @@
if (LayoutClass != RD)
CreateDefinition = true;
else {
- // We have to convert it to have a record layout.
- Types.ConvertTagDeclType(LayoutClass);
- const CGRecordLayout &CGLayout = Types.getCGRecordLayout(LayoutClass);
- if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) {
+ const ASTRecordLayout &Layout =
+ getContext().getASTRecordLayout(LayoutClass);
+
+ if (const CXXMethodDecl *KeyFunction = Layout.getKeyFunction()) {
if (!KeyFunction->getBody()) {
// If there is a KeyFunction, and it isn't defined, just build a
// reference to the vtable.
@@ -1316,10 +1316,9 @@
vtbl = CGM.GenerateVtable(RD, RD);
bool CreateDefinition = true;
- // We have to convert it to have a record layout.
- CGM.getTypes().ConvertTagDeclType(RD);
- const CGRecordLayout &CGLayout = CGM.getTypes().getCGRecordLayout(RD);
- if (const CXXMethodDecl *KeyFunction = CGLayout.getKeyFunction()) {
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+ if (const CXXMethodDecl *KeyFunction = Layout.getKeyFunction()) {
if (!KeyFunction->getBody()) {
// If there is a KeyFunction, and it isn't defined, just build a
// reference to the vtable.
@@ -1339,3 +1338,31 @@
uint64_t Offset) {
return CGM.GenerateVtable(LayoutClass, RD, Offset);
}
+
+void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
+ const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+ const CXXRecordDecl *RD = MD->getParent();
+
+ const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
+
+ // Get the key function.
+ const CXXMethodDecl *KeyFunction = Layout.getKeyFunction();
+
+ if (!KeyFunction) {
+ // If there's no key function, we don't want to emit the vtable here.
+ return;
+ }
+
+ // Check if we have the key function.
+ if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
+ return;
+
+ // If the key function is a destructor, we only want to emit the vtable once,
+ // so do it for the complete destructor.
+ if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Complete)
+ return;
+
+ // Emit the data.
+ GenerateClassData(RD);
+}
+
diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h
index ac3cdee..5c2b74c 100644
--- a/lib/CodeGen/CGVtable.h
+++ b/lib/CodeGen/CGVtable.h
@@ -91,6 +91,11 @@
void ComputeMethodVtableIndices(const CXXRecordDecl *RD);
+ /// GenerateClassData - Generate all the class data requires to be generated
+ /// upon definition of a KeyFunction. This includes the vtable, the
+ /// rtti data structure and the VTT.
+ void GenerateClassData(const CXXRecordDecl *RD);
+
public:
CGVtableInfo(CodeGenModule &CGM)
: CGM(CGM) { }
@@ -111,10 +116,9 @@
llvm::Constant *getVtable(const CXXRecordDecl *RD);
llvm::Constant *getCtorVtable(const CXXRecordDecl *RD,
const CXXRecordDecl *Class, uint64_t Offset);
- /// GenerateClassData - Generate all the class data requires to be generated
- /// upon definition of a KeyFunction. This includes the vtable, the
- /// rtti data structure and the VTT.
- void GenerateClassData(const CXXRecordDecl *RD);
+
+
+ void MaybeEmitVtable(GlobalDecl GD);
};
}
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index a14733a..4b3b122 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -21,6 +21,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/RecordLayout.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
@@ -614,18 +615,9 @@
Context.getSourceManager(),
"Generating code for declaration");
- if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
- const CXXRecordDecl *RD = MD->getParent();
- // We have to convert it to have a record layout.
- Types.ConvertTagDeclType(RD);
- const CGRecordLayout &CGLayout = Types.getCGRecordLayout(RD);
- // A definition of a KeyFunction, generates all the class data, such
- // as vtable, rtti and the VTT.
- if (CGLayout.getKeyFunction()
- && (CGLayout.getKeyFunction()->getCanonicalDecl()
- == MD->getCanonicalDecl()))
- getVtableInfo().GenerateClassData(RD);
- }
+ if (isa<CXXMethodDecl>(D))
+ getVtableInfo().MaybeEmitVtable(GD);
+
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D))
EmitCXXConstructor(CD, GD.getCtorType());
else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D))
diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h
index 55827aa..2ff602f 100644
--- a/lib/CodeGen/CodeGenTypes.h
+++ b/lib/CodeGen/CodeGenTypes.h
@@ -64,17 +64,9 @@
/// is a member pointer, or a struct that contains a member pointer.
bool ContainsMemberPointer;
- /// KeyFunction - The key function of the record layout (if one exists),
- /// which is the first non-pure virtual function that is not inline at the
- /// point of class definition.
- /// See http://www.codesourcery.com/public/cxx-abi/abi.html#vague-vtable.
- const CXXMethodDecl *KeyFunction;
-
public:
- CGRecordLayout(const llvm::Type *T, bool ContainsMemberPointer,
- const CXXMethodDecl *KeyFunction)
- : LLVMType(T), ContainsMemberPointer(ContainsMemberPointer),
- KeyFunction(KeyFunction) { }
+ CGRecordLayout(const llvm::Type *T, bool ContainsMemberPointer)
+ : LLVMType(T), ContainsMemberPointer(ContainsMemberPointer) { }
/// getLLVMType - Return llvm type associated with this record.
const llvm::Type *getLLVMType() const {
@@ -84,10 +76,6 @@
bool containsMemberPointer() const {
return ContainsMemberPointer;
}
-
- const CXXMethodDecl *getKeyFunction() const {
- return KeyFunction;
- }
};
/// CodeGenTypes - This class organizes the cross-module state that is used