private LinkedHashMap<ClassID, List<ClassID>> depthFirstVirtualBases() {

		if (depthFirstVirtualBases != null) {
			return depthFirstVirtualBases;
		}
		depthFirstVirtualBases = new LinkedHashMap<>();

		for (DirectLayoutBaseClass base : directLayoutBaseClasses) {
			CppCompositeType bt = base.getBaseClassType();
			LinkedHashMap<ClassID, List<ClassID>> baseResults = bt.depthFirstVirtualBases();
			// It is bad to replace an existing entry: we are counting on the parentage of the
			//  first one that occurs.  Thus, we need to inspect and add them one at a time instead
			//  of using addAll().
			for (Map.Entry<ClassID, List<ClassID>> entry : baseResults.entrySet()) {
				if (!depthFirstVirtualBases.containsKey(entry.getKey())) {
					depthFirstVirtualBases.put(entry.getKey(), entry.getValue());
				}
			}
		}
		// If we have a vbt for this class in memory, we can properly place all virtual (direct
		//  and indirect) for this class.  Problem is if we don't have a vbt in program memory,
		//  the problem cannot be solved appropriately.
		// Problem is that MSFT PDB reports all DirectBases (non-virtual)  first, followed by all
		//  DirectVirtualBases, followed by all IndirectVirtualBases.  But by doing so, they
		//  throw away useful information regarding the order of defined base classes for this
		//  class.  The PDB contents won't distinguish between
		//     class A : B, virtual C
		//       and
		//     class A : virtual C, B
		//  ... but these classes can lay out differently when B has its own virtual class(es).
		// The indirect virtual bases cloud things even further.  The direct virtual bases
		//  and indirect virtual base (we call both of these, collectively, virtual bases) will
		//  have representation in the main vbt for this class, and depending on the definition
		//  hierarchy direct virtual bases can intermingled with the indirect virtual bases.
		// We essentially walk the hierarchy of direct non-virtual bases and direct virtual bases
		//  to craft our own list of indirect virtual bases to try to help with this, and it seems
		//  to help a little.  We only use the PDB-provided indirect virtual bases for when
		//  finding the offset of the base using the vbt (when we have a real vbt in program
		//  memory).
		// This algorithm is meant to try its best to help when we don't have a vbt in program
		//  memory.
		for (VirtualLayoutBaseClass base : virtualLayoutBaseClasses) {
			CppCompositeType bt = base.getBaseClassType();
			LinkedHashMap<ClassID, List<ClassID>> baseResults = bt.depthFirstVirtualBases();
			// It is bad to replace an existing entry: we are counting on the parentage of the
			//  first one that occurs.  Thus, we need to inspect and add them one at a time instead
			//  of using addAll().
			for (Map.Entry<ClassID, List<ClassID>> entry : baseResults.entrySet()) {
				if (!depthFirstVirtualBases.containsKey(entry.getKey())) {
					depthFirstVirtualBases.put(entry.getKey(), entry.getValue());
				}
			}
		}
		for (DirectVirtualLayoutBaseClass base : directVirtualLayoutBaseClasses) {
			CppCompositeType bt = base.getBaseClassType();
			ClassID baseId = bt.getClassId();
			ArrayList<ClassID> baseParentage = new ArrayList<>(List.of(baseId));
			depthFirstVirtualBases.put(baseId, baseParentage);
		}
		// add self to all parentage
		for (List<ClassID> parentage : depthFirstVirtualBases.values()) {
			parentage.addFirst(myId);
		}
		return depthFirstVirtualBases;
	}
Returns depth-first occurrences of ClassIDs along with their parentage with the assumption
that all direct (non-virtual) base classes occur before direct virtual base classes.
It is also presumed that the list of direct virtual base classes for any class are found
in their definition correct order (though might be interspersed with direct non-virtual
bases in the actual definition)
@return the ClassIDs and corresponding parentages (referred to by their ClassIDs)
Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/CppCompositeType.java