private void findVariablesInLine(ClangLine line, List<DecompilerReference> results) {

			List<ClangToken> allTokens = line.getAllTokens();
			Iterable<ClangToken> filteredTokens =
				IterableUtils.filteredIterable(allTokens, token -> {
					// Only include desirable tokens (this is really just for easier debugging).
					// Update this filter if the loop below ever needs other types of tokens.
					return (token instanceof ClangTypeToken) ||
						(token instanceof ClangVariableToken) || (token instanceof ClangFieldToken);
				});

			// gather any casts until we can use them (the type they modify will follow)
			List<DecompilerVariable> castsSoFar = new ArrayList<>();

			VariableDR declaration = null;
			VariableAccessDR access = null;
			for (ClangToken token : filteredTokens) {

				DtrfDbg.println(dbgPrefix + "checking token: " + token);

				if (token instanceof ClangTypeToken) {

					if (token.Parent() instanceof ClangReturnType) {
						DtrfDbg.println(dbgPrefix + "\treturn type: " + line);

						results.add(new ReturnTypeDR(line, (ClangTypeToken) token));
					}
					else if (token.isVariableRef()) {
						// Note: variable refs will get their variable in an upcoming token
						if (isFunctionPrototype(token.Parent())) {

							DtrfDbg.println(dbgPrefix + "\tparameter: " + line);

							declaration = new ParameterDR(line, (ClangTypeToken) token);
						}
						else {

							DtrfDbg.println(dbgPrefix + "\tlocal var: " + line);

							declaration = new LocalVariableDR(line, (ClangTypeToken) token);
						}

						results.add(declaration);
					}
					else {

						DtrfDbg.println(dbgPrefix + "\tadding a cast");

						// Assumption: this is a cast inside of a ClangStatement
						// Assumption: there can be multiple casts concatenated
						castsSoFar.add(new DecompilerVariableType(token));
					}
				}
				else if (token instanceof ClangVariableToken) {

					//
					// Observations:
					// 1) 'access' will be null if we are on a C statement that
					//    is a declaration (parameter or variable).  In this case,
					//    'declaration' will be an instance of VariableDR.
					// 2) 'access' will be null the first time a variable is used in
					//    a statement.
					// 3) if 'access' is non-null, but already has a variable assigned,
					//    then this means the current ClangVariableToken represents a new
					//    variable access/usage.
					//
					if (declaration != null) {

						DtrfDbg.println(dbgPrefix + "\thave declaration - " + declaration);

						declaration.setVariable((ClangVariableToken) token);
						declaration = null;
					}
					else {
						if (access == null || access.getVariable() != null) {

							DtrfDbg.println(dbgPrefix + "\tcreating variable access: " + line);

							access = new VariableAccessDR(line);
							results.add(access);
						}

						List<DecompilerVariable> casts = new ArrayList<>(castsSoFar);
						access.setVariable((ClangVariableToken) token, casts);
						castsSoFar.clear();
					}
				}
				else if (token instanceof ClangFieldToken) {

					List<DecompilerVariable> casts = new ArrayList<>(castsSoFar);

					if (access == null) {
						// Uh-oh.  I've only seen this when line-wrapping is happening.  In that
						// case, try to get the last variable that we've seen and assume that
						// is the variable to which this field belongs.
						access = getLastAccess(results);
						if (access == null) {
							Msg.debug(this,
								"Found a field access without a preceding " +
									"variable for\n\tline: " + line + "\n\tfield: " + token +
									"\n\tfunction: " + function);

							continue;
						}
					}

					ClangFieldToken field = (ClangFieldToken) token;
					if (typesDoNotMatch(access, field)) {

						DtrfDbg.println(
							dbgPrefix + "\tcreating an anonymous variable access: " + line);

						// this can happen when a field is used anonymously, such as directly
						// after a nested array index operation
						results.add(new AnonymousVariableAccessDR(line, field));
						continue;
					}

					access.addField(field, casts);
					castsSoFar.clear();
				}
			}
		}
Uses the given line to find variables (also parameters and return types) and any
accesses to them in that line.   A given variable may be used directly or, as in
the case with Composite types, may have one of its fields accessed.  Each result
found by this method will be at least a variable access and may also itself have
field accesses.

<p>Sometimes a line is structured such that there are anonymous variable accesses.  This
is the case where a Composite is being accessed, but the Composite itself is
not a variable in the current function.  See {@link AnonymousVariableAccessDR} for
more details.

@param line the current line being processed from the Decompiler
@param results the accumulator into which matches will be placed
Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/extension/datatype/finder/DecompilerDataTypeReferenceFinder.java