@Override
	public boolean applyTo(Program program, TaskMonitor monitor) {

		try {

			// Check destination functions within set
			SymbolTable symbolTable = program.getSymbolTable();
			SymbolIterator fnSymbols = symbolTable.getSymbols(set, SymbolType.FUNCTION, true);
			while (fnSymbols.hasNext()) {
				monitor.checkCancelled();
				Symbol s = fnSymbols.next();
				Address entry = s.getAddress();

				processFunctionJumpReferences(program, entry, monitor);
			}

			if (assumeContiguousFunctions) {
				// assume if checkAllJumpReferences then set is much more than new function starts

				AddressSet jumpScanSet = new AddressSet();

				fnSymbols = symbolTable.getSymbols(set, SymbolType.FUNCTION, true);
				while (fnSymbols.hasNext()) {
					monitor.checkCancelled();
					Symbol s = fnSymbols.next();
					checkAboveFunction(s, jumpScanSet);
					checkBelowFunction(s, jumpScanSet);
				}

				// Used for caching forward/backward function lookups as we
				// move forward through jump references
				Address functionAfterSrc = null;
				Address functionBeforeSrc = null;

				ReferenceManager refMgr = program.getReferenceManager();
				AddressIterator refSrcIter = refMgr.getReferenceSourceIterator(jumpScanSet, true);
				while (refSrcIter.hasNext()) {
					monitor.checkCancelled();
					Address srcAddr = refSrcIter.next();
					RefType flow = null;
					Address destAddr = null;
					for (Reference ref : refMgr.getReferencesFrom(srcAddr)) {
						RefType refType = ref.getReferenceType();
						if (refType.isFlow()) {
							if (flow != null) {
								// ignore points with multiple flows
								break;
							}
							flow = refType;
							destAddr = ref.getToAddress();
						}
					}
					if (destAddr == null || flow == null || !flow.isJump() ||
						!flow.isUnConditional()) {
						continue;
					}
					if (srcAddr.getAddressSpace() != destAddr.getAddressSpace()) {
						continue; // can't handle flows between different spaces/overlays
					}

					// Reset cached functions if we transition to a different space/overlay
					if (functionAfterSrc != null &&
						functionAfterSrc.getAddressSpace() != srcAddr.getAddressSpace()) {
						functionAfterSrc = null;
					}
					if (functionBeforeSrc != null &&
						functionBeforeSrc.getAddressSpace() != srcAddr.getAddressSpace()) {
						functionBeforeSrc = null;
					}

					if (srcAddr.compareTo(destAddr) < 0) {
						// forward jump
						if (functionAfterSrc == Address.NO_ADDRESS) {
							continue; // no function after srcAddr
						}
						if (functionAfterSrc == null || functionAfterSrc.compareTo(srcAddr) <= 0) {
							Function nextFunction = getFunctionAfter(program, srcAddr);
							if (nextFunction != null) {
								functionAfterSrc = nextFunction.getEntryPoint();
							}
							else {
								functionAfterSrc = Address.NO_ADDRESS;
								continue; // no function after srcAddr
							}
						}
						if (destAddr.compareTo(functionAfterSrc) >= 0) {
							createFunction(program, destAddr, monitor);
						}
					}
					else {

						// prime lastFunctionAfterSrc if not previously set
						if (functionAfterSrc == null) {
							Function nextFunction = getFunctionAfter(program, srcAddr);
							if (nextFunction != null) {
								functionAfterSrc = nextFunction.getEntryPoint();
							}
							else {
								functionAfterSrc = Address.NO_ADDRESS;
							}
						}

						// backward jump
						if (functionBeforeSrc == Address.NO_ADDRESS) {
							if (functionAfterSrc == Address.NO_ADDRESS) {
								continue; // no functions exist - rare
							}
							if (srcAddr.compareTo(functionAfterSrc) < 0) {
								continue; // we have not passed next function - no function before
							}
							functionBeforeSrc = null; // must re-query - lastFunctionAfterSrc is also invalid
							Function nextFunction = getFunctionAfter(program, srcAddr);
							if (nextFunction != null) {
								functionAfterSrc = nextFunction.getEntryPoint();
							}
							else {
								functionAfterSrc = Address.NO_ADDRESS;
							}
						}

						// if we have not passed lastFunctionAfter then no change to lastFunctionBefore
						if (functionBeforeSrc != null && (functionAfterSrc == Address.NO_ADDRESS ||
							srcAddr.compareTo(functionAfterSrc) < 0)) {
							// we have not passed lastFunctionAfterSrc - no change to lastFunctionBeforeSrc
						}
						else {
							Function prevFunction = getFunctionBefore(program, srcAddr);
							if (prevFunction != null) {
								functionBeforeSrc = prevFunction.getEntryPoint();
							}
							else {
								functionBeforeSrc = Address.NO_ADDRESS;
								continue; // no function before srcAddr
							}
						}

						if (destAddr.compareTo(functionBeforeSrc) < 0) {
							createFunction(program, destAddr, monitor);
						}

					}
				}
			}

		}
		catch (CancelledException e) {
			// ignore
		}

		return true;
	}
Constructor
@param set set of addresses over which destination functions will be
examined for Jump reference to those functions.
@param assumeContiguousFunctions if true it will be assumed that any unconditional
jump over another function will trigger a call-return override and the creation of
@param considerConditionalBranches if true conditional jumps can also be considered for jumping
to another function as a shared return.
a function at the destination.
Ghidra/Features/Base/src/main/java/ghidra/app/cmd/analysis/SharedReturnAnalysisCmd.java