/*******************************************************************************
 * Copyright (c) 2004, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Markus Schorn (Wind River Systems)
 *     Bryan Wilkinson (QNX)
 *     Sergey Prigogin (Google)
 *     Andrew Ferguson (Symbian)
 *     Anton Gorenkov
 *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;

import static org.eclipse.cdt.core.parser.util.ArrayUtil.appendAt;
import static org.eclipse.cdt.core.parser.util.ArrayUtil.trim;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.core.runtime.CoreException;

/**
 * Holds common implementation of methods for ICPPClassType implementations that have
 * a corresponding textual definition in the source code.
 *
 * @see CPPClassType
 * @see CPPClassTemplate
 */
public class ClassTypeHelper {
	public static IBinding[] getFriends(ICPPInternalClassTypeMixinHost host) {
		if (host.getDefinition() == null) {
			host.checkForDefinition();
			if (host.getDefinition() == null) {
				ICPPClassType backup= getBackupDefinition(host);
				if (backup != null)
					return backup.getFriends();
				IASTNode[] declarations= host.getDeclarations();
				IASTNode node = (declarations != null && declarations.length != 0) ? declarations[0] : null;
				return new IBinding[] { new ProblemBinding(node, IProblemBinding.SEMANTIC_DEFINITION_NOT_FOUND, host.getNameCharArray()) };
			}
		}
		ObjectSet<IBinding> resultSet = new ObjectSet<>(2);
		IASTDeclaration[] members = host.getCompositeTypeSpecifier().getMembers();
		for (IASTDeclaration decl : members) {
			while (decl instanceof ICPPASTTemplateDeclaration) {
				decl = ((ICPPASTTemplateDeclaration) decl).getDeclaration();
			}

			if (decl instanceof IASTSimpleDeclaration) {
				ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration) decl).getDeclSpecifier();
				if (declSpec.isFriend()) {
					IASTDeclarator[] dtors = ((IASTSimpleDeclaration) decl).getDeclarators();
					if (dtors.length == 0) {
						if (declSpec instanceof ICPPASTElaboratedTypeSpecifier) {
							resultSet.put(((ICPPASTElaboratedTypeSpecifier) declSpec).getName().resolveBinding());
						} else if (declSpec instanceof ICPPASTNamedTypeSpecifier) {
							resultSet.put(((ICPPASTNamedTypeSpecifier) declSpec).getName().resolveBinding());
						}
					} else {
						for (IASTDeclarator dtor : dtors) {
							if (dtor == null) break;
							dtor= ASTQueries.findInnermostDeclarator(dtor);
							resultSet.put(dtor.getName().resolveBinding());
						}
					}
				}
			} else if (decl instanceof IASTFunctionDefinition) {
				ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTFunctionDefinition) decl).getDeclSpecifier();
				if (declSpec.isFriend()) {
					IASTDeclarator dtor = ((IASTFunctionDefinition) decl).getDeclarator();
					dtor= ASTQueries.findInnermostDeclarator(dtor);
					resultSet.put(dtor.getName().resolveBinding());
				}
			}
		}

		return resultSet.keyArray(IBinding.class);
	}

	/**
	 * Checks if a binding is a friend of a class. Only classes and functions can be friends of a class.
	 * A class is considered a friend of itself.
	 *
	 * @param binding a binding.
	 * @param classType a class.
	 * @return {@code true} if {@code binding} is a friend of {@code classType}.
	 */
	public static boolean isFriend(IBinding binding, ICPPClassType classType) {
		IType type;
		if (binding instanceof ICPPClassType) {
			type = (IType) binding;
			if (type.isSameType(classType)) {
				return true;
			}
			for (IBinding friend : classType.getFriends()) {
				if (friend instanceof ICPPClassType && type.isSameType((IType) friend)) {
					return true;
				}
			}
		} else if (binding instanceof ICPPFunction) {
			type = ((ICPPFunction) binding).getType();
			char[] name = binding.getNameCharArray();
			for (IBinding friend : classType.getFriends()) {
				if (friend instanceof ICPPFunction &&
						CharArrayUtils.equals(name, friend.getNameCharArray()) &&
						SemanticUtil.haveSameOwner(binding, friend) &&
						type.isSameType(((ICPPFunction) friend).getType())) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * A host maybe backed up with a definition from the index.
	 */
	private static ICPPClassType getBackupDefinition(ICPPInternalClassTypeMixinHost host) {
		ICPPClassScope scope = host.getCompositeScope();
		if (scope != null) {
			ICPPClassType b = scope.getClassType();
			if (!(b instanceof ICPPInternalClassTypeMixinHost))
				return b;
		}
		return null;
	}

	public static ICPPBase[] getBases(ICPPInternalClassTypeMixinHost host) {
		if (host.getDefinition() == null) {
			host.checkForDefinition();
			if (host.getDefinition() == null) {
				ICPPClassType backup= getBackupDefinition(host);
				if (backup != null)
					return backup.getBases();

				return ICPPBase.NO_BASES_BECAUSE_TYPE_IS_INCOMPLETE;
			}
		}

		ICPPASTBaseSpecifier[] baseSpecifiers = host.getCompositeTypeSpecifier().getBaseSpecifiers();
		if (baseSpecifiers.length == 0)
			return ICPPBase.EMPTY_BASE_ARRAY;

        ICPPBase[] bases = new ICPPBase[baseSpecifiers.length];
		for (int i = 0; i < baseSpecifiers.length; i++) {
			bases[i] = new CPPBaseClause(baseSpecifiers[i]);
		}

		return bases;
	}

	public static ICPPField[] getDeclaredFields(ICPPInternalClassTypeMixinHost host) {
		if (host.getDefinition() == null) {
			host.checkForDefinition();
			if (host.getDefinition() == null) {
				ICPPClassType backup= getBackupDefinition(host);
				if (backup != null)
					return backup.getDeclaredFields();

				return ICPPField.EMPTY_CPPFIELD_ARRAY;
			}
		}
		IBinding binding = null;
		ICPPField[] result = ICPPField.EMPTY_CPPFIELD_ARRAY;
		int resultSize = 0;

		IASTDeclaration[] decls = host.getCompositeTypeSpecifier().getMembers();
		for (IASTDeclaration decl : decls) {
			if (decl instanceof IASTSimpleDeclaration) {
				IASTDeclarator[] dtors = ((IASTSimpleDeclaration) decl).getDeclarators();
				for (IASTDeclarator dtor : dtors) {
					binding = ASTQueries.findInnermostDeclarator(dtor).getName().resolveBinding();
					if (binding instanceof ICPPField)
						result = ArrayUtil.appendAt(result, resultSize++, (ICPPField) binding);
				}
			} else if (decl instanceof ICPPASTUsingDeclaration) {
				IASTName n = ((ICPPASTUsingDeclaration) decl).getName();
				binding = n.resolveBinding();
				if (binding instanceof ICPPUsingDeclaration) {
					IBinding[] bs = ((ICPPUsingDeclaration) binding).getDelegates();
					for (IBinding element : bs) {
						if (element instanceof ICPPField)
							result = ArrayUtil.appendAt(result, resultSize++, (ICPPField) element);
					}
				} else if (binding instanceof ICPPField) {
					result = ArrayUtil.appendAt(result, resultSize++, (ICPPField) binding);
				}
			}
		}
		return ArrayUtil.trim(result, resultSize);
	}

	/**
	 * Returns all direct and indirect base classes.
	 *
	 * @param classType a class
	 * @return An array of base classes in arbitrary order.
	 */
	public static ICPPClassType[] getAllBases(ICPPClassType classType) {
		Set<ICPPClassType> result= new HashSet<>();
		result.add(classType);
		getAllBases(classType, result);
		result.remove(classType);
		return result.toArray(new ICPPClassType[result.size()]);
	}

	private static void getAllBases(ICPPClassType classType, Set<ICPPClassType> result) {
		ICPPBase[] bases= classType.getBases();
		for (ICPPBase base : bases) {
			IBinding b= base.getBaseClass();
			if (b instanceof ICPPClassType) {
				final ICPPClassType baseClass = (ICPPClassType) b;
				if (result.add(baseClass)) {
					getAllBases(baseClass, result);
				}
			}
		}
	}

	/**
	 * Returns all (direct or indirect) virtual base classes of {@code classType}.
	 */
	public static ICPPClassType[] getVirtualBases(ICPPClassType classType) {
		Set<ICPPClassType> virtualBases = new HashSet<>();
		Set<ICPPClassType> nonvirtualBases = new HashSet<>();
		nonvirtualBases.add(classType);
		getVirtualBases(classType, virtualBases, nonvirtualBases);
		return virtualBases.toArray(new ICPPClassType[virtualBases.size()]);
	}

	/**
	 * Helper function for {@link #getVirtualBases(ICPPClassType)}.
	 */
	private static void getVirtualBases(ICPPClassType classType, Set<ICPPClassType> virtualBases,
			Set<ICPPClassType> nonvirtualBases) {
		ICPPBase[] bases = classType.getBases();
		for (ICPPBase base : bases) {
			IBinding b = base.getBaseClass();
			if (b instanceof ICPPClassType) {
				final ICPPClassType baseClass = (ICPPClassType) b;
				if (base.isVirtual()) {
					if (virtualBases.add(baseClass)) {
						getVirtualBases(baseClass, virtualBases, nonvirtualBases);
					}
				} else {
					// A non-virtual base could have virtual bases in its hierarchy.
					if (nonvirtualBases.add(baseClass)) {
						getVirtualBases(baseClass, virtualBases, nonvirtualBases);
					}
				}
			}
		}
	}

	/**
	 * Checks inheritance relationship between two classes.
	 *
	 * @return {@code true} if {@code subclass} is a subclass of {@code superclass}.
	 */
	public static boolean isSubclass(ICPPClassType subclass, ICPPClassType superclass) {
		ICPPBase[] bases= subclass.getBases();
		for (ICPPBase base : bases) {
			IBinding b= base.getBaseClass();
			if (b instanceof ICPPClassType) {
				ICPPClassType baseClass = (ICPPClassType) b;
				if (baseClass.isSameType(superclass)) {
					return true;
				}
				if (isSubclass(baseClass, superclass)) {
					return true;
				}
			}
		}
		return false;
	}

	public static ICPPMethod[] getAllDeclaredMethods(ICPPClassType ct) {
		ICPPMethod[] methods= ct.getDeclaredMethods();
		ICPPClassType[] bases= getAllBases(ct);
		for (ICPPClassType base : bases) {
			methods = ArrayUtil.addAll(ICPPMethod.class, methods, base.getDeclaredMethods());
		}
		return ArrayUtil.trim(ICPPMethod.class, methods);
	}

	public static ICPPMethod[] getMethods(ICPPClassType ct) {
		ObjectSet<ICPPMethod> set = getOwnMethods(ct);

		ICPPClassType[] bases= getAllBases(ct);
		for (ICPPClassType base : bases) {
			set.addAll(base.getDeclaredMethods());
			set.addAll(getImplicitMethods(base));
		}
		return set.keyArray(ICPPMethod.class);
	}

	/**
	 * Returns methods either declared by the given class or generated by the compiler. Does not
	 * include methods declared in base classes.
	 */
	public static ObjectSet<ICPPMethod> getOwnMethods(ICPPClassType classType) {
		ObjectSet<ICPPMethod> set= new ObjectSet<>(4);
		set.addAll(classType.getDeclaredMethods());
		set.addAll(getImplicitMethods(classType));
		return set;
	}

	public static ICPPMethod[] getImplicitMethods(ICPPClassType classType) {
		return getImplicitMethods(classType.getCompositeScope());
	}

	public static ICPPMethod[] getImplicitMethods(IScope scope) {
		if (scope instanceof ICPPClassScope) {
			return ((ICPPClassScope) scope).getImplicitMethods();
		}
		return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
	}

	public static ICPPMethod[] getDeclaredMethods(ICPPInternalClassTypeMixinHost host) {
		if (host.getDefinition() == null) {
			host.checkForDefinition();
			if (host.getDefinition() == null) {
				ICPPClassType backup= getBackupDefinition(host);
				if (backup != null)
					return backup.getDeclaredMethods();

				return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
			}
		}
		IBinding binding = null;
		ICPPMethod[] result = ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
		int resultSize = 0;

		IASTDeclaration[] decls = host.getCompositeTypeSpecifier().getMembers();
		for (IASTDeclaration decl : decls) {
			while (decl instanceof ICPPASTTemplateDeclaration)
				decl = ((ICPPASTTemplateDeclaration) decl).getDeclaration();
			if (decl instanceof IASTSimpleDeclaration) {
				final IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) decl;
				if (!((ICPPASTDeclSpecifier) sdecl.getDeclSpecifier()).isFriend()) {
					IASTDeclarator[] dtors = sdecl.getDeclarators();
					for (IASTDeclarator dtor : dtors) {
						binding = ASTQueries.findInnermostDeclarator(dtor).getName().resolveBinding();
						if (binding instanceof ICPPMethod)
							result = ArrayUtil.appendAt(result, resultSize++, (ICPPMethod) binding);
					}
				}
			} else if (decl instanceof IASTFunctionDefinition) {
				final IASTFunctionDefinition fdef = (IASTFunctionDefinition) decl;
				if (!((ICPPASTDeclSpecifier) fdef.getDeclSpecifier()).isFriend()) {
					IASTDeclarator dtor = fdef.getDeclarator();
					dtor = ASTQueries.findInnermostDeclarator(dtor);
					binding = dtor.getName().resolveBinding();
					if (binding instanceof ICPPMethod) {
						result = ArrayUtil.appendAt(result, resultSize++, (ICPPMethod) binding);
					}
				}
			} else if (decl instanceof ICPPASTUsingDeclaration) {
				IASTName n = ((ICPPASTUsingDeclaration) decl).getName();
				binding = n.resolveBinding();
				if (binding instanceof ICPPUsingDeclaration) {
					IBinding[] bs = ((ICPPUsingDeclaration) binding).getDelegates();
					for (IBinding element : bs) {
						if (element instanceof ICPPMethod)
							result = ArrayUtil.appendAt(result, resultSize++, (ICPPMethod) element);
					}
				} else if (binding instanceof ICPPMethod) {
					result = ArrayUtil.appendAt(result, resultSize++, (ICPPMethod) binding);
				}
			}
		}
		return ArrayUtil.trim(result, resultSize);
	}

	/**
	 * @see ICPPClassType#getConstructors()
	 */
	public static ICPPConstructor[] getConstructors(ICPPInternalClassTypeMixinHost host) {
		ICPPClassScope scope = host.getCompositeScope();
		if (scope == null) {
			return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY;
		}
		ICPPConstructor[] constructors = scope.getConstructors();
		return getAllConstructors(host, constructors);
	}

	/**
	 * Returns all constructors for a given class type. The returned constructors include the explicitly
	 * declared, the implicit, and the inherited ones.
	 *
	 * @param classType the class to get the constructors for
	 * @param declaredAndImplicitConstructors the declared and implicit constructors of the class
	 * @return an array of all class constructors
	 */
	public static ICPPConstructor[] getAllConstructors(ICPPClassType classType,
			ICPPConstructor[] declaredAndImplicitConstructors) {
		IType[][] paramTypes = new IType[declaredAndImplicitConstructors.length][];
		for (int i = 0; i < declaredAndImplicitConstructors.length; i++) {
			ICPPConstructor ctor = declaredAndImplicitConstructors[i];
			paramTypes[i] = ctor.getType().getParameterTypes();
		}
		ICPPConstructor[] inheritedConstructors = getInheritedConstructors(
				(ICPPClassScope) classType.getCompositeScope(), classType.getBases(), paramTypes);
    	return ArrayUtil.addAll(declaredAndImplicitConstructors, inheritedConstructors);
	}

	/**
	 * Returns inherited constructors for a given class scope.
	 *
	 * @param scope the composite scope of the class to get the constructors for
	 * @param bases the base class relationships of the class
	 * @param existingConstructorParamTypes parameter types of the declared and the implicit constructors
	 * @return an array of all inherited constructors
	 */
	public static ICPPConstructor[] getInheritedConstructors(ICPPClassScope scope, ICPPBase[] bases,
			IType[][] existingConstructorParamTypes) {
		ICPPConstructor[] inheritedConstructors = ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY;
		int n = 0;
		for (ICPPBase base : bases) {
			if (!base.isInheritedConstructorsSource())
				continue;
			IBinding baseType = base.getBaseClass();
        	if (!(baseType instanceof ICPPClassType))
        		continue;
    		ICPPClassType baseClass = (ICPPClassType) baseType;
			ICPPConstructor[] ctors = baseClass.getConstructors();
    		for (ICPPConstructor ctor : ctors) {
    			if (canBeInherited(ctor, baseClass, existingConstructorParamTypes))
        			inheritedConstructors = appendAt(inheritedConstructors, n++, ctor);
    		}
		}
		return trim(inheritedConstructors, n);
	}

	private static boolean canBeInherited(ICPPConstructor ctor, ICPPClassType baseClass,
			IType[][] existingConstructorParamTypes) {
		ICPPParameter[] params = ctor.getParameters();
		// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0136r1.html
		// 7.3.3-4 [Note] If a constructor or assignment operator brought from a base class into a derived
		// class has the signature of a copy/move constructor or assignment operator for the derived class
		// (12.8), the using-declaration does not by itself suppress the implicit declaration of the derived
		// class member; the member from the base class is hidden or overridden by the implicitly-declared
		// copy/move constructor or assignment operator of the derived class, as described below.
		for (int k = Math.max(ctor.getRequiredArgumentCount(), 1); k <= params.length; k++) {
			if (k == 1 && isReferenceToClass(params[0].getType(), baseClass)) {
				continue;  // Skip the copy constructor.
			}
			if (findMatchingSignature(params, k, existingConstructorParamTypes) < 0) {
				return true;
			}
		}
		return false;
	}

	private static boolean isReferenceToClass(IType type, IType classType) {
		type= SemanticUtil.getNestedType(type, TDEF);
		if (type instanceof ICPPReferenceType && !((ICPPReferenceType) type).isRValueReference()) {
			type= SemanticUtil.getNestedType(type, TDEF|REF|CVTYPE);
			return classType.isSameType(type);
		}
		return false;
	}

	private static int findMatchingSignature(ICPPParameter[] params, int numParams, IType[][] paramTypes) {
		for (int i = 0; i < paramTypes.length; i++) {
			if (doParameterTypesMatch(params, numParams, paramTypes[i]))
				return i;
		}
		return -1;
	}

	private static boolean doParameterTypesMatch(ICPPParameter[] params, int numParams, IType[] types) {
		if (numParams != types.length)
			return false;
		for (int i = 0; i < numParams; i++) {
			if (!params[i].getType().isSameType(types[i]))
				return false;
		}
		return true;
	}

	public static ICPPClassType[] getNestedClasses(ICPPInternalClassTypeMixinHost host) {
		if (host.getDefinition() == null) {
			host.checkForDefinition();
			if (host.getDefinition() == null) {
				ICPPClassType backup= getBackupDefinition(host);
				if (backup != null)
					return backup.getNestedClasses();

				return ICPPClassType.EMPTY_CLASS_ARRAY;
			}
		}

		ICPPClassType[] result = ICPPClassType.EMPTY_CLASS_ARRAY;
		int resultSize = 0;

		IASTDeclaration[] decls = host.getCompositeTypeSpecifier().getMembers();
		for (IASTDeclaration decl : decls) {
			while (decl instanceof ICPPASTTemplateDeclaration)
				decl = ((ICPPASTTemplateDeclaration) decl).getDeclaration();
			if (decl instanceof IASTSimpleDeclaration) {
				IBinding binding = null;
				IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration) decl).getDeclSpecifier();
				if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
					binding = ((ICPPASTCompositeTypeSpecifier) declSpec).getName().resolveBinding();
				} else if (declSpec instanceof ICPPASTElaboratedTypeSpecifier &&
						((IASTSimpleDeclaration) decl).getDeclarators().length == 0) {
					binding = ((ICPPASTElaboratedTypeSpecifier) declSpec).getName().resolveBinding();
				}
				if (binding instanceof ICPPClassType)
					result = ArrayUtil.appendAt(result, resultSize++, (ICPPClassType) binding);
			}
		}
		return ArrayUtil.trim(result, resultSize);
	}
	
	public static ICPPUsingDeclaration[] getUsingDeclarations(ICPPInternalClassTypeMixinHost host) {
		if (host.getDefinition() == null) {
			host.checkForDefinition();
			if (host.getDefinition() == null) {
				ICPPClassType backup= getBackupDefinition(host);
				if (backup != null)
					return backup.getUsingDeclarations();

				return ICPPUsingDeclaration.EMPTY_USING_DECL_ARRAY;
			}
		}
		ICPPUsingDeclaration[] result = ICPPUsingDeclaration.EMPTY_USING_DECL_ARRAY;
		int resultSize = 0;

		IASTDeclaration[] decls = host.getCompositeTypeSpecifier().getMembers();
		for (IASTDeclaration decl : decls) {
			if (decl instanceof ICPPASTUsingDeclaration) {
				IBinding binding = ((ICPPASTUsingDeclaration) decl).getName().resolveBinding();
				if (binding instanceof ICPPUsingDeclaration) {
					result = ArrayUtil.appendAt(result, resultSize++, (ICPPUsingDeclaration) binding);
				}
			}
		}
		return ArrayUtil.trim(result, resultSize);

	}

	public static ICPPField[] getFields(ICPPClassType ct) {
		ICPPField[] fields = ct.getDeclaredFields();
		ICPPClassType[] bases = getAllBases(ct);
		for (ICPPClassType base : bases) {
			fields = ArrayUtil.addAll(ICPPField.class, fields, base.getDeclaredFields());
		}
		return ArrayUtil.trim(ICPPField.class, fields);
	}

	public static IField findField(ICPPClassType ct, String name) {
		IBinding[] bindings = CPPSemantics.findBindings(ct.getCompositeScope(), name, true);
		IField field = null;
		for (IBinding binding : bindings) {
			if (binding instanceof IField) {
				if (field == null) {
					field = (IField) binding;
				} else {
					IASTNode[] decls= ASTInternal.getDeclarationsOfBinding(ct);
					IASTNode node= (decls != null && decls.length > 0) ? decls[0] : null;
					return new CPPField.CPPFieldProblem(ct, node, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, name.toCharArray());
				}
			}
		}
		return field;
	}

	/**
	 * Returns whether {@code method} is virtual. This is the case if it is declared to be virtual
	 * or overrides another virtual method.
	 */
	public static boolean isVirtual(ICPPMethod m) {
		if (m instanceof ICPPConstructor)
			return false;
		if (m.isVirtual())
			return true;

		final char[] mname= m.getNameCharArray();
		final ICPPClassType mcl= m.getClassOwner();
		if (mcl != null) {
			final ICPPFunctionType mft= m.getType();
			ICPPMethod[] allMethods= ClassTypeHelper.getMethods(mcl);
			for (ICPPMethod method : allMethods) {
				if (CharArrayUtils.equals(mname, method.getNameCharArray()) && functionTypesAllowOverride(mft, method.getType())) {
					if (method.isVirtual()) {
						return true;
					}
				}
			}
		}
		return false;
	}

	/**
	 * Checks if the function types are consistent enough to be considered overrides.
	 */
	private static boolean functionTypesAllowOverride(ICPPFunctionType a, ICPPFunctionType b) {
        if (a.isConst() != b.isConst() || a.isVolatile() != b.isVolatile() || a.takesVarArgs() != b.takesVarArgs()) {
            return false;
        }

        IType[] paramsA = a.getParameterTypes();
        IType[] paramsB = b.getParameterTypes();

        if (paramsA.length == 1 && paramsB.length == 0) {
			if (!SemanticUtil.isVoidType(paramsA[0]))
				return false;
		} else if (paramsB.length == 1 && paramsA.length == 0) {
			if (!SemanticUtil.isVoidType(paramsB[0]))
				return false;
		} else if (paramsA.length != paramsB.length) {
		    return false;
		} else {
			for (int i = 0; i < paramsA.length; i++) {
		        if (paramsA[i] == null || ! paramsA[i].isSameType(paramsB[i]))
		            return false;
		    }
		}
		return true;
	}

	/**
	 * Returns {@code true} if {@code source} overrides {@code target}.
	 */
	public static boolean isOverrider(ICPPMethod source, ICPPMethod target) {
		if (source instanceof ICPPConstructor || target instanceof ICPPConstructor)
			return false;
		if (!isVirtual(target))
			return false;
		if (!functionTypesAllowOverride(source.getType(), target.getType()))
			return false;

		final ICPPClassType sourceClass= source.getClassOwner();
		final ICPPClassType targetClass= target.getClassOwner();
		if (sourceClass == null || targetClass == null)
			return false;

		ICPPClassType[] bases= getAllBases(sourceClass);
		for (ICPPClassType base : bases) {
			if (base.isSameType(targetClass))
				return true;
		}

		return false;
	}

	/**
	 * Returns all methods that are overridden by the given {@code method}.
	 */
	public static ICPPMethod[] findOverridden(ICPPMethod method) {
		if (method instanceof ICPPConstructor)
			return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;

		final char[] mname= method.getNameCharArray();
		final ICPPClassType mcl= method.getClassOwner();
		if (mcl == null)
			return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;

		final ArrayList<ICPPMethod> result= new ArrayList<>();
		final HashMap<ICPPClassType, Boolean> virtualInClass= new HashMap<>();
		final ICPPFunctionType methodType= method.getType();

		virtualInClass.put(mcl, method.isVirtual());
		ICPPBase[] bases= mcl.getBases();
		for (ICPPBase base : bases) {
			IBinding b= base.getBaseClass();
			if (b instanceof ICPPClassType) {
				findOverridden((ICPPClassType) b, mname, methodType, virtualInClass,
						result, CPPSemantics.MAX_INHERITANCE_DEPTH);
			}
		}

		// List is filled from most derived up to here, reverse it.
		Collections.reverse(result);
		return result.toArray(new ICPPMethod[result.size()]);
	}

	/**
	 * Searches for overridden methods starting in {@code classType}. The map {@code virtualInClass}
	 * contains a mapping of classes that have been visited to the information whether they
	 * (or a base-class) contain an overridden method.
	 *
	 * @return whether {@code classType} contains an overridden method.
	 */
	private static boolean findOverridden(ICPPClassType classType, char[] methodName,
			ICPPFunctionType methodType, Map<ICPPClassType, Boolean> virtualInClass,
			List<ICPPMethod> result, int maxdepth) {
		// Prevent recursion due to a hierarchy of unbounded depth, e.g. A<I> deriving from A<I - 1>.
		if (maxdepth <= 0)
			return false;

		Boolean visitedBefore= virtualInClass.get(classType);
		if (visitedBefore != null)
			return visitedBefore;

		ICPPMethod[] methods= classType.getDeclaredMethods();
		ICPPMethod candidate= null;
		boolean hasOverridden= false;
		for (ICPPMethod method : methods) {
			if (methodName[0] == '~' && method.isDestructor()
				|| (CharArrayUtils.equals(methodName, method.getNameCharArray())
					&& functionTypesAllowOverride(methodType, method.getType()))) {
				candidate= method;
				hasOverridden= method.isVirtual();
				break;
			}
		}

		// Prevent recursion due to a class inheriting (directly or indirectly) from itself.
		virtualInClass.put(classType, hasOverridden);
		ICPPBase[] bases= classType.getBases();
		for (ICPPBase base : bases) {
			IBinding b= base.getBaseClass();
			if (b instanceof ICPPClassType) {
				if (findOverridden((ICPPClassType) b, methodName, methodType, virtualInClass,
						result, maxdepth - 1)) {
					hasOverridden= true;
				}
			}
		}
		if (hasOverridden) {
			// The candidate is virtual.
			if (candidate != null)
				result.add(candidate);
			virtualInClass.put(classType, hasOverridden);
		}
		return hasOverridden;
	}

	/**
	 * Returns all methods found in the index, that override the given {@code method}.
	 */
	public static ICPPMethod[] findOverriders(IIndex index, ICPPMethod method) 
			throws CoreException {
		if (!isVirtual(method))
			return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;

		final ICPPClassType mcl= method.getClassOwner();
		if (mcl == null)
			return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;

		ICPPClassType[] subclasses= getSubClasses(index, mcl);
		return findOverriders(subclasses, method);
	}

	/**
	 * Returns all methods belonging to the given set of classes that override the given {@code method}.
	 */
	public static ICPPMethod[] findOverriders(ICPPClassType[] subclasses, ICPPMethod method) {
		final char[] mname= method.getNameCharArray();
		final ICPPFunctionType mft= method.getType();
		final ArrayList<ICPPMethod> result= new ArrayList<>();
		for (ICPPClassType subClass : subclasses) {
			ICPPMethod[] methods= subClass.getDeclaredMethods();
			for (ICPPMethod candidate : methods) {
				if (CharArrayUtils.equals(mname, candidate.getNameCharArray()) &&
						functionTypesAllowOverride(mft, candidate.getType())) {
					result.add(candidate);
				}
			}
		}
		return result.toArray(new ICPPMethod[result.size()]);
	}

	private static ICPPClassType[] getSubClasses(IIndex index, ICPPClassType mcl) throws CoreException {
		Deque<ICPPBinding> result= new ArrayDeque<>();
		HashSet<String> handled= new HashSet<>();
		getSubClasses(index, mcl, result, handled);
		result.removeFirst();
		return result.toArray(new ICPPClassType[result.size()]);
	}

	private static void getSubClasses(IIndex index, ICPPBinding classOrTypedef,
			Collection<ICPPBinding> result, HashSet<String> handled) throws CoreException {
		if (!(classOrTypedef instanceof IType))
			return;

		final String key = ASTTypeUtil.getType((IType) classOrTypedef, true);
		if (!handled.add(key)) {
			return;
		}

		if (classOrTypedef instanceof ICPPClassType) {
			result.add(classOrTypedef);
		}

		// TODO(nathanridge): Also find subclasses referenced via decltype-specifiers rather than names.
		IIndexName[] names= index.findNames(classOrTypedef, IIndex.FIND_REFERENCES | IIndex.FIND_DEFINITIONS);
		for (IIndexName indexName : names) {
			if (indexName.isBaseSpecifier()) {
				IIndexName subClassDef= indexName.getEnclosingDefinition();
				if (subClassDef != null) {
					IBinding subClass= index.findBinding(subClassDef);
					if (subClass instanceof ICPPBinding) {
						getSubClasses(index, (ICPPBinding) subClass, result, handled);
					}
				}
			}
		}
	}

	public enum MethodKind {
		DEFAULT_CTOR,
		COPY_CTOR,
		MOVE_CTOR,
		COPY_ASSIGNMENT_OP,
		MOVE_ASSIGNMENT_OP,
		DTOR,
		OTHER
	}

	public static MethodKind getMethodKind(ICPPClassType classType, ICPPMethod method) {
		if (method instanceof ICPPConstructor) {
			final List<IType> params= getTypesOfRequiredParameters(method);
			if (params.isEmpty())
				return MethodKind.DEFAULT_CTOR;
			if (params.size() == 1) {
				IType t= SemanticUtil.getNestedType(params.get(0), SemanticUtil.TDEF);
				if (SemanticUtil.isVoidType(t))
					return MethodKind.DEFAULT_CTOR;

				ICPPReferenceType refToClass = getRefToClass(classType, t);
				if (refToClass != null)
					return refToClass.isRValueReference() ? MethodKind.MOVE_CTOR : MethodKind.COPY_CTOR;
			}
			return MethodKind.OTHER;
		}

		if (method.isDestructor())
			return MethodKind.DTOR;

		if (CharArrayUtils.equals(method.getNameCharArray(), OverloadableOperator.ASSIGN.toCharArray())) {
			final List<IType> params= getTypesOfRequiredParameters(method);
			if (params.size() == 1) {
				IType t= params.get(0);
				ICPPReferenceType refToClass = getRefToClass(classType, t);
				if (refToClass != null)
					return refToClass.isRValueReference() ? MethodKind.MOVE_ASSIGNMENT_OP : MethodKind.COPY_ASSIGNMENT_OP;
			}
			return MethodKind.OTHER;
		}
		return MethodKind.OTHER;
	}

	/**
	 * Returns types of method parameters that don't have defaults.
	 */
	private static List<IType> getTypesOfRequiredParameters(ICPPMethod method) {
		ICPPParameter[] parameters = method.getParameters();
		if (parameters.length == 0)
			return Collections.emptyList();
		List<IType> types = new ArrayList<>(parameters.length);
		for (ICPPParameter parameter : parameters) {
			if (!parameter.hasDefaultValue() && !parameter.isParameterPack())
				types.add(parameter.getType());
		}
		return types;
	}

	/**
	 * For implicit methods the exception specification is inherited, search it.
	 */
	public static IType[] getInheritedExceptionSpecification(ICPPMethod implicitMethod) {
		// See 15.4.13
		ICPPClassType owner= implicitMethod.getClassOwner();
		if (owner == null || owner.getBases().length == 0)
			return null;

		// We use a list as types aren't comparable, and can have duplicates (15.4.6)
		MethodKind kind= getMethodKind(owner, implicitMethod);
		if (kind == MethodKind.OTHER)
			return null;

		List<IType> inheritedTypeids = new ArrayList<>();
		ICPPClassType[] bases= getAllBases(owner);
		for (ICPPClassType base : bases) {
			if (!(base instanceof ICPPDeferredClassInstance)) {
				ICPPMethod  baseMethod= getMethodInClass(base, kind);
				if (baseMethod != null) {
					IType[] baseExceptionSpec= baseMethod.getExceptionSpecification();
					if (baseExceptionSpec == null)
						return null;
					for (IType baseTypeId : baseMethod.getExceptionSpecification()) {
						inheritedTypeids.add(baseTypeId);
					}
				}
			}
		}
		return inheritedTypeids.toArray(new IType[inheritedTypeids.size()]);
	}

	/**
	 * If {@code type} is a, possibly qualified, reference type referring to {@code classType},
	 * returns that reference type. Otherwise returns {@code null}.
	 */
	private static ICPPReferenceType getRefToClass(ICPPClassType classType, IType type) {
		while (type instanceof ITypedef) {
			type= ((ITypedef) type).getType();
		}

		if (type instanceof ICPPReferenceType) {
			ICPPReferenceType refType = (ICPPReferenceType) type;
			type= refType.getType();
			while (type instanceof ITypedef) {
				type= ((ITypedef) type).getType();
			}
			if (type instanceof IQualifierType) {
				type= ((IQualifierType) type).getType();
				if (classType.isSameType(type))
					return refType;
			}
		}
		return null;
	}

	public static ICPPMethod getMethodInClass(ICPPClassType ct, MethodKind kind) {
		switch (kind) {
		case DEFAULT_CTOR:
		case COPY_CTOR:
		case MOVE_CTOR:
			for (ICPPConstructor ctor : ct.getConstructors()) {
				if (!ctor.isImplicit() && getMethodKind(ct, ctor) == kind)
					return ctor;
			}
			return null;
		case COPY_ASSIGNMENT_OP:
		case MOVE_ASSIGNMENT_OP:
			for (ICPPMethod method : ct.getDeclaredMethods()) {
				if (method instanceof ICPPConstructor)
					continue;
				if (getMethodKind(ct, method) == kind)
					return method;
			}
			return null;
		case DTOR:
			for (ICPPMethod method : ct.getDeclaredMethods()) {
				if (method.isDestructor())
					return method;
			}
			return null;
		case OTHER:
			break;
		}
		return null;
	}

	/**
	 * Returns the visibility for a given {@code member} in the {@code host}.
	 * Throws an IllegalArgumentException if {@code member} is not a member of {@code host}
	 *
	 * @param classType The class to get the member's visibility specifier of.
	 * @return the visibility of the {@code member}.
	 */
	public static int getVisibility(ICPPInternalClassTypeMixinHost classType, IBinding member) {
		if (classType.getDefinition() == null) {
			classType.checkForDefinition();
			if (classType.getDefinition() == null) {
				ICPPClassType backup = getBackupDefinition(classType);
				if (backup != null) {
					return backup.getVisibility(member);
				}
				if (classType instanceof ICPPClassSpecialization) {
					// A class instance doesn't have a definition. Delegate to the class template.
					ICPPClassType specialized = ((ICPPClassSpecialization) classType).getSpecializedBinding();
					if (!specialized.equals(member.getOwner())) {
						if (!(member instanceof ICPPSpecialization))
							throw invalidMember(specialized, member);
						member = ((ICPPSpecialization) member).getSpecializedBinding();
					}
					return specialized.getVisibility(member);
				}

				return ICPPClassType.v_public; // Fallback visibility
			}
		}

		// The concept of visibility does not apply to a lambda, which can end
		// up having a class as its owner if they are used in the initializer
		// of a field or a member function parameter.
		if (member instanceof CPPClosureType) {
			return ICPPClassType.v_public;
		}

		ICPPASTCompositeTypeSpecifier classDeclSpec = classType.getCompositeTypeSpecifier();
		int visibility = getVisibility(classDeclSpec, member);
		if (visibility >= 0)
			return visibility;

		ICPPMethod[] implicitMethods = getImplicitMethods(classType);
		for (ICPPMethod implicitMethod : implicitMethods) {
			if (member.equals(implicitMethod)) {
				return ICPPClassType.v_public;
			}
		}

		// It's possible that we haven't found the member because the class was illegally redefined
		// and the member belongs to another definition. Try to search the definition containing
		// the member.
		if (member instanceof ICPPInternalBinding) {
			IASTNode node = ((ICPPInternalBinding) member).getDefinition();
			if (node != null) {
				IASTName ownerName = CPPVisitor.findDeclarationOwnerDefinition(node, false);
				if (ownerName != null && !ownerName.equals(classDeclSpec.getName()) &&
						ownerName.getPropertyInParent() == ICPPASTCompositeTypeSpecifier.TYPE_NAME) {
					classDeclSpec = (ICPPASTCompositeTypeSpecifier) ownerName.getParent();
					visibility = getVisibility(classDeclSpec, member);
					if (visibility >= 0)
						return visibility;
				}
			}
		}

		throw invalidMember(classType, member);
	}

	private static int getVisibility(ICPPASTCompositeTypeSpecifier classDeclSpec, IBinding member) {
		int visibility = classDeclSpec.getKey() == ICPPASTCompositeTypeSpecifier.k_class ?
				ICPPClassType.v_private : ICPPClassType.v_public;
		IASTDeclaration[] hostMembers = classDeclSpec.getMembers();
		for (IASTDeclaration hostMember : hostMembers) {
			if (hostMember instanceof ICPPASTVisibilityLabel) {
				visibility = ((ICPPASTVisibilityLabel) hostMember).getVisibility();
				continue;
			}
			while (hostMember instanceof ICPPASTTemplateDeclaration) {
				hostMember = ((ICPPASTTemplateDeclaration) hostMember).getDeclaration();
			}
			if (hostMember instanceof IASTSimpleDeclaration) {
				IASTSimpleDeclaration memberDeclaration = (IASTSimpleDeclaration) hostMember;
				for (IASTDeclarator memberDeclarator : memberDeclaration.getDeclarators()) {
					IBinding memberBinding =
							ASTQueries.findInnermostDeclarator(memberDeclarator).getName().resolveBinding();
					if (member.equals(memberBinding)) {
						return visibility;
					}
				}

				IASTDeclSpecifier declSpec = memberDeclaration.getDeclSpecifier();
				if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
					IBinding memberBinding =
							((ICPPASTCompositeTypeSpecifier) declSpec).getName().resolveBinding();
					if (member.equals(memberBinding)) {
						return visibility;
					}
				} else if (declSpec instanceof ICPPASTElaboratedTypeSpecifier
						&& memberDeclaration.getDeclarators().length == 0) {
					IBinding memberBinding =
							((ICPPASTElaboratedTypeSpecifier) declSpec).getName().resolveBinding();
					if (member.equals(memberBinding)) {
						return visibility;
					}
				} else if (declSpec instanceof ICPPASTEnumerationSpecifier) {
					IBinding enumerationBinding = ((ICPPASTEnumerationSpecifier) declSpec).getName().resolveBinding();
					if (member.equals(enumerationBinding)) {
						return visibility;
					}
				}
			} else if (hostMember instanceof IASTFunctionDefinition) {
				IASTDeclarator declarator = ((IASTFunctionDefinition) hostMember).getDeclarator();
				declarator = ASTQueries.findInnermostDeclarator(declarator);
				IBinding functionBinding = declarator.getName().resolveBinding();
				if (member.equals(functionBinding)) {
					return visibility;
				}
			} else if (hostMember instanceof ICPPASTAliasDeclaration) {
				IBinding aliasBinding = ((ICPPASTAliasDeclaration) hostMember).getAlias().resolveBinding();
				if (member.equals(aliasBinding)) {
					return visibility;
				}
			} else if (hostMember instanceof ICPPASTUsingDeclaration) {
				IBinding usingBinding = ((ICPPASTUsingDeclaration) hostMember).getName().resolveBinding();
				if (member.equals(usingBinding)) {
					return visibility;
				}
			} else if (hostMember instanceof ICPPASTNamespaceDefinition) { // Not valid but possible due to the parser
				IBinding namespaceBinding = ((ICPPASTNamespaceDefinition) hostMember).getName().resolveBinding();
				if (member.equals(namespaceBinding)) {
					return visibility;
				}
			}
		}
		return -1;
	}

	private static IllegalArgumentException invalidMember(IBinding classType, IBinding member) {
		String name = member.getName();
		if (name.isEmpty())
			name = "<anonymous>"; //$NON-NLS-1$
		return new IllegalArgumentException(name + " is not a member of " + classType.getName()); //$NON-NLS-1$
	}
}
