Skip to content

Commit 34624e8

Browse files
Merge pull request #702 from andreasfertig/fixIssue701
Fixed #701: Use correct vtable entry index.
2 parents 52ea4fd + c9639bb commit 34624e8

5 files changed

+184
-25
lines changed

CfrontCodeGenerator.cpp

+23-21
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,27 @@ static std::string GetFirstPolymorphicBaseName(const RecordDecl* decl, const Rec
844844
}
845845
//-----------------------------------------------------------------------------
846846

847+
///! Find the first polymorphic base class.
848+
static const CXXRecordDecl* GetFirstPolymorphicBase(const RecordDecl* decl)
849+
{
850+
if(const auto* rdecl = dyn_cast_or_null<CXXRecordDecl>(decl); rdecl->getNumBases() >= 1) {
851+
for(const auto& base : rdecl->bases()) {
852+
const auto* rd = base.getType()->getAsRecordDecl();
853+
854+
if(const auto* cxxRd = dyn_cast_or_null<CXXRecordDecl>(rd); not cxxRd or not cxxRd->isPolymorphic()) {
855+
continue;
856+
} else if(const CXXRecordDecl* ret = GetFirstPolymorphicBase(rd)) {
857+
return ret;
858+
}
859+
860+
break;
861+
}
862+
}
863+
864+
return dyn_cast_or_null<CXXRecordDecl>(decl);
865+
}
866+
//-----------------------------------------------------------------------------
867+
847868
void CfrontCodeGenerator::InsertArg(const CXXRecordDecl* stmt)
848869
{
849870
auto* recordDecl = Struct(GetName(*stmt));
@@ -954,6 +975,8 @@ void CfrontCodeGenerator::InsertArg(const CXXRecordDecl* stmt)
954975

955976
mInitExprs.push_back(InitList({thunkOffset, Int32(0), reicast}, vtblData.vtableRecordType));
956977

978+
mVirtualFunctions[{md, {stmt, GetFirstPolymorphicBase(stmt)}}] = funIdx;
979+
957980
++funIdx;
958981
break;
959982
}
@@ -1006,27 +1029,6 @@ void CfrontCodeGenerator::InsertArg(const CXXRecordDecl* stmt)
10061029
}
10071030
//-----------------------------------------------------------------------------
10081031

1009-
///! Find the first polymorphic base class.
1010-
static const CXXRecordDecl* GetFirstPolymorphicBase(const RecordDecl* decl)
1011-
{
1012-
if(const auto* rdecl = dyn_cast_or_null<CXXRecordDecl>(decl); rdecl->getNumBases() >= 1) {
1013-
for(const auto& base : rdecl->bases()) {
1014-
const auto* rd = base.getType()->getAsRecordDecl();
1015-
1016-
if(const auto* cxxRd = dyn_cast_or_null<CXXRecordDecl>(rd); not cxxRd or not cxxRd->isPolymorphic()) {
1017-
continue;
1018-
} else if(const CXXRecordDecl* ret = GetFirstPolymorphicBase(rd)) {
1019-
return ret;
1020-
}
1021-
1022-
break;
1023-
}
1024-
}
1025-
1026-
return dyn_cast_or_null<CXXRecordDecl>(decl);
1027-
}
1028-
//-----------------------------------------------------------------------------
1029-
10301032
void CfrontCodeGenerator::InsertArg(const CXXMemberCallExpr* stmt)
10311033
{
10321034
if(const auto* me = dyn_cast_or_null<MemberExpr>(stmt->getCallee())) {

tests/EduCfrontVtable4Test.expect

+2-2
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ int __main(void)
106106
{
107107
C b;
108108
Constructor_C((C *)&b);
109-
(*((void (*)(C *))((&b)->__vptrA[0]).f))((((C *)(char *)(&b)) + ((&b)->__vptrA[0]).d));
109+
(*((void (*)(C *))((&b)->__vptrA[1]).f))((((C *)(char *)(&b)) + ((&b)->__vptrA[1]).d));
110110
A * a = (A *)&b;
111-
(*((void (*)(A *))((a)->__vptrA[0]).f))((((A *)(char *)(a)) + ((a)->__vptrA[0]).d));
111+
(*((void (*)(A *))((a)->__vptrA[1]).f))((((A *)(char *)(a)) + ((a)->__vptrA[1]).d));
112112
return 0;
113113
(*((void (*)(C *))((&b)->__vptrA[0]).f))((((C *)(char *)(&b)) + ((&b)->__vptrA[0]).d));
114114
}

tests/EduCfrontVtable7Test.expect

+2-2
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ int __main(void)
9898
{
9999
PinkLady delicious;
100100
Constructor_PinkLady((PinkLady *)&delicious);
101-
(*((void (*)(PinkLady *))((&delicious)->__vptrFruit[0]).f))((((PinkLady *)(char *)(&delicious)) + ((&delicious)->__vptrFruit[0]).d));
101+
(*((void (*)(PinkLady *))((&delicious)->__vptrFruit[1]).f))((((PinkLady *)(char *)(&delicious)) + ((&delicious)->__vptrFruit[1]).d));
102102
Fruit * f = (Fruit *)&delicious;
103-
(*((void (*)(Fruit *))((f)->__vptrFruit[0]).f))((((Fruit *)(char *)(f)) + ((f)->__vptrFruit[0]).d));
103+
(*((void (*)(Fruit *))((f)->__vptrFruit[1]).f))((((Fruit *)(char *)(f)) + ((f)->__vptrFruit[1]).d));
104104
return 0;
105105
(*((void (*)(PinkLady *))((&delicious)->__vptrFruit[0]).f))((((PinkLady *)(char *)(&delicious)) + ((&delicious)->__vptrFruit[0]).d));
106106
}

tests/Issue701.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// cmdlineinsights:-edu-show-cfront
2+
3+
#include <stdio.h>
4+
5+
struct Fruit {
6+
double mWeight{};
7+
virtual ~Fruit() { puts("~Fruit"); }
8+
virtual void Print() { puts("Fruit's Print"); }
9+
};
10+
11+
struct Apple : Fruit {
12+
int mRipeGrade{5};
13+
void Print() override { printf("Apple's Print: %d\n", mRipeGrade); }
14+
};
15+
16+
struct PinkLady : Apple {
17+
int mColorGrade{8};
18+
void Print() override { printf("Pink Ladies Print: %d\n", mColorGrade); }
19+
};
20+
21+
int main() {
22+
PinkLady delicious{};
23+
delicious.Print();
24+
Fruit *f{static_cast<Fruit *>(&delicious)};
25+
f->Print();
26+
}

tests/Issue701.expect

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*************************************************************************************
2+
* NOTE: This an educational hand-rolled transformation. Things can be incorrect or *
3+
* buggy. *
4+
*************************************************************************************/
5+
void __cxa_start(void);
6+
void __cxa_atexit(void);
7+
typedef int (*__vptp)();
8+
9+
struct __mptr
10+
{
11+
short d;
12+
short i;
13+
__vptp f;
14+
};
15+
16+
extern struct __mptr* __vtbl_array[];
17+
18+
19+
#include <stdio.h>
20+
21+
typedef struct Fruit
22+
{
23+
__mptr * __vptrFruit;
24+
double mWeight;
25+
} Fruit;
26+
27+
inline void Destructor_Fruit(Fruit * __this)
28+
{
29+
puts("~Fruit");
30+
}
31+
32+
inline void PrintFruit(Fruit * __this)
33+
{
34+
puts("Fruit's Print");
35+
}
36+
37+
inline Fruit * Constructor_Fruit(Fruit * __this)
38+
{
39+
__this->__vptrFruit = __vtbl_array[0];
40+
__this->mWeight = 0.0;
41+
return __this;
42+
}
43+
44+
45+
typedef struct Apple
46+
{
47+
__mptr * __vptrFruit;
48+
double mWeight;
49+
int mRipeGrade;
50+
} Apple;
51+
52+
inline void PrintApple(Apple * __this)
53+
{
54+
printf("Apple's Print: %d\n", __this->mRipeGrade);
55+
}
56+
57+
inline void Destructor_Apple(Apple * __this)
58+
{
59+
Destructor_Fruit((Fruit *)__this);
60+
}
61+
62+
inline Apple * Constructor_Apple(Apple * __this)
63+
{
64+
Constructor_Fruit((Fruit *)__this);
65+
__this->__vptrFruit = __vtbl_array[1];
66+
__this->mRipeGrade = 5;
67+
return __this;
68+
}
69+
70+
71+
typedef struct PinkLady
72+
{
73+
__mptr * __vptrFruit;
74+
double mWeight;
75+
int mRipeGrade;
76+
int mColorGrade;
77+
} PinkLady;
78+
79+
inline void PrintPinkLady(PinkLady * __this)
80+
{
81+
printf("Pink Ladies Print: %d\n", __this->mColorGrade);
82+
}
83+
84+
inline void Destructor_PinkLady(PinkLady * __this)
85+
{
86+
Destructor_Apple((Apple *)__this);
87+
}
88+
89+
inline PinkLady * Constructor_PinkLady(PinkLady * __this)
90+
{
91+
Constructor_Apple((Apple *)__this);
92+
__this->__vptrFruit = __vtbl_array[2];
93+
__this->mColorGrade = 8;
94+
return __this;
95+
}
96+
97+
98+
int __main(void)
99+
{
100+
PinkLady delicious;
101+
Constructor_PinkLady((PinkLady *)&delicious);
102+
(*((void (*)(PinkLady *))((&delicious)->__vptrFruit[1]).f))((((PinkLady *)(char *)(&delicious)) + ((&delicious)->__vptrFruit[1]).d));
103+
Fruit * f = (Fruit *)&delicious;
104+
(*((void (*)(Fruit *))((f)->__vptrFruit[1]).f))((((Fruit *)(char *)(f)) + ((f)->__vptrFruit[1]).d));
105+
return 0;
106+
(*((void (*)(PinkLady *))((&delicious)->__vptrFruit[0]).f))((((PinkLady *)(char *)(&delicious)) + ((&delicious)->__vptrFruit[0]).d));
107+
}
108+
109+
int main(void)
110+
{
111+
__cxa_start();
112+
int ret = __main();
113+
__cxa_atexit();
114+
return ret;
115+
/* ret // lifetime ends here */
116+
}
117+
118+
__mptr __vtbl_Fruit[2] = {{0, 0, (__vptp)Destructor_Fruit}, {0, 0, (__vptp)PrintFruit}};
119+
__mptr __vtbl_Apple[2] = {{0, 0, (__vptp)Destructor_Apple}, {0, 0, (__vptp)PrintApple}};
120+
__mptr __vtbl_PinkLady[2] = {{0, 0, (__vptp)Destructor_PinkLady}, {0, 0, (__vptp)PrintPinkLady}};
121+
122+
__mptr * __vtbl_array[3] = {__vtbl_Fruit, __vtbl_Apple, __vtbl_PinkLady};
123+
124+
void __cxa_start(void)
125+
{
126+
}
127+
128+
void __cxa_atexit(void)
129+
{
130+
}
131+

0 commit comments

Comments
 (0)