List<LocalVariableConflict> determineLocalVariableInfoConflicts(Function[] functions,
			boolean autoMerge, FunctionVariableStorageConflicts storageConflicts,
			TaskMonitor monitor) throws CancelledException {
		monitor.checkCancelled();
		ArrayList<LocalVariableConflict> varConflictList = null;
		Address entry = (functions[LATEST] != null) ? functions[LATEST].getEntryPoint()
				: ((functions[MY] != null) ? functions[MY].getEntryPoint()
						: functions[ORIGINAL].getEntryPoint());
		Variable[] origLocals =
			(functions[ORIGINAL] != null) ? functions[ORIGINAL].getLocalVariables()
					: new Variable[0];
		Variable[] latestLocals =
			(functions[LATEST] != null) ? functions[LATEST].getLocalVariables() : new Variable[0];
		Variable[] myLocals =
			(functions[MY] != null) ? functions[MY].getLocalVariables() : new Variable[0];
		Arrays.sort(origLocals);
		Arrays.sort(latestLocals);
		Arrays.sort(myLocals);
		// Match up the variables by offset and firstUseOffset.
		MultiComparableArrayIterator<Variable> varIter = new MultiComparableArrayIterator<>(
			new Variable[][] { origLocals, latestLocals, myLocals });
		while (varIter.hasNext()) {
			Variable[] vars = varIter.next();
			Variable origVar = vars[ORIGINAL_VAR];
			Variable latestVar = vars[LATEST_VAR];
			Variable myVar = vars[MY_VAR];

			// if MultiComparableArrayIterator returns both latestVar and myVar their should be
			// no conflict since they must have the same storage to be matched-up
			if ((latestVar == null || myVar == null) && storageConflicts != null) {
				if (storageConflicts.isConflicted(latestVar, myVar)) {
					continue;
				}
			}

			int latestMyChanges = getVariableDiffs(latestVar, myVar);
			if (latestMyChanges == 0) {
				continue; // latest and my are same or both deleted 
			}

			boolean removedLatest = (origVar != null && latestVar == null);
			boolean removedMy = (origVar != null && myVar == null);
			int originalLatestChanges = getVariableDiffs(origVar, latestVar);
			int originalMyChanges = getVariableDiffs(origVar, myVar);
			int varConflicts = 0;

			if ((removedLatest && (originalMyChanges != 0)) ||
				(removedMy && (originalLatestChanges != 0))) {
				varConflicts |= VAR_REMOVED;
			}
			else if (removedMy) {
				if (autoMerge && !removedLatest) {
					// Auto merge variable removal 
					getMergeMy().replaceFunctionVariable(entry, origVar, monitor);
				}
				continue;
			}
			else if (origVar == null && myVar != null && latestVar == null) {
				if (autoMerge) {
					// Auto merge variable added to MY function
					getMergeMy().replaceFunctionVariable(entry, myVar, monitor);
				}
				continue;
			}
			else {

//			varConflicts |=
//				determineVariableConflict(entry, VAR_TYPE, myVar, latestMyChanges,
//					originalLatestChanges, originalMyChanges, monitor);
//			if (varConflicts == 0) {
				varConflicts |= determineVariableConflict(entry, VAR_NAME, myVar, latestMyChanges,
					originalLatestChanges, originalMyChanges, autoMerge, monitor);
				varConflicts |= determineVariableConflict(entry, VAR_DATATYPE, myVar,
					latestMyChanges, originalLatestChanges, originalMyChanges, autoMerge, monitor);
//			varConflicts |=
//				determineVariableConflict(entry, VAR_LENGTH, myVar, latestMyChanges,
//					originalLatestChanges, originalMyChanges, autoMerge, monitor);
				varConflicts |= determineVariableConflict(entry, VAR_COMMENT, myVar,
					latestMyChanges, originalLatestChanges, originalMyChanges, autoMerge, monitor);
//				varConflicts |=
//					determineVariableConflict(entry, VAR_FIRST_USE, myVar, latestMyChanges,
//						originalLatestChanges, originalMyChanges, monitor);
//			varConflicts |=
//				determineVariableConflict(entry, VAR_STORAGE, myVar, latestMyChanges,
//					originalLatestChanges, originalMyChanges, autoMerge, monitor);
//				varConflicts |=
//					determineVariableConflict(entry, VAR_ORDINAL, myVar, latestMyChanges,
//						originalLatestChanges, originalMyChanges, monitor);
//				varConflicts |=
//					determineVariableConflict(entry, VAR_REGISTER, myVar, latestMyChanges,
//						originalLatestChanges, originalMyChanges, monitor);
			}
			if (varConflicts != 0) {
				if (varConflictList == null) {
					varConflictList = new ArrayList<>();
				}
				varConflictList.add(new LocalVariableConflict(entry, vars, varConflicts));
			}
		}
		if (varConflictList != null) {
			saveFunctionDetailConflict(functions, FUNC_LOCAL_DETAILS);
		}
		return varConflictList;
	}
Determines differences between two variables.
@param var1 the first variable
@param var2 the second variable
@return an int with bits set indicating where the two variables differ.
Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/AbstractFunctionMerger.java