/*******************************************************************************
 * Copyright (c) 2004, 2016 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:
 *     Andrew Niefer (IBM) - Initial API and implementation
 *     Markus Schorn (Wind River Systems)
 *     Bryan Wilkinson (QNX)
 *     Andrew Ferguson (Symbian)
 *     Sergey Prigogin (Google)
 *     Mike Kucera (IBM)
 *     Thomas Corbat (IFS)
 *     Nathan Ridge
 *     Richard Eames
 *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;

import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ARRAY;
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.MPTR;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.PTR;
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 static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.calculateInheritanceDepth;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.isConversionOperator;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
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.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdInitializerExpression;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IScope.ScopeLookupData;
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
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.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDecltypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSwitchStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypeId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
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.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
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.ICPPFunctionInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.CollectionUtils;
import org.eclipse.cdt.core.parser.util.DebugUtil;
import org.eclipse.cdt.core.parser.util.IUnaryPredicate;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator;
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
import org.eclipse.cdt.internal.core.dom.parser.IRecursionResolvingBinding;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.IntegralValue;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBuiltinParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredConstructor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespaceScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownField;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMemberClass;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMethod;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDirective;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPClassSpecializationScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalNamespaceScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMAdaptedASTNode;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;

/**
 * Name resolution.
 */
public class CPPSemantics {
	/**
	 * The maximum depth to search ancestors before assuming infinite looping.
	 */
	public static final int MAX_INHERITANCE_DEPTH= 40;

	public static final String EMPTY_NAME = ""; //$NON-NLS-1$
	public static final char[] OPERATOR_ = new char[] {'o','p','e','r','a','t','o','r',' '};
	public static final IType VOID_TYPE = new CPPBasicType(Kind.eVoid, 0);
	public static final IType INT_TYPE = new CPPBasicType(Kind.eInt, 0);

	private static final char[] CALL_FUNCTION = "call-function".toCharArray(); //$NON-NLS-1$
	private static final ICPPEvaluation[] NO_INITCLAUSE_EVALUATION = {};

	// Set to true for debugging.
	public static boolean traceBindingResolution = false;
	public static int traceIndent= 0;

	// special return value for costForFunctionCall
	private static final FunctionCost CONTAINS_DEPENDENT_TYPES = new FunctionCost(null, 0);

	// A regular expression for matching qualified names.  This allows for optional global qualification
	// (leading ::) and then separates the first part of the name from the rest (if present).  There are
	// three capture groups:
	//   (1) If the input name specifies the global namespace (leading ::) then capture group 1 will
	//       be ::.  Group 1 will be null otherwise.
	//   (2) The text of the first component of the qualified name, including leading :: if present in
	//       the input string.  Leading and trailing whitespace is trimmed.  There is no effort to check
	//       that the name contains valid C++ identifier characters.
	//   (3) The text of everything after the first component of the qualified name.
	//
	// E.g., -- Input Name --   ---- Capture Groups ----
	//       "::nsA::nsB::b" => { "::", "nsA", "nsB::b" }
	//       "a"             => { null, "a",   null     }
	//       "::  i"         => { "::", "i",   null     }
	private static final Pattern QUALNAME_REGEX = Pattern.compile("^\\s*(::)?\\s*([^\\s:]+)\\s*(?:::(.*))?$"); //$NON-NLS-1$
	
	// This flag controls whether name lookup is allowed to find bindings in headers
	// that are not reachable via includes from the file containing the name.
	// Generally this is not allowed, but certain consumers, such as IncludeOrganizer,
	// need it (since the whole point of IncludeOrganizer is to find missing headers).
	private static final ThreadLocal<Boolean> fAllowPromiscuousBindingResolution = new ThreadLocal<Boolean>() {
		@Override
		protected Boolean initialValue() {
			return false;
		}
	};
	
	private static final ThreadLocal<Deque<IASTNode>> fLookupPoints = new ThreadLocal<Deque<IASTNode>>() {
		@Override
		protected Deque<IASTNode> initialValue() {
			return new ArrayDeque<>();
		}
	};
	public static void pushLookupPoint(IASTNode point) {
		fLookupPoints.get().push(point);
	}
	public static void popLookupPoint() {
		fLookupPoints.get().pop();
	}
	/**
	 * Get the current point of instantiation / point of lookup for name lookups.
	 * 
	 * NOTE: This is meant to be used primarily for "declaredBefore" purposes, that is,
	 *       for determining whether something was declared before or after the point
	 *       of lookup. It is NOT meant to be used as a general mechanism for accessing
	 *       information about a call site without having to pass that information along
	 *       the usual way (via function arguments).
	 */
	public static IASTNode getCurrentLookupPoint() {
		Deque<IASTNode> lookupPoints = fLookupPoints.get();
		return lookupPoints.isEmpty() ? null : lookupPoints.peek();
	}

	static protected IBinding resolveBinding(IASTName name) {
		if (traceBindingResolution) {
			for (int i = 0; i < traceIndent; i++) {
				System.out.print("  "); //$NON-NLS-1$
			}
			System.out.println("Resolving " + name + ':' + ((ASTNode) name).getOffset()); //$NON-NLS-1$
			traceIndent++;
		}
		if (name instanceof CPPASTNameBase) {
			((CPPASTNameBase) name).incResolutionDepth();
		}

		// 1: Get some context info off of the name to figure out what kind of lookup we want.
		LookupData data = createLookupData(name);

		IBinding binding;
		pushLookupPoint(name);
		try {
			try {
				// 2: Lookup
				lookup(data, null);
	
				// Perform argument dependent lookup
				if (data.checkAssociatedScopes() && !data.hasTypeOrMemberFunctionOrVariableResult()) {
					doArgumentDependentLookup(data);
				}
			} catch (DOMException e) {
				data.problem = (ProblemBinding) e.getProblem();
			}
			if (data.problem != null)
				return data.problem;
	
			// 3: Resolve ambiguities
			try {
				binding = resolveAmbiguities(data);
			} catch (DOMException e) {
				binding = e.getProblem();
			}
			// 4: Post processing
			binding = postResolution(binding, data);
		} finally {
			popLookupPoint();
		}
		if (traceBindingResolution) {
			traceIndent--;
			for (int i = 0; i < traceIndent; i++) {
				System.out.print("  "); //$NON-NLS-1$
			}
			System.out.println("Resolved  " + name + ':' + ((ASTNode) name).getOffset() +  //$NON-NLS-1$
					" to " + DebugUtil.toStringWithClass(binding) + ':' + System.identityHashCode(binding)); //$NON-NLS-1$
		}
		return binding;
	}

	protected static IBinding postResolution(IBinding binding, IASTName name) {
		LookupData data = createLookupData(name);
		return postResolution(binding, data);
	}

	private static IBinding postResolution(IBinding binding, LookupData data) {
		final IASTName lookupName = data.getLookupName();
		if (lookupName == null)
			return binding;

		// If this is the unqualified name of a function in a function call in a template and some
		// of the function arguments are dependent, a matching function could be found via
		// argument-dependent lookup at the point of instantiation.
		if (binding == null || binding instanceof IProblemBinding) {
			if (!data.qualified && data.isFunctionCall() && CPPTemplates.containsDependentType(data.getFunctionArgumentTypes())) {
				binding = CPPDeferredFunction.createForName(lookupName.getSimpleID());
			}
		}

		if (binding instanceof IProblemBinding)
			return binding;

		IASTNode lookupPoint = data.getLookupPoint();

		if (binding == null && data.checkClassContainingFriend()) {
			// 3.4.1-10 If we don't find a name used in a friend declaration in the member
			// declaration's class, we should look in the class granting friendship.
			IASTNode parent = lookupName.getParent();
			while (parent != null && !(parent instanceof ICPPASTCompositeTypeSpecifier)) {
				parent = parent.getParent();
			}
			if (parent instanceof ICPPASTCompositeTypeSpecifier) {
				IScope scope = ((ICPPASTCompositeTypeSpecifier) parent).getScope();
				try {
					lookup(data, scope);
					binding = resolveAmbiguities(data);
				} catch (DOMException e) {
					binding = e.getProblem();
				}
			}
		}

		// Explicit type conversion in functional notation.
		if (binding instanceof ICPPClassTemplate && lookupName instanceof ICPPASTTemplateId) {
			final IASTNode parent = lookupName.getParent();
			if (parent instanceof IASTIdExpression &&
					parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
				return binding;
			}
		}

		/* 14.6.1-1:
		 * Within the scope of a class template, when the name of the template is neither qualified
		 * nor followed by <, it is equivalent to the name followed by the template arguments
		 * enclosed in <>.
		 */
		if (binding instanceof ICPPClassTemplate
				&& !(binding instanceof ICPPClassSpecialization)
				&& !(binding instanceof ICPPTemplateParameter)
				&& !(lookupName instanceof ICPPASTTemplateId)) {
			ASTNodeProperty prop = lookupName.getPropertyInParent();
			if (prop != ICPPASTTemplateId.TEMPLATE_NAME && !lookupName.isQualified()) {
				// You cannot use a class template name outside of the class template scope,
				// mark it as a problem.
				IBinding user= CPPTemplates.isUsedInClassTemplateScope((ICPPClassTemplate) binding, lookupName);
				if (user instanceof ICPPClassTemplate) {
					binding= ((ICPPClassTemplate) user).asDeferredInstance();
				} else if (user != null) {
					binding= user;
				} else {
					boolean ok= false;
					IASTNode node= lookupName.getParent();
					while (node != null && !ok) {
						if (node instanceof ICPPASTTemplateId ||
								node instanceof ICPPASTTemplatedTypeTemplateParameter) {
							ok= true; // Can be argument or default-value for template template parameter
							break;
						} else if (node instanceof IASTElaboratedTypeSpecifier) {
							IASTNode parent= node.getParent();
							if (parent instanceof IASTSimpleDeclaration) {
								IASTDeclSpecifier declspec = ((IASTSimpleDeclaration) parent).getDeclSpecifier();
								if (declspec instanceof ICPPASTDeclSpecifier) {
									if (((ICPPASTDeclSpecifier) declspec).isFriend()) {
										ok= true;  // A friend class template declarations uses resolution.
										break;
									}
								}
							}
						}
						node= node.getParent();
					}
					if (!ok) {
						binding = new ProblemBinding(lookupName, lookupPoint,
								IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings());
					}
				}
			}
		} else if (binding instanceof ICPPDeferredClassInstance) {
			// Try to replace binding by the one pointing to the enclosing template declaration.
			ICPPDeferredClassInstance dcl= (ICPPDeferredClassInstance) binding;
			IBinding usedHere= CPPTemplates.isUsedInClassTemplateScope(dcl.getClassTemplate(), lookupName);
			if (usedHere instanceof ICPPClassTemplatePartialSpecialization) {
				if (CPPTemplates.areSameArguments(((ICPPClassTemplatePartialSpecialization) usedHere).getTemplateArguments(), dcl.getTemplateArguments()))
					binding= ((ICPPClassTemplatePartialSpecialization) usedHere).asDeferredInstance();
			} else if (usedHere instanceof ICPPClassTemplate) {
				if (CPPTemplates.areSameArguments(CPPTemplates.templateParametersAsArguments((ICPPClassTemplate) usedHere), dcl.getTemplateArguments())) {
					binding= ((ICPPClassTemplate) usedHere).asDeferredInstance();
				}
			}
		}

		if (binding instanceof IType) {
			IType t = getNestedType((IType) binding, TDEF);
			if (t instanceof ICPPClassType && convertClassToConstructor(lookupName)) {
				ICPPClassType cls= (ICPPClassType) t;
				if (cls instanceof IIndexBinding) {
					cls= data.getTranslationUnit().mapToAST(cls);
				}
				try {
					if (lookupName instanceof ICPPASTTemplateId && cls instanceof ICPPClassTemplate) {
						if (data.getTranslationUnit() != null) {
							ICPPASTTemplateId id = (ICPPASTTemplateId) lookupName;
							ICPPTemplateArgument[] args = CPPTemplates.createTemplateArgumentArray(id);
							IBinding inst= CPPTemplates.instantiate((ICPPClassTemplate) cls, args);
							if (inst instanceof ICPPClassType) {
								cls= (ICPPClassType) inst;
							}
						}
					}
					if (cls instanceof ICPPUnknownBinding) {
						binding= new CPPDeferredConstructor(cls);
					} else {
						// Do not interpret template arguments to a template class as being
						// explicit template arguments to its templated constructor.
						data.setTemplateArguments(null);
						binding= resolveFunction(data, cls.getConstructors(), true, false);
					}
				} catch (DOMException e) {
					return e.getProblem();
				}
			}
		}

		IASTName name= lookupName;
		IASTNode nameParent= name.getParent();
		if (nameParent instanceof ICPPASTTemplateId) {
			if (binding instanceof ICPPTemplateInstance) {
				final ICPPTemplateInstance instance = (ICPPTemplateInstance) binding;
				binding = instance.getSpecializedBinding();
				name.setBinding(binding);
				((ICPPASTTemplateId) nameParent).setBinding(instance);
			}
			name= (ICPPASTTemplateId) nameParent;
			nameParent= name.getParent();
		}
		boolean isNestedNameSpecifier = false;
		if (nameParent instanceof ICPPASTQualifiedName) {
			if (name == ((ICPPASTQualifiedName) nameParent).getLastName()) {
				name= (IASTName) nameParent;
				nameParent= name.getParent();
			} else {
				isNestedNameSpecifier = true;
			}
		}

		// If the lookup in base-classes ran into a deferred instance, use the computed unknown
		// binding.
		final ASTNodeProperty namePropertyInParent = name.getPropertyInParent();
		if (binding == null && data.skippedScope != null) {
			if (isNestedNameSpecifier || namePropertyInParent == IASTNamedTypeSpecifier.NAME) {
				binding= new CPPUnknownMemberClass(data.skippedScope, name.getSimpleID());
			} else if (data.isFunctionCall()) {
				binding= new CPPUnknownMethod(data.skippedScope, name.getSimpleID());
			} else {
				binding= new CPPUnknownField(data.skippedScope, name.getSimpleID());
			}
		}

		if (binding != null) {
			if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) {
				if (!(binding instanceof IType || binding instanceof ICPPConstructor)) {
					IASTNode parent = name.getParent().getParent();
					if (parent instanceof IASTTypeId && parent.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) {
						if (!(binding instanceof IType)) {
							// A type id needs to hold a type.
							binding = new ProblemBinding(lookupName, lookupPoint,
									IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings());
						}
						// Don't create a problem here.
					} else {
						binding = new ProblemBinding(lookupName, lookupPoint,
								IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings());
					}
				}
			} else if (namePropertyInParent == IASTIdExpression.ID_NAME) {
				if (binding instanceof IType) {
					final IASTNode idExpr = name.getParent();
					ASTNodeProperty pip = idExpr.getPropertyInParent();
					if (pip == ICPPASTTemplatedTypeTemplateParameter.DEFAULT_VALUE) {
						// Default for template template parameter is a type.
					} else if (pip == IASTFunctionCallExpression.FUNCTION_NAME) {
						// Explicit type conversion in functional notation.
					} else if (pip == IASTUnaryExpression.OPERAND
							&& ((ICPPASTUnaryExpression) idExpr.getParent()).getOperator() == IASTUnaryExpression.op_sizeofParameterPack) {
						// Argument of sizeof... can be a type
					} else {
						binding= new ProblemBinding(lookupName, lookupPoint,
								IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings());
					}
				}
			}
		}

		// Some declarations are found via name resolution (e.g. when using a qualified name),
		// add name as definition and check the declaration specifier.
		final IASTDeclaration declaration = data.forDeclaration();
		if (declaration != null) {
			// Functions
			if (binding instanceof IFunction) {
				binding= checkDeclSpecifier(binding, lookupName, declaration);
				if (!(binding instanceof IProblemBinding)) {
					if (declaration instanceof ICPPASTFunctionDefinition) {
						ASTInternal.addDefinition(binding, lookupName);
					}
				}
			}
			// Definitions of static fields.
			if (binding instanceof ICPPField && lookupName.isDefinition()) {
				if (declaration.getPropertyInParent() != IASTCompositeTypeSpecifier.MEMBER_DECLARATION) {
					ASTInternal.addDefinition(binding, lookupName);
				}
			}
		}

		// If the result is a virtual method called without explicit qualification, and we can determine a
		// unique final overrider for it in the hierarchy of the method call's implied object type, replace
		// the method with its final overrider.
		if (!(lookupName.getParent() instanceof ICPPASTQualifiedName) &&  binding instanceof ICPPMethod &&
				((ICPPMethod) binding).isVirtual()) {
			IType impliedObjectType = data.getImpliedObjectType();
			if (impliedObjectType instanceof ICPPClassType) {
				ICPPMethod finalOverrider = CPPInheritance.getFinalOverrider((ICPPMethod) binding,
						(ICPPClassType) impliedObjectType);
				if (finalOverrider != null) {
					binding = finalOverrider;
				}
			}
		}

		// If we're still null...
		if (binding == null) {
			if (name instanceof ICPPASTQualifiedName && declaration != null) {
				binding = new ProblemBinding(lookupName, lookupPoint,
						IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND, data.getFoundBindings());
			} else {
				binding = new ProblemBinding(lookupName, lookupPoint,
						IProblemBinding.SEMANTIC_NAME_NOT_FOUND, data.getFoundBindings());
			}
		}
		return binding;
	}

	private static boolean convertClassToConstructor(IASTName name) {
		if (name == null)
			return false;
		final ASTNodeProperty propertyInParent = name.getPropertyInParent();
		if (propertyInParent == null)
			return false;

		if (propertyInParent == ICPPASTTemplateId.TEMPLATE_NAME)
			return false;

		IASTNode parent= name.getParent();
		if (parent instanceof ICPPASTQualifiedName) {
			if (((ICPPASTQualifiedName) parent).getLastName() != name)
				return false;
			parent= parent.getParent();
		}
		if (parent instanceof ICPPASTConstructorChainInitializer) {
			return true;
		}
		return false;
	}

	public static void doArgumentDependentLookup(LookupData data) throws DOMException {
		data.ignoreUsingDirectives = true;
		// Set 'qualified' to true for the duration of this function call so the calls to lookup()
		// don't ascend into enclosing scopes.
		boolean originalQualified = data.qualified;
		data.qualified = true;
		data.setArgumentDependent(true);
		Set<ICPPFunction> friendFns = new HashSet<>(2);
		Set<ICPPNamespaceScope> associated = getAssociatedScopes(data, friendFns);
		for (ICPPNamespaceScope scope : associated) {
			if (!data.visited.containsKey(scope)) {
				lookup(data, scope);
			}
		}
		Object[] matchingFriendFns = CollectionUtils.filter(
				friendFns,
				new NameMatcherPredicate(data.getLookupKey())).toArray();
		mergeResults(data, matchingFriendFns, false);
		data.qualified = originalQualified;
		data.setArgumentDependent(false);
	}

	private static class NameMatcherPredicate implements IUnaryPredicate<ICPPFunction> {
		private char[] fKey;

		public NameMatcherPredicate(char[] key) {
			fKey = key;
		}

		@Override
		public boolean apply(ICPPFunction argument) {
			return Arrays.equals(argument.getNameCharArray(), fKey);
		}
	}

	static IBinding checkDeclSpecifier(IBinding binding, IASTName name, IASTNode decl) {
		// Check for empty declaration specifiers.
		if (!isCtorOrConversionOperator(binding)) {
			IASTDeclSpecifier declspec= null;
			if (decl instanceof IASTSimpleDeclaration) {
				declspec= ((IASTSimpleDeclaration) decl).getDeclSpecifier();
			} else if (decl instanceof IASTFunctionDefinition) {
				declspec= ((IASTFunctionDefinition) decl).getDeclSpecifier();
			}
			if (declspec != null && CPPVisitor.doesNotSpecifyType(declspec)) {
				binding= new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_TYPE);
			}
		}
		return binding;
	}

	private static boolean isCtorOrConversionOperator(IBinding binding) {
		if (binding instanceof ICPPConstructor)
			return true;

		if (binding instanceof ICPPMethod) {
			ICPPMethod m= (ICPPMethod) binding;
			if (m.isDestructor())
				return true;
			return isConversionOperator(m);
		}
		return false;
	}

	public static LookupData createLookupData(IASTName name) {
		LookupData data = new LookupData(name);
		IASTNode parent = name.getParent();

		if (parent instanceof ICPPASTTemplateId)
			parent = parent.getParent();
		if (parent instanceof ICPPASTQualifiedName)
			parent = parent.getParent();

		if (parent instanceof IASTDeclarator && parent.getPropertyInParent() == IASTSimpleDeclaration.DECLARATOR) {
			IASTSimpleDeclaration simple = (IASTSimpleDeclaration) parent.getParent();
			if (simple.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef)
				data.qualified = true;
		}

		if (parent instanceof IASTIdExpression) {
			IASTNode grand= parent.getParent();
			while (grand instanceof IASTUnaryExpression
					&& ((IASTUnaryExpression) grand).getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
				parent= grand;
				grand = grand.getParent();
			}
			if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
				parent = parent.getParent();
				IASTInitializerClause[] args = ((IASTFunctionCallExpression) parent).getArguments();
				data.setFunctionArguments(false, args);
			}
		} else if (parent instanceof ICPPASTFieldReference) {
			IASTNode grand= parent.getParent();
			while (grand instanceof IASTUnaryExpression
					&& ((IASTUnaryExpression) grand).getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
				parent= grand;
				grand = grand.getParent();
			}
			if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
				IASTInitializerClause[] exp = ((IASTFunctionCallExpression) parent.getParent()).getArguments();
				data.setFunctionArguments(false, exp);
			}
		} else if (parent instanceof ICPPASTNamedTypeSpecifier && parent.getParent() instanceof IASTTypeId) {
			IASTTypeId typeId = (IASTTypeId) parent.getParent();
			if (typeId.getParent() instanceof ICPPASTNewExpression) {
				ICPPASTNewExpression newExp = (ICPPASTNewExpression) typeId.getParent();
				IASTInitializer init = newExp.getInitializer();
				if (init == null) {
					data.setFunctionArguments(false, NO_INITCLAUSE_EVALUATION);
				} else if (init instanceof ICPPASTConstructorInitializer) {
					data.setFunctionArguments(false, ((ICPPASTConstructorInitializer) init).getArguments());
				} else if (init instanceof ICPPASTInitializerList) {
					data.setFunctionArguments(false, (ICPPASTInitializerList) init);
				}
			}
		} else if (parent instanceof ICPPASTConstructorChainInitializer) {
			ICPPASTConstructorChainInitializer ctorinit = (ICPPASTConstructorChainInitializer) parent;
			IASTInitializer init = ctorinit.getInitializer();
			if (init instanceof ICPPASTConstructorInitializer) {
				data.setFunctionArguments(false, ((ICPPASTConstructorInitializer) init).getArguments());
			} else if (init instanceof ICPPASTInitializerList) {
				data.setFunctionArguments(false, (ICPPASTInitializerList) init);
			}
		}

		return data;
	}

	private static Set<ICPPNamespaceScope> getAssociatedScopes(LookupData data, Set<ICPPFunction> friendFns) {
		if (!data.hasFunctionArguments())
			return Collections.emptySet();

		IType[] ps = data.getFunctionArgumentTypes();
		Set<ICPPNamespaceScope> namespaces = new HashSet<>(2);
		ObjectSet<IType> handled = new ObjectSet<>(2);
		for (IType p : ps) {
			try {
				getAssociatedScopes(p, namespaces, friendFns, handled, data.getTranslationUnit(), true);
			} catch (DOMException e) {
			}
		}

		IASTName lookupName= data.getLookupName();
		if (lookupName != null) {
			final char[] simpleID = lookupName.getSimpleID();
			if (CharArrayUtils.equals(CPPVisitor.BEGIN, simpleID) || CharArrayUtils.equals(CPPVisitor.END, simpleID)) {
				IASTNode parent = lookupName.getParent();	 // id-expression
				if (parent != null)
					parent= parent.getParent();	 		  // function call
				if (parent != null)
					parent= parent.getParent();	 		  // the loop
				if (parent instanceof ICPPASTRangeBasedForStatement) {
					IASTTranslationUnit tu = parent.getTranslationUnit();
					IBinding[] std= tu.getScope().find(CPPVisitor.STD, tu);
					for (IBinding binding : std) {
						if (binding instanceof ICPPNamespace) {
							namespaces.add(((ICPPNamespace) binding).getNamespaceScope());
						}
					}
				}
			}
		}
		return namespaces;
	}

	// 3.4.2-2
	private static void getAssociatedScopes(IType t, Set<ICPPNamespaceScope> namespaces,
			Set<ICPPFunction> friendFns, ObjectSet<IType> handled, CPPASTTranslationUnit tu,
			boolean lookInBaseClasses) throws DOMException {
		t = getNestedType(t, TDEF | CVTYPE | PTR | ARRAY | REF);
		// No point getting namespaces associated with a dependent type - we don't know what they
		// are yet.
		if (CPPTemplates.isDependentType(t))
			return;
		if (t instanceof IBinding) {
			if (handled.containsKey(t))
				return;
			handled.put(t);

			if (t instanceof IEnumeration) {
				// [basic.lookup.argdep] p2.3: an enumeration's only associated namespace
				// is the innermost enclosing namespace of its declaration.
				getAssociatedNamespaceScopes(getContainingNamespaceScope((IBinding) t, tu), namespaces);
			} else {
				IBinding owner= ((IBinding) t).getOwner();
				if (owner instanceof ICPPClassType) {
					getAssociatedScopes((IType) owner, namespaces, friendFns, handled, tu,
							false /* do not look at base classes of the enclosing class */);
				} else {
					getAssociatedNamespaceScopes(getContainingNamespaceScope((IBinding) t, tu), namespaces);
				}
			}
		}
		if (t instanceof ICPPClassType && !(t instanceof ICPPClassTemplate)) {
			ICPPClassType ct= (ICPPClassType) t;
			if (lookInBaseClasses) {
				ICPPBase[] bases = ct.getBases();
				for (ICPPBase base : bases) {
					IBinding b = base.getBaseClass();
					if (b instanceof IType)
						getAssociatedScopes((IType) b, namespaces, friendFns, handled, tu, true);
				}
			}
			// Furthermore, if T is a class template ...
			// * ... types of the template arguments for template type parameters
			//	   (excluding template template parameters);
			// * ... owners of which any template template arguments are members;
			if (ct instanceof ICPPSpecialization) {
				for (IBinding friend : ct.getFriends()) {
					if (friend instanceof ICPPFunction) {
						friendFns.add((ICPPFunction) friend);
					}
				}
				if (ct instanceof ICPPTemplateInstance) {
					ICPPTemplateArgument[] args = ((ICPPTemplateInstance) ct).getTemplateArguments();
					for (ICPPTemplateArgument arg : args) {
						if (arg.isTypeValue()) {
							getAssociatedScopes(arg.getTypeValue(), namespaces, friendFns, handled, tu, true);
						}
					}
				}
			}
		} else if (t instanceof IFunctionType) {
			IFunctionType ft = (IFunctionType) t;
			getAssociatedScopes(ft.getReturnType(), namespaces, friendFns, handled, tu, true);
			IType[] ps = ft.getParameterTypes();
			for (IType pt : ps) {
				getAssociatedScopes(pt, namespaces, friendFns, handled, tu, true);
			}
		} else if (t instanceof ICPPPointerToMemberType) {
			final ICPPPointerToMemberType pmt = (ICPPPointerToMemberType) t;
			getAssociatedScopes(pmt.getMemberOfClass(), namespaces, friendFns, handled, tu, true);
			getAssociatedScopes(pmt.getType(), namespaces, friendFns, handled, tu, true);
		} else if (t instanceof FunctionSetType) {
			FunctionSetType fst= (FunctionSetType) t;
			for (ICPPFunction fn : fst.getFunctionSet().getBindings()) {
				getAssociatedScopes(fn.getType(), namespaces, friendFns, handled, tu, true);
			}
		}
	}

	private static ICPPNamespaceScope getContainingNamespaceScope(IBinding binding,
			CPPASTTranslationUnit tu) throws DOMException {
		if (binding == null)
			return null;
		IScope scope = binding.getScope();
		scope = SemanticUtil.mapToAST(scope, tu);
		while (scope != null && !(scope instanceof ICPPNamespaceScope)) {
			scope = getParentScope(scope, tu);
		}
		return (ICPPNamespaceScope) scope;
	}

	public static void getAssociatedNamespaceScopes(ICPPNamespaceScope scope, Set<ICPPNamespaceScope> namespaces) {
		if (scope == null || !namespaces.add(scope))
			return;

		if (scope instanceof ICPPInternalNamespaceScope) {
			final ICPPInternalNamespaceScope internalScope = (ICPPInternalNamespaceScope) scope;
			for (ICPPNamespaceScope mem : internalScope.getEnclosingNamespaceSet()) {
				namespaces.add(mem);
			}
		}
	}

	static ICPPScope getLookupScope(IASTName name) throws DOMException {
		IASTNode parent = name.getParent();
		IScope scope = null;
		if (parent instanceof ICPPASTBaseSpecifier) {
			ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) parent.getParent();
			IASTName n = compSpec.getName();
			if (n instanceof ICPPASTQualifiedName) {
				n = n.getLastName();
			}
			scope = CPPVisitor.getContainingScope(n);
		} else {
			scope = CPPVisitor.getContainingScope(name);
		}
		if (scope instanceof ICPPScope) {
			return (ICPPScope) scope;
		} else if (scope instanceof IProblemBinding) {
			return new CPPScope.CPPScopeProblem(((IProblemBinding) scope).getASTNode(),
					IProblemBinding.SEMANTIC_BAD_SCOPE, ((IProblemBinding) scope).getNameCharArray());
		}
		return new CPPScope.CPPScopeProblem(name, IProblemBinding.SEMANTIC_BAD_SCOPE);
	}

	private static void mergeResults(LookupData data, Object results, boolean scoped) {
		if (!data.contentAssist) {
			if (results instanceof IBinding) {
				data.foundItems = ArrayUtil.append(Object.class, (Object[]) data.foundItems, results);
			} else if (results instanceof Object[]) {
				data.foundItems = ArrayUtil.addAll(Object.class, (Object[]) data.foundItems, (Object[]) results);
			}
		} else {
			@SuppressWarnings("unchecked")
			final CharArrayObjectMap<Object> oldItems = (CharArrayObjectMap<Object>) data.foundItems;
			data.foundItems = mergePrefixResults(oldItems, results, scoped);
		}
	}

	/**
	 * @param dest
	 * @param source : either Object[] or CharArrayObjectMap
	 * @param scoped
	 * @return
	 */
	static CharArrayObjectMap<Object> mergePrefixResults(CharArrayObjectMap<Object> dest, Object source, boolean scoped) {
		if (source == null) return dest;
		CharArrayObjectMap<Object> resultMap = (dest != null) ? dest : new CharArrayObjectMap<>(2);

		CharArrayObjectMap<Object> map = null;
		Object[] objs = null;
		int size;
		if (source instanceof CharArrayObjectMap) {
			@SuppressWarnings("unchecked")
			final CharArrayObjectMap<Object> sourceMap = (CharArrayObjectMap<Object>) source;
			map = sourceMap;
			size= map.size();
		} else {
			if (source instanceof Object[])
				objs = ArrayUtil.trim(Object.class, (Object[]) source);
			else
				objs = new Object[]{ source };
			size= objs.length;
		}

		int resultInitialSize = resultMap.size();
		for (int i = 0; i < size; i ++) {
			char[] key;
			Object so;
			if (map != null) {
				key= map.keyAt(i);
				so= map.get(key);
			} else if (objs != null) {
				so= objs[i];
				key= (so instanceof IBinding) ? ((IBinding) so).getNameCharArray() : ((IASTName) so).getSimpleID();
			} else {
				return resultMap;
			}
			int idx = resultMap.lookup(key);
			if (idx == -1) {
				resultMap.put(key, so);
			} else if (!scoped || idx >= resultInitialSize) {
				Object obj = resultMap.get(key);
				if (obj instanceof Object[]) {
					if (so instanceof IBinding || so instanceof IASTName) {
						obj = ArrayUtil.append(Object.class, (Object[]) obj, so);
					} else {
						obj = ArrayUtil.addAll(Object.class, (Object[]) obj, (Object[]) so);
					}
				} else {
					if (so instanceof IBinding || so instanceof IASTName) {
						obj = new Object[] { obj, so };
					} else {
						Object[] temp = new Object[((Object[]) so).length + 1];
						temp[0] = obj;
						obj = ArrayUtil.addAll(Object.class, temp, (Object[]) so);
					}
				}
				resultMap.put(key, obj);
			}
		}

		return resultMap;
	}

	/**
	 * Perform a lookup with the given data starting in the given scope, considering bases and parent scopes.
	 * @param data the lookup data created off a name
	 * @param start either a scope or a name.
	 */
	static protected void lookup(LookupData data, IScope start) throws DOMException {
		if (start == null && lookupDestructor(data)) {
			return;
		}

		ICPPScope nextScope= null;
		ICPPTemplateScope nextTmplScope= null;
		if (start instanceof ICPPScope) {
			nextScope= (ICPPScope) start;
		} else {
			IASTName lookupName= data.getLookupName();
			if (lookupName == null)
				return;

			nextScope= getLookupScope(lookupName);

			if (nextScope instanceof ICPPTemplateScope) {
				nextTmplScope= (ICPPTemplateScope) nextScope;
				nextScope= getParentScope(nextScope, data.getTranslationUnit());
			} else {
				nextTmplScope= enclosingTemplateScope(lookupName);
			}
			if (data.qualified && nextTmplScope != null) {
				nextTmplScope= null;
				if (dependsOnTemplateFieldReference(lookupName)) {
					data.setIgnorePointOfDeclaration(true);
				}
			}
		}
		if (nextScope == null)
			return;

		boolean friendInLocalClass = false;
		if (nextScope instanceof ICPPClassScope && data.forFriendship()) {
			try {
				ICPPClassType cls = ((ICPPClassScope) nextScope).getClassType();
				friendInLocalClass = !cls.isGloballyQualified();
			} catch (DOMException e) {
			}
		}

		while (nextScope != null || nextTmplScope != null) {
			// When the non-template scope is no longer contained within the first template scope,
			// we use the template scope for the next iteration.
			boolean useTemplScope= false;
			if (nextTmplScope != null) {
				useTemplScope= true;
				if (nextScope instanceof IASTInternalScope) {
					final IASTNode node= ((IASTInternalScope) nextScope).getPhysicalNode();
					if (node != null && nextTmplScope.getTemplateDeclaration().contains(node)) {
						useTemplScope= false;
					}
				}
			}
			ICPPScope scope= useTemplScope ? nextTmplScope : nextScope;
			scope = (ICPPScope) SemanticUtil.mapToAST(scope, data.getTranslationUnit());

			if (!data.usingDirectivesOnly && !(data.ignoreMembers && scope instanceof ICPPClassScope)) {
				mergeResults(data, getBindingsFromScope(scope, data), true);

				// Nominate using-directives found in this block or namespace.
				if (scope instanceof ICPPNamespaceScope) {
					final ICPPNamespaceScope namespaceScope= (ICPPNamespaceScope) scope;

					if (data.qualified && namespaceScope.getKind() != EScopeKind.eLocal) {
						lookupInlineNamespaces(data, namespaceScope);
					}
					if (data.contentAssist || !data.hasResults() || !data.qualified) {
						// Nominate namespaces
						nominateNamespaces(data, namespaceScope);
					}
				}
			}

			// Lookup in nominated namespaces
			if (!data.ignoreUsingDirectives && scope instanceof ICPPNamespaceScope && !(scope instanceof ICPPBlockScope)) {
				if (!data.hasResults() || !data.qualified || data.contentAssist) {
					lookupInNominated(data, (ICPPNamespaceScope) scope);
				}
			}

			if (friendInLocalClass && !(scope instanceof ICPPClassScope))
				return;
			if (!data.contentAssist && hasReachableResult(data))
				return;

			// Lookup in base classes
			if (!data.usingDirectivesOnly && scope instanceof ICPPClassScope && !data.ignoreMembers) {
				BaseClassLookup.lookupInBaseClasses(data, (ICPPClassScope) scope);
				if (!data.contentAssist && data.hasResultOrProblem())
					return;
			}

			if (data.qualified && !(scope instanceof ICPPTemplateScope)) {
				if (data.ignoreUsingDirectives || data.usingDirectives.isEmpty())
					return;
				data.usingDirectivesOnly = true;
			}

			// Compute next scopes
			if (useTemplScope && nextTmplScope != null) {
				nextTmplScope= enclosingTemplateScope(nextTmplScope.getTemplateDeclaration());
			} else {
				nextScope= getParentScope(scope, data.getTranslationUnit());
			}
		}
	}

	/**
	 * Checks if lookup data contains result bindings reachable through includes
	 * from the translation unit where lookup started. Any binding is considered reachable
	 * if the lookup is not done in a context of a translation unit.
	 *
	 * @param data the LookupData object.
	 * @return {@code true} if the lookup data contains at least one reachable binding.
	 */
	private static boolean hasReachableResult(LookupData data) {
		if (data.foundItems instanceof Object[]) {
			for (Object item : (Object[]) data.foundItems) {
				if (item instanceof IBinding) {
					IBinding binding = (IBinding) item;
					CPPASTTranslationUnit tu = data.getTranslationUnit();
					if (!isFromIndex(binding) || tu == null || isReachableFromAst(tu, binding)) {
						return true;
					}
				}
			}
		}
		return false;
	}

	private static void lookupInlineNamespaces(LookupData data, ICPPNamespaceScope namespace)
			throws DOMException {
		lookupInlineNamespaces(data, namespace, new HashSet<ICPPInternalNamespaceScope>());
	}

	private static void lookupInlineNamespaces(LookupData data, ICPPNamespaceScope namespace,
			Set<ICPPInternalNamespaceScope> visited) throws DOMException {
		if (namespace instanceof ICPPInternalNamespaceScope) {
			ICPPInternalNamespaceScope ns= (ICPPInternalNamespaceScope) namespace;
			visited.add(ns);
			for (ICPPInternalNamespaceScope inline : ns.getInlineNamespaces()) {
				if (visited.contains(inline)) {
					CCorePlugin.log(IStatus.WARNING,
							"Detected circular reference between inline namespaces");  //$NON-NLS-1$
					continue;
				}
				mergeResults(data, getBindingsFromScope(inline, data), true);
				lookupInlineNamespaces(data, inline, visited);
				nominateNamespaces(data, inline);
			}
		}
	}

	private static void nominateNamespaces(LookupData data, final ICPPNamespaceScope blockScope)
			throws DOMException {
		final boolean isBlockScope = blockScope.getKind() == EScopeKind.eLocal;
		if (!isBlockScope) {
			data.visited.put(blockScope);	// Mark as searched.
			CPPASTTranslationUnit tu= data.getTranslationUnit();
			if (tu != null) {
				tu.handleAdditionalDirectives(blockScope);
			}
		}
		ICPPUsingDirective[] uds= blockScope.getUsingDirectives();
		if (uds != null && uds.length > 0) {
			HashSet<ICPPNamespaceScope> handled= new HashSet<>();
			for (final ICPPUsingDirective ud : uds) {
				if (data.isIgnorePointOfDeclaration() || declaredBefore(ud, data.getLookupPoint(), false)) {
					storeUsingDirective(data, blockScope, ud, handled);
				}
			}
		}
	}

	private static boolean lookupDestructor(LookupData data) throws DOMException {
		IASTName typeDtorName= data.getLookupName();
		if (typeDtorName == null)
			return false;
		final char[] typeDtorChars= typeDtorName.getSimpleID();
		if (typeDtorChars.length == 0 || typeDtorChars[0] != '~')
			return false;

		// Assume class C; typedef C T;
		// When looking up ~T the strategy is to lookup T::~C in two steps:
		// * First resolve 'T', then compute '~C' and resolve it.
		IASTNode parent= typeDtorName.getParent();
		if (parent instanceof ICPPASTQualifiedName) {
			ICPPASTQualifiedName dqname= (ICPPASTQualifiedName) parent;
			if (dqname.getLastName() != typeDtorName)
				return false;
		}
		char[] tchars= new char[typeDtorChars.length - 1];
		System.arraycopy(typeDtorChars, 1, tchars, 0, tchars.length);

		ICPPTemplateArgument[] templateArgs = data.getTemplateArguments();
		LookupData ld2= new LookupData(tchars, templateArgs, data.getLookupPoint());
		ld2.setIgnorePointOfDeclaration(data.isIgnorePointOfDeclaration());
		ld2.contentAssist= data.contentAssist;
		ld2.fNoNarrowing= data.fNoNarrowing;
		ld2.fHeuristicBaseLookup= data.fHeuristicBaseLookup;
		ld2.qualified= parent instanceof ICPPASTQualifiedName;
		ld2.typesOnly= true;
		lookup(ld2, getLookupScope(typeDtorName));
		IBinding[] typedefs = ld2.getFoundBindings();
		ITypedef typedef = null;
		for (IBinding candidate : typedefs) {
			if (!(candidate instanceof IType)) {
				continue;
			}
			IType type = (IType) candidate;
			if (templateArgs != null && type instanceof ICPPAliasTemplate) {
				IBinding instantiated = CPPTemplates.instantiateAliasTemplate((ICPPAliasTemplate) type, 
						templateArgs);
				if (instantiated instanceof IType) {
					type = (IType) instantiated;
				}
			}
			if (type instanceof ITypedef) {
				typedef = (ITypedef) type;
				break;
			}
		}
		if (typedef == null) {
			return false;
		}

		IType t= SemanticUtil.getNestedType(typedef, TDEF);
		if (t instanceof ICPPUnknownBinding || t instanceof ISemanticProblem ||
				!(t instanceof ICPPClassType)) {
			return false;
		}

		ICPPClassType classType= (ICPPClassType) t;
		final IScope scope = ((ICPPClassType) t).getCompositeScope();
		if (scope == null) {
			return false;
		}

		char[] classChars= classType.getNameCharArray();
		char[] classDtorChars= new char[classChars.length + 1];
		classDtorChars[0]= '~';
		System.arraycopy(classChars, 0, classDtorChars, 1, classChars.length);
		data.setLookupKey(classDtorChars);
		lookup(data, scope);
		return true;
	}

	/**
	 * Checks whether the name directly or indirectly depends on the this pointer.
	 */
	private static boolean dependsOnTemplateFieldReference(IASTName astName) {
		if (astName.getPropertyInParent() != IASTFieldReference.FIELD_NAME)
			return false;

		final boolean[] result= {false};
		final IASTExpression fieldOwner = ((IASTFieldReference) astName.getParent()).getFieldOwner();
		fieldOwner.accept(new ASTVisitor() {
			{
				shouldVisitNames= true;
				shouldVisitExpressions= true;
			}

			@Override
			public int visit(IASTName name) {
				IBinding b= name.resolvePreBinding();
				if (b instanceof ICPPUnknownBinding || b instanceof ICPPTemplateDefinition) {
					result[0]= true;
					return PROCESS_ABORT;
				}
				if (b instanceof ICPPMember) {
					ICPPMember mem= (ICPPMember) b;
					if (!mem.isStatic()) {
						ICPPClassType owner= mem.getClassOwner();
						if (owner instanceof ICPPUnknownBinding || owner instanceof ICPPTemplateDefinition) {
							result[0]= true;
							return PROCESS_ABORT;
						}
					}
				}
				if (b instanceof IVariable) {
					IType t= SemanticUtil.getUltimateType(((IVariable) b).getType(), true);
					if (t instanceof ICPPUnknownBinding || t instanceof ICPPTemplateDefinition) {
						result[0]= true;
						return PROCESS_ABORT;
					}
				}
				if (name instanceof ICPPASTTemplateId)
					return PROCESS_SKIP;
				return PROCESS_CONTINUE;
			}

			@Override
			public int visit(IASTExpression expression) {
				if (expression instanceof ICPPASTLiteralExpression) {
					final ICPPASTLiteralExpression litExpr = (ICPPASTLiteralExpression) expression;
					if (litExpr.getKind() == IASTLiteralExpression.lk_this) {
						final IType thisType = SemanticUtil.getNestedType(litExpr.getEvaluation().getType(), TDEF | ALLCVQ | PTR | ARRAY | MPTR | REF);
						if (thisType instanceof ICPPUnknownBinding || thisType instanceof ICPPTemplateDefinition) {
							result[0]= true;
							return PROCESS_ABORT;
						}
					}
				}
				if (expression instanceof IASTUnaryExpression) {
					switch (((IASTUnaryExpression) expression).getOperator()) {
					case IASTUnaryExpression.op_sizeof:
					case IASTUnaryExpression.op_sizeofParameterPack:
					case IASTUnaryExpression.op_typeid:
					case IASTUnaryExpression.op_throw:
						return PROCESS_SKIP;
					}
				} else if (expression instanceof IASTTypeIdExpression) {
					switch (((IASTTypeIdExpression) expression).getOperator()) {
					case IASTTypeIdExpression.op_sizeof:
					case IASTTypeIdExpression.op_typeid:
						return PROCESS_SKIP;
					}
				} else if (expression instanceof IASTCastExpression) {
					if (!((IASTCastExpression) expression).getTypeId().accept(this)) {
						return PROCESS_ABORT;
					}
					return PROCESS_SKIP;
				} else if (expression instanceof ICPPASTNewExpression) {
					if (!((ICPPASTNewExpression) expression).getTypeId().accept(this)) {
						return PROCESS_ABORT;
					}
					return PROCESS_SKIP;
				} else if (expression instanceof ICPPASTSimpleTypeConstructorExpression) {
					return PROCESS_SKIP;
				} else if (expression instanceof IASTTypeIdInitializerExpression) {
					if (!((IASTTypeIdInitializerExpression) expression).getTypeId().accept(this)) {
						return PROCESS_ABORT;
					}
					return PROCESS_SKIP;
				}
				return PROCESS_CONTINUE;
			}
		});
		return result[0];
	}

	static IBinding[] getBindingsFromScope(ICPPScope scope, LookupData data) throws DOMException {
		IBinding[] bindings= scope.getBindings(data);

		if (scope instanceof ICPPASTInternalScope && scope instanceof ICPPClassScope) {
			final IASTName lookupName = data.getLookupName();
			if (LookupData.checkWholeClassScope(lookupName)) {
				// Bug 103857: Members declared after the point of completion cannot be
				//	 found in the partial AST, we look them up in the index
				CPPASTTranslationUnit tu = data.getTranslationUnit();
				if (tu != null && tu.isForContentAssist()) {
					IIndex index = tu.getIndex();
					IASTNode node = ((IASTInternalScope) scope).getPhysicalNode();
					if (index != null && node != null && node.contains(lookupName)) {
						IBinding indexBinding= index.adaptBinding(((ICPPClassScope) scope).getClassType());
						if (indexBinding instanceof ICPPClassType) {
							IScope scopeInIndex= ((ICPPClassType) indexBinding).getCompositeScope();
							bindings= ArrayUtil.addAll(bindings, scopeInIndex.getBindings(data));
						}
					}
				}
			}
		}

		if (data.ignoreRecursionResolvingBindings()) {
			bindings = ArrayUtil.filter(bindings, new RecursionResolvingBindingFilter());
		}

		if (data.namespacesOnly) {
			bindings = ArrayUtil.filter(bindings, (argument) -> {
				return argument instanceof ICPPNamespace;
			});
		}

		return expandUsingDeclarationsAndRemoveObjects(bindings, data);
	}

	private static class RecursionResolvingBindingFilter implements IUnaryPredicate<IBinding> {
		@Override
		public boolean apply(IBinding argument) {
			return !(argument instanceof IRecursionResolvingBinding);
		}
	}

	private static IBinding[] expandUsingDeclarationsAndRemoveObjects(final IBinding[] bindings,
			LookupData data) {
		if (bindings == null || bindings.length == 0)
			return IBinding.EMPTY_BINDING_ARRAY;

		for (IBinding b : bindings) {
			if (b == null)
				break;

			if (b instanceof ICPPUsingDeclaration || (data.typesOnly && isObject(b))) {
				List<IBinding> result= new ArrayList<>(bindings.length);
				expandUsingDeclarations(bindings, data, result);
				return result.toArray(new IBinding[result.size()]);
			}
		}
		return bindings;
	}

	private static boolean isObject(IBinding b) {
		return !(b instanceof IType || b instanceof ICPPNamespace);
	}

	private static void expandUsingDeclarations(IBinding[] bindings, LookupData data, List<IBinding> result) {
		if (bindings != null) {
			for (IBinding b : bindings) {
				if (b == null)
					return;
				// Lookup for a declaration shall ignore the using declarations.
				if (b instanceof ICPPUsingDeclaration) {
					if (data.forDeclaration() == null) {
						for (IBinding d : ((ICPPUsingDeclaration) b).getDelegates()) {
							// Note on excluding constructors:
							// Constructors are never found during name lookup ([class.ctor] p2).
							// Binding resolution sometimes resolves names to constructors, and as
							// such, the delegates of a using-declaration can include constructors,
							// but when using these delegates in the process of name lookup,
							// constructors are ignored. If the binding resolution triggering this
							// name lookup wants to ultimately resolve to a constructor, it can do so
							// after the name lookup phase, e.g. in the convertClassToConstructor()
							// call in postResolution().
							if (d != null && !(data.typesOnly && isObject(d)) &&
									!(d instanceof ICPPConstructor)) {
								result.add(d);
							}
						}
					}
				} else if (!(data.typesOnly && isObject(b))) {
					result.add(b);
				}
			}
		}
	}

	private static ICPPTemplateScope enclosingTemplateScope(IASTNode node) {
		IASTNode parent= node.getParent();
		if (parent instanceof IASTName) {
			if (parent instanceof ICPPASTTemplateId) {
				node= parent;
				parent= node.getParent();
			}
			if (parent instanceof ICPPASTQualifiedName) {
				ICPPASTQualifiedName qname= (ICPPASTQualifiedName) parent;
				if (qname.isFullyQualified() || qname.getQualifier()[0] != node)
					return null;
			}
		}
		while (!(parent instanceof ICPPASTTemplateDeclaration)) {
			if (parent == null)
				return null;
			parent= parent.getParent();
		}
		return ((ICPPASTTemplateDeclaration) parent).getScope();
	}

	static ICPPScope getParentScope(IScope scope, IASTTranslationUnit unit) throws DOMException {
		IScope parentScope= scope.getParent();
		// The index cannot return the translation unit as parent scope.
		if (parentScope == null && scope instanceof ICPPClassSpecializationScope
				&& unit instanceof CPPASTTranslationUnit) {
			parentScope = unit.getScope();
		} else {
			parentScope = SemanticUtil.mapToAST(parentScope, unit);
		}
		return (ICPPScope) parentScope;
	}

	/**
	 * Stores the using directive with the scope where the members of the nominated namespace will
	 * appear. In case of an unqualified lookup the transitive directives are stored, also.
	 * This is important because the members nominated by a transitive directive can appear before
	 * those of the original directive.
	 */
	private static void storeUsingDirective(LookupData data, ICPPNamespaceScope container,
			ICPPUsingDirective directive, Set<ICPPNamespaceScope> handled) throws DOMException {
		ICPPNamespaceScope nominated= directive.getNominatedScope();
		CPPASTTranslationUnit tu= data.getTranslationUnit();
		if (tu != null) {
			nominated= (ICPPNamespaceScope) tu.mapToASTScope(nominated);
		}
		if (nominated == null || data.visited.containsKey(nominated) || (handled != null && !handled.add(nominated))) {
			return;
		}
		// 7.3.4.1 names appear at end of common enclosing scope of container and nominated scope.
		final IScope appearsIn= getCommonEnclosingScope(nominated, container, tu);
		if (appearsIn instanceof ICPPNamespaceScope) {
			// store the directive with the scope where it has to be considered
			List<ICPPNamespaceScope> listOfNominated= data.usingDirectives.get(appearsIn);
			if (listOfNominated == null) {
				listOfNominated= new ArrayList<>(1);
				if (data.usingDirectives.isEmpty()) {
					data.usingDirectives= new HashMap<ICPPNamespaceScope, List<ICPPNamespaceScope>>();
				}
				data.usingDirectives.put((ICPPNamespaceScope) appearsIn, listOfNominated);
			}
			listOfNominated.add(nominated);
		}

		// In a non-qualified lookup the transitive directive have to be stored right away,
		// they may overtake the container.
		if (!data.qualified || data.contentAssist) {
			assert handled != null;
			if (tu != null) {
				tu.handleAdditionalDirectives(nominated);
			}
			ICPPUsingDirective[] transitive= nominated.getUsingDirectives();
			for (ICPPUsingDirective element : transitive) {
				storeUsingDirective(data, container, element, handled);
			}
		}
	}

	/**
	 * Computes the common enclosing scope of s1 and s2.
	 */
	private static ICPPScope getCommonEnclosingScope(IScope s1, IScope s2, ICPPASTTranslationUnit tu)
			throws DOMException {
		ObjectSet<IScope> set = new ObjectSet<>(2);
		IScope parent= s1;
		while (parent != null) {
			set.put(parent);
			parent= getParentScope(parent, tu);
		}
		parent= s2;
		while (parent != null && !set.containsKey(parent)) {
			parent = getParentScope(parent, tu);
		}
		return (ICPPScope) parent;
	}

	public static void populateCache(ICPPASTInternalScope scope) {
		IASTNode[] nodes = null;
		IASTNode parent= ASTInternal.getPhysicalNodeOfScope(scope);

		IASTName[] namespaceDefs = null;
		int namespaceIdx = -1;

		if (parent instanceof IASTCompoundStatement) {
			IASTNode p = parent.getParent();
			if (p instanceof IASTFunctionDefinition) {
				ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) ((IASTFunctionDefinition) p).getDeclarator();
				nodes = dtor.getParameters();
			} else if (p instanceof ICPPASTLambdaExpression) {
				ICPPASTLambdaExpression lambdaExpression = (ICPPASTLambdaExpression) p;
				for (ICPPASTCapture capture : lambdaExpression.getCaptures()) {
					if (capture instanceof ICPPASTInitCapture) {
						IASTName name = capture.getIdentifier();
						if (name != null) {
							ASTInternal.addName(scope, name);
						}
					}
				}
				ICPPASTFunctionDeclarator lambdaDeclarator = lambdaExpression.getDeclarator();
				if (lambdaDeclarator != null) {
					nodes = lambdaDeclarator.getParameters();
				}
			}
			if (p instanceof ICPPASTCatchHandler) {
				parent = p;
			} else if (nodes == null || nodes.length == 0) {
				IASTCompoundStatement compound = (IASTCompoundStatement) parent;
				nodes = compound.getStatements();
			}
		} else if (parent instanceof IASTTranslationUnit) {
			IASTTranslationUnit translation = (IASTTranslationUnit) parent;
			nodes = translation.getDeclarations();
		} else if (parent instanceof ICPPASTCompositeTypeSpecifier) {
			ICPPASTCompositeTypeSpecifier comp = (ICPPASTCompositeTypeSpecifier) parent;
			nodes = comp.getMembers();
		} else if (parent instanceof ICPPASTNamespaceDefinition) {
			// Need binding because namespaces can be split.
			CPPNamespace namespace = (CPPNamespace) ((ICPPASTNamespaceDefinition) parent).getName().resolveBinding();
			namespaceDefs = namespace.getNamespaceDefinitions();
			nodes = ((ICPPASTNamespaceDefinition) namespaceDefs[++namespaceIdx].getParent()).getDeclarations();
			while (nodes.length == 0 && ++namespaceIdx < namespaceDefs.length) {
				nodes= ((ICPPASTNamespaceDefinition) namespaceDefs[namespaceIdx].getParent()).getDeclarations();
			}
		} else if (parent instanceof ICPPASTFunctionDeclarator) {
			ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) parent;
			nodes = dtor.getParameters();
		} else if (parent instanceof ICPPASTTemplateDeclaration) {
			ICPPASTTemplateDeclaration template = (ICPPASTTemplateDeclaration) parent;
			nodes = template.getTemplateParameters();
		} else if (parent instanceof ICPPASTForStatement) {
			ICPPASTForStatement forStatement = (ICPPASTForStatement) parent;
			final IASTDeclaration conditionDeclaration = forStatement.getConditionDeclaration();
			IASTStatement initDeclaration= forStatement.getInitializerStatement();
			if (conditionDeclaration != null) {
				nodes= new IASTNode[] {initDeclaration, conditionDeclaration};
			} else {
				nodes= new IASTNode[] {initDeclaration};
			}
		} else if (parent instanceof ICPPASTSwitchStatement) {
			ICPPASTSwitchStatement ifStatement = (ICPPASTSwitchStatement) parent;
			final IASTStatement initStatement = ifStatement.getInitializerStatement();
			final IASTDeclaration controllerDeclaration = ifStatement.getControllerDeclaration();
			if (initStatement != null) {
				nodes = new IASTNode[] {initStatement, controllerDeclaration};
			} else {
				nodes = new IASTNode[] {controllerDeclaration};
			}
		} else if (parent instanceof ICPPASTIfStatement) {
			ICPPASTIfStatement ifStatement = (ICPPASTIfStatement) parent;
			final IASTStatement initStatement = ifStatement.getInitializerStatement();
			final IASTDeclaration conditionDeclaration = ifStatement.getConditionDeclaration();
			if (initStatement != null) {
				nodes = new IASTNode[] {initStatement, conditionDeclaration};
			} else {
				nodes = new IASTNode[] {conditionDeclaration};
			}
		} else if (parent instanceof ICPPASTWhileStatement) {
			nodes = new IASTNode[] { ((ICPPASTWhileStatement) parent).getConditionDeclaration() };
		} else if (parent instanceof ICPPASTRangeBasedForStatement) {
			ICPPASTRangeBasedForStatement forStatement = (ICPPASTRangeBasedForStatement) parent;
			final IASTDeclaration decl = forStatement.getDeclaration();
			nodes= new IASTNode[] {decl};
		} else if (parent instanceof ICPPASTEnumerationSpecifier) {
			// The enumeration scope contains the enumeration items
			for (IASTEnumerator enumerator : ((ICPPASTEnumerationSpecifier) parent).getEnumerators()) {
				ASTInternal.addName(scope, enumerator.getName());
			}
			return;
		} else if (parent instanceof ICPPASTTemplatedTypeTemplateParameter) {
			// The template-template parameter scope contains the parameters
			for (ICPPASTTemplateParameter par : ((ICPPASTTemplatedTypeTemplateParameter) parent).getTemplateParameters()) {
				IASTName name= CPPTemplates.getTemplateParameterName(par);
				if (name != null) {
					ASTInternal.addName(scope, name);
				}
			}
			return;
		}

		int idx = -1;
		IASTNode item = (nodes != null ? (nodes.length > 0 ? nodes[++idx] : null) : parent);
		IASTNode[][] nodeStack = null;
		int[] nodeIdxStack = null;
		int nodeStackPos = -1;
		while (item != null) {
			if (item instanceof ICPPASTLinkageSpecification) {
				IASTDeclaration[] decls = ((ICPPASTLinkageSpecification) item).getDeclarations();
				if (decls != null && decls.length > 0) {
					nodeStack = ArrayUtil.append(IASTNode[].class, nodeStack, nodes);
					nodeIdxStack = ArrayUtil.setInt(nodeIdxStack, ++nodeStackPos, idx);
					nodes = ((ICPPASTLinkageSpecification) item).getDeclarations();
					idx = 0;
					item = nodes[idx];
					continue;
				}
			}
			while (item instanceof IASTLabelStatement) {
				item= ((IASTLabelStatement) item).getNestedStatement();
			}
			if (item instanceof IASTDeclarationStatement)
				item = ((IASTDeclarationStatement) item).getDeclaration();
			if (item instanceof ICPPASTUsingDirective) {
				if (scope instanceof ICPPNamespaceScope) {
					final ICPPNamespaceScope nsscope = (ICPPNamespaceScope) scope;
					final ICPPASTUsingDirective usingDirective = (ICPPASTUsingDirective) item;
					nsscope.addUsingDirective(new CPPUsingDirective(usingDirective));
				}
			} else if (item instanceof ICPPASTNamespaceDefinition) {
				final ICPPASTNamespaceDefinition nsDef = (ICPPASTNamespaceDefinition) item;
				final boolean isUnnamed = nsDef.getName().getLookupKey().length == 0;
				boolean isInline = nsDef.isInline();
				// An inline namespace can be re-opened without repeating the inline keyword,
				// so we need to consult the binding to check inlineness. 
				if (!isUnnamed && !isInline) {
					IBinding nsBinding = nsDef.getName().resolveBinding();
					if (nsBinding instanceof ICPPNamespace) {
						isInline = ((ICPPNamespace) nsBinding).isInline();
					}
				}
				if (isUnnamed || isInline) {
					if (scope instanceof CPPNamespaceScope) {
						final CPPNamespaceScope nsscope = (CPPNamespaceScope) scope;
						nsscope.addUsingDirective(new CPPUsingDirective(nsDef));
						if (isInline) {
							nsscope.addInlineNamespace(nsDef);
						}
					}
				}
				if (!isUnnamed) {
					populateCache(scope, item);
				}
			} else {
				populateCache(scope, item);
			}

			if (nodes != null && ++idx < nodes.length) {
				item = nodes[idx];
			} else {
				item = null;
				while (true) {
					if (namespaceDefs != null) {
						// Check all definitions of this namespace.
						while (++namespaceIdx < namespaceDefs.length) {
							nodes = ((ICPPASTNamespaceDefinition) namespaceDefs[namespaceIdx].getParent()).getDeclarations();
							if (nodes.length > 0) {
								idx = 0;
								item = nodes[0];
								break;
							}
						}
					} else if (parent instanceof IASTCompoundStatement && nodes instanceof IASTParameterDeclaration[]) {
						// Function body, we were looking at parameters, now check the body itself.
						IASTCompoundStatement compound = (IASTCompoundStatement) parent;
						nodes = compound.getStatements();
						if (nodes.length > 0) {
							idx = 0;
							item = nodes[0];
							break;
						}
					} else if (parent instanceof ICPPASTCatchHandler) {
						parent = ((ICPPASTCatchHandler) parent).getCatchBody();
						if (parent instanceof IASTCompoundStatement) {
							nodes = ((IASTCompoundStatement) parent).getStatements();
							if (nodes.length > 0) {
								idx = 0;
								item = nodes[0];
								break;
							}
						}
					}
					if (item == null && nodeStack != null && nodeIdxStack != null && nodeStackPos >= 0) {
						nodes = nodeStack[nodeStackPos];
						nodeStack[nodeStackPos] = null;
						idx = nodeIdxStack[nodeStackPos--];
						if (++idx >= nodes.length)
							continue;

						item = nodes[idx];
					}
					break;
				}
			}
		}
	}

	public static void populateCache(ICPPASTInternalScope scope, IASTNode node) {
		IASTDeclaration declaration = null;
		if (node instanceof ICPPASTTemplateDeclaration) {
			declaration = ((ICPPASTTemplateDeclaration) node).getDeclaration();
		} else if (node instanceof IASTDeclaration) {
			declaration = (IASTDeclaration) node;
		} else if (node instanceof IASTDeclarationStatement) {
			declaration = ((IASTDeclarationStatement) node).getDeclaration();
		} else if (node instanceof ICPPASTCatchHandler) {
			declaration = ((ICPPASTCatchHandler) node).getDeclaration();
		} else if (node instanceof IASTParameterDeclaration) {
			IASTParameterDeclaration parameterDeclaration = (IASTParameterDeclaration) node;
			IASTDeclarator dtor = parameterDeclaration.getDeclarator();
			IASTDeclarator innermost= dtor;
			while (dtor != null) {
				if (dtor instanceof IASTAmbiguousDeclarator)
					return;
				innermost= dtor;
				dtor= dtor.getNestedDeclarator();
			}
			if (innermost != null) { // Could be null when content assist in the declSpec
				IASTName declName = innermost.getName();
				ASTInternal.addName(scope, declName);
				return;
			}
		} else if (node instanceof ICPPASTTemplateParameter) {
			IASTName name = CPPTemplates.getTemplateParameterName((ICPPASTTemplateParameter) node);
			ASTInternal.addName(scope, name);
			return;
		}
		if (declaration == null || declaration instanceof ASTAmbiguousNode) {
			return;
		}

		if (declaration instanceof IASTSimpleDeclaration) {
			IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration;
			ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) simpleDeclaration.getDeclSpecifier();
			IASTDeclarator[] declarators = simpleDeclaration.getDeclarators();
			if (!declSpec.isFriend()) {
				for (IASTDeclarator declarator : declarators) {
					IASTDeclarator innermost= null;
					while (declarator != null) {
						if (declarator instanceof IASTAmbiguousDeclarator) {
							innermost= null;
							break;
						}
						innermost= declarator;
						declarator= declarator.getNestedDeclarator();
					}
					if (innermost != null) {
						IASTName declaratorName = innermost.getName();
						ASTInternal.addName(scope, declaratorName);
					}
				}
			}

			// Declaration specifiers defining or declaring a type
			IASTName specName = null;
			final EScopeKind scopeKind = scope.getKind();
			if (declSpec instanceof IASTElaboratedTypeSpecifier) {
				// 3.3.1.5 Point of declaration
				if (!declSpec.isFriend()) {
					if (declarators.length == 0 || scopeKind == EScopeKind.eGlobal
							|| scopeKind == EScopeKind.eNamespace) {
						specName = ((IASTElaboratedTypeSpecifier) declSpec).getName();
					}
				}
			} else if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
				ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) declSpec;
				specName = compSpec.getName();

				// Anonymous union or struct (GCC supports anonymous structs too)
				if (declarators.length == 0 && specName.getLookupKey().length == 0) {
					IASTDeclaration[] decls = compSpec.getMembers();
					for (IASTDeclaration decl : decls) {
						populateCache(scope, decl);
					}
				}
			} else if (declSpec instanceof ICPPASTEnumerationSpecifier) {
				ICPPASTEnumerationSpecifier enumeration = (ICPPASTEnumerationSpecifier) declSpec;
				specName = enumeration.getName();

				handleEnumeration(enumeration, scope);
			}
			if (specName != null) {
				if (!(specName instanceof ICPPASTQualifiedName)) {
					ASTInternal.addName(scope, specName);
				}
			}
			// Collect friends and elaborated type specifiers with declarators from nested classes.
			if (declarators.length > 0 || declSpec instanceof ICPPASTCompositeTypeSpecifier) {
				switch (scopeKind) {
				case eLocal:
				case eGlobal:
				case eNamespace:
					NamespaceTypeCollector visitor = new NamespaceTypeCollector(scope);
					declSpec.accept(visitor);
					for (IASTDeclarator dtor : declarators) {
						dtor.accept(visitor);
					}
					break;

				default:
					break;
				}
			}
		} else if (declaration instanceof ICPPASTUsingDeclaration) {
			ICPPASTUsingDeclaration using = (ICPPASTUsingDeclaration) declaration;
			IASTName name = using.getName();
			if (name instanceof ICPPASTQualifiedName) {
				name = name.getLastName();
			}
			ASTInternal.addName(scope, name);
		} else if (declaration instanceof ICPPASTNamespaceDefinition) {
			IASTName namespaceName = ((ICPPASTNamespaceDefinition) declaration).getName();
			ASTInternal.addName(scope, namespaceName);
		} else if (declaration instanceof ICPPASTNamespaceAlias) {
			IASTName alias = ((ICPPASTNamespaceAlias) declaration).getAlias();
			ASTInternal.addName(scope, alias);
		} else if (declaration instanceof ICPPASTAliasDeclaration) {
			ICPPASTAliasDeclaration aliasDecl = (ICPPASTAliasDeclaration) declaration;
			IASTName alias = aliasDecl.getAlias();
			ASTInternal.addName(scope, alias);

			// The mapping-type-id could declare an enumeration.
			IASTDeclSpecifier declSpec = aliasDecl.getMappingTypeId().getDeclSpecifier();
			if (declSpec instanceof ICPPASTEnumerationSpecifier) {
				handleEnumeration((ICPPASTEnumerationSpecifier) declSpec, scope);
			}
		} else if (declaration instanceof IASTFunctionDefinition) {
 			IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration;
			final IASTDeclSpecifier declSpec = functionDef.getDeclSpecifier();
			IASTFunctionDeclarator declarator = functionDef.getDeclarator();

			if (!((ICPPASTDeclSpecifier) declSpec).isFriend()) {
				// Check the function itself
				IASTName declName = ASTQueries.findInnermostDeclarator(declarator).getName();
				ASTInternal.addName(scope, declName);
			}
			// Collect elaborated type specifiers and friends
			final EScopeKind scopeKind = scope.getKind();
			switch (scopeKind) {
			case eLocal:
			case eGlobal:
			case eNamespace:
				NamespaceTypeCollector visitor = new NamespaceTypeCollector(scope);
				declSpec.accept(visitor);
				declarator.accept(visitor);
				break;

			default:
				break;
			}
		}
	}

	private static void handleEnumeration(ICPPASTEnumerationSpecifier enumSpec,
			IScope enclosingScope) {
		// Add unscoped enumerators to the enclosing scope
		if (!enumSpec.isScoped()) {
			for (IASTEnumerator enumerator : enumSpec.getEnumerators()) {
				ASTInternal.addName(enclosingScope, enumerator.getName());
			}
		}
	}

	/**
	 * Perform lookup in nominated namespaces that appear in the given scope. For unqualified
	 * lookups the method assumes that transitive directives have been stored in the lookup-data.
	 * For qualified lookups the transitive directives are considered if the lookup of the original
	 * directive returns empty.
	 */
	private static void lookupInNominated(LookupData data, ICPPNamespaceScope scope) throws DOMException {
		List<ICPPNamespaceScope> allNominated= data.usingDirectives.remove(scope);
		while (allNominated != null) {
			for (ICPPNamespaceScope nominated : allNominated) {
				if (data.visited.containsKey(nominated)) {
					continue;
				}
				data.visited.put(nominated);

				boolean found = false;
				IBinding[] bindings= getBindingsFromScope(nominated, data);
				if (bindings != null && bindings.length > 0) {
					mergeResults(data, bindings, true);
					found = true;
				}

				// In the qualified lookup we have to nominate the transitive directives only when
				// the lookup did not succeed. In the qualified case this is done earlier, when
				// the directive is encountered.
				if (!found && data.qualified && !data.contentAssist) {
					final CPPASTTranslationUnit tu = data.getTranslationUnit();
					if (tu != null) {
						tu.handleAdditionalDirectives(nominated);
					}
					ICPPUsingDirective[] usings= nominated.getUsingDirectives();
					for (ICPPUsingDirective using : usings) {
						storeUsingDirective(data, scope, using, null);
					}
				}
			}
			// Retry with transitive directives that may have been nominated in a qualified lookup
			allNominated= data.usingDirectives.remove(scope);
		}
	}

	public static IBinding resolveAmbiguities(IASTName name, Object[] bindings) {
		bindings = ArrayUtil.trim(Object.class, bindings);
		if (bindings == null || bindings.length == 0) {
			return null;
		} else if (bindings.length == 1) {
			IBinding candidate= null;
			if (bindings[0] instanceof IBinding) {
				candidate= (IBinding) bindings[0];
			} else if (bindings[0] instanceof IASTName) {
				candidate= ((IASTName) bindings[0]).getPreBinding();
			} else {
				return null;
			}
			if (candidate != null) {
				if (!(candidate instanceof IType) && !(candidate instanceof ICPPNamespace) &&
						!(candidate instanceof ICPPUsingDeclaration) &&
						LookupData.typesOnly(name)) {
					return null;
				}

				// Bug 238180
				if (candidate instanceof ICPPClassTemplatePartialSpecialization)
					return null;

				// Specialization is selected during instantiation
				if (candidate instanceof ICPPTemplateInstance)
					candidate= ((ICPPTemplateInstance) candidate).getSpecializedBinding();

				if (!(candidate instanceof ICPPFunctionTemplate))
					return candidate;
			}
		}

		LookupData data = createLookupData(name);
		data.foundItems = bindings;
		try {
			return resolveAmbiguities(data);
		} catch (DOMException e) {
			return e.getProblem();
		}
//
//        IBinding[] result = null;
//        for (Object binding : bindings) {
//            if (binding instanceof IASTName) {
//                result = ArrayUtil.append(IBinding.class, result, ((IASTName) binding).resolveBinding());
//            } else if (binding instanceof IBinding) {
//                result = ArrayUtil.append(IBinding.class, result, (IBinding) binding);
//            }
//        }
//        return new CPPCompositeBinding(result);
	}

	public static boolean declaredBefore(Object obj, IASTNode node, boolean indexBased) {
		if (node instanceof IPDOMAdaptedASTNode) {
			// Get the underlying ASTNode.
			node = ((IPDOMAdaptedASTNode) node).getDelegate();
		}
		if (!(node instanceof ASTNode))
			return true;

		// The pointOfRef and pointOfDecl variables contain node offsets scaled by a factor of two.
		// This is done to distinguish between left and right points for the same offset.
		final int pointOfRef= ((ASTNode) node).getOffset() * 2;
		ASTNode nd = null;
		while (obj instanceof ICPPSpecialization) {
			obj = ((ICPPSpecialization) obj).getSpecializedBinding();
		}

		int pointOfDecl= -1;
		if (obj instanceof ICPPInternalBinding) {
			ICPPInternalBinding cpp = (ICPPInternalBinding) obj;
			IASTNode[] n = cpp.getDeclarations();
			if (n != null && n.length > 0) {
				nd = (ASTNode) n[0];
			}
			ASTNode def = (ASTNode) cpp.getDefinition();
			if (def != null && (nd == null || def.getOffset() < nd.getOffset())) {
				nd = def;
			}
			if (nd == null)
				return true;
		} else {
			if (indexBased && obj instanceof IASTName) {
				IBinding b= ((IASTName) obj).getPreBinding();
				if (b instanceof ICPPInternalBinding) {
					if (acceptDeclaredAfter((ICPPInternalBinding) b))
						return true;
				}
			}
			if (obj instanceof ASTNode) {
				nd = (ASTNode) obj;
			} else if (obj instanceof ICPPUsingDirective) {
				pointOfDecl= ((ICPPUsingDirective) obj).getPointOfDeclaration() * 2;
			}
		}

		if (pointOfDecl < 0) {
			if (nd != null) {
				pointOfDecl = getPointOfDeclaration(nd);
			} else if (obj instanceof IIndexBinding && !isUsingPromiscuousBindingResolution()) {
				IIndexBinding indexBinding = (IIndexBinding) obj;
				if (indexBinding instanceof ICPPMethod && ((ICPPMethod) indexBinding).isImplicit()) {
					return true;
				}
				IASTTranslationUnit tu = node.getTranslationUnit();
				IIndexFileSet indexFileSet = tu.getIndexFileSet();
				return (indexFileSet != null && indexFileSet.containsDeclaration(indexBinding));
			}
		}
		return pointOfDecl < pointOfRef;
	}
	
	/**
	 * Returns the point of declaration for the given AST node. The point of declaration is a node offset
	 * scaled by a factor of two. This is done to distinguish between left and right points for the offset.
	 */
	private static int getPointOfDeclaration(ASTNode nd) {
		ASTNodeProperty prop = nd.getPropertyInParent();
		if (prop == IASTDeclarator.DECLARATOR_NAME || nd instanceof IASTDeclarator) {
			// Point of declaration for a name is immediately after its complete declarator
			// and before its initializer.
			IASTDeclarator dtor = (IASTDeclarator)((nd instanceof IASTDeclarator) ? nd : nd.getParent());
			while (dtor.getParent() instanceof IASTDeclarator) {
				dtor = (IASTDeclarator) dtor.getParent();
			}
			IASTInitializer init = dtor.getInitializer();
			// [basic.scope.pdecl]/p9: The point of declaration for a template parameter
			// is immediately after its complete template-parameter.
			// Note: can't just check "dtor.getParent() instanceof ICPPASTTemplateParameter"
			// because function parameter declarations implement ICPPASTTemplateParameter too.
			boolean isTemplateParameter = dtor.getParent() instanceof ICPPASTTemplateParameter
					&& dtor.getParent().getPropertyInParent() == ICPPASTTemplateDeclaration.PARAMETER;
			if (init != null && !isTemplateParameter) {
				return ((ASTNode) init).getOffset() * 2 - 1;
			} else {
				return (((ASTNode) dtor).getOffset() + ((ASTNode) dtor).getLength()) * 2 - 1;
			}
		} else if (prop == IASTEnumerator.ENUMERATOR_NAME) {
			// Point of declaration for an enumerator is immediately after it
			// enumerator-definition
			IASTEnumerator enumtor = (IASTEnumerator) nd.getParent();
			if (enumtor.getValue() != null) {
				ASTNode exp = (ASTNode) enumtor.getValue();
				return (exp.getOffset() + exp.getLength()) * 2 - 1;
			} else {
				return (nd.getOffset() + nd.getLength()) * 2 - 1;
			}
		} else if (prop == ICPPASTUsingDeclaration.NAME) {
			nd = (ASTNode) nd.getParent();
			return nd.getOffset() * 2;
		} else if (prop == ICPPASTNamespaceAlias.ALIAS_NAME) {
			nd = (ASTNode) nd.getParent();
			return (nd.getOffset() + nd.getLength()) * 2 - 1;
		} else if (prop == ICPPASTAliasDeclaration.ALIAS_NAME) {
			// [basic.scope.pdecl]/p3: The point of declaration of an alias or alias template
			// immediately follows the type-id to which the alias refers.
			ASTNode targetType = (ASTNode) ((ICPPASTAliasDeclaration) nd.getParent()).getMappingTypeId();
			return (targetType.getOffset() + targetType.getLength()) * 2 - 1;
		} else if (prop == ICPPASTSimpleTypeTemplateParameter.PARAMETER_NAME
				|| prop == ICPPASTTemplatedTypeTemplateParameter.PARAMETER_NAME) {
			// [basic.scope.pdecl]/p9: The point of declaration for a template parameter
			// is immediately after its complete template-parameter.
			// Type and template template parameters are handled here;
			// non-type template parameters are handled in the DECLARATOR_NAME
			// case above.
			nd = (ASTNode) nd.getParent();
			return (nd.getOffset() + nd.getLength()) * 2 - 1;
		} else {
			return (nd.getOffset() + nd.getLength()) * 2 - 1;
		}
	}

	private static boolean acceptDeclaredAfter(ICPPInternalBinding cpp) {
		try {
			if (cpp instanceof ICPPNamespace || cpp instanceof ICPPFunction || cpp instanceof ICPPVariable) {
				IScope scope= cpp.getScope();
				if (!(scope instanceof ICPPBlockScope) && scope instanceof ICPPNamespaceScope) {
					return true;
				}
			} else if (cpp instanceof ICompositeType || cpp instanceof IEnumeration) {
				IScope scope= cpp.getScope();
				if (!(scope instanceof ICPPBlockScope) && scope instanceof ICPPNamespaceScope) {
					// If this is not the definition, it may be found in a header. (bug 229571)
					if (cpp.getDefinition() == null) {
						return true;
					}
				}
			}
		} catch (DOMException e) {
		}
		return false;
	}

	private static IBinding resolveAmbiguities(LookupData data) throws DOMException {
		if (!data.hasResults() || data.contentAssist)
			return null;

		final IASTName lookupName = data.getLookupName();
		IASTNode lookupPoint = data.getLookupPoint();
		final boolean indexBased= data.getIndex() != null;
		final boolean checkWholeClass= lookupName == null || LookupData.checkWholeClassScope(lookupName);
		ObjectSet<ICPPFunction> fns= ObjectSet.emptySet();
		IBinding type = null;
		IBinding obj = null;
		boolean ambiguous = false;
		IBinding temp = null;

		final CPPASTTranslationUnit tu = data.getTranslationUnit();
		Object[] items = (Object[]) data.foundItems;
		for (int i = 0; i < items.length && items[i] != null; i++) {
			Object o = items[i];
			boolean declaredBefore = data.isIgnorePointOfDeclaration() || declaredBefore(o, lookupPoint, indexBased);
			boolean checkResolvedNamesOnly= false;
			if (!checkWholeClass && !declaredBefore) {
				if (lookupName != null && lookupName.getRoleOfName(false) != IASTNameOwner.r_reference) {
					checkResolvedNamesOnly= true;
					declaredBefore= true;
				} else {
					continue;
				}
			}
			if (o instanceof IASTName) {
				IASTName on= (IASTName) o;
				if (checkResolvedNamesOnly) {
					temp = on.getPreBinding();
				} else {
					temp= on.resolvePreBinding();
				}
				if (temp == null)
					continue;
			} else if (o instanceof IBinding) {
				temp = (IBinding) o;
			} else {
				continue;
			}

			// Select among those bindings that have been created without problems.
			if (temp instanceof IProblemBinding)
				continue;

			if (!declaredBefore && !(temp instanceof ICPPMember) && !(temp instanceof IType) &&
					!(temp instanceof IEnumerator)) {
				continue;
			}

			// Specializations are selected during instantiation.
			if (temp instanceof ICPPPartialSpecialization)
				continue;
			if (temp instanceof ICPPTemplateInstance && lookupName instanceof ICPPASTTemplateId) {
				temp= ((ICPPTemplateInstance) temp).getSpecializedBinding();
				if (!(temp instanceof IType))
					continue;
			}

			if (temp instanceof ICPPUsingDeclaration) {
				IBinding[] bindings = ((ICPPUsingDeclaration) temp).getDelegates();
				mergeResults(data, bindings, false);
				items = (Object[]) data.foundItems;
				continue;
			} else if (temp instanceof CPPCompositeBinding) {
				IBinding[] bindings = ((CPPCompositeBinding) temp).getBindings();
				mergeResults(data, bindings, false);
				items = (Object[]) data.foundItems;
				continue;
			} else if (temp instanceof ICPPFunction) {
				if (temp instanceof ICPPTemplateInstance) {
					temp= ((ICPPTemplateInstance) temp).getSpecializedBinding();
					if (!(temp instanceof IFunction))
						continue;
				}
				if (fns == ObjectSet.EMPTY_SET)
					fns = new ObjectSet<>(2);
				fns.put((ICPPFunction) temp);
			} else if (temp instanceof IType) {
				if (type == null) {
					type = temp;
					ambiguous = false;
				} else if (!type.equals(temp)) {
					int c = compareByRelevance(tu, type, temp);
					if (c < 0) {
						type= temp;
						ambiguous = false;
					} else if (c == 0) {
						if (((IType) type).isSameType((IType) temp)) {
							if (type instanceof ITypedef && !(temp instanceof ITypedef)) {
								// Between same types prefer non-typedef.
								type= temp;
								ambiguous = false;
							}
						} else {
							ambiguous = true;
						}
					}
				}
			} else {
				if (obj == null) {
					obj = temp;
					ambiguous = false;
				} else if (!obj.equals(temp)) {
					if (obj instanceof ICPPNamespace && temp instanceof ICPPNamespace &&
							SemanticUtil.isSameNamespace((ICPPNamespace) obj, (ICPPNamespace) temp)) {
						continue;
					}
					int c = compareByRelevance(tu, obj, temp);
					if (c < 0) {
						obj= temp;
						ambiguous = false;
					} else if (c == 0) {
						ambiguous = true;
					}
				}
			}
		}
		if (ambiguous) {
			return new ProblemBinding(lookupName, lookupPoint,
					IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
		}

		if (data.forUsingDeclaration) {
			int cmp= -1;
			if (obj != null) {
				cmp= 1;
				if (fns.size() > 0) {
					IFunction[] fnArray= fns.keyArray(IFunction.class);
					cmp= compareByRelevance(data, obj, fnArray);
					if (cmp == 0) {
						return new ProblemBinding(lookupName, lookupPoint,
								IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
					}
				}
			}

			IBinding[] bindings = IBinding.EMPTY_BINDING_ARRAY;
			if (cmp > 0) {
				bindings = ArrayUtil.append(bindings, obj);
				bindings = ArrayUtil.append(bindings, type);
			} else {
				bindings = ArrayUtil.append(bindings, type);
				bindings = ArrayUtil.addAll(bindings, fns.keyArray());
			}
			bindings = ArrayUtil.trim(IBinding.class, bindings);
			ICPPUsingDeclaration composite = new CPPUsingDeclaration(lookupName, bindings);
			return composite;
		}

		if (obj != null && type != null) {
			if (obj instanceof ICPPNamespace) {
				if (compareByRelevance(tu, type, obj) >= 0) {
					obj= null;
				}
			} else if (!data.typesOnly && overrulesByRelevance(data, type, obj)) {
				obj= null;
			}
		}

		if (data.typesOnly) {
			if (obj instanceof ICPPNamespace)
				return obj;

			return type;
		}

		if (!fns.isEmpty()) {
			final ICPPFunction[] fnArray = fns.keyArray(ICPPFunction.class);
			if (type != null && overrulesByRelevance(data, type, fnArray)) {
				return type;
			}

			if (obj != null) {
				int cmp= compareByRelevance(data, obj, fnArray);
				if (cmp == 0) {
					return new ProblemBinding(lookupName, lookupPoint,
							IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
				}
				if (cmp > 0) {
					return obj;
				}
			}
			return resolveFunction(data, fnArray, true, false);
		}

		if (obj != null) {
			return obj;
		}
		return type;
	}

	/**
	 * Compares two bindings for relevance in the context of an AST. AST bindings are
	 * considered more relevant than index ones since the index may be out of date,
	 * built for a different configuration, etc. Index bindings reachable through includes
	 * are more relevant than unreachable ones.
	 * @param ast
	 * @param b1
	 * @param b2
	 * @return 1 if binding <code>b1</code> is more relevant than <code>b2</code>; 0 if
	 * the two bindings have the same relevance; -1 if <code>b1</code> is less relevant than
	 * <code>b2</code>.
	 */
	static int compareByRelevance(IASTTranslationUnit tu, IBinding b1, IBinding b2) {
		boolean b1FromIndex= isFromIndex(b1);
		boolean b2FromIndex= isFromIndex(b2);
		if (b1FromIndex != b2FromIndex) {
			return !b1FromIndex ? 1 : -1;
		} else if (b1FromIndex) {
			// Both are from index.
			if (tu != null) {
				boolean b1Reachable= isReachableFromAst(tu, b1);
				boolean b2Reachable= isReachableFromAst(tu, b2);
				if (b1Reachable != b2Reachable) {
					return b1Reachable ? 1 : -1;
				}
			}
		}
		return 0;
	}

	/**
	 * Compares two bindings for relevance in the context of an AST. Type bindings are
	 * considered to overrule object bindings when the former is reachable but the
	 * latter is not.
	 */
	static boolean overrulesByRelevance(LookupData data, IBinding type, IBinding b2) {
		if (data == null)
			return false;
		final CPPASTTranslationUnit tu = data.getTranslationUnit();
		if (tu != null) {
			return !isReachableFromAst(tu, b2) && isReachableFromAst(tu, type);
		}
		return false;
	}

	/**
	 * Compares a binding with a list of function candidates for relevance in the
	 * context of an AST. Types are considered to overrule object bindings when
	 * the former is reachable but none of the functions are.
	 */
	static boolean overrulesByRelevance(LookupData data, IBinding type, IFunction[] fns) {
		if (data == null)
			return false;
		final CPPASTTranslationUnit tu = data.getTranslationUnit();

		for (int i = 0; i < fns.length; i++) {
			if (!isFromIndex(fns[i])) {
				return false;	// function from ast
			}
		}

		if (!isReachableFromAst(tu, type)) {
			return false;
		}

		for (IFunction fn : fns) {
			if (isReachableFromAst(tu, fn)) {
				return false;	// function from ast
			}
		}
		return true;
	}


	/**
	 * Compares two bindings for relevance in the context of an AST. AST bindings are
	 * considered more relevant than index ones since the index may be out of date,
	 * built for a different configuration, etc. Index bindings reachable through includes
	 * are more relevant than unreachable ones.
	 * @param ast
	 * @param b1
	 * @param b2
	 * @return 1 if binding <code>b1</code> is more relevant than <code>b2</code>; 0 if
	 * the two bindings have the same relevance; -1 if <code>b1</code> is less relevant than
	 * <code>b2</code>.
	 */
	static int compareByRelevance(LookupData data, IName b1, IName b2) {
		boolean b1FromIndex= (b1 instanceof IIndexName);
		boolean b2FromIndex= (b2 instanceof IIndexName);
		if (b1FromIndex != b2FromIndex) {
			return !b1FromIndex ? 1 : -1;
		} else if (b1FromIndex) {
			// Both are from index.
			final CPPASTTranslationUnit tu = data.getTranslationUnit();
			if (tu != null) {
				boolean b1Reachable= isReachableFromAst(tu, b1);
				boolean b2Reachable= isReachableFromAst(tu, b2);
				if (b1Reachable != b2Reachable) {
					return b1Reachable ? 1 : -1;
				}
			}
		}
		return 0;
	}

	/**
	 * Compares a binding with a list of function candidates for relevance in the context of an AST. AST bindings are
	 * considered more relevant than index ones since the index may be out of date,
	 * built for a different configuration, etc. Index bindings reachable through includes
	 * are more relevant than unreachable ones.
	 * @return 1 if binding <code>obj</code> is more relevant than the function candidates; 0 if
	 * the they have the same relevance; -1 if <code>obj</code> is less relevant than
	 * the function candidates.
	 */
	static int compareByRelevance(LookupData data, IBinding obj, IFunction[] fns) {
		if (isFromIndex(obj)) {
			for (int i = 0; i < fns.length; i++) {
				if (!isFromIndex(fns[i])) {
					return -1;	// function from ast
				}
			}
			// Everything is from the index
			final CPPASTTranslationUnit tu = data.getTranslationUnit();
			if (!isReachableFromAst(tu, obj)) {
				return -1; // obj not reachable
			}

			for (IFunction fn : fns) {
				if (isReachableFromAst(tu, fn)) {
					return 0; // obj reachable, 1 function reachable
				}
			}
			return 1;  // no function is reachable
		}

		// obj is not from the index
		for (int i = 0; i < fns.length; i++) {
			if (!isFromIndex(fns[i])) {
				return 0; // obj and function from ast
			}
		}
		return 1; // only obj is from ast.
	}

	private static boolean isFromIndex(IBinding binding) {
		if (binding instanceof IIndexBinding) {
			return true;
		}
		if (binding instanceof ICPPSpecialization) {
			return ((ICPPSpecialization) binding).getSpecializedBinding() instanceof IIndexBinding;
		}
		return false;
	}

	/**
	 * Checks if a binding is an AST binding, or is reachable from the AST through includes.
	 * The binding is assumed to belong to the AST, if it is not an {@link IIndexBinding} and not
	 * a specialization of an IIndexBinding.
	 *
	 * @param ast the ast to check
	 * @param binding the binding to check
	 * @return {@code true} if the {@code binding}> is reachable from the {@code ast}
	 */
	private static boolean isReachableFromAst(IASTTranslationUnit ast, IBinding binding) {
		IIndexBinding indexBinding = null;
		if (binding instanceof IIndexBinding) {
			indexBinding = (IIndexBinding) binding;
		}
		if (binding instanceof ICPPSpecialization) {
			binding = ((ICPPSpecialization) binding).getSpecializedBinding();
			if (binding instanceof IIndexBinding) {
				indexBinding = (IIndexBinding) binding;
			}
		}
		if (indexBinding == null) {
			// We don't check if the binding really belongs to the AST specified by the ast
			// parameter assuming that the caller doesn't deal with two ASTs at a time.
			return true;
		}
		IIndexFileSet indexFileSet = ast.getIndexFileSet();
		IIndexFileSet astFileSet = ast.getASTFileSet();
		return indexFileSet != null &&
				(indexFileSet.containsDeclaration(indexBinding) ||
				 astFileSet.containsDeclaration(indexBinding));
	}

	/**
	 * Checks if a name is an AST name, or is reachable from the AST through includes.
	 * The name is assumed to belong to the AST, if it is not an {@link IIndexName}.
	 *
	 * @param ast the ast to check
	 * @param name the name to check
	 * @return {@code true} if the {@code name}> is reachable from the {@code ast}
	 */
	private static boolean isReachableFromAst(IASTTranslationUnit ast, IName name) {
		if (!(name instanceof IIndexName)) {
			return true;
		}
		IIndexName indexName = (IIndexName) name;
		try {
			IIndexFile file= indexName.getFile();
			IIndexFileSet indexFileSet = ast.getIndexFileSet();
			return indexFileSet != null && indexFileSet.contains(file);
		} catch (CoreException e) {
			return false;
		}
	}

	private static ICPPFunction[] selectByArgumentCount(LookupData data, ICPPFunction[] functions) throws DOMException {
		assert data.forDeclaration() == null;

		final int argumentCount = data.getFunctionArgumentCount();
		final int packExpansionCount= data.getFunctionArgumentPackExpansionCount();

		// Trim the list down to the set of viable functions
		ICPPFunction[] result= new ICPPFunction[functions.length];
		int idx= 0;
		for (ICPPFunction fn : functions) {
			if (fn != null && !(fn instanceof IProblemBinding)) {
				if (fn instanceof ICPPUnknownBinding) {
					return new ICPPFunction[] {fn};
				}

				// The index is optimized to provide the function type, try not to use the parameters
				// as long as possible.
				final ICPPFunctionType ft = fn.getType();
				final IType[] parameterTypes = ft.getParameterTypes();
				int numPars = parameterTypes.length;
				if (numPars == 1 && SemanticUtil.isVoidType(parameterTypes[0]))
					numPars= 0;

				int numArgs = argumentCount;
				if (fn instanceof ICPPMethod && data.argsContainImpliedObject)
					numArgs--;

				boolean ok;
				if (numArgs - packExpansionCount > numPars) {
					// More arguments than parameters --> need ellipsis or parameter pack
					ok= fn.takesVarArgs() || fn.hasParameterPack();
				} else {
					ok = numArgs >= fn.getRequiredArgumentCount() || packExpansionCount > 0;
				}
				if (ok) {
					if (fn instanceof IIndexBinding) {
						for (ICPPFunction other : result) {
							if (other == null || other instanceof IIndexBinding)
								break;
							if (other.getType().isSameType(ft)) {
								ok= false;
								break;
							}
						}
					}
					if (ok) {
						result[idx++]= fn;
					}
				}
			}
		}
		return result;
	}

	public static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC,
			boolean resolveTargetedArgumentTypes) throws DOMException {
		final IASTName lookupName = data.getLookupName();
		if (fns == null || fns.length == 0 || fns[0] == null)
			return null;
		fns= ArrayUtil.trim(fns);

		sortAstBeforeIndex(fns);

		if (data.forUsingDeclaration)
			return new CPPUsingDeclaration(lookupName, fns);

		if (lookupName instanceof ICPPASTConversionName) {
			return resolveUserDefinedConversion(data, fns);
		}

		if (data.forDeclaration() != null) {
			return resolveFunctionDeclaration(data, fns);
		}

		// No arguments to resolve function
		final IASTNode lookupPoint = data.getLookupPoint();
		if (!data.hasFunctionArguments()) {
			return createFunctionSet(fns, data.getTemplateArguments(), lookupName);
		}

		// Reduce our set of candidate functions to only those who have the right number of parameters.
		final IType[] argTypes = data.getFunctionArgumentTypes();
		ICPPFunction[] tmp= selectByArgumentCount(data, fns);
		if (tmp.length == 0 || tmp[0] == null)
			return new ProblemBinding(lookupName, lookupPoint, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, fns);
		tmp= CPPTemplates.instantiateForFunctionCall(tmp, data.getTemplateArguments(),
				Arrays.asList(argTypes),
				Arrays.asList(data.getFunctionArgumentValueCategories()),
				data.argsContainImpliedObject);
		if (tmp.length == 0 || tmp[0] == null)
			return new ProblemBinding(lookupName, lookupPoint, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, fns);

		int viableCount= 0;
		for (IFunction f : tmp) {
			if (f instanceof ICPPUnknownBinding) {
				setTargetedFunctionsToUnknown(argTypes);
				return f;
			}
			if (f == null)
				break;
			++viableCount;
		}
		if (viableCount == 0)
			return new ProblemBinding(lookupName, lookupPoint, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, fns);

		// Check for dependent arguments
		fns= tmp;
		if (CPPTemplates.containsDependentType(argTypes)) {
			setTargetedFunctionsToUnknown(argTypes);
			return CPPDeferredFunction.createForCandidates(fns);
		}

		IFunction[] ambiguousFunctions= null;   // Ambiguity, two or more functions are equally good.
		FunctionCost bestFnCost = null;			// The cost of the best function.

		// Loop over all functions
		List<FunctionCost> potentialCosts= null;
		ICPPFunction unknownFunction= null;
		final CPPASTTranslationUnit tu = data.getTranslationUnit();
		for (ICPPFunction fn : fns) {
			if (fn == null)
				continue;

			UDCMode udc = allowUDC ? UDCMode.DEFER : UDCMode.FORBIDDEN;
			FunctionCost fnCost= costForFunctionCall(fn, udc, data, resolveTargetedArgumentTypes);
			if (fnCost == null)
				continue;

			if (fnCost == CONTAINS_DEPENDENT_TYPES) {
				if (viableCount == 1)
					return fn;
				unknownFunction = fn;
				continue;
			}

			if (fnCost.hasDeferredUDC()) {
				if (potentialCosts == null) {
					potentialCosts= new ArrayList<>();
				}
				potentialCosts.add(fnCost);
				continue;
			}
			int cmp= fnCost.compareTo(tu, bestFnCost);
			if (cmp < 0) {
				bestFnCost= fnCost;
				ambiguousFunctions= null;
			} else if (cmp == 0) {
				ambiguousFunctions= ArrayUtil.append(IFunction.class, ambiguousFunctions, fn);
			}
		}

		if (potentialCosts != null) {
			for (FunctionCost fnCost : potentialCosts) {
				if (!fnCost.mustBeWorse(bestFnCost) && fnCost.performUDC()) {
					int cmp= fnCost.compareTo(tu, bestFnCost);
					if (cmp < 0) {
						bestFnCost= fnCost;
						ambiguousFunctions= null;
					} else if (cmp == 0) {
						ambiguousFunctions= ArrayUtil.append(IFunction.class, ambiguousFunctions, fnCost.getFunction());
					}
				}
			}
		}

		if (bestFnCost == null) {
			if (unknownFunction == null)
				return null;

			setTargetedFunctionsToUnknown(argTypes);
			return CPPDeferredFunction.createForCandidates(fns);
		}

		if (ambiguousFunctions != null) {
			ambiguousFunctions= ArrayUtil.append(IFunction.class, ambiguousFunctions, bestFnCost.getFunction());
			return new ProblemBinding(lookupName, lookupPoint,
					IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, ambiguousFunctions);
		}
		if (bestFnCost.hasAmbiguousUserDefinedConversion()) {
			return new ProblemBinding(lookupName, lookupPoint,
					IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.getFoundBindings());
		}

		for (int i = 0; i < argTypes.length; i++) {
			IType iType = argTypes[i];
			if (iType instanceof FunctionSetType) {
				((FunctionSetType) iType).applySelectedFunction(bestFnCost.getCost(i).getSelectedFunction());
			}
		}
		IFunction result= bestFnCost.getFunction();
		if (bestFnCost.isDirectInitWithCopyCtor()) {
			Cost c0= bestFnCost.getCost(0);
			IFunction firstConversion= c0.getUserDefinedConversion();
			if (firstConversion instanceof ICPPConstructor)
				return firstConversion;
		}
		return result;
	}

	/**
	 * If {@code type} is a {@link FunctionSetType} or a pointer type containing a FunctionSetType,
	 * resolves the FunctionSetType using the given target type.
	 *
	 * @param type the type to resolve
	 * @param targetType the target type
	 * @param point the name lookup context
	 * @return the resolved type, or the given {@type} if the type didn't contain a FunctionSetType
	 *     or the targeted function resolution failed
	 */
	private static IType resolveTargetedFunctionSetType(IType type, IType targetType) {
		IType t = type;
		if (type instanceof IPointerType) {
			t = ((IPointerType) type).getType();
		}

		if (t instanceof FunctionSetType) {
			ICPPFunction function =
					resolveTargetedFunction(targetType, ((FunctionSetType) t).getFunctionSet());
			if (function != null && !(function instanceof IProblemBinding)) {
				type = function.getType();
				if (targetType instanceof ITypeContainer) {
					ITypeContainer containerType = (ITypeContainer) targetType.clone();
					containerType.setType(type);
					type = containerType;
				}
			}
		}
		return type;
	}

	private static IBinding createFunctionSet(ICPPFunction[] fns, ICPPTemplateArgument[] args, IASTName name) {
		// First try to find a unique function
		if (name != null && name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
			name= (IASTName) name.getParent();
		}
		ICPPFunction f= getUniqueFunctionForSet(fns, args);
		return f == null ? new CPPFunctionSet(fns, args, name) : f;
	}

	private static ICPPFunction getUniqueFunctionForSet(ICPPFunction[] fns, ICPPTemplateArgument[] args) {
		// First try to find a unique function
		ICPPFunction result= null;
		boolean haveASTResult= false;
		for (ICPPFunction f : fns) {
			// Use the ast binding
			final boolean fromIndex = isFromIndex(f);
			if (haveASTResult && fromIndex)
				break;

			boolean isCandidate;
			if (f instanceof ICPPFunctionTemplate) {
				if (args == null) {
					isCandidate= true;
				} else {
					// See 14.3-7
					ICPPFunctionTemplate funcTemp = (ICPPFunctionTemplate) f;
					final ICPPTemplateParameter[] tpars = funcTemp.getTemplateParameters();
					final CPPTemplateParameterMap map = new CPPTemplateParameterMap(tpars.length);
					if (!TemplateArgumentDeduction.addExplicitArguments(funcTemp, tpars, args, map)) {
						isCandidate= false;
					} else {
						f = CPPTemplates.instantiateForAddressOfFunction(funcTemp, null, args);
						isCandidate= f != null;
					}
				}
			} else {
				isCandidate= args == null;
			}
			if (isCandidate) {
				if (result != null)
					return null;
				result= f;
				haveASTResult= !fromIndex;
			}
		}

		if (result instanceof ICPPFunctionTemplate)
			return CPPTemplates.instantiateForAddressOfFunction((ICPPFunctionTemplate) result, null, args);

		return result;
	}

	private static void setTargetedFunctionsToUnknown(IType[] argTypes) {
		for (IType argType : argTypes) {
			if (argType instanceof FunctionSetType) {
				((FunctionSetType) argType).setToUnknown();
			}
		}
	}

	/**
	 * Called for declarations with qualified name or template-id. Also for explicit function
	 * specializations or instantiations.
	 */
	private static IBinding resolveFunctionDeclaration(LookupData data, ICPPFunction[] fns) throws DOMException {
		final IASTDeclarator dtor= ASTQueries.findTypeRelevantDeclarator(data.getDeclarator());
		final IType t = CPPVisitor.createType(dtor);
		if (!(t instanceof ICPPFunctionType))
			return null;

		final ICPPFunctionType ft= (ICPPFunctionType) t;

		IASTName templateID= data.getLookupName();
		if (templateID.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME) {
			templateID= (ICPPASTTemplateId) templateID.getParent();
		}

		// 14.5.4 Friends with template ids require instantiation
		boolean isFriend= CPPVisitor.isFriendDeclaration(data.forDeclaration());
		if (!data.forExplicitFunctionSpecialization()
				&& !(isFriend && templateID instanceof ICPPASTTemplateId)) {
			// Search for a matching function
			for (ICPPFunction fn : fns) {
				if (fn != null && !(fn instanceof IProblemBinding) && !(fn instanceof ICPPUnknownBinding)) {
					if (isSameFunction(fn, dtor)) {
						return fn;
					}
				}
			}
			// 14.5.4 Friends with qualified ids allow for instantiation
			if (!data.forExplicitFunctionInstantiation()
					&& !(isFriend && templateID.getParent() instanceof ICPPASTQualifiedName)) {
				return null;
			}
		}

		// Try to instantiate a template
		IASTTranslationUnit tu= data.getTranslationUnit();
		ICPPTemplateArgument[] tmplArgs= ICPPTemplateArgument.EMPTY_ARGUMENTS;
		if (templateID instanceof ICPPASTTemplateId) {
			tmplArgs = CPPTemplates.createTemplateArgumentArray((ICPPASTTemplateId) templateID);
		}

		ICPPFunctionTemplate bestTemplate= null;
		ICPPFunction bestInst= null;
		boolean isAmbiguous= false;
		for (ICPPFunction fn : fns) {
			if (fn instanceof ICPPFunctionTemplate
					&& !(fn instanceof IProblemBinding) && !(fn instanceof ICPPUnknownBinding)) {
				// If the declared function type is dependent, there is no point trying to use it
				// to instantiate the template, so return a deferred function instead.
				// Note that CPPTemplates.instantiateForFunctionCall() behaves similarly.
				if (CPPTemplates.isDependentType(ft)) {
					return CPPDeferredFunction.createForCandidates(fns);
				}
				ICPPFunctionTemplate template= (ICPPFunctionTemplate) fn;
				ICPPFunction inst= CPPTemplates.instantiateForFunctionDeclaration(template, tmplArgs, ft);
				if (inst != null) {
					int cmp= CPPTemplates.orderFunctionTemplates(bestTemplate, template, TypeSelection.PARAMETERS_AND_RETURN_TYPE);
					if (cmp == 0)
						cmp= compareByRelevance(tu, bestTemplate, template);

					if (cmp == 0)
						isAmbiguous= true;

					if (cmp < 0) {
						isAmbiguous= false;
						bestTemplate= template;
						bestInst= inst;
					}
				}
			}
		}
		if (isAmbiguous)
			return new ProblemBinding(data.getLookupName(), data.getLookupPoint(),
					IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, fns);

		return bestInst;
	}

	public static void sortAstBeforeIndex(IFunction[] fns) {
		int iast= 0;
		for (int i = 0; i < fns.length; i++) {
			IFunction fn= fns[i];
			if (!(fn instanceof IIndexBinding)) {
				if (iast != i) {
					fns[i]= fns[iast];
					fns[iast]= fn;
				}
				iast++;
			}
		}
	}

	private static FunctionCost costForFunctionCall(ICPPFunction fn, UDCMode udc, LookupData data,
			boolean resolveTargetedArgumentTypes) throws DOMException {
		final ICPPFunctionType ftype= fn.getType();
		if (ftype == null)
			return null;

		IType[] argTypes= data.getFunctionArgumentTypes();
		ValueCategory[] argValueCategories= data.getFunctionArgumentValueCategories();
		if (resolveTargetedArgumentTypes) {
			IType[] newArgTypes = null;
			IType[] paramTypes = fn.getType().getParameterTypes();
			for (int i = 0; i < argTypes.length && i < paramTypes.length; i++) {
				IType argType = argTypes[i];
				IType paramType = paramTypes[i];
				IType newArgType = resolveTargetedFunctionSetType(argType, paramType);
				if (newArgType != argType) {
					if (newArgTypes == null) {
						newArgTypes = new IType[argTypes.length];
						System.arraycopy(argTypes, 0, newArgTypes, 0, argTypes.length);
					}
					newArgTypes[i] = newArgType;
				}
			}
			if (newArgTypes != null) {
				argTypes = newArgTypes;
			}
		}

		int skipArg= 0;
		IType implicitParameterType= null;
		IType impliedObjectType= null;
		ValueCategory impliedObjectValueCategory= null;
		final IType[] paramTypes= ftype.getParameterTypes();
		if (fn instanceof ICPPMethod && !(fn instanceof ICPPConstructor)) {
			implicitParameterType = getImplicitParameterType((ICPPMethod) fn);
			if (data.argsContainImpliedObject) {
				impliedObjectType= argTypes[0];
				impliedObjectValueCategory= argValueCategories[0];
				skipArg= 1;
			}
		}

		int k= 0;
		Cost cost;
		final int sourceLen= argTypes.length - skipArg;
		final FunctionCost result;
		if (implicitParameterType == null) {
			result= new FunctionCost(fn, sourceLen);
		} else {
			result= new FunctionCost(fn, sourceLen + 1);

			if (impliedObjectType == null) {
				impliedObjectType= data.getImpliedObjectType();
			}
			if (impliedObjectValueCategory == null) {
				impliedObjectValueCategory= data.getImpliedObjectValueCategory();
				if (impliedObjectValueCategory == null)
					impliedObjectValueCategory= ValueCategory.LVALUE;
			}

			if (fn instanceof ICPPMethod &&
					(((ICPPMethod) fn).isDestructor() || ASTInternal.isStatic(fn, false))) {
				// 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost
				cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
				cost.setImpliedObject();
			} else if (impliedObjectType == null) {
				return null;
			} else if (impliedObjectType.isSameType(implicitParameterType)) {
				cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
				cost.setImpliedObject();
			} else {
				Context context = ftype.hasRefQualifier() ?
						Context.IMPLICIT_OBJECT_FOR_METHOD_WITH_REF_QUALIFIER :
						Context.IMPLICIT_OBJECT_FOR_METHOD_WITHOUT_REF_QUALIFIER;
				cost = Conversions.checkImplicitConversionSequence(implicitParameterType, impliedObjectType,
						impliedObjectValueCategory, UDCMode.FORBIDDEN, context);
				if (cost.converts()) {
					cost.setImpliedObject();
				} else {
					if (CPPTemplates.isDependentType(implicitParameterType) || CPPTemplates.isDependentType(impliedObjectType)) {
						IType s= getNestedType(impliedObjectType, TDEF|REF|CVTYPE);
						IType t= getNestedType(implicitParameterType, TDEF|REF|CVTYPE);
						if (SemanticUtil.calculateInheritanceDepth(s, t) >= 0)
							return null;

						return CONTAINS_DEPENDENT_TYPES;
					}
				}
			}
			if (!cost.converts())
				return null;

			result.setCost(k++, cost, impliedObjectValueCategory);
		}

		for (int j = 0; j < sourceLen; j++) {
			final IType argType= SemanticUtil.getNestedType(argTypes[j + skipArg], TDEF | REF);
			if (argType == null)
				return null;

			final ValueCategory argValueCategory = argValueCategories[j + skipArg];

			IType paramType;
			if (j < paramTypes.length) {
				paramType= getNestedType(paramTypes[j], TDEF);
			} else if (!fn.takesVarArgs()) {
				paramType= VOID_TYPE;
			} else {
				cost = new Cost(argType, null, Rank.ELLIPSIS_CONVERSION);
				result.setCost(k++, cost, argValueCategory);
				continue;
			}

			if (argType instanceof FunctionSetType) {
				cost= ((FunctionSetType) argType).costForTarget(paramType);
			} else if (argType.isSameType(paramType)) {
				cost = new Cost(argType, paramType, Rank.IDENTITY);
			} else {
				if (CPPTemplates.isDependentType(paramType))
					return CONTAINS_DEPENDENT_TYPES;

				Context ctx= Context.ORDINARY;
				if (j == 0 && sourceLen == 1 && fn instanceof ICPPConstructor) {
					if (paramType instanceof ICPPReferenceType) {
						if (((ICPPConstructor) fn).getClassOwner().isSameType(getNestedType(paramType, TDEF|REF|CVTYPE))) {
							ctx= Context.FIRST_PARAM_OF_DIRECT_COPY_CTOR;
							result.setIsDirectInitWithCopyCtor(true);
						}
					}
				}
				cost = Conversions.checkImplicitConversionSequence(paramType, argType, argValueCategory,
						udc, ctx);
				if (data.fNoNarrowing && cost.isNarrowingConversion()) {
					cost= Cost.NO_CONVERSION;
				}
			}
			if (!cost.converts())
				return null;

			result.setCost(k++, cost, argValueCategory);
		}
		return result;
	}

	static IType getImplicitParameterType(ICPPMethod m)	{
		IType implicitType;
		ICPPClassType owner= m.getClassOwner();
		if (owner instanceof ICPPClassTemplate) {
			owner= (ICPPClassType) ((ICPPClassTemplate) owner).asDeferredInstance();
		}
		ICPPFunctionType ft= m.getType();
		implicitType= SemanticUtil.addQualifiers(owner, ft.isConst(), ft.isVolatile(), false);
		return new CPPReferenceType(implicitType, ft.isRValueReference());
	}

	private static IBinding resolveUserDefinedConversion(LookupData data, ICPPFunction[] fns) {
		ICPPASTConversionName astName= (ICPPASTConversionName) data.getLookupName();
		IType t= CPPVisitor.createType(astName.getTypeId());
		if (t instanceof ISemanticProblem) {
			return new ProblemBinding(astName, data.getLookupPoint(),
					IProblemBinding.SEMANTIC_INVALID_TYPE, data.getFoundBindings());
		}
		if (data.forDeclaration() == null ||
				data.forExplicitFunctionSpecialization() || data.forExplicitFunctionInstantiation()) {
			fns= CPPTemplates.instantiateConversionTemplates(fns, t);
		}

		IFunction unknown= null;
		for (IFunction function : fns) {
			if (function != null) {
				IType t2= function.getType().getReturnType();
				if (t.isSameType(t2))
					return function;
				if (unknown == null && function instanceof ICPPUnknownBinding) {
					unknown= function;
				}
			}
		}
		if (unknown != null)
			return unknown;
		return new ProblemBinding(astName, data.getLookupPoint(),
				IProblemBinding.SEMANTIC_NAME_NOT_FOUND, data.getFoundBindings());
	}

	/**
	 * 13.4-1 A use of an overloaded function without arguments is resolved in certain contexts to
	 * a function.
	 */
	static IBinding resolveTargetedFunction(IASTName name, CPPFunctionSet functionSet) {
		pushLookupPoint(name);
		try {
			boolean addressOf= false;
			IASTNode node= name.getParent();
			while (node instanceof IASTName) {
				node= node.getParent();
			}
	
			if (!(node instanceof IASTIdExpression))
				return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD);
	
			ASTNodeProperty prop= node.getPropertyInParent();
			IASTNode parent = node.getParent();
			while (parent instanceof IASTUnaryExpression) {
				final int op= ((IASTUnaryExpression) parent).getOperator();
				if (op == IASTUnaryExpression.op_bracketedPrimary) {
				} else if (!addressOf && op == IASTUnaryExpression.op_amper) {
					addressOf= true;
				} else {
					break;
				}
				node= parent;
				prop= node.getPropertyInParent();
				parent= node.getParent();
			}
	
			IType targetType= null;
			if (prop == IASTDeclarator.INITIALIZER) {
				// Target is an object or reference being initialized
				IASTDeclarator dtor = (IASTDeclarator) parent;
				targetType= CPPVisitor.createType(dtor);
			} else if (prop == IASTEqualsInitializer.INITIALIZER) {
				final IASTNode grandpa = parent.getParent();
				if (grandpa instanceof IASTDeclarator) {
					IASTDeclarator dtor = ASTQueries.findInnermostDeclarator((IASTDeclarator) grandpa);
					IBinding var= dtor.getName().resolvePreBinding();
					if (var instanceof IVariable)
						targetType= ((IVariable) var).getType();
				}
			} else if (prop == ICPPASTConstructorInitializer.ARGUMENT) {
				ICPPASTConstructorInitializer init = (ICPPASTConstructorInitializer) parent;
				final IASTNode parentOfInit = init.getParent();
				if (parentOfInit instanceof IASTDeclarator) {
					IASTDeclarator dtor = (IASTDeclarator) parentOfInit;
					targetType= CPPVisitor.createType(dtor);
				} else if (parentOfInit instanceof ICPPASTConstructorChainInitializer) {
					ICPPASTConstructorChainInitializer memInit= (ICPPASTConstructorChainInitializer) parentOfInit;
					IBinding var= memInit.getMemberInitializerId().resolveBinding();
					if (var instanceof IVariable) {
						targetType= ((IVariable) var).getType();
					}
				}
				targetType= getNestedType(targetType, TDEF | REF | CVTYPE | PTR | MPTR);
				if (init.getArguments().length != 1 || !(targetType instanceof ICPPFunctionType)) {
					if (targetType instanceof ICPPClassType) {
						LookupData data= new LookupData(name);
						data.setFunctionArguments(false, init.getArguments());
						try {
							IBinding ctor = resolveFunction(data,
									((ICPPClassType) targetType).getConstructors(), true, false);
							if (ctor instanceof ICPPConstructor) {
								int i= 0;
								for (IASTNode arg : init.getArguments()) {
									if (arg == node) {
										IType[] params= ((ICPPConstructor) ctor).getType().getParameterTypes();
										if (params.length > i) {
											targetType= params[i];
										}
										break;
									}
									i++;
								}
							}
						} catch (DOMException e) {
						}
					}
				}
			} else if (prop == IASTBinaryExpression.OPERAND_TWO) {
				IASTBinaryExpression binaryExp = (IASTBinaryExpression) parent;
				if (binaryExp.getOperator() == IASTBinaryExpression.op_assign) {
					targetType= binaryExp.getOperand1().getExpressionType();
				}
			} else if (prop == IASTFunctionCallExpression.ARGUMENT) {
				// Target is a parameter of a function, need to resolve the function call
				IASTFunctionCallExpression fnCall = (IASTFunctionCallExpression) parent;
				IType t= SemanticUtil.getNestedType(fnCall.getFunctionNameExpression().getExpressionType(), TDEF | REF | CVTYPE);
				if (t instanceof IPointerType) {
					t= SemanticUtil.getNestedType(((IPointerType) t).getType(), TDEF | REF | CVTYPE);
				}
				if (t instanceof IFunctionType) {
					int i= 0;
					for (IASTNode arg : fnCall.getArguments()) {
						if (arg == node) {
							IType[] params= ((IFunctionType) t).getParameterTypes();
							if (params.length > i) {
								targetType= params[i];
							}
							break;
						}
						i++;
					}
				}
			} else if (prop == IASTCastExpression.OPERAND) {
				// target is an explicit type conversion
				IASTCastExpression cast = (IASTCastExpression) parent;
				targetType= CPPVisitor.createType(cast.getTypeId().getAbstractDeclarator());
			} else if (prop == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT) {
				// target is a template non-type parameter (14.3.2-5)
				ICPPASTTemplateId id = (ICPPASTTemplateId) parent;
				IASTNode[] args = id.getTemplateArguments();
				int i = 0;
				for (; i < args.length; i++) {
					if (args[i] == node) {
						break;
					}
				}
				IBinding template = id.getTemplateName().resolveBinding();
				if (template instanceof ICPPTemplateDefinition) {
					ICPPTemplateParameter[] ps = ((ICPPTemplateDefinition) template).getTemplateParameters();
					if (i < args.length && i < ps.length && ps[i] instanceof ICPPTemplateNonTypeParameter) {
						targetType= ((ICPPTemplateNonTypeParameter) ps[i]).getType();
					}
				}
			} else if (prop == IASTReturnStatement.RETURNVALUE) {
				// target is the return value of a function, operator or conversion
				while (parent != null && !(parent instanceof IASTFunctionDefinition)) {
					parent = parent.getParent();
				}
				if (parent instanceof IASTFunctionDefinition) {
					IASTDeclarator dtor = ((IASTFunctionDefinition) parent).getDeclarator();
					dtor= ASTQueries.findInnermostDeclarator(dtor);
					IBinding binding = dtor.getName().resolveBinding();
					if (binding instanceof IFunction) {
						IFunctionType ft = ((IFunction) binding).getType();
						targetType= ft.getReturnType();
					}
				}
			}
			if (targetType == null && parent instanceof ICPPASTExpression
					&& parent instanceof IASTImplicitNameOwner) {
				// Trigger resolution of overloaded operator, which may resolve the
				// function set.
				((IASTImplicitNameOwner) parent).getImplicitNames();
				final IBinding newBinding = name.getPreBinding();
				if (!(newBinding instanceof CPPFunctionSet))
					return newBinding;
	
				// If we're in a dependent context, we don't have enough information
				// to resolve the function set.
				if (((ICPPASTExpression) parent).getEvaluation().isTypeDependent()) {
					return CPPDeferredFunction.createForCandidates(functionSet.getBindings());
				}
			}
	
			ICPPFunction function = resolveTargetedFunction(targetType, functionSet);
			if (function == null)
				return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD);
	
			return function;
		} finally {
			popLookupPoint();
		}
	}

	private static boolean isViableUserDefinedLiteralOperator(IBinding binding, int kind) {
		if (binding == null || binding instanceof ProblemBinding) {
			return false;
		}
		if (binding instanceof ICPPFunction) {
			ICPPFunction func = (ICPPFunction) binding;
			if (func.getRequiredArgumentCount() == 1) {
				IType type = null;
				if (kind == IASTLiteralExpression.lk_integer_constant) {
					type = new CPPBasicType(Kind.eInt, IBasicType.IS_UNSIGNED | IBasicType.IS_LONG_LONG);
				} else if (kind == IASTLiteralExpression.lk_float_constant) {
					type = new CPPBasicType(Kind.eDouble, IBasicType.IS_LONG);
				}
				return SemanticUtil.getNestedType(func.getParameters()[0].getType(), CVTYPE).isSameType(type);
			}
		}
		return false;
	}

	/**
	 * Given a LiteralExpression with a user-defined literal suffix,
	 * finds the corresponding defined operator.
	 * Tries to implement 2.14.8.(2-10)
	 * @param exp <code>IASTLiteralExpression</code> which has a user-defined literal suffix
	 * @return CPPFunction or null
	 * @throws DOMException
	 */
	public static IBinding findUserDefinedLiteralOperator(IASTLiteralExpression exp) throws DOMException {
		pushLookupPoint(exp);
		IBinding ret = null;
		try {
			/*
			 * 2.14.8.2
			 * Let `IASTLiteralExpression exp` = L
			 * Let `exp.getSuffix()` = X
			 * Let `bindings` = S
			 * A user-defined-literal is treated as a call to a literal operator or
			 * literal operator template (13.5.8). To determine the form of this
			 * call for a given user-defined-literal L with ud-suffix X, the
			 * literal-operator-id whose literal suffix identifier is X is looked up
			 * in the context of L using the rules for unqualified name lookup (3.4.1).
			 * Let S be the set of declarations found by this lookup.
			 * S shall not be empty.
			 *
			 */
			int kind = exp.getKind();
			IScope lookupScope = CPPVisitor.getContainingScope(exp);
			IBinding[] bindings = findBindings(lookupScope, ((CPPASTLiteralExpression) exp).getOperatorName(), false);
			ICPPFunction[] funcs = new ICPPFunction[bindings.length];
			ICPPFunctionTemplate[] tplFunctions = new ICPPFunctionTemplate[bindings.length];
			LookupData data = new LookupData(((CPPASTLiteralExpression) exp).getOperatorName(), null, exp);
	
			int i = 0, j = 0;
			for (IBinding binding : bindings) {
				if (binding instanceof ICPPFunction || binding instanceof ICPPFunctionTemplate) {
					funcs[i++] = (ICPPFunction) binding;
					if (binding instanceof ICPPFunctionTemplate) {
						tplFunctions[j++] = (ICPPFunctionTemplate) binding;
					}
				}
			}
	
			funcs = ArrayUtil.trim(funcs, i);
			tplFunctions = ArrayUtil.trim(tplFunctions, j);
	
			if (funcs.length == 0) {
				// S shall not be empty
				return new ProblemBinding(data.getLookupName(), exp, IProblemBinding.SEMANTIC_NAME_NOT_FOUND);
			}
	
			if (kind == IASTLiteralExpression.lk_integer_constant || kind == IASTLiteralExpression.lk_float_constant) {
				if (kind == IASTLiteralExpression.lk_integer_constant) {
					/*
					 * 2.14.8.3
					 * Let `exp.getValue()` = n
					 * If L is a user-defined-integer-literal, let n be the literal
					 * without its ud-suffix. If S contains a literal operator with
					 * parameter type unsigned long long, then use operator "" X(n ULL)
					 */
					CPPBasicType t = new CPPBasicType(Kind.eInt, IBasicType.IS_UNSIGNED | IBasicType.IS_LONG_LONG, exp);
					data.setFunctionArguments(false, createArgForType(exp, t));
					ret = resolveFunction(data, funcs, true, false);
					if (isViableUserDefinedLiteralOperator(ret, kind)) {
						return ret;
					}
				} else if (kind == IASTLiteralExpression.lk_float_constant) {
					/*
					 * 2.14.8.4
					 * Let `exp.getValue()` = f
					 * If L is a user-defined-floating-literal, let f be the literal
					 * without its ud-suffix. If S contains a literal operator with
					 * parameter type long double, then use operator "" X(f L)
					 */
					CPPBasicType t = new CPPBasicType(Kind.eDouble, IBasicType.IS_LONG, exp);
					data.setFunctionArguments(false, createArgForType(exp, t));
					ret = resolveFunction(data, funcs, true, false);
					if (isViableUserDefinedLiteralOperator(ret, kind)) {
						return ret;
					}
				}
	
				/*
				 * 2.14.8.3 (cont.), 2.14.8.4 (cont.)
				 * Otherwise, S shall contain a raw literal operator or a literal
				 * operator template but not both.
				 */
				// Raw literal operator `operator "" _op(const char * c)`
				CPPPointerType charArray = new CPPPointerType(CPPBasicType.CHAR, true, false, false);
				data = new LookupData(((CPPASTLiteralExpression) exp).getOperatorName(), null, exp);
				data.setFunctionArguments(false, createArgForType(exp, charArray));
				ret = resolveFunction(data, funcs, true, false);
	
				//
				char[] stringLiteral = exp.getValue(); // The string literal that was passed to the operator
	
				// The string literal is passed to the operator as chars:
				// "literal"_op -> operator "" _op<'l', 'i', 't', 'e', 'r', 'a', 'l'>();
				ICPPTemplateArgument args[] = new ICPPTemplateArgument[stringLiteral.length];
				for (int k = 0; k < stringLiteral.length; k++) {
					args[k] = new CPPTemplateNonTypeArgument(new EvalFixed(CPPBasicType.CHAR, PRVALUE, IntegralValue.create(stringLiteral[k])));
				}
	
				data = new LookupData(((CPPASTLiteralExpression) exp).getOperatorName(), args, exp);
				IBinding litTpl = resolveFunction(data, tplFunctions, true, false);
	
				// Do we have valid template and non-template bindings?
				if (ret != null && !(ret instanceof IProblemBinding)) {
					// Do we have valid template and non-template bindings?
					if (litTpl instanceof ICPPFunctionInstance) {
						// Ambiguity? It has two valid options, and the spec says it shouldn't
						return new ProblemBinding(data.getLookupName(), exp, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, tplFunctions);
					}
				} else {
					if (litTpl instanceof ICPPFunctionInstance) {
						// Only the template binding is valid
						ret = litTpl;
					} else {
						// Couldn't find a valid operator
						return ret;
					}
				}
			} else if (kind == IASTLiteralExpression.lk_string_literal) {
				/*
				 * 2.14.8.5
				 * If L is a user-defined-string-literal, let str be the literal
				 * without its ud-suffix and let len be the number of code units in
				 * str (i.e., its length excluding the terminating null character).
				 * L is treated as operator "" X(str, len)
				 */
				CPPPointerType strType = new CPPPointerType(new CPPBasicType(((CPPASTLiteralExpression) exp).getBasicCharKind(), 0, null), true, false, false);
				IASTInitializerClause[] initializer = new IASTInitializerClause[] {
					createArgForType(exp, strType),
					createArgForType(null, CPPBasicType.UNSIGNED_INT)
				};
				data.setFunctionArguments(false, initializer);
				ret = resolveFunction(data, funcs, true, false);
			} else if (kind == IASTLiteralExpression.lk_char_constant) {
				/*
				 * 2.14.8.6
				 * If L is a user-defined-character-literal, let ch be the literal
				 * without its ud-suffix. S shall contain a literal operator whose
				 * only parameter has the type ch and the literal L is treated as a
				 * call operator "" X(ch)
				 */
				CPPBasicType t = new CPPBasicType(((CPPASTLiteralExpression) exp).getBasicCharKind(), 0, exp);
				data.setFunctionArguments(false, createArgForType(exp, t));
				ret = resolveFunction(data, funcs, true, false);
			}
		} finally {
			popLookupPoint();
		}

		return ret;
	}

	/**
	 * 13.4-1 A use of an overloaded function without arguments is resolved in certain contexts to
	 * a function.
	 */
	static ICPPFunction resolveTargetedFunction(IType targetType, CPPFunctionSet set) {
		targetType= getNestedType(targetType, TDEF | REF | CVTYPE | PTR | MPTR);
		if (!(targetType instanceof ICPPFunctionType))
			return null;

		// First pass, consider functions
		ICPPFunction[] fns= set.getBindings();
		for (ICPPFunction fn : fns) {
			if (!(fn instanceof ICPPFunctionTemplate)) {
				if (targetType.isSameType(fn.getType()))
					return fn;
			}
		}

		// Second pass, consider templates
		ICPPFunction result= null;
		ICPPFunctionTemplate resultTemplate= null;
		boolean isAmbiguous= false;
		final IASTTranslationUnit tu= CPPSemantics.getCurrentLookupPoint().getTranslationUnit();
		for (IFunction fn : fns) {
			try {
				if (fn instanceof ICPPFunctionTemplate) {
					final ICPPFunctionTemplate template = (ICPPFunctionTemplate) fn;
					ICPPFunction inst= CPPTemplates.instantiateForAddressOfFunction(template,
							(ICPPFunctionType) targetType, set.getTemplateArguments());
					if (inst != null) {
						int cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template,
								TypeSelection.PARAMETERS_AND_RETURN_TYPE);
						if (cmp == 0)
							cmp= compareByRelevance(tu, resultTemplate, template);

						if (cmp == 0)
							isAmbiguous= true;

						if (cmp < 0) {
							isAmbiguous= false;
							resultTemplate= template;
							result= inst;
						}
					}
				}
			} catch (DOMException e) {
			}
		}
		if (isAmbiguous)
			return null;

		return result;
	}

	public static ICPPFunction findOverloadedBinaryOperator(IScope pointOfDefinition,
			OverloadableOperator op, ICPPEvaluation arg1, ICPPEvaluation arg2) {
		if (op == null || arg1 == null || arg2 == null)
			return null;

		IType op1type = getNestedType(arg1.getType(), TDEF | REF | CVTYPE);
		if (!isUserDefined(op1type) && !isUserDefined(
				getNestedType(arg2.getType(), TDEF | REF | CVTYPE)))
			return null;

		final LookupMode lookupNonMember;
		if (op == OverloadableOperator.ASSIGN || op == OverloadableOperator.BRACKET) {
			lookupNonMember = LookupMode.NO_GLOBALS;
		} else {
			lookupNonMember= LookupMode.LIMITED_GLOBALS;
		}
		return findOverloadedOperator(pointOfDefinition, new ICPPEvaluation[] {arg1, arg2}, op1type, op, 
				lookupNonMember);
	}

	public static ICPPFunction findOverloadedOperator(ICPPASTNewExpression expr) {
		pushLookupPoint(expr);
		try {
			OverloadableOperator op = OverloadableOperator.fromNewExpression(expr);
			final ICPPEvaluation evaluation = expr.getEvaluation();
			if (evaluation.isTypeDependent())
				return null;
	
			final IASTInitializerClause[] placement = expr.getPlacementArguments();
			final ICPPEvaluation arg1= new EvalUnary(IASTUnaryExpression.op_star, evaluation, null, expr);
			final ICPPEvaluation arg2= new EvalUnary(IASTUnaryExpression.op_sizeof, evaluation, null, expr);
	
			ICPPEvaluation[] args;
			if (placement == null) {
				args= new ICPPEvaluation[] { arg1, arg2 };
			} else {
				args= new ICPPEvaluation[2 + placement.length];
				args[0]= arg1;
				args[1]= arg2;
				int i= 2;
				for (IASTInitializerClause p : placement) {
					final ICPPEvaluation a = ((ICPPASTInitializerClause) p).getEvaluation();
					if (a.isTypeDependent())
						return null;
					args[i++]= a;
				}
			}
			IType type= getNestedType(arg1.getType(), TDEF | REF | CVTYPE);
			return findOverloadedOperator(null, args, type, op, LookupMode.GLOBALS_IF_NO_MEMBERS);
		} finally {
			popLookupPoint();
		}
	}

	public static ICPPFunction findOverloadedOperator(ICPPASTDeleteExpression expr) {
		pushLookupPoint(expr);
		try {
			OverloadableOperator op = OverloadableOperator.fromDeleteExpression(expr);
			IType type = getTypeOfPointer(expr.getOperand().getExpressionType());
			if (type == null)
				return null;
		
			ICPPEvaluation[] args = {
					new EvalFixed(type, LVALUE, IntegralValue.UNKNOWN),
					((ICPPASTExpression) expr.getOperand()).getEvaluation()
				};
			return findOverloadedOperator(null, args, type, op, LookupMode.GLOBALS_IF_NO_MEMBERS);
		} finally {
			popLookupPoint();
		}
	}

	private static IType getTypeOfPointer(IType type) {
		type = SemanticUtil.getNestedType(type, SemanticUtil.TDEF | SemanticUtil.REF | SemanticUtil.CVTYPE);
		if (type instanceof IPointerType) {
			return getNestedType(((IPointerType) type).getType(), TDEF | REF | CVTYPE);
		}
		return null;
	}

	/**
	 * Returns constructor called by a declarator, or {@code null} if no constructor is called.
	 */
	public static IBinding findImplicitlyCalledConstructor(final ICPPASTDeclarator declarator) {
		pushLookupPoint(declarator);
		try {
			if (declarator.getNestedDeclarator() != null)
				return null;
			IASTDeclarator dtor= ASTQueries.findOutermostDeclarator(declarator);
			IASTNode parent = dtor.getParent();
			if (parent instanceof IASTSimpleDeclaration) {
				final IASTInitializer initializer = dtor.getInitializer();
				if (initializer == null) {
					IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration) parent).getDeclSpecifier();
					parent = parent.getParent();
					if (parent instanceof IASTCompositeTypeSpecifier ||
							declSpec.getStorageClass() == IASTDeclSpecifier.sc_extern) {
						// No initialization is performed for class members and extern declarations
						// without an initializer.
						return null;
					}
				}
				return findImplicitlyCalledConstructor(declarator.getName(), initializer);
			}
		} finally {
			popLookupPoint();
		}
		return null;
	}

	/**
	 * Returns constructor called by a class member initializer in a constructor initializer chain.
	 * Returns {@code null} if no constructor is called. Returns a {@link IProblemBinding} if the called
	 * constructor cannot be uniquely resolved.
	 */
	public static IBinding findImplicitlyCalledConstructor(ICPPASTConstructorChainInitializer initializer) {
		return findImplicitlyCalledConstructor(initializer.getMemberInitializerId(), initializer.getInitializer());
	}

	/**
	 * Returns constructor called by a variable declarator or an initializer in a constructor
	 * initializer chain. Returns {@code null} if no constructor is called.
	 */
	private static IBinding findImplicitlyCalledConstructor(IASTName name, IASTInitializer initializer) {
		IBinding binding = name.resolveBinding();
		if (!(binding instanceof ICPPVariable))
			return null;

		IType type = ((ICPPVariable) binding).getType();
		type = SemanticUtil.getNestedType(type, TDEF | CVTYPE);
		if (!(type instanceof ICPPClassType))
			return null;
		if (type instanceof ICPPClassTemplate || type instanceof ICPPUnknownType || type instanceof ISemanticProblem)
			return null;
		
		// The class type may be declared in a header but defined in the AST.
		// In such a case, we want the constructors as AST bindings (since as
		// index bindings they would fail declaredBefore() filtering), so map 
		// the class type to its AST representation.
		type = SemanticUtil.mapToAST(type);

		return findImplicitlyCalledConstructor((ICPPClassType) type, initializer, name);
	}

	/**
	 * Returns the constructor implicitly called by the given expression, or {@code null} if there is no
	 * constructor call, or a {@link IProblemBinding} if the called constructor cannot be uniquely resolved.
	 */
	public static IBinding findImplicitlyCalledConstructor(ICPPASTNewExpression expr) {
		IType type = getNestedType(expr.getExpressionType(), TDEF | REF | CVTYPE);
		if (!(type instanceof IPointerType))
			return null;
		type = ((IPointerType) type).getType();
		if (type instanceof ICPPClassType) {
			return findImplicitlyCalledConstructor((ICPPClassType) type,
					expr.getInitializer(), expr.getTypeId());
		}
		return null;
	}

	private static IBinding findImplicitlyCalledConstructor(ICPPClassType type, IASTInitializer initializer,
			IASTNode typeId) {
		pushLookupPoint(typeId);
		try {
			if (initializer instanceof IASTEqualsInitializer) {
				// Copy initialization.
				IASTEqualsInitializer eqInit= (IASTEqualsInitializer) initializer;
				ICPPASTInitializerClause evalOwner = (ICPPASTInitializerClause) eqInit.getInitializerClause();
				final ICPPEvaluation evaluation = evalOwner.getEvaluation();
				IType sourceType= evaluation.getType();
				ValueCategory isLValue= evaluation.getValueCategory();
				if (sourceType != null) {
					Cost c;
					if (calculateInheritanceDepth(sourceType, type) >= 0) {
						c = Conversions.copyInitializationOfClass(isLValue, sourceType, type, false);
					} else {
						c = Conversions.checkImplicitConversionSequence(type, sourceType, isLValue,
								UDCMode.ALLOWED, Context.ORDINARY);
					}
					if (c.converts()) {
						ICPPFunction f = c.getUserDefinedConversion();
						if (f instanceof ICPPConstructor)
							return f;
						// If a conversion is used, the constructor is elided.
					}
				}
			} else if (initializer instanceof ICPPASTInitializerList) {
				// List initialization.
				ICPPEvaluation eval= ((ICPPASTInitializerClause) initializer).getEvaluation();
				if (eval instanceof EvalInitList) {
					Cost c= Conversions.listInitializationSequence((EvalInitList) eval, type, UDCMode.ALLOWED, true);
					if (c.converts()) {
						ICPPFunction f = c.getUserDefinedConversion();
						if (f instanceof ICPPConstructor)
							return f;
					}
				}
			} else if (initializer instanceof ICPPASTConstructorInitializer) {
				// Direct initialization.
				return findImplicitlyCalledConstructor(type,
						(ICPPASTConstructorInitializer) initializer, typeId);
			} else if (initializer == null) {
				// Default initialization.
				ICPPConstructor[] ctors = type.getConstructors();
				for (ICPPConstructor ctor : ctors) {
					if (ctor.getRequiredArgumentCount() == 0)
						return ctor;
				}
				return null;
			}
		} catch (DOMException e) {
		} finally {
			popLookupPoint();
		}
		return null;
	}

	private static IBinding findImplicitlyCalledConstructor(ICPPClassType classType,
			ICPPASTConstructorInitializer initializer, IASTNode typeId) {
		final IASTInitializerClause[] arguments = initializer.getArguments();
		CPPASTName astName = new CPPASTName();
		astName.setName(classType.getNameCharArray());
		astName.setOffsetAndLength((ASTNode) typeId);
		CPPASTIdExpression idExp = new CPPASTIdExpression(astName);
		idExp.setParent(typeId.getParent());
		idExp.setPropertyInParent(IASTFunctionCallExpression.FUNCTION_NAME);

		LookupData data = new LookupData(astName);
		data.setFunctionArguments(false, arguments);
		data.qualified = true;
		data.foundItems = classType.getConstructors();
		try {
			return resolveAmbiguities(data);
		} catch (DOMException e) {
			return null;
		}
	}

	public static ICPPFunction findImplicitlyCalledDestructor(ICPPASTDeleteExpression expr) {
		IType t = getTypeOfPointer(expr.getOperand().getExpressionType());
		if (!(t instanceof ICPPClassType))
			return null;

		ICPPClassType cls = (ICPPClassType) t;
		IScope scope = cls.getCompositeScope();
		if (scope == null)
			return null;

		final char[] name = CharArrayUtils.concat("~".toCharArray(), cls.getNameCharArray()); //$NON-NLS-1$
		LookupData data = new LookupData(name, null, expr);
		data.qualified = true;
		data.setFunctionArguments(true, new EvalFixed(cls, LVALUE, IntegralValue.UNKNOWN));
		try {
			lookup(data, scope);
			IBinding[] found= data.getFoundBindings();
			if (found.length > 0 && found[0] instanceof ICPPFunction) {
				return (ICPPFunction) found[0];
			}
		} catch (DOMException e) {
		}
		return null;
	}

	public static ICPPASTExpression createArgForType(IASTNode node, final IType type) {
		CPPASTName x= new CPPASTName();
		x.setBinding(new CPPVariable(x) {
			@Override public IType getType() {
				return type;
			}
		});
		final CPPASTIdExpression idExpression = new CPPASTIdExpression(x);
		idExpression.setParent(node);
		return idExpression;
	}

	/**
	 * For simplicity returns an operator of form RT (T, T) rather than RT (boolean, T, T)
	 */
	public static ICPPFunction findOverloadedConditionalOperator(IScope pointOfDefinition,
			ICPPEvaluation positive, ICPPEvaluation negative) {
		final ICPPEvaluation[] args = new ICPPEvaluation[] {positive, negative};
		return findOverloadedOperator(pointOfDefinition, args, null,
				OverloadableOperator.CONDITIONAL_OPERATOR, LookupMode.NO_GLOBALS);
	}

	/**
	 * Returns the operator,() function that would apply to the two given arguments.
	 * The lookup type of the class where the operator,() might be found must also be provided.
	 */
	public static ICPPFunction findOverloadedOperatorComma(IScope pointOfDefinition,
			ICPPEvaluation arg1, ICPPEvaluation arg2) {
		IType op1type = getNestedType(arg1.getType(), TDEF | REF | CVTYPE);
		IType op2type = getNestedType(arg2.getType(), TDEF | REF | CVTYPE);
		if (!isUserDefined(op1type) && !isUserDefined(op2type))
			return null;

		ICPPEvaluation[] args = { arg1 , arg2 };
		return findOverloadedOperator(pointOfDefinition, args, op1type,
				OverloadableOperator.COMMA, LookupMode.LIMITED_GLOBALS);
	}


	static enum LookupMode {NO_GLOBALS, GLOBALS_IF_NO_MEMBERS, LIMITED_GLOBALS, ALL_GLOBALS}
	
	static LookupData findOverloadedMemberOperator(IType methodLookupType, OverloadableOperator operator, 
			ICPPEvaluation[] args, IASTNode pointOfInstantiation) {
		LookupData methodData = null;
		if (methodLookupType instanceof ISemanticProblem)
			return null;
		if (methodLookupType instanceof ICPPClassType) {
			ICPPClassType classType = (ICPPClassType) methodLookupType;
			methodData = new LookupData(operator.toCharArray(), null, pointOfInstantiation);
			methodData.setFunctionArguments(true, args);
			methodData.qualified = true; // (13.3.1.2.3)

			try {
				IScope scope = classType.getCompositeScope();
				if (scope == null)
					return null;
				lookup(methodData, scope);

			} catch (DOMException e) {
				return null;
			}
		}
		return methodData;
	}
	
	static LookupData findOverloadedNonmemberOperator(IType methodLookupType, OverloadableOperator operator, 
			ICPPEvaluation[] args, IASTNode pointOfInstantiation, IScope pointOfDefinition, 
			LookupData methodData, LookupMode mode, IType type2, ICPPClassType callToObjectOfClassType) {
		LookupData funcData = new LookupData(operator.toCharArray(), null, pointOfInstantiation);

		// Global new and delete operators do not take an argument for the this pointer.
		switch (operator) {
		case DELETE: case DELETE_ARRAY:
		case NEW: case NEW_ARRAY:
			args= ArrayUtil.removeFirst(args);
			break;
		default:
			break;
		}
		funcData.setFunctionArguments(true, args);
		funcData.ignoreMembers = true; // (13.3.1.2.3)
		boolean haveMembers= methodData != null && methodData.hasResults();
		if (mode == LookupMode.ALL_GLOBALS || mode == LookupMode.LIMITED_GLOBALS
				|| (mode == LookupMode.GLOBALS_IF_NO_MEMBERS && !haveMembers)) {
			try {
				IScope scope = CPPVisitor.getContainingScope(pointOfInstantiation);
				if (scope == null)
					return funcData;
				lookup(funcData, scope);
				try {
					doArgumentDependentLookup(funcData);
				} catch (DOMException e) {
				}

				// Also do a lookup at the point of definition.
				if (pointOfDefinition != null) {
					LookupData funcData2 = new LookupData(operator.toCharArray(), null, pointOfInstantiation);
					funcData2.setFunctionArguments(true, args);
					funcData2.ignoreMembers = true;
					lookup(funcData2, pointOfDefinition);
					if (funcData2.hasResults()) {
						mergeResults(funcData, funcData2.foundItems, false);
					}
				}

				// Filter with file-set
				IASTTranslationUnit tu= pointOfInstantiation.getTranslationUnit();
				if (tu != null && funcData.foundItems instanceof Object[]) {
					final IIndexFileSet fileSet = tu.getIndexFileSet();
					if (fileSet != null) {
						int j= 0;
						final Object[] items= (Object[]) funcData.foundItems;
						for (int i = 0; i < items.length; i++) {
							Object item = items[i];
							items[i]= null;
							if (item instanceof IIndexBinding) {
								if (!indexBindingIsReachable(fileSet, (IIndexBinding) item)) {
									continue;
								}
							}
							items[j++]= item;
						}
					}
				}
			} catch (DOMException e) {
				return funcData;
			}

			if (operator == OverloadableOperator.NEW || operator == OverloadableOperator.DELETE
					|| operator == OverloadableOperator.NEW_ARRAY || operator == OverloadableOperator.DELETE_ARRAY) {
				// Those operators replace the built-in operator
				Object[] items= (Object[]) funcData.foundItems;
				int j= 0;
				for (Object object : items) {
					if (object instanceof ICPPFunction) {
						ICPPFunction func= (ICPPFunction) object;
						if (!(func instanceof CPPImplicitFunction))
							items[j++]= func;
					}
				}
				if (j > 0) {
					while (j < items.length) {
						items[j++]= null;
					}
				}
			}
			// 13.3.1.2.3
			// However, if no operand type has class type, only those non-member functions ...
			if (mode == LookupMode.LIMITED_GLOBALS) {
				if (funcData.foundItems != null && !(methodLookupType instanceof ICPPClassType) && !(type2 instanceof ICPPClassType)) {
					IEnumeration enum1= null;
					IEnumeration enum2= null;
					if (methodLookupType instanceof IEnumeration) {
						enum1= (IEnumeration) methodLookupType;
					}
					if (type2 instanceof IEnumeration) {
						enum2= (IEnumeration) type2;
					}
					Object[] items= (Object[]) funcData.foundItems;
					int j= 0;
					for (Object object : items) {
						if (object instanceof ICPPFunction) {
							ICPPFunction func= (ICPPFunction) object;
							ICPPFunctionType ft = func.getType();
							IType[] pts= ft.getParameterTypes();
							if ((enum1 != null && pts.length > 0 && enum1.isSameType(getUltimateTypeUptoPointers(pts[0]))) ||
									(enum2 != null && pts.length > 1 && enum2.isSameType(getUltimateTypeUptoPointers(pts[1])))) {
								items[j++]= object;
							}
						}
					}
					while (j < items.length) {
						items[j++]= null;
					}
				}
			}
		}

		if (callToObjectOfClassType != null) {
			try {
				// 13.3.1.1.2 call to object of class type
				ICPPMethod[] ops = SemanticUtil.getConversionOperators(callToObjectOfClassType);
				for (ICPPMethod op : ops) {
					if (op.isExplicit())
						continue;
					IFunctionType ft= op.getType();
					if (ft != null) {
						IType rt= SemanticUtil.getNestedType(ft.getReturnType(), SemanticUtil.TDEF);
						if (rt instanceof IPointerType) {
							IType ptt= SemanticUtil.getNestedType(((IPointerType) rt).getType(), SemanticUtil.TDEF);
							if (ptt instanceof IFunctionType) {
								IFunctionType ft2= (IFunctionType) ptt;
								IBinding sf= createSurrogateCallFunction(pointOfInstantiation.getTranslationUnit().getScope(), ft2.getReturnType(), rt, ft2.getParameterTypes());
								mergeResults(funcData, sf, false);
							}
						}
					}
				}
			} catch (DOMException e) {
				return funcData;
			}
		}

		if (methodLookupType instanceof ICPPClassType || type2 instanceof ICPPClassType) {
			ICPPFunction[] builtins= BuiltinOperators.create(operator, args, (Object[]) funcData.foundItems);
			mergeResults(funcData, builtins, false);
		}
		
		return funcData;
	}
	
	static ICPPFunction findOverloadedOperator(IScope pointOfDefinition, ICPPEvaluation[] args, 
			IType methodLookupType, OverloadableOperator operator, LookupMode mode) {
		IASTNode pointOfInstantiation = CPPSemantics.getCurrentLookupPoint();
		while (pointOfInstantiation instanceof IASTName) {
			pointOfInstantiation= pointOfInstantiation.getParent();
		}

		ICPPClassType callToObjectOfClassType= null;
		IType type2= null;
		if (args.length >= 2) {
			type2 = args[1].getType();
			type2= getNestedType(type2, TDEF | REF | CVTYPE);
		}

		// Find a method
		LookupData methodData = findOverloadedMemberOperator(methodLookupType, operator, args, 
				pointOfInstantiation);
		if (methodData != null && operator == OverloadableOperator.PAREN) {
			callToObjectOfClassType = (ICPPClassType) methodLookupType;
		}

		// Find a function
		LookupData funcData = findOverloadedNonmemberOperator(methodLookupType, operator, args, 
				pointOfInstantiation, pointOfDefinition, methodData, mode, type2, callToObjectOfClassType);

		try {
			IBinding binding = null;
			if (methodData != null && funcData.hasResults()) {
				// if there was two lookups then merge the results
				mergeResults(funcData, methodData.foundItems, false);
				binding = resolveAmbiguities(funcData);
			} else if (funcData.hasResults()) {
				binding = resolveAmbiguities(funcData);
			} else if (methodData != null) {
				binding = resolveAmbiguities(methodData);
			}

			if (binding instanceof ICPPFunction)
				return (ICPPFunction) binding;
		} catch (DOMException e) {
		}

		return null;
	}

	private static boolean indexBindingIsReachable(IIndexFileSet fileSet, IIndexBinding item) {
		if (fileSet.containsDeclaration(item)) {
			return true;
		}

		// Specializations of friend functions are sometimes created in the context
		// of the file for which the AST is created, and which is thus not in the index
		// file set. In some cases, an AST binding cannot be created for such 
		// specializations. To support these cases, consider the binding reachable if
		// the friend function being specialized is reachable.
		// This situation only arises in the presence of #includes that are not at
		// global scope. Once bug 315964 is fixed, this workaround can be removed.
		if (item instanceof ICPPFunctionSpecialization && !(item instanceof ICPPFunctionInstance)) {
			IBinding specialized = ((ICPPFunctionSpecialization) item).getSpecializedBinding();
			return !(specialized instanceof IIndexBinding) 
				|| fileSet.containsDeclaration((IIndexBinding) specialized);
		}
		
		return false;
	}

	private static IBinding createSurrogateCallFunction(IScope scope, IType returnType, IType rt, IType[] parameterTypes) {
		IType[] parms = new IType[parameterTypes.length + 1];
		ICPPParameter[] theParms = new ICPPParameter[parms.length];

		parms[0] = rt;
		theParms[0]= new CPPBuiltinParameter(rt);
		for (int i = 1; i < parms.length; i++) {
			IType t = parameterTypes[i - 1];
			parms[i]= t;
			theParms[i]= new CPPBuiltinParameter(t);
		}
		ICPPFunctionType functionType = new CPPFunctionType(returnType, parms);
		return new CPPImplicitFunction(CALL_FUNCTION, scope, functionType, theParms, false, false);
	}

	static boolean isUserDefined(IType type) {
		if (type instanceof ISemanticProblem)
			return false;

		return type instanceof ICPPClassType || type instanceof IEnumeration || type instanceof ICPPUnknownType;
	}

	public static IBinding[] findBindingsInScope(IScope scope, String name, IASTTranslationUnit tu) {
		LookupData data = new LookupData(name.toCharArray(), null, tu);
		return standardLookup(data, scope);
	}

	public static IBinding[] findBindings(IScope scope, String name, boolean qualified) {
		return findBindings(scope, name.toCharArray(), qualified, null);
	}

	public static IBinding[] findBindings(IScope scope, char[] name, boolean qualified) {
		return findBindings(scope, name, qualified, null);
	}

	public static IBinding[] findBindings(IScope scope, char[] name, boolean qualified, IASTNode beforeNode) {
		LookupData data;
		if (beforeNode == null) {
			data= new LookupData(name, null, ASTInternal.getPhysicalNodeOfScope(scope));
			data.setIgnorePointOfDeclaration(true);
		} else {
			data= new LookupData(name, null, beforeNode);
			data.setIgnorePointOfDeclaration(false);
		}
		data.qualified = qualified;
		return standardLookup(data, scope);
	}

	public static IBinding[] findBindingsForContentAssist(IASTName name, boolean prefixLookup,
			String[] additionalNamespaces) {
		LookupData data = createLookupData(name);
		data.contentAssist = true;
		data.fHeuristicBaseLookup = true;
		data.setPrefixLookup(prefixLookup);
		data.foundItems = new CharArrayObjectMap<>(2);

		// Convert namespaces to scopes.
		List<ICPPScope> nsScopes= new ArrayList<>();
		IASTTranslationUnit tu = name.getTranslationUnit();
		if (additionalNamespaces != null && tu instanceof CPPASTTranslationUnit) {
			for (String nsName : additionalNamespaces) {
				nsName= nsName.trim();
				if (nsName.startsWith("::")) { //$NON-NLS-1$
					nsName= nsName.substring(2);
				}
				String[] namespaceParts = nsName.split("::"); //$NON-NLS-1$
				try {
					ICPPScope nsScope = getNamespaceScope((CPPASTTranslationUnit) tu, namespaceParts, name);
					if (nsScope != null) {
						nsScopes.add(nsScope);
					}
				} catch (DOMException e) {
					// Errors in source code, continue with next candidate.
				}
			}
		}
		return contentAssistLookup(data, nsScopes);
	}
	
	/**
	 * Similar to {@link CPPSemantics#findBindingsForContentAssist(IASTName, boolean, String[])},
	 * but in lieu of a name hooked up to the AST, accepts just a string, a position in the file
	 * (represented as an IASTNode, and used to serve as the point of reference for the lookup),
	 * and a starting scope (which is required).
	 */
	public static IBinding[] findBindingsForContentAssist(char[] name, boolean prefixLookup,
			IScope lookupScope, IASTNode point) {
		LookupData data = new LookupData(name, null, point);
		data.contentAssist = true;
		data.fHeuristicBaseLookup = true;
		data.setPrefixLookup(prefixLookup);
		data.foundItems = new CharArrayObjectMap<>(2);
		try {
			CPPSemantics.lookup(data, lookupScope);
		} catch (DOMException e) {
		}
		return collectContentAssistBindings(data);
	}
	
	private static IScope getLookupScope(IASTNode node) {
		if (node == null)
			return null;

		if (node instanceof IASTCompositeTypeSpecifier)
			return ((IASTCompositeTypeSpecifier) node).getScope();

		if (node instanceof ICPPASTNamespaceDefinition)
			return ((ICPPASTNamespaceDefinition) node).getScope();

		if (!(node instanceof ICPPInternalBinding))
			return null;

		IASTNode defn = ((ICPPInternalBinding) node).getDefinition();
		if (defn == null)
			return null;

		return getLookupScope(defn.getParent());
	}

	private static IScope getLookupScope(IBinding binding) {
		if (binding == null)
			return null;

		if (binding instanceof IASTCompositeTypeSpecifier)
			return ((IASTCompositeTypeSpecifier) binding).getScope();

		if (!(binding instanceof ICPPInternalBinding))
			return null;

		IASTNode defn = ((ICPPInternalBinding) binding).getDefinition();
		if (defn == null)
			return null;

		return getLookupScope(defn.getParent());
	}

	/**
	 * Uses C++ lookup semantics to find the possible bindings for the given qualified name starting
	 * in the given scope.
	 */
	public static IBinding[] findBindingsForQualifiedName(IScope scope, String qualifiedName) {
		// Return immediately if the qualifiedName does not match a known format.
		Matcher m = QUALNAME_REGEX.matcher(qualifiedName);
		if (!m.matches())
			return IBinding.EMPTY_BINDING_ARRAY;

		// If the qualified name is rooted in the global namespace, then navigate to that scope.
		boolean isGlobal = m.group(1) != null;
		if (isGlobal) {
			IScope global = scope;
			try {
				while (global.getParent() != null) {
					global = global.getParent();
				}
			} catch (DOMException e) {
				CCorePlugin.log(e);
			}
			scope = global;
		}

		Set<IBinding> bindings = new HashSet<>();

		// Look for the name in the given scope.
		findBindingsForQualifiedName(scope, qualifiedName, bindings);

		// If the qualified name is not rooted in the global namespace (with a leading ::), then
		// look at all parent scopes.
		if (!isGlobal) {
			try {
				while (scope != null) {
					scope = scope.getParent();
					if (scope != null)
						findBindingsForQualifiedName(scope, qualifiedName, bindings);
				}
			} catch (DOMException e) {
				CCorePlugin.log(e);
			}
		}

		return bindings.size() == 0 ? IBinding.EMPTY_BINDING_ARRAY : bindings.toArray(new IBinding[bindings.size()]);
	}

	private static void findBindingsForQualifiedName(IScope scope, String qualifiedName, Collection<IBinding> bindings) {
		// Split the qualified name into the first part (before the first :: qualifier) and the rest. All
		// bindings for the first part are found and their scope is used to find the rest of the name.  When
		// the call tree gets to a leaf (non-qualified name) then a simple lookup happens and all matching
		// bindings are added to the result.
		Matcher m = QUALNAME_REGEX.matcher(qualifiedName);
		if (!m.matches())
			return;

		String part1 = m.group(2);
		String part2 = m.group(3);

		// When we're down to a single component name, then use the normal lookup method.
		if (part2 == null || part2.isEmpty()) {
			bindings.addAll(Arrays.asList(findBindings(scope, part1, false)));
			return;
		}

		// Find all bindings that match the first part of the name.  For each such binding,
		// lookup the second part of the name.
		for (IBinding binding : findBindings(scope, part1, false)) {
			findBindingsForQualifiedName(getLookupScope(binding), part2, bindings);
		}
	}

	private static ICPPScope getNamespaceScope(CPPASTTranslationUnit tu, String[] namespaceParts,
			IASTNode point) throws DOMException {
		ICPPScope nsScope= tu.getScope();
		outer: for (String nsPart : namespaceParts) {
			nsPart= nsPart.trim();
			if (nsPart.length() != 0) {
				IBinding[] nsBindings = nsScope.getBindings(new ScopeLookupData(nsPart.toCharArray(), point));
				for (IBinding nsBinding : nsBindings) {
					if (nsBinding instanceof ICPPNamespace) {
						nsScope= ((ICPPNamespace) nsBinding).getNamespaceScope();
						continue outer;
					}
				}
				// There was no matching namespace
				return null;
			}
		}

		// Name did not specify a namespace, e.g. "::"
		if (nsScope == tu.getScope())
			return null;

		return nsScope;
	}

	private static IBinding[] contentAssistLookup(LookupData data, List<ICPPScope> additionalNamespaces) {
		try {
			lookup(data, null);

			if (additionalNamespaces != null) {
				data.ignoreUsingDirectives = true;
				data.qualified = true;
				for (ICPPScope nsScope : additionalNamespaces) {
					if (!data.visited.containsKey(nsScope)) {
						lookup(data, nsScope);
					}
				}
			}
		} catch (DOMException e) {
		}
		return collectContentAssistBindings(data);
	}
	
	private static IBinding[] collectContentAssistBindings(LookupData data) {
		@SuppressWarnings("unchecked")
		CharArrayObjectMap<Object> map = (CharArrayObjectMap<Object>) data.foundItems;
		IBinding[] result = IBinding.EMPTY_BINDING_ARRAY;
		if (!map.isEmpty()) {
			char[] key = null;
			int size = map.size();
			for (int i = 0; i < size; i++) {
				key = map.keyAt(i);
				result = addContentAssistBinding(result, map.get(key));
			}
		}
		return ArrayUtil.trim(result);
	}

	public static IBinding[] addContentAssistBinding(IBinding[] result, Object obj) {
		if (obj instanceof Object[]) {
			for (Object	o : (Object[]) obj) {
				result= addContentAssistBinding(result, o);
			}
			return result;
		}

		if (obj instanceof IASTName) {
			return addContentAssistBinding(result, ((IASTName) obj).resolveBinding());
		}

		if (obj instanceof IBinding && !(obj instanceof IProblemBinding)) {
			final IBinding binding = (IBinding) obj;
			if (binding instanceof ICPPFunction) {
				final ICPPFunction function = (ICPPFunction) binding;
				if (function.isDeleted()) {
					return result;
				}
			}
			return ArrayUtil.append(result, binding);
		}

		return result;
	}

	private static IBinding[] standardLookup(LookupData data, IScope start) {
		try {
			lookup(data, start);
		} catch (DOMException e) {
			return new IBinding[] { e.getProblem() };
		}

		Object[] items = (Object[]) data.foundItems;
		if (items == null)
			return IBinding.EMPTY_BINDING_ARRAY;

		ObjectSet<IBinding> set = new ObjectSet<>(items.length);
		IBinding binding = null;
		for (Object item : items) {
			if (item instanceof IASTName) {
				binding = ((IASTName) item).resolveBinding();
			} else if (item instanceof IBinding) {
				binding = (IBinding) item;
			} else {
				binding = null;
			}

			if (binding != null) {
				if (binding instanceof ICPPUsingDeclaration) {
					set.addAll(((ICPPUsingDeclaration) binding).getDelegates());
				} else if (binding instanceof CPPCompositeBinding) {
					set.addAll(((CPPCompositeBinding) binding).getBindings());
				} else {
					set.put(binding);
				}
			}
		}

		return set.keyArray(IBinding.class);
	}

	public static boolean isSameFunction(ICPPFunction function, IASTDeclarator declarator) {
		final ICPPASTDeclarator innerDtor = (ICPPASTDeclarator) ASTQueries.findInnermostDeclarator(declarator);
		IASTName name = innerDtor.getName();
		ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
		if (templateDecl != null) {

			if (templateDecl instanceof ICPPASTTemplateSpecialization) {
				if (!(function instanceof ICPPTemplateInstance))
					return false;
				if (!((ICPPTemplateInstance) function).isExplicitSpecialization())
					return false;
			} else {
				if (function instanceof ICPPTemplateDefinition) {
					final ICPPTemplateDefinition funcTemplate = (ICPPTemplateDefinition) function;
					if (!isSameTemplateParameterList(funcTemplate.getTemplateParameters(),
							templateDecl.getTemplateParameters())) {
						return false;
					}
				} else {
					return false;
				}
			}
		} else if (function instanceof ICPPTemplateDefinition) {
			return false;
		}

		declarator= ASTQueries.findTypeRelevantDeclarator(declarator);
		if (declarator instanceof ICPPASTFunctionDeclarator) {
			// For declaration matching, compare the declared types (placeholders not resolved).
			IType type = function.getDeclaredType();
			return type.isSameType(CPPVisitor.createType(declarator, CPPVisitor.DO_NOT_RESOLVE_PLACEHOLDERS));
		}
		return false;
	}

	private static boolean isSameTemplateParameterList(ICPPTemplateParameter[] tplist,
			ICPPASTTemplateParameter[] tps) {
		if (tplist.length != tps.length)
			return false;

		for (int i = 0; i < tps.length; i++) {
			if (!isSameTemplateParameter(tplist[i], tps[i]))
				return false;
		}
		return true;
	}

	static boolean isSameTemplateParameter(ICPPTemplateParameter tp1, ICPPASTTemplateParameter tp2) {
		if (tp1.isParameterPack() != tp2.isParameterPack())
			return false;

		if (tp1 instanceof ICPPTemplateNonTypeParameter) {
			if (tp2 instanceof ICPPASTParameterDeclaration) {
				IType t1= ((ICPPTemplateNonTypeParameter) tp1).getType();
				IType t2= CPPVisitor.createType((ICPPASTParameterDeclaration) tp2, true);
				return t1 != null && t1.isSameType(t2);
			}
			return false;
		}
		if (tp1 instanceof ICPPTemplateTypeParameter) {
			if (tp2 instanceof ICPPASTSimpleTypeTemplateParameter) {
				return true;
			}
			return false;
		}
		if (tp1 instanceof ICPPTemplateTemplateParameter) {
			if (tp2 instanceof ICPPASTTemplatedTypeTemplateParameter) {
				final ICPPTemplateTemplateParameter ttp1 = (ICPPTemplateTemplateParameter) tp1;
				final ICPPASTTemplatedTypeTemplateParameter ttp2 = (ICPPASTTemplatedTypeTemplateParameter) tp2;
				return isSameTemplateParameterList(ttp1.getTemplateParameters(), ttp2.getTemplateParameters());
			}
			return false;
		}

		return false;
	}

	protected static IBinding resolveUnknownName(IScope scope, ICPPUnknownBinding unknown) {
		final char[] unknownName = unknown.getNameCharArray();
		IASTNode point = CPPSemantics.getCurrentLookupPoint();
		LookupData data = new LookupData(unknownName, null, point);
		data.setIgnorePointOfDeclaration(true);
		data.typesOnly= unknown instanceof IType;
		data.qualified= true;

		try {
			// 2: Lookup
			lookup(data, scope);
		} catch (DOMException e) {
			data.problem = (ProblemBinding) e.getProblem();
		}

		if (data.problem != null)
			return data.problem;

		// 3: Resolve ambiguities
		IBinding binding;
		try {
			binding = resolveAmbiguities(data);
		} catch (DOMException e) {
			binding = e.getProblem();
		}
		// 4: Normal post processing is not possible, because the name is not rooted in AST
		if (binding == null)
			binding = new ProblemBinding(new CPPASTName(unknownName), point, IProblemBinding.SEMANTIC_NAME_NOT_FOUND);

		return binding;
	}
	
	public static void enablePromiscuousBindingResolution() {
		fAllowPromiscuousBindingResolution.set(true);
	}

	public static void disablePromiscuousBindingResolution() {
		fAllowPromiscuousBindingResolution.set(false);
	}
	
	public static boolean isUsingPromiscuousBindingResolution() {
		return fAllowPromiscuousBindingResolution.get();
	}

	/**
	 * Compute decltype(expr) for an expression represented by an evaluation.
	 * This is similar to CPPVisitor.getDeclType(IASTExpression), but used in cases where the
	 * original expression was dependent, so we had to represent it as an evaluation and
	 * instantiate it.
	 * 
	 * @param eval the (instantiated) evaluation representing the expression
	 */
	public static IType getDeclTypeForEvaluation(ICPPEvaluation eval) {
		IType expressionType = eval.getType();
		boolean namedEntity = eval instanceof EvalBinding || eval instanceof EvalMemberAccess;
		if (!namedEntity && !(expressionType instanceof ICPPReferenceType)) {
			switch (eval.getValueCategory()) {
			case XVALUE:
				return new CPPReferenceType(expressionType, true);
			case LVALUE:
				return new CPPReferenceType(expressionType, false);
			case PRVALUE:
				break;
			}
		}
		return expressionType;
	}
	
	/**
	 * This method performs type deduction for auto, decltype or typeof
	 * declarations. This is used by {@code CSourceHover} and
	 * {@code OpenDeclarationsJob} after checking (see
	 * {@code SemanticUtil#isAutoOrDecltype(String)}) whether the selected text
	 * equals any of the mentioned keywords.
	 *
	 * @param node
	 *            The decl-specifier or decltype-specifier in which the 'auto'
	 *            or 'decltype' occurs.
	 * @return the deduced type or null
	 */
	public static IType resolveDecltypeOrAutoType(IASTNode node) {
		IType type = null;
		if (node instanceof ICPPASTDecltypeSpecifier) {
			type = ((ICPPASTDecltypeSpecifier) node).getDecltypeExpression().getExpressionType();
		}
		if (node instanceof ICPPASTSimpleDeclSpecifier) {
			int builtin = ((ICPPASTSimpleDeclSpecifier) node).getType();
			if (builtin == ICPPASTSimpleDeclSpecifier.t_auto || builtin == ICPPASTSimpleDeclSpecifier.t_typeof
					|| builtin == ICPPASTSimpleDeclSpecifier.t_decltype) {
				IASTNode parent = node.getParent();
				IASTDeclarator declarator = null;
				if (parent instanceof IASTSimpleDeclaration) {
					IASTDeclarator[] declarators = ((IASTSimpleDeclaration) parent).getDeclarators();
					// It's invalid for different declarators to deduce
					// different types with 'auto', so just get the type based on the
					// first declarator.
					if (declarators.length > 0)
						declarator = declarators[0];
				} else if (parent instanceof IASTParameterDeclaration
						&& builtin != ICPPASTSimpleDeclSpecifier.t_auto) {
					declarator = ((IASTParameterDeclaration) parent).getDeclarator();
				} else if (parent instanceof ICPPASTTypeId && builtin != ICPPASTSimpleDeclSpecifier.t_auto) {
					declarator = ((ICPPASTTypeId) parent).getAbstractDeclarator();
				} else if (parent instanceof ICPPASTFunctionDefinition) {
					declarator = ((ICPPASTFunctionDefinition) parent).getDeclarator();
				}
				if (declarator != null) {
					type = CPPVisitor.createType(declarator);
					if (type instanceof ICPPFunctionType) {
						type = ((ICPPFunctionType) type).getReturnType();
					}
				}
			}
		}
		return type;
	}
}
