private List<GccTypeinfo> createTypeinfoStructs(List<GccTypeinfo> specialTypeinfos,
			List<SpecialVtable> specialVtables) throws CancelledException, Exception {

		StructureDataType classTypeInfoStructure = createClassTypeInfoStructure();
		StructureDataType siClassTypeInfoStructure =
			createSiClassTypeInfoStructure(classTypeInfoStructure);
		StructureDataType baseClassTypeInfoStructure =
			createBaseClassTypeInfoStructure(classTypeInfoStructure);

		List<GccTypeinfo> typeinfos = new ArrayList<GccTypeinfo>(specialTypeinfos);

		// Apply typeinfo structs to special typeinfos if the typeinfo is not in
		// external mem block or external program
		for (GccTypeinfo specialTypeinfo : specialTypeinfos) {
			monitor.checkCancelled();

			if (specialTypeinfo.isInProgramMemory()) {
				Data struct =
					applyTypeinfoStructure(siClassTypeInfoStructure, specialTypeinfo.getAddress());
				if (struct == null) {
					Msg.error(this,
						specialTypeinfo.getNamespace().getName() + ": cannot apply structure");
					continue;
				}
				typeinfoToStructuretypeMap.put(specialTypeinfo.getAddress(),
					SI_CLASS_TYPE_INFO_STRUCTURE);
			}
		}

		AddressSetView executeSet = program.getMemory().getExecuteSet();
		MemoryBlock idataBlock = program.getMemory().getBlock(".idata");

		AddressSet specialTypeinfosAddrSet = getSpecialTypeinfosAddrSet();

		for (SpecialVtable specialVtable : specialVtables) {

			monitor.checkCancelled();

			Address typeinfoRefAddr = specialVtable.getVfunctionTop();
			if (typeinfoRefAddr == null) {
				typeinfoRefAddr = specialVtable.getAddress();
			}

			List<Address> refsToClassTypeinfo = getAllReferencesTo(typeinfoRefAddr);
			for (Address typeinfoAddress : refsToClassTypeinfo) {

				monitor.checkCancelled();

				if (executeSet.contains(typeinfoAddress)) {
					continue;
				}

				// check to see if the reference is in a special vtable or special typeinfo and
				// skip if so only looking to return the non-special typeinfos
				if (specialTypeinfosAddrSet.contains(typeinfoAddress)) {
					continue;
				}

				if (hasExistingTypeinfoStructure(typeinfoAddress)) {
					continue;
				}

				// skip if ref is in idata (windows gcc IAT)
				if (idataBlock != null && idataBlock.contains(typeinfoAddress)) {
					continue;
				}

				// test if creating the pointer at typeinfoAddress would overlap anything
				// else and skip if so
				if (!canContainPointer(typeinfoAddress)) {
					continue;
				}

				// test to see if there is a string at the typeinfo name location in the would be
				// typeinfo structure
				if (!hasStringAtTypeinfoNameLocation(typeinfoAddress)) {
					continue;
				}

				Data newStructure = null;
				String specialTypeinfoNamespaceName = null;

				// create a "no inheritance" struct here
				if (specialVtable.getNamespace().getName().equals(CLASS_TYPEINFO_NAMESPACE)) {
					specialTypeinfoNamespaceName = CLASS_TYPEINFO_NAMESPACE;
					typeinfoToStructuretypeMap.put(typeinfoAddress, CLASS_TYPE_INFO_STRUCTURE);
					newStructure = applyTypeinfoStructure(classTypeInfoStructure, typeinfoAddress);
				}

				// create a "single inheritance" struct here
				else if (specialVtable.getNamespace()
						.getName()
						.equals(SI_CLASS_TYPEINFO_NAMESPACE)) {
					specialTypeinfoNamespaceName = SI_CLASS_TYPEINFO_NAMESPACE;
					typeinfoToStructuretypeMap.put(typeinfoAddress, SI_CLASS_TYPE_INFO_STRUCTURE);
					newStructure =
						applyTypeinfoStructure(siClassTypeInfoStructure, typeinfoAddress);
				}

				// create a "virtual multip inheritance" struct here
				else if (specialVtable.getNamespace()
						.getName()
						.equals(VMI_CLASS_TYPEINFO_NAMESPACE)) {
					specialTypeinfoNamespaceName = VMI_CLASS_TYPEINFO_NAMESPACE;
					typeinfoToStructuretypeMap.put(typeinfoAddress, VMI_CLASS_TYPE_INFO_STRUCTURE);
					Structure vmiClassTypeinfoStructure = getOrCreateVmiTypeinfoStructure(
						typeinfoAddress, baseClassTypeInfoStructure);
					if (vmiClassTypeinfoStructure != null) {
						newStructure =
							applyTypeinfoStructure(vmiClassTypeinfoStructure, typeinfoAddress);
					}
				}

				if (newStructure == null) {
					// is a typeinfo that inherits a non class typeinfo so skip it
					// or there was an issue creating it so skip it
					continue;
				}

				// check for existing symbol and if none, demangle the name and apply
				Symbol typeinfoSymbol = api.getSymbolAt(typeinfoAddress);
				if (typeinfoSymbol == null || typeinfoSymbol.getSource() == SourceType.DEFAULT ||
					typeinfoSymbol.getName().startsWith(".rdata$")) {

					typeinfoSymbol = createDemangledTypeinfoSymbol(typeinfoAddress);
					if (typeinfoSymbol == null) {
						//If no mangled class name, check for non-mangled pascal type class name
						typeinfoSymbol =
							createTypeinfoSymbolFromNonMangledString(typeinfoAddress);
						if (typeinfoSymbol == null) {
							Msg.debug(this, "Could not create typeinfo symbol at " +
								typeinfoAddress.toString());
							continue;
						}
					}
				}

				if (typeinfoSymbol.getName().equals("typeinfo")) {
					promoteToClassNamespace(typeinfoSymbol.getParentNamespace());
					GccTypeinfo typeinfo = createGccTypeinfo(typeinfoSymbol, false);
					if (specialTypeinfoNamespaceName == null) {
						continue;
					}

					typeinfo.setInheritedSpecialTypeinfoNamespace(specialVtable.getNamespace());

					typeinfos.add(typeinfo);
					continue;
				}
			}
		}

		// remove typeinfos that do not inherit one of the three special typeinfos
		List<GccTypeinfo> typeinfosToRemove = new ArrayList<GccTypeinfo>();
		Map<Address, GccTypeinfo> typeinfoMap = new HashMap<Address, GccTypeinfo>();

		for (GccTypeinfo typeinfo : typeinfos) {
			monitor.checkCancelled();
			Address typeinfoAddress = typeinfo.getAddress();
			if (typeinfo.getInheritedSpecialTypeinfoNamespace() == null) {

				typeinfosToRemove.add(typeinfo);
				continue;
			}
			typeinfoMap.put(typeinfoAddress, typeinfo);
		}
		typeinfos.removeAll(typeinfosToRemove);

		// update typeinfos with their base classes
		updateTypeinfosWithBases(typeinfos, typeinfoMap);

		return typeinfos;
	}
Method to create and apply typeinfo structs of one of the three types used by
rtti classes

@throws CancelledException if cancelled
@throws Exception          if could not apply a type info structure
Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java