3535#include " llvm/Support/Debug.h"
3636#include " llvm/Support/raw_os_ostream.h"
3737
38+ #include < map>
3839#include < set>
3940#include < sstream>
4041#include < string>
@@ -1222,20 +1223,22 @@ namespace Cpp {
12221223 return 0 ;
12231224 }
12241225
1225- intptr_t GetVariableOffset (compat::Interpreter& I, Decl* D) {
1226+ intptr_t GetVariableOffset (compat::Interpreter& I, Decl* D,
1227+ CXXRecordDecl* BaseCXXRD) {
12261228 if (!D)
12271229 return 0 ;
12281230
12291231 auto & C = I.getSema ().getASTContext ();
12301232
12311233 if (auto * FD = llvm::dyn_cast<FieldDecl>(D)) {
1232- const clang::RecordDecl* RD = FD->getParent ();
1234+ clang::RecordDecl* FieldParentRecordDecl = FD->getParent ();
12331235 intptr_t offset =
12341236 C.toCharUnitsFromBits (C.getFieldOffset (FD)).getQuantity ();
1235- while (RD->isAnonymousStructOrUnion ()) {
1236- const clang::RecordDecl* anon = RD;
1237- RD = llvm::dyn_cast<RecordDecl>(anon->getParent ());
1238- for (auto F = RD->field_begin (); F != RD->field_end (); ++F) {
1237+ while (FieldParentRecordDecl->isAnonymousStructOrUnion ()) {
1238+ clang::RecordDecl* anon = FieldParentRecordDecl;
1239+ FieldParentRecordDecl = llvm::dyn_cast<RecordDecl>(anon->getParent ());
1240+ for (auto F = FieldParentRecordDecl->field_begin ();
1241+ F != FieldParentRecordDecl->field_end (); ++F) {
12391242 const auto * RT = F->getType ()->getAs <RecordType>();
12401243 if (!RT)
12411244 continue ;
@@ -1246,6 +1249,46 @@ namespace Cpp {
12461249 }
12471250 offset += C.toCharUnitsFromBits (C.getFieldOffset (FD)).getQuantity ();
12481251 }
1252+ if (BaseCXXRD && BaseCXXRD != FieldParentRecordDecl) {
1253+ // FieldDecl FD belongs to some class C, but the base class BaseCXXRD is
1254+ // not C. That means BaseCXXRD derives from C. Offset needs to be
1255+ // calculated for Derived class
1256+
1257+ // Depth first Search is performed to the class that declears FD from
1258+ // the base class
1259+ std::vector<CXXRecordDecl*> stack;
1260+ std::map<CXXRecordDecl*, CXXRecordDecl*> direction;
1261+ stack.push_back (BaseCXXRD);
1262+ while (!stack.empty ()) {
1263+ CXXRecordDecl* RD = stack.back ();
1264+ stack.pop_back ();
1265+ size_t num_bases = GetNumBases (RD);
1266+ bool flag = false ;
1267+ for (size_t i = 0 ; i < num_bases; i++) {
1268+ auto * CRD = static_cast <CXXRecordDecl*>(GetBaseClass (RD, i));
1269+ direction[CRD] = RD;
1270+ if (CRD == FieldParentRecordDecl) {
1271+ flag = true ;
1272+ break ;
1273+ }
1274+ stack.push_back (CRD);
1275+ }
1276+ if (flag)
1277+ break ;
1278+ }
1279+ if (auto * RD = llvm::dyn_cast<CXXRecordDecl>(FieldParentRecordDecl)) {
1280+ // add in the offsets for the (multi level) base classes
1281+ while (BaseCXXRD != RD) {
1282+ CXXRecordDecl* Parent = direction.at (RD);
1283+ offset += C.getASTRecordLayout (Parent)
1284+ .getBaseClassOffset (RD)
1285+ .getQuantity ();
1286+ RD = Parent;
1287+ }
1288+ } else {
1289+ assert (false && " Unreachable" );
1290+ }
1291+ }
12491292 return offset;
12501293 }
12511294
@@ -1321,9 +1364,11 @@ namespace Cpp {
13211364 return 0 ;
13221365 }
13231366
1324- intptr_t GetVariableOffset (TCppScope_t var) {
1367+ intptr_t GetVariableOffset (TCppScope_t var, TCppScope_t parent ) {
13251368 auto * D = static_cast <Decl*>(var);
1326- return GetVariableOffset (getInterp (), D);
1369+ auto * RD =
1370+ llvm::dyn_cast_or_null<CXXRecordDecl>(static_cast <Decl*>(parent));
1371+ return GetVariableOffset (getInterp (), D, RD);
13271372 }
13281373
13291374 // Check if the Access Specifier of the variable matches the provided value.
0 commit comments