private void assignParentClassToVftables(List<RecoveredClass> recoveredClasses)
			throws Exception {

		for (RecoveredClass recoveredClass : recoveredClasses) {
			monitor.checkCancelled();
			if (!recoveredClass.hasVftable()) {
				continue;
			}

			List<Address> vftableAddresses = recoveredClass.getVftableAddresses();
			if (vftableAddresses.size() == 0) {
				continue;
			}

			List<RecoveredClass> parentsWithVirtualFunctions =
				getParentsWithVirtualFunctions(recoveredClass);
			if (parentsWithVirtualFunctions.size() == 0) {
				continue;
			}

			List<RecoveredClass> ancestorsAllowedToMap = new ArrayList<RecoveredClass>();

			List<RecoveredClass> ancestorsWithoutVfunctions =
				getAncestorsWithoutVfunctions(recoveredClass);

			// case where more than one parent with virtual functions and class has multiple 
			// virtual inheritance, ie the diamond case, need to remove parents with common
			// ancestors from parent list and replace with the common ancestor
			if (recoveredClass.hasMultipleVirtualInheritance()) {
				// need to find common ancestor inherited in the diamond shape and replace
				// the parents that use it with the ancestor. The resulting list should 
				// equal the number of vftables
				ancestorsAllowedToMap = replaceParentsWithCommonAncestor(recoveredClass);
				ancestorsAllowedToMap.removeAll(ancestorsWithoutVfunctions);
				mapVftablesToParents(recoveredClass, ancestorsAllowedToMap);
				continue;
			}

			// case where class has multiple inheritance flag because an ancestor has mult inheritance but
			// TODO: pull into separate method
			if (recoveredClass.hasMultipleInheritance() &&
				recoveredClass.getClassHierarchyMap().size() == 1 &&
				recoveredClass.getVftableAddresses().size() > 1) {

				List<RecoveredClass> parents =
					new ArrayList<RecoveredClass>(recoveredClass.getClassHierarchyMap().keySet());
				RecoveredClass singleParent = parents.get(0);
				List<RecoveredClass> grandParents = getParentsWithVirtualFunctions(singleParent);
				// check that they both have vftables 
				// get their order from the class hierarchy list
				// first see if it has a parent order map and just make it the same one 

				if (grandParents.size() == recoveredClass.getVftableAddresses().size()) {
					// get the sorted order of vftables
					Map<Integer, Address> orderToVftableMap = recoveredClass.getOrderToVftableMap();
					List<Integer> sortedOrder = new ArrayList<Integer>(orderToVftableMap.keySet());
					Collections.sort(sortedOrder);

					int order = 0;
					// iterate over the hierarchy list and use it to get the order of the parentsParents and assign
					// to correct vftable
					List<RecoveredClass> classHierarchy = recoveredClass.getClassHierarchy();
					for (RecoveredClass ancestor : classHierarchy) {
						monitor.checkCancelled();
						if (grandParents.contains(ancestor)) {
							Integer index = sortedOrder.get(order);
							Address vftableAddress = orderToVftableMap.get(index);
							recoveredClass.addVftableToBaseClassMapping(vftableAddress, ancestor);
							order++;
						}
					}

				}

				continue;
			}

			if (recoveredClass.hasSingleInheritance() &&
				recoveredClass.getParentList().size() == 1 &&
				recoveredClass.getVftableAddresses().size() == 2) {

				// case 1: class's direct parent is virtually inherited and has vtable
				// first Vftable is mapped to null parent because it is used in class struct by current class
				// second is mapped to first virtual ancestor with vftable  

				// case 2: class's direct parent is non-virt with vtable, it has ancestor that is virtual with vftable
				// use the mapping function to map correct parent to correct vftable

				// case multiple vftables and there is only one parent that is virtually inherited
				// one vftable is used for current class and one for the virt in
				RecoveredClass virtualAncestorWithVfunctions =
					getFirstVirtuallyInheritedAncestorWithVfunctions(recoveredClass);

				if (virtualAncestorWithVfunctions != null) {

					//RecoveredClass parentClass = recoveredClass.getParentClass();

					RecoveredClass parentClass = recoveredClass.getParentList().get(0);

					if (virtualAncestorWithVfunctions.equals(parentClass)) {

						// map the current class to the first vftable
						recoveredClass.addVftableToBaseClassMapping(
							recoveredClass.getVftableAddresses().get(0), recoveredClass);
						// map the virtual parent to the second vftable
						recoveredClass.addVftableToBaseClassMapping(
							recoveredClass.getVftableAddresses().get(1), parentClass);
						continue;
					}

					// map the non-virtual parent to the first vftable
					recoveredClass.addVftableToBaseClassMapping(
						recoveredClass.getVftableAddresses().get(0), parentClass);
					// map the first virtual ancestor to the second vftable 
					recoveredClass.addVftableToBaseClassMapping(
						recoveredClass.getVftableAddresses().get(1), virtualAncestorWithVfunctions);
					continue;

				}

			}

			// the rest should work for both single and regular multiple inheritance 			
			ancestorsAllowedToMap = parentsWithVirtualFunctions;

			// when only one direct parent with virtual functions, map the vftable to that parent 
			if (ancestorsAllowedToMap.size() == 1 && vftableAddresses.size() == 1) {
				recoveredClass.addVftableToBaseClassMapping(
					recoveredClass.getVftableAddresses().get(0), ancestorsAllowedToMap.get(0));
				continue;
			}

			// All other cases where the number of vftables should equal the number of 
			// parents (virtual or otherwise) 
			mapVftablesToParents(recoveredClass, ancestorsAllowedToMap);

		}

	}
Method to create vftable address and parent class map for each class object
@param recoveredClasses list of class objects
@throws Exception when cancelled
Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIWindowsClassRecoverer.java