private void updateStructure(long sourceDtID, Structure sourceDt, Structure destStruct,
			MyIdentityHashMap<Long, DataType> resolvedDataTypes) {

		// NOTE: it is possible for the same destStruct to be updated more than once;
		// therefor we must cleanup any previous obsolete fixups
		removeFixUps(sourceDtID);

// TODO: Preserve timestamp?

		// Get an empty destination structure that is the correct size.
		destStruct.deleteAll();

		// Set to correct alignment and packing.
		updateAlignment(sourceDt, destStruct);

		DataTypeManager sourceDTM = sourceDt.getDataTypeManager();
		boolean packed = sourceDt.isPackingEnabled();

		// Add each of the defined components back in.
		DataTypeComponent[] comps = sourceDt.getDefinedComponents();

		// Component sequence must be flipped for components that share the same offset
		// (i.e., when zero-length components exist) to ensure that the insert at offset
		// does not alter the intended order.
		List<DataTypeComponent> compList = new ArrayList<>();
		int prevOffset = -1;
		int index = -1;
		for (DataTypeComponent dtc : comps) {
			int offset = dtc.getOffset();
			if (offset == prevOffset) {
				compList.add(index, dtc);
			}
			else {
				prevOffset = offset;
				index = compList.size();
				compList.add(dtc);
			}
		}
		comps = null; // prevent improper use

		// Track dependency errors to avoid duplicate popups
		HashMap<Long, String> badIdDtMsgs = new HashMap<>();

		for (int i = 0; i < compList.size(); i++) {

			DataTypeComponent sourceComp = compList.get(i);

			DataType sourceCompDt = sourceComp.getDataType();
			BitFieldDataType bfDt = null;
			String comment = sourceComp.getComment();
			DataType resultCompDt = null;

			if (sourceComp.isBitFieldComponent()) {
				// NOTE: primitive type will be used if unable to resolve base type
				bfDt = (BitFieldDataType) sourceCompDt;
				sourceCompDt = bfDt.getBaseDataType();
				if (sourceCompDt instanceof AbstractIntegerDataType) {
					resultCompDt = sourceCompDt.clone(dtms[RESULT]);
				}
			}

			long sourceComponentID = sourceDTM.getID(sourceCompDt);

			// Try to get a mapping of the source data type to a result data type.
			if (resultCompDt == null) {
				resultCompDt = getResolvedComponent(sourceComponentID, resolvedDataTypes);
			}

			if (resultCompDt == null) {
				// We didn't have a map entry for the data type.
				if (!myDtAddedList.contains(Long.valueOf(sourceComponentID))) {
					// Not added so should be in result if it wasn't deleted there.
					resultCompDt = dtms[RESULT].getDataType(sourceComponentID);
				}
				if (resultCompDt == null) {
					// Not added/resolved yet
					// put an entry in the fixup list
					fixUpList.add(new FixUpInfo(sourceDtID, sourceComponentID,
						sourceComp.getOrdinal(), sourceComp, resolvedDataTypes));
					fixUpIDSet.add(sourceDtID);
				}
				if (bfDt != null &&
					(resultCompDt == null || !BitFieldDataType.isValidBaseDataType(resultCompDt))) {
					// use primitive type as fixup placeholder
					resultCompDt = bfDt.getPrimitiveBaseDataType();
				}
			}

			if (resultCompDt != null && !resultCompDt.isDeleted()) {

				long dtId = dtms[RESULT].getID(resultCompDt);
				String badMsg = badIdDtMsgs.get(Long.valueOf(dtId));

				int length = resultCompDt.getLength();
				if (length <= 0) {
					length = sourceComp.getLength();
				}

				// There is a matching component data type in the result.
				if (packed) {
					if (bfDt != null) {
						try {
							destStruct.addBitField(resultCompDt, bfDt.getDeclaredBitSize(),
								sourceComp.getFieldName(), comment);
						}
						catch (InvalidDataTypeException e) {
							displayError(destStruct, e);
							// Try again with primitive base type
							DataType primitiveBaseDt = bfDt.getPrimitiveBaseDataType();
							comment = buildDataTypeFailureComment(sourceCompDt, e.getMessage(),
								sourceComp.getComment());
							try {
								destStruct.addBitField(primitiveBaseDt, bfDt.getDeclaredBitSize(),
									sourceComp.getFieldName(), comment);
							}
							catch (InvalidDataTypeException exc) {
								throw new RuntimeException(exc); // unexpected
							}
						}
					}
					else if (badMsg == null) {
						try {
							// If I have compDt, it should now be from result DTM.
							destStruct.add(resultCompDt, length, sourceComp.getFieldName(),
								comment);
						}
						catch (IllegalArgumentException e) {
							comment =
								buildDataTypeFailureComment(sourceCompDt, e.getMessage(), comment);
							destStruct.add(BadDataType.dataType, sourceComp.getLength(),
								sourceComp.getFieldName(), comment);
							if (e.getCause() instanceof DataTypeDependencyException) {
								badIdDtMsgs.put(dtId, e.getMessage());
							}
							displayError(destStruct, e);
						}
					}
					else {
						// Preserve non-fixup ordinal with bad placeholder
						comment = buildDataTypeFailureComment(sourceCompDt, badMsg, comment);
						destStruct.add(BadDataType.dataType, sourceComp.getLength(),
							sourceComp.getFieldName(), badMsg + "; " + comment);
					}
				}
				else if (bfDt != null) {
					// non-packed bitfield
					try {
						destStruct.insertBitFieldAt(sourceComp.getOffset(), sourceComp.getLength(),
							bfDt.getBitOffset(), resultCompDt, bfDt.getDeclaredBitSize(),
							sourceComp.getFieldName(), comment);
					}
					catch (InvalidDataTypeException e) {
						displayError(destStruct, e);
						// Try again with primitive base type
						DataType primitiveBaseDt = bfDt.getPrimitiveBaseDataType();
						comment = buildDataTypeFailureComment(sourceCompDt, e.getMessage(),
							sourceComp.getComment());
						try {
							destStruct.addBitField(primitiveBaseDt, bfDt.getDeclaredBitSize(),
								sourceComp.getFieldName(), comment);
						}
						catch (InvalidDataTypeException exc) {
							throw new RuntimeException(exc); // unexpected
						}
					}
				}
				else {
					// normal non-packed component
					if (badMsg == null) {
						try {
							// If not last component must constrain length to original component size
							if (i < compList.size() - 1) {
								int offset = sourceComp.getOffset();
								DataTypeComponent nextDtc = compList.get(i + 1);
								int available = nextDtc.getOffset() - offset;
								if (length > available) {
									// The data type is too big, so adjust the component length to what will fit.
									int extraBytesNeeded = length - available;
									length = available;
									// Output a warning indicating the structure has a data type that doesn't fit.
									String message =
										"Structure Merge: Not enough undefined bytes to fit " +
											resultCompDt.getPathName() + " in structure " +
											destStruct.getPathName() + " at offset 0x" +
											Integer.toHexString(offset) + "." + "\nIt needs " +
											extraBytesNeeded + " more byte(s) to be able to fit.";
									Msg.warn(this, message);
								}
							}

							destStruct.insertAtOffset(sourceComp.getOffset(), resultCompDt, length,
								sourceComp.getFieldName(), comment);
						}
						catch (IllegalArgumentException e) {
							comment =
								buildDataTypeFailureComment(sourceCompDt, e.getMessage(), comment);
							destStruct.insertAtOffset(sourceComp.getOffset(), BadDataType.dataType,
								length, sourceComp.getFieldName(), comment);

							if (e.getCause() instanceof DataTypeDependencyException) {
								badIdDtMsgs.put(dtId, e.getMessage());
							}
							displayError(destStruct, e);
						}
					}
					else {
						// Preserve non-fixup ordinal with bad placeholder
						comment = buildDataTypeFailureComment(sourceCompDt, badMsg, comment);
						destStruct.insertAtOffset(sourceComp.getOffset(), BadDataType.dataType,
							sourceComp.getLength(), sourceComp.getFieldName(), comment);
					}
				}
			}
			else if (packed) {
				// Add fixup placeholder to prevent the ordinal values and component sizes from 
				// changing.  Nothing we can do about packing which may be affected.
				// These should get fixed-up later.
				destStruct.add(BadDataType.dataType, sourceComp.getLength(),
					sourceComp.getFieldName(), comment);
			}
			else {
				// Add fixup placeholder to prevent the ordinal values and component sizes from 
				// changing.  These should get fixed-up later.
				destStruct.insertAtOffset(sourceComp.getOffset(), BadDataType.dataType,
					sourceComp.getLength(), sourceComp.getFieldName(), comment);
			}
		}
		if (!packed) {
			adjustStructureSize(destStruct, sourceDt.getLength());
		}
	}
Compute the next non-packed component ordinal based upon the newly minted result
component {@code resultDtc} and the offset of the next source component based upon
the specified source component list {@code compList} and the current component
index.
@param resultDtc newly minted result component
@param compList source component list
@param index index of current source component
@return next result component ordinal
Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java