r245489 - Generating available_externally vtables bugfix
Piotr Padlewski via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 19 13:09:10 PDT 2015
Author: prazek
Date: Wed Aug 19 15:09:09 2015
New Revision: 245489
URL: http://llvm.org/viewvc/llvm-project?rev=245489&view=rev
Log:
Generating available_externally vtables bugfix
Bugfix revealed in r245264.
http://reviews.llvm.org/D12128
Modified:
cfe/trunk/include/clang/AST/VTableBuilder.h
cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp
Modified: cfe/trunk/include/clang/AST/VTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/VTableBuilder.h?rev=245489&r1=245488&r2=245489&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/VTableBuilder.h (original)
+++ cfe/trunk/include/clang/AST/VTableBuilder.h Wed Aug 19 15:09:09 2015
@@ -123,30 +123,50 @@ public:
const CXXRecordDecl *getRTTIDecl() const {
assert(getKind() == CK_RTTI && "Invalid component kind!");
-
return reinterpret_cast<CXXRecordDecl *>(getPointer());
}
const CXXMethodDecl *getFunctionDecl() const {
- assert(getKind() == CK_FunctionPointer);
-
+ assert(isFunctionPointerKind() && "Invalid component kind!");
+ if (isDestructorKind())
+ return getDestructorDecl();
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
const CXXDestructorDecl *getDestructorDecl() const {
- assert((getKind() == CK_CompleteDtorPointer ||
- getKind() == CK_DeletingDtorPointer) && "Invalid component kind!");
-
+ assert(isDestructorKind() && "Invalid component kind!");
return reinterpret_cast<CXXDestructorDecl *>(getPointer());
}
const CXXMethodDecl *getUnusedFunctionDecl() const {
- assert(getKind() == CK_UnusedFunctionPointer);
-
+ assert(getKind() == CK_UnusedFunctionPointer && "Invalid component kind!");
return reinterpret_cast<CXXMethodDecl *>(getPointer());
}
+ bool isDestructorKind() const { return isDestructorKind(getKind()); }
+
+ bool isUsedFunctionPointerKind() const {
+ return isUsedFunctionPointerKind(getKind());
+ }
+
+ bool isFunctionPointerKind() const {
+ return isFunctionPointerKind(getKind());
+ }
+
private:
+ static bool isFunctionPointerKind(Kind ComponentKind) {
+ return isUsedFunctionPointerKind(ComponentKind) ||
+ ComponentKind == CK_UnusedFunctionPointer;
+ }
+ static bool isUsedFunctionPointerKind(Kind ComponentKind) {
+ return ComponentKind == CK_FunctionPointer ||
+ isDestructorKind(ComponentKind);
+ }
+ static bool isDestructorKind(Kind ComponentKind) {
+ return ComponentKind == CK_CompleteDtorPointer ||
+ ComponentKind == CK_DeletingDtorPointer;
+ }
+
VTableComponent(Kind ComponentKind, CharUnits Offset) {
assert((ComponentKind == CK_VCallOffset ||
ComponentKind == CK_VBaseOffset ||
@@ -158,12 +178,8 @@ private:
}
VTableComponent(Kind ComponentKind, uintptr_t Ptr) {
- assert((ComponentKind == CK_RTTI ||
- ComponentKind == CK_FunctionPointer ||
- ComponentKind == CK_CompleteDtorPointer ||
- ComponentKind == CK_DeletingDtorPointer ||
- ComponentKind == CK_UnusedFunctionPointer) &&
- "Invalid component kind!");
+ assert((ComponentKind == CK_RTTI || isFunctionPointerKind(ComponentKind)) &&
+ "Invalid component kind!");
assert((Ptr & 7) == 0 && "Pointer not sufficiently aligned!");
@@ -178,11 +194,7 @@ private:
}
uintptr_t getPointer() const {
- assert((getKind() == CK_RTTI ||
- getKind() == CK_FunctionPointer ||
- getKind() == CK_CompleteDtorPointer ||
- getKind() == CK_DeletingDtorPointer ||
- getKind() == CK_UnusedFunctionPointer) &&
+ assert((getKind() == CK_RTTI || isFunctionPointerKind()) &&
"Invalid component kind!");
return static_cast<uintptr_t>(Value & ~7ULL);
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=245489&r1=245488&r2=245489&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Wed Aug 19 15:09:09 2015
@@ -306,17 +306,15 @@ public:
void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
private:
- /// Checks if function has any virtual inline function.
- bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const {
+ bool hasAnyUsedVirtualInlineFunction(const CXXRecordDecl *RD) const {
const auto &VtableLayout =
CGM.getItaniumVTableContext().getVTableLayout(RD);
for (const auto &VtableComponent : VtableLayout.vtable_components()) {
- if (VtableComponent.getKind() !=
- VTableComponent::Kind::CK_FunctionPointer)
+ if (!VtableComponent.isUsedFunctionPointerKind())
continue;
- const auto &Method = VtableComponent.getFunctionDecl();
+ const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
if (Method->getCanonicalDecl()->isInlined())
return true;
}
@@ -1510,7 +1508,7 @@ bool ItaniumCXXABI::canEmitAvailableExte
// then we are safe to emit available_externally copy of vtable.
// FIXME we can still emit a copy of the vtable if we
// can emit definition of the inline functions.
- return !hasAnyVirtualInlineFunction(RD);
+ return !hasAnyUsedVirtualInlineFunction(RD);
}
static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
llvm::Value *Ptr,
Modified: cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp?rev=245489&r1=245488&r2=245489&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/vtable-available-externally.cpp Wed Aug 19 15:09:09 2015
@@ -7,6 +7,10 @@
// RUN: FileCheck --check-prefix=CHECK-TEST9 %s < %t.opt
// RUN: FileCheck --check-prefix=CHECK-TEST10 %s < %t.opt
// RUN: FileCheck --check-prefix=CHECK-TEST11 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-TEST12 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-TEST13 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-TEST14 %s < %t.opt
+// RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt
#include <typeinfo>
@@ -289,3 +293,76 @@ void g() {
g(d);
}
} // Test 11
+
+namespace Test12 {
+
+// CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant
+struct A {
+ virtual void foo();
+ virtual ~A() {}
+};
+// CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant
+struct B : A {
+ void foo();
+};
+
+void g() {
+ A a;
+ a.foo();
+ B b;
+ b.foo();
+}
+}
+
+namespace Test13 {
+
+// CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant
+// CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant
+struct A {
+ virtual ~A();
+};
+struct B : A {
+ virtual void f();
+ void operator delete(void *);
+ ~B() {}
+};
+
+void g() {
+ A *b = new B;
+}
+}
+
+namespace Test14 {
+
+// CHECK-TEST14: @_ZTVN6Test141AE = available_externally unnamed_addr constant
+struct A {
+ virtual void f();
+ void operator delete(void *);
+ ~A();
+};
+
+void g() {
+ A *b = new A;
+ delete b;
+}
+}
+
+namespace Test15 {
+// In this test D's vtable has two slots for function f(), but uses only one,
+// so the second slot is set to null.
+// CHECK-TEST15: @_ZTVN6Test151DE = available_externally unnamed_addr constant
+struct A { virtual void f() {} };
+struct B : virtual A {};
+struct C : virtual A {};
+struct D : B, C {
+ virtual void g();
+ void f();
+};
+
+void test() {
+ D * d = new D;
+ d->f();
+}
+}
+
+
More information about the cfe-commits
mailing list