Skip to content

Commit a7cf98a

Browse files
committed
Fix #4779 - C++ classes need TypeInfo
1 parent b5f7bb0 commit a7cf98a

File tree

6 files changed

+56
-9
lines changed

6 files changed

+56
-9
lines changed

gen/typinf.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,8 +506,19 @@ class DeclareOrDefineVisitor : public Visitor {
506506
auto cd = decl->tinfo->isTypeClass()->sym;
507507
DtoResolveClass(cd);
508508

509+
auto irclass = getIrAggr(cd, true);
509510
IrGlobal *irg = getIrGlobal(decl, true);
510-
irg->value = getIrAggr(cd)->getClassInfoSymbol();
511+
512+
auto ti = irclass->getClassInfoSymbol();
513+
irg->value = ti;
514+
515+
// check if the definition can be elided
516+
if (irclass->suppressTypeInfo()) {
517+
return;
518+
}
519+
520+
irclass->getClassInfoSymbol(true);
521+
ti->setLinkage(TYPEINFO_LINKAGE_TYPE); // override
511522
}
512523

513524
// Build all other TypeInfos.

ir/irclass.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "gen/runtime.h"
3030
#include "gen/tollvm.h"
3131
#include "gen/typinf.h"
32+
#include "gen/linkage.h"
3233
#include "ir/iraggr.h"
3334
#include "ir/irdsymbol.h"
3435
#include "ir/irfunction.h"
@@ -89,8 +90,10 @@ LLGlobalVariable *IrClass::getVtblSymbol(bool define) {
8990

9091
if (define) {
9192
auto init = getVtblInit(); // might define vtbl
92-
if (!vtbl->hasInitializer())
93+
if (!vtbl->hasInitializer()) {
9394
defineGlobal(vtbl, init, aggrdecl);
95+
vtbl->setLinkage(TYPEINFO_LINKAGE_TYPE); // override
96+
}
9497
}
9598

9699
return vtbl;
@@ -140,8 +143,10 @@ LLGlobalVariable *IrClass::getClassInfoSymbol(bool define) {
140143

141144
if (define) {
142145
auto init = getClassInfoInit();
143-
if (!typeInfo->hasInitializer())
146+
if (!typeInfo->hasInitializer()) {
144147
defineGlobal(typeInfo, init, aggrdecl);
148+
typeInfo->setLinkage(TYPEINFO_LINKAGE_TYPE); // override
149+
}
145150
}
146151

147152
return typeInfo;
@@ -381,7 +386,7 @@ LLConstant *IrClass::getClassInfoInit() {
381386
if (isInterface) {
382387
b.push_array(0, getNullPtr());
383388
} else {
384-
b.push_array(cd->vtbl.length, getVtblSymbol());
389+
b.push_array(cd->vtbl.length, getVtblSymbol(true)); // override
385390
}
386391

387392
// Interface[] interfaces
@@ -391,7 +396,9 @@ LLConstant *IrClass::getClassInfoInit() {
391396
assert(!isInterface || !cd->baseClass);
392397
if (cd->baseClass) {
393398
DtoResolveClass(cd->baseClass);
394-
b.push(getIrAggr(cd->baseClass)->getClassInfoSymbol());
399+
auto ti = getIrAggr(cd->baseClass)->getClassInfoSymbol(true);
400+
ti->setLinkage(TYPEINFO_LINKAGE_TYPE); // override
401+
b.push(ti);
395402
} else {
396403
b.push_null(cinfoType);
397404
}
@@ -743,7 +750,7 @@ LLConstant *IrClass::getClassInfoInterfaces() {
743750
assert(itc && "null interface IrTypeClass");
744751

745752
// classinfo
746-
LLConstant *ci = irinter->getClassInfoSymbol();
753+
LLConstant *ci = irinter->getClassInfoSymbol(true);
747754

748755
// vtbl
749756
LLConstant *vtb;
@@ -772,6 +779,7 @@ LLConstant *IrClass::getClassInfoInterfaces() {
772779
LLConstant *arr = LLConstantArray::get(array_type, constants);
773780
auto ciarr = getInterfaceArraySymbol();
774781
defineGlobal(ciarr, arr, cd);
782+
ciarr->setLinkage(TYPEINFO_LINKAGE_TYPE); // override
775783

776784
// return null, only baseclass provide interfaces
777785
if (cd->vtblInterfaces->length == 0) {

tests/codegen/pragma_no_typeinfo.d

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ struct StructWithTypeInfo {}
1010
// force emission
1111
auto ti = typeid(StructWithTypeInfo);
1212

13-
// CHECK: _D18pragma_no_typeinfo17ClassWithTypeInfo7__ClassZ = global %object.TypeInfo_Class
13+
// CHECK: _D18pragma_no_typeinfo17ClassWithTypeInfo7__ClassZ = linkonce_odr global %object.TypeInfo_Class
1414
class ClassWithTypeInfo {}
1515

16-
// CHECK: _D18pragma_no_typeinfo21InterfaceWithTypeInfo11__InterfaceZ = global %object.TypeInfo_Class
16+
// CHECK: _D18pragma_no_typeinfo21InterfaceWithTypeInfo11__InterfaceZ = linkonce_odr global %object.TypeInfo_Class
1717
interface InterfaceWithTypeInfo {}
1818

1919

tests/codegen/static_typeid_gh1540.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct S
1515
{
1616
}
1717

18-
// CHECK-DAG: _D{{.*}}1C7__ClassZ{{\"?}} = global %object.TypeInfo_Class
18+
// CHECK-DAG: _D{{.*}}1C7__ClassZ{{\"?}} = linkonce_odr global %object.TypeInfo_Class
1919
// CHECK-DAG: _D{{.*}}classvarC14TypeInfo_Class{{\"?}} = thread_local global ptr {{.*}}1C7__ClassZ
2020
auto classvar = typeid(C);
2121

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module inputs.typeinfo_on_demand2;
2+
3+
extern(C++) class MyClass : MyInterface1 {
4+
void method() {}
5+
}
6+
7+
extern(C++) interface MyInterface1 {
8+
void method();
9+
}
10+
11+
extern(C++) interface MyInterface2 {
12+
void method();
13+
}

tests/linking/typeinfo_on_demand.d

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Tests that TypeInfo is generated per CU to enable on demand usage
2+
3+
// RUN: %ldc -of%t_lib%obj -betterC -c %S/inputs/typeinfo_on_demand2.d
4+
// RUN: %ldc -I%S %t_lib%obj -run %s
5+
6+
import inputs.typeinfo_on_demand2;
7+
8+
void main() {
9+
MyChildClass mcc = new MyChildClass;
10+
mcc.method();
11+
}
12+
13+
extern(C++) class MyChildClass : MyClass, MyInterface2 {
14+
override void method() {}
15+
}

0 commit comments

Comments
 (0)