@Override
	public boolean applyTo(Program program, Address address, DemanglerOptions options,
			TaskMonitor monitor) throws Exception {

		// Account for register context.  This class may trigger disassembly, so we need to make
		// sure that the context is correctly set before that happens.  Also, be sure to apply
		// the function to the correct address.

		if (address.isMemoryAddress()) {
			address = PseudoDisassembler.setTargetContextForDisassembly(program, address);
		}

		if (!passesPreconditions(program, address)) {
			return true; // eventually will not return anything 
		}

		if (!super.applyTo(program, address, options, monitor)) {
			return false;
		}

		boolean disassemble = shouldDisassemble(program, address, options);
		Function function = createFunction(program, address, disassemble, monitor);
		if (function == null) {
			// No function whose signature we need to update
			return false;
		}

		if (function.isThunk()) {
			// If thunked function has same mangled name we can discard our
			// symbol if no other symbols at this address (i.e., rely entirely on
			// thunked function).
			// NOTE: mangled name on external may be lost once it is demangled.
			if (shouldThunkBePreserved(function)) {
				// Preserve thunk and remove mangled symbol.  Allow to proceed normally by returning true.
				function.getSymbol().setName(null, SourceType.DEFAULT);
				return true;
			}

			// Break thunk relationship and continue applying demangle function below
			function.setThunkedFunction(null);
		}

		// If existing function signature is user defined - add demangled label only
		boolean makePrimary = (function.getSignatureSource() != SourceType.USER_DEFINED);

		Symbol demangledSymbol =
			applyDemangledName(function.getEntryPoint(), makePrimary, false, program);
		if (demangledSymbol == null) {
			return false;
		}

		if (!options.applySignature() || function.getSignatureSource() == SourceType.USER_DEFINED) {
			return true;
		}

		boolean hasCallingConvention = !CompilerSpec.isUnknownCallingConvention(callingConvention);
		if (hasCallingConvention) {
			// Ensure that calling convention name exists and can be used
			ProgramBasedDataTypeManagerDB dtm =
				(ProgramBasedDataTypeManagerDB) program.getDataTypeManager();
			dtm.getCallingConventionID(callingConvention, false);
		}

		if (signatureSourceType == SourceType.DEFAULT) {
			// Only apply calling convention if specified with DEFAULT source
			if (hasCallingConvention) {
				function.setCallingConvention(callingConvention);
			}
			return true;
		}

		Structure classStructure =
			maybeUpdateCallingConventionAndCreateClass(program, function, options);

		FunctionDefinitionDataType signature = new FunctionDefinitionDataType(function, true);

		List<ParameterDefinitionImpl> args = convertMangledToParamDef(program);
		signature.setArguments(args.toArray(new ParameterDefinition[args.size()]));
		if (hasVarArgs()) {
			signature.setVarArgs(true);
		}
		if (!function.isExternal() && isParameterMismatch(function, signature)) {
			bookmarkParameterMismatch(program, function.getEntryPoint());
			return true;
		}

		DataType resolvedReturnType = resolveReturnType(program, function, classStructure);
		if (resolvedReturnType != null) {
			signature.setReturnType(resolvedReturnType);
		}

		ApplyFunctionSignatureCmd cmd = new ApplyFunctionSignatureCmd(function.getEntryPoint(),
			signature, signatureSourceType, true, false, DataTypeConflictHandler.DEFAULT_HANDLER,
			FunctionRenameOption.RENAME_IF_DEFAULT);
		cmd.applyTo(program);

		return true;
	}
This method assumes preconditions test has been run.
Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunction.java