static void studyCompositeForwardReferenceAndDefinition(AbstractPdb pdb, TaskMonitor monitor)
			throws CancelledException {
		int indexNumber = pdb.getTypeProgramInterface().getTypeIndexMin();
		int indexLimit = pdb.getTypeProgramInterface().getTypeIndexMaxExclusive();
		int num = indexLimit - indexNumber;
		boolean covered[] = new boolean[indexLimit];

		monitor.initialize(num);
		monitor.setMessage("Study: NAMES_START " + (indexLimit - indexNumber));
		PdbLog.message("STUDY_START: studyCompositeFwdRefDef");
		//System.out.println("STUDY_START");
		while (indexNumber < indexLimit) {
			monitor.checkCancelled();
			if (!covered[indexNumber]) {
				AbstractMsType type = pdb.getTypeRecord(RecordNumber.typeRecordNumber(indexNumber));
				covered[indexNumber] = true;
				String name = getSpecialRecordStart(type);
				if (name != null) {
					MsProperty p;
					String ps;
					int c;
					boolean isForwardReference = false;
					Map<Integer, Set<String>> map = new HashMap<>();
					if (type instanceof AbstractCompositeMsType) {
						AbstractCompositeMsType compType = (AbstractCompositeMsType) type;
						c = compType.getNumElements();
						p = compType.getMsProperty();
						isForwardReference = p.isForwardReference();
						if (c == 0 && !isForwardReference) {
							doNothingSetBreakPointHere();
							// For PDBs that we have looked at, if count is zero
							// for a forward reference, then the field list record number is zero;
							// if count is zero for a definition, then, the field list record
							// number refers to an actual field list.
							// So... seems we can trust forward reference and ignore count.
							if (compType
									.getFieldDescriptorListRecordNumber() == RecordNumber.NO_TYPE) {
								doNothingSetBreakPointHere();
							}
						}
						else if (c != 0 && isForwardReference) {
							doNothingSetBreakPointHere();
						}
//					ps = c + (p.isForwardReference() ? "fwdref" : "");
					}
					else { //type instanceof AbstractEnumMsType
						AbstractEnumMsType enumType = (AbstractEnumMsType) type;
						c = 0; // made up.
//					p = enumType.getMsProperty();
//					ps = p.toString();
					}
					ps = type.toString();
					Set<String> set = new HashSet<>();
					set.add(ps);
					map.put(c, set);
					PdbLog.message(
						"----------\n" + name + "\n" + c + (isForwardReference ? " fwdref" : ""));
					//System.out.println("----------\n" + name + "\n" + c);
					int innerIndexNumber = indexNumber + 1;
					while (innerIndexNumber < indexLimit) {
						monitor.checkCancelled();
						if (!covered[innerIndexNumber]) {
							AbstractMsType innerType =
								pdb.getTypeRecord(RecordNumber.typeRecordNumber(innerIndexNumber));
							String innerName = getSpecialRecordStart(innerType);
							if (name.equals(innerName)) {
								covered[innerIndexNumber] = true;
								isForwardReference = false;
								if (type instanceof AbstractCompositeMsType) {
									AbstractCompositeMsType compType =
										(AbstractCompositeMsType) innerType;
									c = compType.getNumElements();
									p = compType.getMsProperty();
									isForwardReference = p.isForwardReference();
									if (c == 0 && !isForwardReference) {
										// For PDBs that we have looked at, if count is zero
										// for a forward reference, then the field list record
										// number is zero; if count is zero for a definition, then,
										// the field list record number refers to an actual field
										// list. So... seems we can trust forward reference and
										// ignore count.
										if (compType
												.getFieldDescriptorListRecordNumber() == RecordNumber.NO_TYPE) {
											doNothingSetBreakPointHere();
										}
									}
									else if (c != 0 && isForwardReference) {
										doNothingSetBreakPointHere();
									}
//								ps = c + (p.isForwardReference() ? "fwdref" : "");
								}
								else { //type instanceof AbstractEnumMsType
									AbstractEnumMsType enumType = (AbstractEnumMsType) type;
									c = 0; // made up.
//								p = enumType.getMsProperty();
//								ps = "" + c;
								}
								String psi = innerType.toString();
								set = map.get(c);
								String message = "";
								if (set == null) {
									set = new HashSet<>();
									map.put(c, set);
									set.add(psi);
								}
								else if (!set.contains(psi)) { // conflict
									message = " <-- conflict";
									set.add(psi);
								}
								else {
									message = " <-- repeat";
								}
								PdbLog.message(c + (isForwardReference ? " fwdref" : "") + message);
								if (c == 0 && isForwardReference) {
									PdbLog.message("Orig: " + ps + "\nNew: " + psi);
								}
								//System.out.println(c + message);
							}
						}
						innerIndexNumber++;
					}
				}

			}
			indexNumber++;
			monitor.incrementProgress(1);
		}
		PdbLog.message("STUDY_END: studyCompositeFwdRefDef");
		//System.out.println("STUDY_END");
	}
Gets a demangles the name and returns the qualified name. Returns null if not mangled
or if error in demangling.
@param mangledString the mangled string to be decoded
@return the qualified name of the demangled string or null if not mangled or error.
Ghidra/Features/PDB/src/main/java/ghidra/app/util/pdb/pdbapplicator/PdbResearch.java