/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *     Stephan Herrmann - Contributions for
 *								bug 349326 - [1.7] new warning for missing try-with-resources
 *								bug 186342 - [compiler][null] Using annotations for null checking
 *								bug 364890 - BinaryTypeBinding should use char constants from Util
 *								bug 365387 - [compiler][null] bug 186342: Issues to follow up post review and verification.
 *								bug 358903 - Filter practically unimportant resource leak warnings
 *								bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
 *								bug 388800 - [1.8][compiler] detect default methods in class files
 *								bug 388281 - [compiler][null] inheritance of null annotations as an option
 *								bug 331649 - [compiler][null] consider null annotations for fields
 *								bug 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
 *								Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *								Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
 *								Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
 *								Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
 *								Bug 427199 - [1.8][resource] avoid resource leak warnings on Streams that have no resource
 *								Bug 392245 - [1.8][compiler][null] Define whether / how @NonNullByDefault applies to TYPE_USE locations
 *								Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
 *								Bug 390889 - [1.8][compiler] Evaluate options to support 1.7- projects against 1.8 JRE.
 *								Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
 *								Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type
 *								Bug 434602 - Possible error with inferred null annotations leading to contradictory null annotations
 *								Bug 440477 - [null] Infrastructure for feeding external annotations into compilation
 *								Bug 441693 - [1.8][null] Bogus warning for type argument annotated with @NonNull
 *								Bug 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
 *								Bug 453475 - [1.8][null] Contradictory null annotations (4.5 M3 edition)
 *								Bug 454182 - Internal compiler error when using 1.8 compliance for simple project
 *								Bug 470467 - [null] Nullness of special Enum methods not detected from .class file
 *								Bug 447661 - [1.8][null] Incorrect 'expression needs unchecked conversion' warning
 *    Jesper Steen Moller - Contributions for
 *								Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing
 *								Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
 *    Sebastian Zarnekow - Contributions for
 *								bug 544921 - [performance] Poor performance with large source files
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;

import java.util.ArrayList;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.AnnotationInfo;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.FieldInfo;
import org.eclipse.jdt.internal.compiler.classfmt.MethodInfo;
import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider.IMethodAnnotationWalker;
import org.eclipse.jdt.internal.compiler.classfmt.MethodInfoWithAnnotations;
import org.eclipse.jdt.internal.compiler.classfmt.NonNullDefaultAwareTypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.classfmt.TypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
import org.eclipse.jdt.internal.compiler.env.ClassSignature;
import org.eclipse.jdt.internal.compiler.env.EnumConstantSignature;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
import org.eclipse.jdt.internal.compiler.env.IBinaryField;
import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
import org.eclipse.jdt.internal.compiler.env.ITypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AbstractAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.AnchorMapping;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticBaseCallSurrogate;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleBridgeMethodBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.SyntheticRoleFieldAccess;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.FieldModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel.FakeKind;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.RoleTypeCreator;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.TSuperHelper;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.TypeAnalyzer;

/*
Not all fields defined by this type are initialized when it is created.
Some are initialized only when needed.

Accessors have been provided for some public fields so all TypeBindings have the same API...
but access public fields directly whenever possible.
Non-public fields have accessors which should be used everywhere you expect the field to be initialized.

null is NOT a valid value for a non-public field... it just means the field is not initialized.
*/
/**
 * OTDT changes:
 *
 * STRUCTURE:
 * What: support team package (cf. ReferenceBinding.maybeSetTeamPackage()).
 *
 * What: allow adding methods (for callout-to-field)
 *
 * READ FROM BYTE CODE:
 * What: restore predefined confined types.
 * Why:  + Synthetic flag is not set in the byte-code
 *       + Team.Confined has NO superclass.
 *
 * What: initialize AccRole, model, _teamModel and roleModel
 *
 * What: Read some information that normally would be skipped:
 * Which:+ Local types (plus set enclosingType, see LookupEnvironment.enclosingRole)
 * 	     + Synthetic methods of teams and roles
 * Why:  Need this info for copy inheritance.
 *
 * What: Evaluate OT-specific byte code attributes
 * How:  During cachePartsFrom call
 * 			+ ModelElement.evaluateAttributes(..),
 *          + AbstractAttribute.evaluateFieldAttributes(..) // only if fields are built
 *          + AbstractAttribute.clearReadAttributes()
 *
 * What: For methods: register(store) byte code, evaluate attributes (maybeRegister())
 *
 *
 * What: A ROFI intermediate patch for parsing a role file of a binary team.
 *       Source roles should always be compiled together with their team!
 * 		 FIXME: This patch is only used to detect source role in binary team,
 *              which must be strictly avoided any way.
 *
 * RESOLVE:
 * What: Methods/fields wrap types in signatures, link tsupers to their source.
 */

@SuppressWarnings({ "rawtypes", "unchecked" })
public class BinaryTypeBinding extends ReferenceBinding {

	public static final char[] TYPE_QUALIFIER_DEFAULT = "TypeQualifierDefault".toCharArray(); //$NON-NLS-1$

	private static final IBinaryMethod[] NO_BINARY_METHODS = new IBinaryMethod[0];

	// all of these fields are ONLY guaranteed to be initialized if accessed using their public accessor method
	protected ReferenceBinding superclass;
	protected ReferenceBinding enclosingType;
	protected ReferenceBinding[] superInterfaces;
	protected FieldBinding[] fields;
	protected MethodBinding[] methods;
	protected ReferenceBinding[] memberTypes;
	protected TypeVariableBinding[] typeVariables;
	protected ModuleBinding module;
	private BinaryTypeBinding prototype;

	// For the link with the principle structure
	protected LookupEnvironment environment;

	protected SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder

	private ReferenceBinding containerAnnotationType;
	int defaultNullness = 0;
	boolean memberTypesSorted = false;
	public enum ExternalAnnotationStatus {
		FROM_SOURCE,
		NOT_EEA_CONFIGURED,
		NO_EEA_FILE,
		TYPE_IS_ANNOTATED;
		public boolean isPotentiallyUnannotatedLib() {
			switch (this) {
				case FROM_SOURCE:
				case TYPE_IS_ANNOTATED:
					return false;
				default:
					return true;
			}
		}
	}
	public ExternalAnnotationStatus externalAnnotationStatus = ExternalAnnotationStatus.NOT_EEA_CONFIGURED; // unless proven differently
	
//{ObjectTeams: support callout-to-field

	/** Callout to field adds faked access method (set or get): */
	@Override
	public void addMethod(MethodBinding methodBinding) {
		// This method is a verbatim copy of SourceTypeBinding.addMethod().
		// differentiate between sorted and unsorted state:
		int size = this.methods.length;
		if ((this.tagBits & TagBits.AreMethodsSorted) != 0) {
			this.methods= ReferenceBinding.sortedInsert(this.methods, methodBinding);
			if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
				resolveTypesFor(methodBinding);
		} else {
			//grow array
			System.arraycopy(this.methods, 0, this.methods= new MethodBinding[size + 1], 0, size);

			this.methods[size] = methodBinding;
		}
	}

	// the class file version
	public long version;

	// enclosing type may be set while evaluating ROLE_LOCAL_TYPES attribte:
	/** Set enclosingType and update dependent fields. */
    public void setEnclosingOfRoleLocal(ReferenceBinding enclosing) {
    	this.enclosingType = enclosing;
		this.tagBits |= TagBits.LocalTypeMask;
		if (enclosingType().isStrictfp())
			this.modifiers |= ClassFileConstants.AccStrictfp;
		if (enclosingType().isDeprecated())
			this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;

		maybeSetRoleModel();
    }
    /**
     * Given that enclosingType is set, and if this is a role (direct or indirect):
     * Create and link RoleModel.
     */
    private void maybeSetRoleModel() {
    	ReferenceBinding enclosingTeam = TeamModel.getEnclosingTeam(this);
    	if (enclosingTeam != null) {

    		// it's either a role or a nested type of a role
    		if (this.roleModel == null) // could have been set while evaluating a byte code attribute
    			this.roleModel = new RoleModel(this);
    	    this.roleModel.setTeamModel(enclosingTeam.getTeamModel());
    	    if (isLocalType())
    	    	this.modifiers &= ~ClassFileConstants.AccPrivate; // AccPrivate is set in the inner class info, but is illegal
    	} else if (isRole()) {
    		// FIXME(SH): handle somehow
    		System.err.println("Role without team!!! "+new String(readableName()));
    	}
    }
// SH}

static Object convertMemberValue(Object binaryValue, LookupEnvironment env, char[][][] missingTypeNames, boolean resolveEnumConstants) {
	if (binaryValue == null) return null;
	if (binaryValue instanceof Constant)
		return binaryValue;
	if (binaryValue instanceof ClassSignature)
		return env.getTypeFromSignature(((ClassSignature) binaryValue).getTypeName(), 0, -1, false, null, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
	if (binaryValue instanceof IBinaryAnnotation)
		return createAnnotation((IBinaryAnnotation) binaryValue, env, missingTypeNames);
	if (binaryValue instanceof EnumConstantSignature) {
		EnumConstantSignature ref = (EnumConstantSignature) binaryValue;
		ReferenceBinding enumType = (ReferenceBinding) env.getTypeFromSignature(ref.getTypeName(), 0, -1, false, null, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
		if (enumType.isUnresolvedType() && !resolveEnumConstants)
			return new ElementValuePair.UnresolvedEnumConstant(enumType, env, ref.getEnumConstantName());
		enumType = (ReferenceBinding) resolveType(enumType, env, false /* no raw conversion */);
		return enumType.getField(ref.getEnumConstantName(), false);
	}
	if (binaryValue instanceof Object[]) {
		Object[] objects = (Object[]) binaryValue;
		int length = objects.length;
		if (length == 0) return objects;
		Object[] values = new Object[length];
		for (int i = 0; i < length; i++)
			values[i] = convertMemberValue(objects[i], env, missingTypeNames, resolveEnumConstants);
		return values;
	}

	// should never reach here.
	throw new IllegalStateException();
}

@Override
public TypeBinding clone(TypeBinding outerType) {
	BinaryTypeBinding copy = new BinaryTypeBinding(this);
	copy.enclosingType = (ReferenceBinding) outerType;
	
	/* BinaryTypeBinding construction is not "atomic" and is split between the constructor and cachePartsFrom and between the two
	   stages of construction, clone can kick in when LookupEnvironment.createBinaryTypeFrom calls PackageBinding.addType. This
	   can result in some URB's being resolved, which could trigger the clone call, leaving the clone with semi-initialized prototype.
	   Fortunately, the protocol for this type demands all clients to use public access methods, where we can deflect the call to the
	   prototype. enclosingType() and memberTypes() should not delegate, so ...
	*/
	if (copy.enclosingType != null) 
		copy.tagBits |= TagBits.HasUnresolvedEnclosingType;
	else 
		copy.tagBits &= ~TagBits.HasUnresolvedEnclosingType;
	
	copy.tagBits |= TagBits.HasUnresolvedMemberTypes;
	return copy;
}

static AnnotationBinding createAnnotation(IBinaryAnnotation annotationInfo, LookupEnvironment env, char[][][] missingTypeNames) {
	// temporary debug for Bug 532176 - [10] NPE during reconcile
	if (annotationInfo instanceof AnnotationInfo) {
		RuntimeException ex = ((AnnotationInfo) annotationInfo).exceptionDuringDecode;
		if (ex != null)
			new IllegalStateException("Accessing annotation with decode error", ex).printStackTrace(); //$NON-NLS-1$
	}
	//--
	IBinaryElementValuePair[] binaryPairs = annotationInfo.getElementValuePairs();
	int length = binaryPairs == null ? 0 : binaryPairs.length;
	ElementValuePair[] pairs = length == 0 ? Binding.NO_ELEMENT_VALUE_PAIRS : new ElementValuePair[length];
	for (int i = 0; i < length; i++)
		pairs[i] = new ElementValuePair(binaryPairs[i].getName(), convertMemberValue(binaryPairs[i].getValue(), env, missingTypeNames, false), null);

	char[] typeName = annotationInfo.getTypeName();
	LookupEnvironment env2 = annotationInfo.isExternalAnnotation() ? env.root : env;
	ReferenceBinding annotationType = env2.getTypeFromConstantPoolName(typeName, 1, typeName.length - 1, false,
			missingTypeNames);
	return env2.createUnresolvedAnnotation(annotationType, pairs);
}

public static AnnotationBinding[] createAnnotations(IBinaryAnnotation[] annotationInfos, LookupEnvironment env, char[][][] missingTypeNames) {
	int length = annotationInfos == null ? 0 : annotationInfos.length;
	AnnotationBinding[] result = length == 0 ? Binding.NO_ANNOTATIONS : new AnnotationBinding[length];
	for (int i = 0; i < length; i++)
		result[i] = createAnnotation(annotationInfos[i], env, missingTypeNames);
	return result;
}

public static TypeBinding resolveType(TypeBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
	switch (type.kind()) {
		case Binding.PARAMETERIZED_TYPE :
			((ParameterizedTypeBinding) type).resolve();
			break;

		case Binding.WILDCARD_TYPE :
		case Binding.INTERSECTION_TYPE :
			return ((WildcardBinding) type).resolve();

		case Binding.ARRAY_TYPE :
			ArrayBinding arrayBinding = (ArrayBinding) type;
			TypeBinding leafComponentType = arrayBinding.leafComponentType;
			resolveType(leafComponentType, environment, convertGenericToRawType);
			if (leafComponentType.hasNullTypeAnnotations() && environment.usesNullTypeAnnotations()) {
				if (arrayBinding.nullTagBitsPerDimension == null)
					arrayBinding.nullTagBitsPerDimension = new long[arrayBinding.dimensions+1];
				arrayBinding.nullTagBitsPerDimension[arrayBinding.dimensions] = leafComponentType.tagBits & TagBits.AnnotationNullMASK;
			}
			break;

		case Binding.TYPE_PARAMETER :
			((TypeVariableBinding) type).resolve();
			break;

		case Binding.GENERIC_TYPE :
			if (convertGenericToRawType) // raw reference to generic ?
				return environment.convertUnresolvedBinaryToRawType(type);
			break;

		default:
			if (type instanceof UnresolvedReferenceBinding)
				return ((UnresolvedReferenceBinding) type).resolve(environment, convertGenericToRawType);
			if (convertGenericToRawType) // raw reference to generic ?
				return environment.convertUnresolvedBinaryToRawType(type);
			break;
	}
	return type;
}

/**
 * Default empty constructor for subclasses only.
 */
protected BinaryTypeBinding() {
	// only for subclasses
	this.prototype = this;
}

public BinaryTypeBinding(BinaryTypeBinding prototype) {
	super(prototype);
	this.superclass = prototype.superclass;
	this.enclosingType = prototype.enclosingType;
	this.superInterfaces = prototype.superInterfaces;
	this.fields = prototype.fields;
	this.methods = prototype.methods;
	this.memberTypes = prototype.memberTypes;
	this.typeVariables = prototype.typeVariables;
	this.prototype = prototype.prototype;
	this.environment = prototype.environment;
	this.storedAnnotations = prototype.storedAnnotations;
}

/**
 * Standard constructor for creating binary type bindings from binary models (classfiles)
 * @param packageBinding
 * @param binaryType
 * @param environment
 */
public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment) {
	this(packageBinding, binaryType, environment, false);
}
/**
 * Standard constructor for creating binary type bindings from binary models (classfiles)
 * @param packageBinding
 * @param binaryType
 * @param environment
 * @param needFieldsAndMethods
 */
public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment, boolean needFieldsAndMethods) {
	
	this.prototype = this;
	this.compoundName = CharOperation.splitOn('/', binaryType.getName());
	computeId();

	this.tagBits |= TagBits.IsBinaryBinding;
	this.environment = environment;
	this.fPackage = packageBinding;
	this.fileName = binaryType.getFileName();
	/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, even in a 1.4 project, we
	   must internalize type variables and observe any parameterization of super class
	   and/or super interfaces in order to be able to detect overriding in the presence
	   of generics.
	 */
	char[] typeSignature = binaryType.getGenericSignature();
	this.typeVariables = typeSignature != null && typeSignature.length > 0 && typeSignature[0] == Util.C_GENERIC_START
		? null // is initialized in cachePartsFrom (called from LookupEnvironment.createBinaryTypeFrom())... must set to null so isGenericType() answers true
		: Binding.NO_TYPE_VARIABLES;

	this.sourceName = binaryType.getSourceName();
	this.modifiers = binaryType.getModifiers();

	if ((binaryType.getTagBits() & TagBits.HierarchyHasProblems) != 0)
		this.tagBits |= TagBits.HierarchyHasProblems;

	if (binaryType.isAnonymous()) {
		this.tagBits |= TagBits.AnonymousTypeMask;
	} else if (binaryType.isLocal()) {
		this.tagBits |= TagBits.LocalTypeMask;
	} else if (binaryType.isMember()) {
		this.tagBits |= TagBits.MemberTypeMask;
	}
	// need enclosing type to access type variables
	char[] enclosingTypeName = binaryType.getEnclosingTypeName();
	if (enclosingTypeName != null) {
		// attempt to find the enclosing type if it exists in the cache (otherwise - resolve it when requested)
		this.enclosingType = environment.getTypeFromConstantPoolName(enclosingTypeName, 0, -1, true, null /* could not be missing */); // pretend parameterized to avoid raw
		this.tagBits |= TagBits.MemberTypeMask;   // must be a member type not a top-level or local type
		this.tagBits |= TagBits.HasUnresolvedEnclosingType;
		if (enclosingType().isStrictfp())
			this.modifiers |= ClassFileConstants.AccStrictfp;
		if (enclosingType().isDeprecated())
			this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
	}
	if (needFieldsAndMethods)
		cachePartsFrom(binaryType, true);
//{ObjectTeams: ROFI if this is a team, record the package that contains its role files.
	maybeSetTeamPackage(this.compoundName, this.fPackage, environment, this.fPackage.enclosingModule);
// SH}
}
@Override
public boolean canBeSeenBy(Scope sco) {
	ModuleBinding mod = sco.module();
	return mod.canAccess(this.fPackage) && super.canBeSeenBy(sco);
}
/**
 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#availableFields()
 */
@Override
public FieldBinding[] availableFields() {
	
	if (!isPrototype()) {
		return this.prototype.availableFields();
	}
	
	if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
		return this.fields;

	// lazily sort fields
	if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
		int length = this.fields.length;
		if (length > 1)
			ReferenceBinding.sortFields(this.fields, 0, length);
		this.tagBits |= TagBits.AreFieldsSorted;
	}
	FieldBinding[] availableFields = new FieldBinding[this.fields.length];
	int count = 0;
	for (int i = 0; i < this.fields.length; i++) {
		try {
			availableFields[count] = resolveTypeFor(this.fields[i]);
			count++;
		} catch (AbortCompilation a){
			// silent abort
		}
	}
	if (count < availableFields.length)
		System.arraycopy(availableFields, 0, availableFields = new FieldBinding[count], 0, count);
	return availableFields;
}

private TypeVariableBinding[] addMethodTypeVariables(TypeVariableBinding[] methodTypeVars) {
	if (!isPrototype()) throw new IllegalStateException();
	if (this.typeVariables == null || this.typeVariables == Binding.NO_TYPE_VARIABLES) {
		return methodTypeVars;
	} 
	if (methodTypeVars == null || methodTypeVars == Binding.NO_TYPE_VARIABLES) {
		return this.typeVariables;
	}
	// uniq-merge both the arrays
	int total = this.typeVariables.length + methodTypeVars.length;
	TypeVariableBinding[] combinedTypeVars = new TypeVariableBinding[total];
	System.arraycopy(this.typeVariables, 0, combinedTypeVars, 0, this.typeVariables.length);
	int size = this.typeVariables.length;
	loop: for (int i = 0, len = methodTypeVars.length; i < len; i++) {
		for (int j = this.typeVariables.length -1 ; j >= 0; j--) {
			if (CharOperation.equals(methodTypeVars[i].sourceName, this.typeVariables[j].sourceName))
				continue loop;
		}
		combinedTypeVars[size++] = methodTypeVars[i];
	}
	if (size != total) {
		System.arraycopy(combinedTypeVars, 0, combinedTypeVars = new TypeVariableBinding[size], 0, size);
	}
	return combinedTypeVars;
}

/**
 * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#availableMethods()
 */
@Override
public MethodBinding[] availableMethods() {
	
	if (!isPrototype()) {
		return this.prototype.availableMethods();
	}

	if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
		return this.methods;

	// lazily sort methods
	if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
		int length = this.methods.length;
		if (length > 1)
			ReferenceBinding.sortMethods(this.methods, 0, length);
		this.tagBits |= TagBits.AreMethodsSorted;
	}
	MethodBinding[] availableMethods = new MethodBinding[this.methods.length];
	int count = 0;
	for (int i = 0; i < this.methods.length; i++) {
		try {
			availableMethods[count] = resolveTypesFor(this.methods[i]);
			count++;
		} catch (AbortCompilation a){
			// silent abort
		}
	}
	if (count < availableMethods.length)
		System.arraycopy(availableMethods, 0, availableMethods = new MethodBinding[count], 0, count);
	return availableMethods;
}

void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
	if (!isPrototype()) throw new IllegalStateException();
	try {
		// default initialization for super-interfaces early, in case some aborting compilation error occurs,
		// and still want to use binaries passed that point (e.g. type hierarchy resolver, see bug 63748).
		this.typeVariables = Binding.NO_TYPE_VARIABLES;
		this.superInterfaces = Binding.NO_SUPERINTERFACES;

//{ObjectTeams: one more field to initialize to empty array:
		this.callinCallouts = Binding.NO_CALLIN_CALLOUT_BINDINGS;
		// enter binary role to its source enclosing
		if (   enclosingType() != null
			&& !this.enclosingType.isBinaryBinding())
		{
			ReferenceBinding[] oldMembers = this.enclosingType.memberTypes();
			int len = oldMembers.length;
			ReferenceBinding[] newMembers = new ReferenceBinding[len+1];
			System.arraycopy(oldMembers, 0, newMembers, 0, len);
			newMembers[len] = this;
			SourceTypeBinding enclosingSourceTypeBinding = (SourceTypeBinding)this.enclosingType;
			enclosingSourceTypeBinding.setMemberTypes(newMembers);
			if (enclosingSourceTypeBinding.scope != null) {
				// remember the name of this binary member type:
				CompilationResult result =
				    enclosingSourceTypeBinding.scope.referenceCompilationUnit().compilationResult();
				result.recordBinaryMemberType(this.compoundName[this.compoundName.length-1]);
			} else {
				// only in state final we know that there is no scope any more.
				// TODO(SH): can we actually tolerate this?
				int state = enclosingSourceTypeBinding.model.getState();
				if (enclosingSourceTypeBinding._teamModel != null)
					state = enclosingSourceTypeBinding._teamModel.getState();
				assert state == ITranslationStates.STATE_FINAL;
			}
		}
// SH}
//{ObjectTeams: set team/role modifiers and create models
		maybeSetRoleModel(); // determined by presence of enclosing team

		if (binaryType instanceof ClassFileReader) {
			// set AccTeam/AccRole to modifiers:
			ClassFileReader reader = (ClassFileReader)binaryType;
			reader.evaluateOTClassFlagsAttribute(this, this.environment, binaryType.getMissingTypeNames());
		}

		if ((this.modifiers & ExtraCompilerModifiers.AccTeam) != 0)
		    this._teamModel = new TeamModel(this);
		// Note, 'model' is already set in ctor of superclass ReferenceBinding.

		// for roles and teams we need the bytes, retrieve them now, if not already present:
		if ((this.modifiers & (ExtraCompilerModifiers.AccRole|ExtraCompilerModifiers.AccTeam)) != 0) {
    		try {
    			binaryType = binaryType.withClassBytes();
			} catch (Exception e) {
				if (this.environment.problemReporter != null) {
					String errorMessage = "Cannot read class file for "+String.valueOf(binaryType.getName())+": "; //$NON-NLS-1$ //$NON-NLS-2$
					this.environment.problemReporter.abortDueToInternalError(errorMessage+e.getMessage());
				}
			}
		}
//SH}

		// must retrieve member types in case superclass/interfaces need them
		this.memberTypes = Binding.NO_MEMBER_TYPES;
		IBinaryNestedType[] memberTypeStructures = binaryType.getMemberTypes();
		if (memberTypeStructures != null) {
			int size = memberTypeStructures.length;
			if (size > 0) {
				this.memberTypes = new ReferenceBinding[size];
				for (int i = 0; i < size; i++) {
					// attempt to find each member type if it exists in the cache (otherwise - resolve it when requested)
					this.memberTypes[i] = this.environment.getTypeFromConstantPoolName(memberTypeStructures[i].getName(), 0, -1, false, null /* could not be missing */);
				}
				this.tagBits |= TagBits.HasUnresolvedMemberTypes;
			}
		}

		CompilerOptions globalOptions = this.environment.globalOptions;
		long sourceLevel = globalOptions.originalSourceLevel;
		/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, even in a 1.4 project, we
		   must internalize type variables and observe any parameterization of super class
		   and/or super interfaces in order to be able to detect overriding in the presence
		   of generics.
		 */
		if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
			// need annotations on the type before processing null annotations on members respecting any @NonNullByDefault:
			scanTypeForNullDefaultAnnotation(binaryType, this.fPackage);
		}
		ITypeAnnotationWalker walker = getTypeAnnotationWalker(binaryType.getTypeAnnotations(), Binding.NO_NULL_DEFAULT);
		ITypeAnnotationWalker toplevelWalker = binaryType.enrichWithExternalAnnotationsFor(walker, null, this.environment);
		this.externalAnnotationStatus = binaryType.getExternalAnnotationStatus();
		if (this.externalAnnotationStatus.isPotentiallyUnannotatedLib() && this.defaultNullness != 0) {
			this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
		}
		char[] typeSignature = binaryType.getGenericSignature(); // use generic signature even in 1.4
		this.tagBits |= binaryType.getTagBits();
		if (this.environment.globalOptions.complianceLevel < ClassFileConstants.JDK1_8)
			this.tagBits &= ~TagBits.AnnotationForTypeUse; // avoid confusion with semantics that are not supported at 1.7-
		
		char[][][] missingTypeNames = binaryType.getMissingTypeNames();
		SignatureWrapper wrapper = null;
		if (typeSignature != null) {
			// ClassSignature = ParameterPart(optional) super_TypeSignature interface_signature
			wrapper = new SignatureWrapper(typeSignature);
			if (wrapper.signature[wrapper.start] == Util.C_GENERIC_START) {
				// ParameterPart = '<' ParameterSignature(s) '>'
				wrapper.start++; // skip '<'
				this.typeVariables = createTypeVariables(wrapper, true, missingTypeNames, toplevelWalker, true/*class*/);
				wrapper.start++; // skip '>'
				this.tagBits |=  TagBits.HasUnresolvedTypeVariables;
				this.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
			}
		}
		TypeVariableBinding[] typeVars = Binding.NO_TYPE_VARIABLES;
		char[] methodDescriptor = binaryType.getEnclosingMethod();
		if (methodDescriptor != null) {
			MethodBinding enclosingMethod = findMethod(methodDescriptor, missingTypeNames);
			if (enclosingMethod != null) {
				typeVars = enclosingMethod.typeVariables;
				this.typeVariables = addMethodTypeVariables(typeVars);			
			}
		}
		if (typeSignature == null)  {
//{ObjectTeams: predefined confined types require special treatment
		  // 1. add the synthetic flag which is missing from the class file:
		  if (CharOperation.equals(this.compoundName, IOTConstants.ORG_OBJECTTEAMS_TEAM_CONFINED))
			this.modifiers |= ClassFileConstants.AccSynthetic;
		  if (TypeAnalyzer.isTopConfined(this)) {
			// 2. don't search a superclass, have none (ie., skip the else part)
		  } else {
// orig:
			char[] superclassName = binaryType.getSuperclassName();
			if (superclassName != null) {
				// attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
				this.superclass = this.environment.getTypeFromConstantPoolName(superclassName, 0, -1, false, missingTypeNames, toplevelWalker.toSupertype((short) -1, superclassName));
				this.tagBits |= TagBits.HasUnresolvedSuperclass;
			}
// :giro
		  }
// SH}

			this.superInterfaces = Binding.NO_SUPERINTERFACES;
			char[][] interfaceNames = binaryType.getInterfaceNames();
			if (interfaceNames != null) {
				int size = interfaceNames.length;
				if (size > 0) {
					this.superInterfaces = new ReferenceBinding[size];
					for (short i = 0; i < size; i++)
						// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
						this.superInterfaces[i] = this.environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1, false, missingTypeNames, toplevelWalker.toSupertype(i, interfaceNames[i]));
					this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
				}
			}
		} else {
			// attempt to find the superclass if it exists in the cache (otherwise - resolve it when requested)
			this.superclass = (ReferenceBinding) this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames, 
																		toplevelWalker.toSupertype((short) -1, wrapper.peekFullType()));
//{ObjectTeams: wrapping of type (incl. its arguments)?
			if (!TypeAnalyzer.isTopConfined(this.superclass))
				this.superclass = (ReferenceBinding) RoleTypeCreator.maybeWrapUnqualifiedRoleType(this.superclass, this);
// SH}
			this.tagBits |= TagBits.HasUnresolvedSuperclass;

			this.superInterfaces = Binding.NO_SUPERINTERFACES;
			if (!wrapper.atEnd()) {
				// attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
				java.util.ArrayList types = new java.util.ArrayList(2);
				short rank = 0;
				do {
//{ObjectTeams: wrapping of type (incl. its arguments)?
/* orig:
					types.add(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames, toplevelWalker.toSupertype(rank++, wrapper.peekFullType())));
  :giro*/
					TypeBinding type = this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames, toplevelWalker.toSupertype(rank++, wrapper.peekFullType()));
					if (this.isDirectRole()
							&& !(type instanceof ReferenceBinding && TSuperHelper.isTSubOf(this, (ReferenceBinding) type)))
						type = RoleTypeCreator.maybeWrapUnqualifiedRoleType(type, this);
					types.add(type);
// SH}
				} while (!wrapper.atEnd());
				this.superInterfaces = new ReferenceBinding[types.size()];
				types.toArray(this.superInterfaces);
				this.tagBits |= TagBits.HasUnresolvedSuperinterfaces;
			}
		}
		boolean canUseNullTypeAnnotations = this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled && this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8;
		if (canUseNullTypeAnnotations && this.externalAnnotationStatus.isPotentiallyUnannotatedLib()) {
			if (this.superclass != null && this.superclass.hasNullTypeAnnotations()) {
				this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
			} else {
				for (TypeBinding ifc : this.superInterfaces) {
					if (ifc.hasNullTypeAnnotations()) {
						this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
						break;
					}
				}
			}
		}

		if (needFieldsAndMethods) {
			IBinaryField[] iFields = binaryType.getFields();
			createFields(iFields, binaryType, sourceLevel, missingTypeNames);
			IBinaryMethod[] iMethods = createMethods(binaryType.getMethods(), binaryType, sourceLevel, missingTypeNames);
			boolean isViewedAsDeprecated = isViewedAsDeprecated();
			if (isViewedAsDeprecated) {
				for (int i = 0, max = this.fields.length; i < max; i++) {
					FieldBinding field = this.fields[i];
					if (!field.isDeprecated()) {
						field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
					}
				}
				for (int i = 0, max = this.methods.length; i < max; i++) {
					MethodBinding method = this.methods[i];
					if (!method.isDeprecated()) {
						method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
					}
				}
			}
			if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
				if (iFields != null) {
					for (int i = 0; i < iFields.length; i++) {
						// below 1.8 we still might use an annotation walker to discover external annotations:
						ITypeAnnotationWalker fieldWalker = ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
						if (sourceLevel < ClassFileConstants.JDK1_8)
							fieldWalker = binaryType.enrichWithExternalAnnotationsFor(walker, iFields[i], this.environment);
						scanFieldForNullAnnotation(iFields[i], this.fields[i], this.isEnum(), fieldWalker);
					}
				}
				if (iMethods != null) {
					for (int i = 0; i < iMethods.length; i++) {
						// below 1.8 we still might use an annotation walker to discover external annotations:
						ITypeAnnotationWalker methodWalker = ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
						if (sourceLevel < ClassFileConstants.JDK1_8)
							methodWalker = binaryType.enrichWithExternalAnnotationsFor(methodWalker, iMethods[i], this.environment);
						scanMethodForNullAnnotation(iMethods[i], this.methods[i], methodWalker, canUseNullTypeAnnotations);
					}
				}
			}
		}
//{ObjectTeams: now this type is setup enough to evaluate attributes
		if (binaryType instanceof ClassFileReader) {
			ClassFileReader reader = (ClassFileReader)binaryType;
			reader.evaluateOtherOTAttributes(this, this.environment, missingTypeNames);
			// remember o.o.Team:
			if (needFieldsAndMethods && TypeAnalyzer.isOrgObjectteamsTeam(this))
				this.environment.getTeamMethodGenerator().maybeRegisterTeamClassBytes(reader, this);
			// store class file version
			this.version = reader.getVersion();
		}
// SH}
		if (this.environment.globalOptions.storeAnnotations) {
			setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames), false);
		} else if (sourceLevel >= ClassFileConstants.JDK9 && isDeprecated() && binaryType.getAnnotations() != null) {
			// prior to Java 9 all standard annotations were marker annotations, not needing to be stored,
			// but since Java 9 we need more information from the @Deprecated annotation:
			for (IBinaryAnnotation annotation : binaryType.getAnnotations()) {
				if (annotation.isDeprecatedAnnotation()) {
					AnnotationBinding[] annotationBindings = createAnnotations(new IBinaryAnnotation[] { annotation }, this.environment, missingTypeNames);
					setAnnotations(annotationBindings, true); // force storing
					for (ElementValuePair elementValuePair : annotationBindings[0].getElementValuePairs()) {
						if (CharOperation.equals(elementValuePair.name, TypeConstants.FOR_REMOVAL)) {
							if (elementValuePair.value instanceof BooleanConstant && ((BooleanConstant) elementValuePair.value).booleanValue()) {
								this.tagBits |= TagBits.AnnotationTerminallyDeprecated;
								markImplicitTerminalDeprecation(this);
							}
						}
					}
					break;
				}
			}
		}
		if (this.isAnnotationType())
			scanTypeForContainerAnnotation(binaryType, missingTypeNames);
	} finally {
		// protect against incorrect use of the needFieldsAndMethods flag, see 48459
		if (this.fields == null)
			this.fields = Binding.NO_FIELDS;
		if (this.methods == null)
			this.methods = Binding.NO_METHODS;
	}
}
void markImplicitTerminalDeprecation(ReferenceBinding type) {
	for (ReferenceBinding member : type.memberTypes()) {
		member.tagBits |= TagBits.AnnotationTerminallyDeprecated;
		markImplicitTerminalDeprecation(member);
	}
	MethodBinding[] methodsOfType = type.unResolvedMethods();
	if (methodsOfType != null)
		for (MethodBinding methodBinding : methodsOfType)
			methodBinding.tagBits |= TagBits.AnnotationTerminallyDeprecated;

	FieldBinding[] fieldsOfType = type.unResolvedFields();
	if (fieldsOfType != null)
		for (FieldBinding fieldBinding : fieldsOfType)
			fieldBinding.tagBits |= TagBits.AnnotationTerminallyDeprecated;
}

/* When creating a method we need to pass in any default 'nullness' from a @NNBD immediately on this method. */
private ITypeAnnotationWalker getTypeAnnotationWalker(IBinaryTypeAnnotation[] annotations, int nullness) {
	if (!isPrototype()) throw new IllegalStateException();
	if (annotations == null || annotations.length == 0 || !this.environment.usesAnnotatedTypeSystem()) {
		if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
			if (nullness == Binding.NO_NULL_DEFAULT)
				nullness = getNullDefault();
			if (nullness > Binding.NULL_UNSPECIFIED_BY_DEFAULT)
				return new NonNullDefaultAwareTypeAnnotationWalker(nullness, this.environment);
		}
		return ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
	}
	if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
		if (nullness == Binding.NO_NULL_DEFAULT)
			nullness = getNullDefault();
		if (nullness > Binding.NULL_UNSPECIFIED_BY_DEFAULT)
			return new NonNullDefaultAwareTypeAnnotationWalker(annotations, nullness, this.environment);
	}
	return new TypeAnnotationWalker(annotations);
}

private int getNullDefaultFrom(IBinaryAnnotation[] declAnnotations) {
	int result = 0;
	if (declAnnotations != null) {
		for (IBinaryAnnotation annotation : declAnnotations) {
			char[][] typeName = signature2qualifiedTypeName(annotation.getTypeName());
			if (this.environment.getNullAnnotationBit(typeName) == TypeIds.BitNonNullByDefaultAnnotation)
				result |= getNonNullByDefaultValue(annotation, this.environment);
		}
	}
	return result;
}

private void createFields(IBinaryField[] iFields, IBinaryType binaryType, long sourceLevel, char[][][] missingTypeNames) {
	if (!isPrototype()) throw new IllegalStateException();
	boolean save = this.environment.mayTolerateMissingType;
	this.environment.mayTolerateMissingType = true;
	try {
		this.fields = Binding.NO_FIELDS;
		if (iFields != null) {
			int size = iFields.length;
			if (size > 0) {
				FieldBinding[] fields1 = new FieldBinding[size];
				boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
				boolean hasRestrictedAccess = hasRestrictedAccess();
				int firstAnnotatedFieldIndex = -1;
				for (int i = 0; i < size; i++) {
					IBinaryField binaryField = iFields[i];
					char[] fieldSignature = use15specifics ? binaryField.getGenericSignature() : null;
					ITypeAnnotationWalker walker = getTypeAnnotationWalker(binaryField.getTypeAnnotations(), getNullDefaultFrom(binaryField.getAnnotations()));
					if (sourceLevel >= ClassFileConstants.JDK1_8) { // below 1.8, external annotations will be attached later
						walker = binaryType.enrichWithExternalAnnotationsFor(walker, iFields[i], this.environment);
					}
					walker = walker.toField();
					TypeBinding type = fieldSignature == null
						? this.environment.getTypeFromSignature(binaryField.getTypeName(), 0, -1, false, this, missingTypeNames, walker)
						: this.environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), Binding.NO_TYPE_VARIABLES, this, missingTypeNames, walker);
					FieldBinding field =
						new FieldBinding(
							binaryField.getName(),
							type,
							binaryField.getModifiers() | ExtraCompilerModifiers.AccUnresolved,
							this,
							binaryField.getConstant());
					boolean forceStoreAnnotations = !this.environment.globalOptions.storeAnnotations
							&& (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK9
							&& binaryField.getAnnotations() != null
							&& (binaryField.getTagBits() & TagBits.AnnotationDeprecated) != 0);
					if (firstAnnotatedFieldIndex < 0
//{ObjectTeams: read annotations within roles to enable copying:
/* orig:
						&& (this.environment.globalOptions.storeAnnotations || forceStoreAnnotations)
  :giro */
						&& (   this.environment.globalOptions.storeAnnotations
							|| forceStoreAnnotations
							|| this.isRole())
// SH}
							&& binaryField.getAnnotations() != null) {
						firstAnnotatedFieldIndex = i;
						if (forceStoreAnnotations)
							storedAnnotations(true, true); // for Java 9 @Deprecated we need to force storing annotations
					}
					field.id = i; // ordinal
					if (use15specifics)
						field.tagBits |= binaryField.getTagBits();
					if (hasRestrictedAccess)
						field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
					if (fieldSignature != null)
						field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
					fields1[i] = field;
//{ObjectTeams:
					// field attributes:
					if (binaryField instanceof FieldInfo)
						((FieldInfo)binaryField).evaluateOTAttributes(field);
					// field as value parameter?
					if ((field.modifiers & ExtraCompilerModifiers.AccValueParam) != 0)
						addValueParameter(field);
// SH}
				}
				this.fields = fields1;
				// second pass for reifying annotations, since may refer to fields being constructed (147875)
				if (firstAnnotatedFieldIndex >= 0) {
					for (int i = firstAnnotatedFieldIndex; i <size; i++) {
						IBinaryField binaryField = iFields[i];
						this.fields[i].setAnnotations(createAnnotations(binaryField.getAnnotations(), this.environment, missingTypeNames), false);
					}
				}
			}
		}
	} finally {
		this.environment.mayTolerateMissingType = save;
	}
}
//{ObjectTeams: some fields are indeed value parameters:
private SyntheticArgumentBinding[] valueParameters = NO_SYNTH_ARGUMENTS;
@Override
public SyntheticArgumentBinding[] valueParamSynthArgs() {
	return this.valueParameters;
}
private void addValueParameter(FieldBinding field) {
	SyntheticArgumentBinding synthArg = new SyntheticArgumentBinding(field.name, (ReferenceBinding)field.type);
	synthArg.matchingField = field;
	if (this.valueParameters == NO_SYNTH_ARGUMENTS)
		this.valueParameters = new SyntheticArgumentBinding[]{synthArg};
	else {
		int len = this.valueParameters.length;
		System.arraycopy(this.valueParameters, 0, this.valueParameters = new SyntheticArgumentBinding[len+1], 0, len);
		this.valueParameters[len] = synthArg;
	}
	// TODO(SH): for multiple value parameters the field would need to store a rank, and here we would need to collect an array of anchors..
	int [] ranks = FieldModel.getAnchorUsageRanks(field);
	if (ranks != null) {
		for (int i=0; i<ranks.length; i++) {
			TypeVariableBinding typeVariable = this.typeVariables[ranks[i]];
			typeVariable.anchors = new ITeamAnchor[] { field };
		}
	}
}
// SH}

private MethodBinding createMethod(IBinaryMethod method, IBinaryType binaryType, long sourceLevel, char[][][] missingTypeNames) {
//{ObjectTeams: be very careful (newly read attributes must be consumed):
  MethodBinding result = null;
  try {
// SH}
	if (!isPrototype()) throw new IllegalStateException();
	int methodModifiers = method.getModifiers() | ExtraCompilerModifiers.AccUnresolved;
	if (sourceLevel < ClassFileConstants.JDK1_5)
		methodModifiers &= ~ClassFileConstants.AccVarargs; // vararg methods are not recognized until 1.5
	if (isInterface() && (methodModifiers & ClassFileConstants.AccAbstract) == 0) {
		// see https://bugs.eclipse.org/388954 superseded by https://bugs.eclipse.org/390889
		if (((methodModifiers & ClassFileConstants.AccStatic) == 0
				&& (methodModifiers & ClassFileConstants.AccPrivate) == 0)) {
			// i.e. even at 1.7- we record AccDefaultMethod when reading a 1.8+ interface to avoid errors caused by default methods added to a library
			methodModifiers |= ExtraCompilerModifiers.AccDefaultMethod;
		}
	}
	ReferenceBinding[] exceptions = Binding.NO_EXCEPTIONS;
	TypeBinding[] parameters = Binding.NO_PARAMETERS;
	TypeVariableBinding[] typeVars = Binding.NO_TYPE_VARIABLES;
	AnnotationBinding[][] paramAnnotations = null;
	TypeBinding returnType = null;

	char[][] argumentNames = method.getArgumentNames();

	final boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
	/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, Since a 1.4 project can have a 1.5
	   type as a super type and the 1.5 type could be generic, we must internalize usages of type
	   variables properly in order to be able to apply substitutions and thus be able to detect
	   overriding in the presence of generics. Seeing the erased form is not good enough.
	 */
	ITypeAnnotationWalker walker = getTypeAnnotationWalker(method.getTypeAnnotations(), getNullDefaultFrom(method.getAnnotations()));
	char[] methodSignature = method.getGenericSignature(); // always use generic signature, even in 1.4
	if (methodSignature == null) { // no generics
		char[] methodDescriptor = method.getMethodDescriptor();   // of the form (I[Ljava/jang/String;)V
		if (sourceLevel >= ClassFileConstants.JDK1_8) { // below 1.8, external annotations will be attached later
			walker = binaryType.enrichWithExternalAnnotationsFor(walker, method, this.environment);
		}
		int numOfParams = 0;
		char nextChar;
		int index = 0; // first character is always '(' so skip it
		while ((nextChar = methodDescriptor[++index]) != Util.C_PARAM_END) {
			if (nextChar != Util.C_ARRAY) {
				numOfParams++;
				if (nextChar == Util.C_RESOLVED)
					while ((nextChar = methodDescriptor[++index]) != Util.C_NAME_END){/*empty*/}
			}
		}

		// Ignore synthetic argument for member types or enum types.
		int startIndex = 0;
		if (method.isConstructor()) {
//{ObjectTeams: we also load local classes
			if ((isMemberType() || isLocalType()) && !isStatic()) {
/* orig
			if (isMemberType() && !isStatic()) {
   */
				// enclosing type
				startIndex++;
			}
// :giro
			// also skip synth args for value parameters
			startIndex += this.valueParameters.length;
// SH}
			if (isEnum()) {
				// synthetic arguments (String, int)
				startIndex += 2;
			}
		}
//{ObjectTeams: similarly for static role methods:
		if (MethodBinding.needsSyntheticEnclosingTeamInstance(methodModifiers, this, method.getSelector()))
			startIndex += 2; // dummy this plus enclosing team instance
// SH}
		int size = numOfParams - startIndex;
		if (size > 0) {
			parameters = new TypeBinding[size];
			if (this.environment.globalOptions.storeAnnotations)
				paramAnnotations = new AnnotationBinding[size][];
			index = 1;
			short visibleIdx = 0;
			int end = 0;   // first character is always '(' so skip it
			for (int i = 0; i < numOfParams; i++) {
				while ((nextChar = methodDescriptor[++end]) == Util.C_ARRAY){/*empty*/}
				if (nextChar == Util.C_RESOLVED)
					while ((nextChar = methodDescriptor[++end]) != Util.C_NAME_END){/*empty*/}

				if (i >= startIndex) {   // skip the synthetic arg if necessary
					// checking for param specific non-null default is not necessary here as no type arguments are present (application to params themselves is handled by ImplicitNullAnnotationVerifier)
					parameters[i - startIndex] = this.environment.getTypeFromSignature(methodDescriptor, index, end, false, this, missingTypeNames, walker.toMethodParameter(visibleIdx++));
					// 'paramAnnotations' line up with 'parameters'
					// int parameter to method.getParameterAnnotations() include the synthetic arg
					if (paramAnnotations != null)
						paramAnnotations[i - startIndex] = createAnnotations(method.getParameterAnnotations(i - startIndex, this.fileName), this.environment, missingTypeNames);
				}
				index = end + 1;
			}
		}

		char[][] exceptionTypes = method.getExceptionTypeNames();
		if (exceptionTypes != null) {
			size = exceptionTypes.length;
			if (size > 0) {
				exceptions = new ReferenceBinding[size];
				for (int i = 0; i < size; i++)
					exceptions[i] = this.environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false, missingTypeNames, walker.toThrows(i));
			}
		}

		if (!method.isConstructor())
			returnType = this.environment.getTypeFromSignature(methodDescriptor, index + 1, -1, false, this, missingTypeNames, walker.toMethodReturn());   // index is currently pointing at the ')'
		
		final int argumentNamesLength = argumentNames == null ? 0 : argumentNames.length;
		if (startIndex > 0 && argumentNamesLength > 0) {
			// We'll have to slice the starting arguments off
			if (startIndex >= argumentNamesLength) {
				argumentNames = Binding.NO_PARAMETER_NAMES; // We know nothing about the argument names
			} else {
				char[][] slicedArgumentNames = new char[argumentNamesLength - startIndex][];
				System.arraycopy(argumentNames, startIndex, slicedArgumentNames, 0, argumentNamesLength - startIndex);
				argumentNames = slicedArgumentNames;
			}
		}

	} else {
		if (sourceLevel >= ClassFileConstants.JDK1_8) { // below 1.8, external annotations will be attached later
			walker = binaryType.enrichWithExternalAnnotationsFor(walker, method, this.environment);
		}
		methodModifiers |= ExtraCompilerModifiers.AccGenericSignature;
		// MethodTypeSignature = ParameterPart(optional) '(' TypeSignatures ')' return_typeSignature ['^' TypeSignature (optional)]
		SignatureWrapper wrapper = new SignatureWrapper(methodSignature, use15specifics);
		if (wrapper.signature[wrapper.start] == Util.C_GENERIC_START) {
			// <A::Ljava/lang/annotation/Annotation;>(Ljava/lang/Class<TA;>;)TA;
			// ParameterPart = '<' ParameterSignature(s) '>'
			wrapper.start++; // skip '<'
			typeVars = createTypeVariables(wrapper, false, missingTypeNames, walker, false/*class*/);
			wrapper.start++; // skip '>'
		}

		if (wrapper.signature[wrapper.start] == Util.C_PARAM_START) {
			wrapper.start++; // skip '('
			if (wrapper.signature[wrapper.start] == Util.C_PARAM_END) {
				wrapper.start++; // skip ')'
			} else {
				java.util.ArrayList types = new java.util.ArrayList(2);
				short rank = 0;
				while (wrapper.signature[wrapper.start] != Util.C_PARAM_END) {
					IBinaryAnnotation[] binaryParameterAnnotations = method.getParameterAnnotations(rank, this.fileName);
					ITypeAnnotationWalker updatedWalker = NonNullDefaultAwareTypeAnnotationWalker.updateWalkerForParamNonNullDefault(walker, getNullDefaultFrom(binaryParameterAnnotations), this.environment);
					types.add(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames, updatedWalker.toMethodParameter(rank)));
					rank++;
				}
				wrapper.start++; // skip ')'
				int numParam = types.size();
				parameters = new TypeBinding[numParam];
				types.toArray(parameters);
				if (this.environment.globalOptions.storeAnnotations) {
					paramAnnotations = new AnnotationBinding[numParam][];
					for (int i = 0; i < numParam; i++)
						paramAnnotations[i] = createAnnotations(method.getParameterAnnotations(i,  this.fileName), this.environment, missingTypeNames);
				}
			}
		}

		// always retrieve return type (for constructors, its V for void - will be ignored)
		returnType = this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames, walker.toMethodReturn());

		if (!wrapper.atEnd() && wrapper.signature[wrapper.start] == Util.C_EXCEPTION_START) {
			// attempt to find each exception if it exists in the cache (otherwise - resolve it when requested)
			java.util.ArrayList types = new java.util.ArrayList(2);
			int excRank = 0;
			do {
				wrapper.start++; // skip '^'
				types.add(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames,
					walker.toThrows(excRank++)));
			} while (!wrapper.atEnd() && wrapper.signature[wrapper.start] == Util.C_EXCEPTION_START);
			exceptions = new ReferenceBinding[types.size()];
			types.toArray(exceptions);
		} else { // get the exceptions the old way
			char[][] exceptionTypes = method.getExceptionTypeNames();
			if (exceptionTypes != null) {
				int size = exceptionTypes.length;
				if (size > 0) {
					exceptions = new ReferenceBinding[size];
					for (int i = 0; i < size; i++)
						exceptions[i] = this.environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1, false, missingTypeNames, walker.toThrows(i));
				}
			}
		}
	}

//{ObjectTeams: recover synthetics:
  if (SyntheticRoleFieldAccess.isRoleFieldAccess(method.getModifiers(), method.getSelector()))
  {
	  result = new SyntheticRoleFieldAccess(this, method.getModifiers(), method.getSelector(), parameters, returnType);
  } else
// ~orig~:
	result = method.isConstructor()
// :~giro~
// SH}
		? new MethodBinding(methodModifiers, parameters, exceptions, this)
		: new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this);
	
	IBinaryAnnotation[] receiverAnnotations = walker.toReceiver().getAnnotationsAtCursor(this.id, false);
	if (receiverAnnotations != null && receiverAnnotations.length > 0) {
		result.receiver = this.environment.createAnnotatedType(this, createAnnotations(receiverAnnotations, this.environment, missingTypeNames));
	}

	boolean forceStoreAnnotations = !this.environment.globalOptions.storeAnnotations
										&& (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK9
										&& method instanceof MethodInfoWithAnnotations
										&& (method.getTagBits() & TagBits.AnnotationDeprecated) != 0);
	if (this.environment.globalOptions.storeAnnotations || forceStoreAnnotations) {
		if (forceStoreAnnotations)
			storedAnnotations(true, true); // for Java 9 @Deprecated we need to force storing annotations
		IBinaryAnnotation[] annotations = method.getAnnotations();
		if (method.isConstructor()) {
			IBinaryAnnotation[] tAnnotations = walker.toMethodReturn().getAnnotationsAtCursor(this.id, false);
			result.setTypeAnnotations(createAnnotations(tAnnotations, this.environment, missingTypeNames));
		}
		result.setAnnotations(
				createAnnotations(annotations, this.environment, missingTypeNames),
				paramAnnotations,
				isAnnotationType() ? convertMemberValue(method.getDefaultValue(), this.environment, missingTypeNames, true) : null,
						this.environment);
	}

	if (argumentNames != null) result.parameterNames = argumentNames;
	
	if (use15specifics)
		result.tagBits |= method.getTagBits();
	result.typeVariables = typeVars;
	// fixup the declaring element of all type variables
	for (int i = 0, length = typeVars.length; i < length; i++)
		this.environment.typeSystem.fixTypeVariableDeclaringElement(typeVars[i], result);
//{ObjectTeams:
	// transfer "callsBaseCtor":
	if (method instanceof MethodInfo && ((MethodInfo)method).callsBaseCtor()) {
		MethodModel.setCallsBaseCtor(result);
	}
	// handle various OT-specific methods:
	char[] selector = method.getSelector();
	if (CharOperation.prefixEquals(IOTConstants.OT_DOLLAR_NAME, selector)) {
		// connect creation method to original constructor:
		if (CopyInheritance.isCreator(result)) {
			// extract the role name:
			char[] roleName = ((ReferenceBinding) result.returnType).sourceName;
			int dollarPos = CharOperation.lastIndexOf('$', roleName);
			if (dollarPos > -1) // for unresolved bindings
				roleName = CharOperation.subarray(roleName, dollarPos+1, -1);
			// get the role class:
			ReferenceBinding site = this;
			if (isSynthInterface())
				site = site.roleModel.getClassPartBinding();
			ReferenceBinding roleClass = site.getMemberType(CharOperation.concat(IOTConstants.OT_DELIM_NAME, roleName));
			if (roleClass instanceof UnresolvedReferenceBinding)
				roleClass = ((UnresolvedReferenceBinding)roleClass).resolve(this.environment, false);
			// get and store the original ctor:
			MethodBinding srcCtor = roleClass.getExactConstructor(result.parameters);
			if (srcCtor != null)
				MethodModel.getModel(result)._srcCtor = srcCtor;
		}
		// is it some other OT-generated method requiring to be marked as fake?
		int secondDollar = CharOperation.indexOf('$', selector, 4, selector.length);
		if (   secondDollar != -1
			&& CharOperation.prefixEquals(SyntheticRoleBridgeMethodBinding.PRIVATE, CharOperation.subarray(selector, secondDollar, -1)))
		{
			MethodModel.getModel(result)._fakeKind = FakeKind.ROLE_FEATURE_BRIDGE;
		}
	}
	// register byte code, evaluate attributes:
  } finally {
	if (result != null) {
		if (method instanceof MethodInfo) {
			if (TypeAnalyzer.isOrgObjectteamsTeam(this))
				this.environment.getTeamMethodGenerator().registerTeamMethod(method, result);
			// Note, that maybeRegister() may reset the MethodInfo (nulling MethodInfo.reference):
			((MethodInfo)method).maybeRegister(this, result, this.environment);
		}
	}
  }
// SH}

	return result;
}

/**
 * Create method bindings for binary type, filtering out <clinit> and synthetics
 * As some iMethods may be ignored in this process we return the matching array of those
 * iMethods for which MethodBindings have been created; indices match those in this.methods.
 */
private IBinaryMethod[] createMethods(IBinaryMethod[] iMethods, IBinaryType binaryType, long sourceLevel, char[][][] missingTypeNames) {
	if (!isPrototype()) throw new IllegalStateException();
	boolean save = this.environment.mayTolerateMissingType;
	this.environment.mayTolerateMissingType = true;
	try {
		int total = 0, initialTotal = 0, iClinit = -1;
		int[] toSkip = null;
		if (iMethods != null) {
			total = initialTotal = iMethods.length;
			boolean keepBridgeMethods = sourceLevel < ClassFileConstants.JDK1_5; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=330347
			for (int i = total; --i >= 0;) {
				IBinaryMethod method = iMethods[i];
				if ((method.getModifiers() & ClassFileConstants.AccSynthetic) != 0) {
//{ObjectTeams: teams and roles don't discard synthetic for the sake of copy inheritance
            	    if (isTeam() || isRole())
                		continue;
// SH}
					if (keepBridgeMethods && (method.getModifiers() & ClassFileConstants.AccBridge) != 0)
						continue; // want to see bridge methods as real methods
					// discard synthetics methods
					if (toSkip == null) toSkip = new int[iMethods.length];
					toSkip[i] = -1;
					total--;
				} else if (iClinit == -1) {
					char[] methodName = method.getSelector();
					if (methodName.length == 8 && methodName[0] == Util.C_GENERIC_START) {
						// discard <clinit>
						iClinit = i;
						total--;
					}
				}
			}
		}
		if (total == 0) {
			this.methods = Binding.NO_METHODS;
			return NO_BINARY_METHODS;
		}

		boolean hasRestrictedAccess = hasRestrictedAccess();
		MethodBinding[] methods1 = new MethodBinding[total];
		if (total == initialTotal) {
			for (int i = 0; i < initialTotal; i++) {
				MethodBinding method = createMethod(iMethods[i], binaryType, sourceLevel, missingTypeNames);
				if (hasRestrictedAccess)
					method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
				methods1[i] = method;
			}
			this.methods = methods1;
			return iMethods;
		} else {
			IBinaryMethod[] mappedBinaryMethods = new IBinaryMethod[total];
			for (int i = 0, index = 0; i < initialTotal; i++) {
				if (iClinit != i && (toSkip == null || toSkip[i] != -1)) {
					MethodBinding method = createMethod(iMethods[i], binaryType, sourceLevel, missingTypeNames);
					if (hasRestrictedAccess)
						method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
					mappedBinaryMethods[index] = iMethods[i];
					methods1[index++] = method;
				}
			}
			this.methods = methods1;
			return mappedBinaryMethods;
		}
	} finally {
		this.environment.mayTolerateMissingType = save;
	}
}
//{ObjectTeams: create bindings for OTRE-generated methods:
public void createOTREMethods(RoleModel role) {
	// clone methods array because getBaseCallSurrogate may add to the original array:
	MethodBinding [] realMethods = new MethodBinding[this.methods.length];
	System.arraycopy(this.methods, 0, realMethods, 0, this.methods.length);
	for (int i = 0; i < realMethods.length; i++) {
		MethodBinding method = realMethods[i];
		if (method.isCallin()  && !isInterface()) {
			resolveTypesFor(method);
			// link callin method and its base-call surrogate:
			MethodBinding surrogate = SyntheticBaseCallSurrogate.getBaseCallSurrogate(method, role, this.environment);
			if (surrogate != null)
				MethodModel.getModel(method).setBaseCallSurrogate(surrogate);
		}
	}
}
// SH}

private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, boolean assignVariables, char[][][] missingTypeNames,
													ITypeAnnotationWalker walker, boolean isClassTypeParameter)
{
	if (!isPrototype()) throw new IllegalStateException();
	// detect all type variables first
	char[] typeSignature = wrapper.signature;
	int depth = 0, length = typeSignature.length;
	int rank = 0;
	ArrayList variables = new ArrayList(1);
	depth = 0;
	boolean pendingVariable = true;
	createVariables: {
		for (int i = 1; i < length; i++) {
			switch(typeSignature[i]) {
				case Util.C_GENERIC_START :
					depth++;
					break;
				case Util.C_GENERIC_END :
					if (--depth < 0)
						break createVariables;
					break;
				case Util.C_NAME_END :
					if ((depth == 0) && (i +1 < length) && (typeSignature[i+1] != Util.C_COLON))
						pendingVariable = true;
					break;
				default:
					if (pendingVariable) {
						pendingVariable = false;
						int colon = CharOperation.indexOf(Util.C_COLON, typeSignature, i);
						char[] variableName = CharOperation.subarray(typeSignature, i, colon);
						TypeVariableBinding typeVariable = new TypeVariableBinding(variableName, this, rank, this.environment);
						AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.toTypeParameter(isClassTypeParameter, rank++).getAnnotationsAtCursor(0, false), 
																										this.environment, missingTypeNames);
						if (annotations != null && annotations != Binding.NO_ANNOTATIONS)
							typeVariable.setTypeAnnotations(annotations, this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
						variables.add(typeVariable);
					}
			}
		}
	}
	// initialize type variable bounds - may refer to forward variables
	TypeVariableBinding[] result;
	variables.toArray(result = new TypeVariableBinding[rank]);
	// when creating the type variables for a type, the type must remember them before initializing each variable
	// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=163680
	if (assignVariables)
		this.typeVariables = result;
	for (int i = 0; i < rank; i++) {
		initializeTypeVariable(result[i], result, wrapper, missingTypeNames, walker.toTypeParameterBounds(isClassTypeParameter, i));
		if (this.externalAnnotationStatus.isPotentiallyUnannotatedLib() && result[i].hasNullTypeAnnotations())
			this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
	}
	return result;
}

/* Answer the receiver's enclosing type... null if the receiver is a top level type.
*
* NOTE: enclosingType of a binary type is resolved when needed
*/
@Override
public ReferenceBinding enclosingType() {  // should not delegate to prototype.
	if ((this.tagBits & TagBits.HasUnresolvedEnclosingType) == 0)
		return this.enclosingType;

	// finish resolving the type
	this.enclosingType = (ReferenceBinding) resolveType(this.enclosingType, this.environment, false /* no raw conversion */);
	this.tagBits &= ~TagBits.HasUnresolvedEnclosingType;
	return this.enclosingType;
}
// NOTE: the type of each field of a binary type is resolved when needed
@Override
public FieldBinding[] fields() {
	
	if (!isPrototype()) {
		return this.fields = this.prototype.fields();
	}

	if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
		return this.fields;

	// lazily sort fields
	if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
		int length = this.fields.length;
		if (length > 1)
			ReferenceBinding.sortFields(this.fields, 0, length);
		this.tagBits |= TagBits.AreFieldsSorted;
	}
	for (int i = this.fields.length; --i >= 0;)
		resolveTypeFor(this.fields[i]);
	this.tagBits |= TagBits.AreFieldsComplete;
	return this.fields;
}

private MethodBinding findMethod(char[] methodDescriptor, char[][][] missingTypeNames) {
	if (!isPrototype()) throw new IllegalStateException();
	int index = -1;
	while (methodDescriptor[++index] != Util.C_PARAM_START) {
		// empty
	}
	char[] selector = new char[index];
	System.arraycopy(methodDescriptor, 0, selector, 0, index);
	TypeBinding[] parameters = Binding.NO_PARAMETERS;
	int numOfParams = 0;
	char nextChar;
	int paramStart = index;
	while ((nextChar = methodDescriptor[++index]) != Util.C_PARAM_END) {
		if (nextChar != Util.C_ARRAY) {
			numOfParams++;
			if (nextChar == Util.C_RESOLVED)
				while ((nextChar = methodDescriptor[++index]) != Util.C_NAME_END){/*empty*/}
		}
	}
	if (numOfParams > 0) {
		parameters = new TypeBinding[numOfParams];
		index = paramStart + 1;
		int end = paramStart; // first character is always '(' so skip it
		for (int i = 0; i < numOfParams; i++) {
			while ((nextChar = methodDescriptor[++end]) == Util.C_ARRAY){/*empty*/}
			if (nextChar == Util.C_RESOLVED)
				while ((nextChar = methodDescriptor[++end]) != Util.C_NAME_END){/*empty*/}

			// not interested in type annotations, type will be used for comparison only, and erasure() is used if needed
			TypeBinding param = this.environment.getTypeFromSignature(methodDescriptor, index, end, false, this, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
			if (param instanceof UnresolvedReferenceBinding) {
				param = resolveType(param, this.environment, true /* raw conversion */);
			}
			parameters[i] = param;
			index = end + 1;
		}
	}

	int parameterLength = parameters.length;
	MethodBinding[] methods2 = this.enclosingType.getMethods(selector, parameterLength);
	// find matching method using parameters
	loop: for (int i = 0, max = methods2.length; i < max; i++) {
		MethodBinding currentMethod = methods2[i];
		TypeBinding[] parameters2 = currentMethod.parameters;
		int currentMethodParameterLength = parameters2.length;
		if (parameterLength == currentMethodParameterLength) {
			for (int j = 0; j < currentMethodParameterLength; j++) {
//{ObjectTeams: weaker form of equality:
/* orig:
				if (TypeBinding.notEquals(parameters[j], parameters2[j]) && TypeBinding.notEquals(parameters[j].erasure(), parameters2[j].erasure())) {
  :giro */
				if (   !AnchorMapping.areTypesEqual(parameters[j], parameters2[j], currentMethod) 
					&& !AnchorMapping.areTypesEqual(parameters[j].erasure(), parameters2[j].erasure(), currentMethod)) {
// SH}
					continue loop;
				}
			}
			return currentMethod;
		}
	}
	return null;
}

/**
 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#genericTypeSignature()
 */
@Override
public char[] genericTypeSignature() {
	if (!isPrototype())
		return this.prototype.computeGenericTypeSignature(this.typeVariables);
	return computeGenericTypeSignature(this.typeVariables);
}

//NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
@Override
public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {

	if (!isPrototype())
		return this.prototype.getExactConstructor(argumentTypes);

	// lazily sort methods
	if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
		int length = this.methods.length;
		if (length > 1)
			ReferenceBinding.sortMethods(this.methods, 0, length);
		this.tagBits |= TagBits.AreMethodsSorted;
	}
	int argCount = argumentTypes.length;
	long range;
	if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) {
		nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
			MethodBinding method = this.methods[imethod];
			if (method.parameters.length == argCount) {
				resolveTypesFor(method);
				TypeBinding[] toMatch = method.parameters;
				for (int iarg = 0; iarg < argCount; iarg++)
//{ObjectTeams: weaker form of equality:
/* orig:
					if (TypeBinding.notEquals(toMatch[iarg], argumentTypes[iarg]))
  :giro */
					if (!AnchorMapping.areTypesEqual(toMatch[iarg], argumentTypes[iarg], method))
// SH}
						continue nextMethod;
				return method;
			}
		}
	}
	return null;
}

//NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
//searches up the hierarchy as long as no potential (but not exact) match was found.
@Override
public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
	// sender from refScope calls recordTypeReference(this)

	if (!isPrototype())
		return this.prototype.getExactMethod(selector, argumentTypes, refScope);

	// lazily sort methods
	if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
		int length = this.methods.length;
		if (length > 1)
			ReferenceBinding.sortMethods(this.methods, 0, length);
		this.tagBits |= TagBits.AreMethodsSorted;
	}

	int argCount = argumentTypes.length;
	boolean foundNothing = true;

	long range;
	if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
		nextMethod: for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
			MethodBinding method = this.methods[imethod];
			foundNothing = false; // inner type lookups must know that a method with this name exists
			if (method.parameters.length == argCount) {
				resolveTypesFor(method);
				TypeBinding[] toMatch = method.parameters;
				for (int iarg = 0; iarg < argCount; iarg++)
//{ObjectTeams: weaker form of equality:
/* orig:
					if (TypeBinding.notEquals(toMatch[iarg], argumentTypes[iarg]))
  :giro */
					if (!AnchorMapping.areTypesEqual(toMatch[iarg], argumentTypes[iarg], method))
// SH}
						continue nextMethod;
				return method;
			}
		}
	}
	if (foundNothing) {
		if (isInterface()) {
//{ObjectTeams: Eclipse BUG?? search in all superinterfaces
/* orig:
			 if (superInterfaces().length == 1) { // ensure superinterfaces are resolved before checking
				if (refScope != null)
					refScope.recordTypeReference(this.superInterfaces[0]);
				return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
			 }
  :giro */
			 if(superInterfaces().length > 0)
			 {
			 	for (int idx = 0; idx < this.superInterfaces.length; idx++) {
					if (refScope != null)
						refScope.recordTypeReference(this.superInterfaces[idx]);
					MethodBinding methodBinding = this.superInterfaces[idx].getExactMethod(selector, argumentTypes, refScope);
					if(methodBinding != null)
						return methodBinding;
				}
			 }
//MW}
		} else if (superclass() != null) { // ensure superclass is resolved before checking
			if (refScope != null)
				refScope.recordTypeReference(this.superclass);
			return this.superclass.getExactMethod(selector, argumentTypes, refScope);
		}
	}
	return null;
}
//NOTE: the type of a field of a binary type is resolved when needed
@Override
public FieldBinding getField(char[] fieldName, boolean needResolve) {
	
	if (!isPrototype())
		return this.prototype.getField(fieldName, needResolve);

	// lazily sort fields
	if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
		int length = this.fields.length;
		if (length > 1)
			ReferenceBinding.sortFields(this.fields, 0, length);
		this.tagBits |= TagBits.AreFieldsSorted;
	}
	FieldBinding field = ReferenceBinding.binarySearch(fieldName, this.fields);
	return needResolve && field != null ? resolveTypeFor(field) : field;
}
/**
 *  Rewrite of default memberTypes() to avoid resolving eagerly all member types when one is requested
 */
@Override
public ReferenceBinding getMemberType(char[] typeName) {

	if (!isPrototype()) {
		ReferenceBinding memberType = this.prototype.getMemberType(typeName);
		return memberType == null ? null : this.environment.createMemberType(memberType, this);
	}

	ReferenceBinding[] members = maybeSortedMemberTypes();
	// do not try to binary search while we are still resolving and the array is not necessarily sorted
//{ObjectTeams: always use old linear lookup:
/* orig:
	if (!this.memberTypesSorted) {
  :giro */
		for (int i = members.length; --i >= 0;) {
		    ReferenceBinding memberType = members[i];
		    if (memberType instanceof UnresolvedReferenceBinding) {
				char[] name = memberType.sourceName; // source name is qualified with enclosing type name
				int prefixLength = this.compoundName[this.compoundName.length - 1].length + 1; // enclosing$
				if (name.length == (prefixLength + typeName.length)) // enclosing $ typeName
					if (CharOperation.fragmentEquals(typeName, name, prefixLength, true)) // only check trailing portion
						return members[i] = (ReferenceBinding) resolveType(memberType, this.environment, false /* no raw conversion for now */);
		    } else if (CharOperation.equals(typeName, memberType.sourceName)) {
		        return memberType;
		    }
		}
/* orig:
		return null;
	}
	int memberTypeIndex = ReferenceBinding.binarySearch(typeName, members);
	if (memberTypeIndex >= 0) {
		return members[memberTypeIndex];
	}
 SH} */

//{ObjectTeams: ROFI: intermediate patch!
	// FIXME(SH): check this whole discussion:
	// wait a minute: without a return this patch was effectless any way!
	// only real effect: refering to binaryEnclosingTeam the parser can
	// throw InternalCompilerError("Requesting role file {0} of team {1} which is already compiled");
	if (isTeam()) {// and therefor have a team package
	    // we might be called without setting up Dependencies, i.e. when resolving the DOM AST
	    // TODO (carp): what else can we do instead of giving up? See TPX171
	    if (!Dependencies.isSetup())
	        return null;

	    // need to set Parser.currentTeam, for enclosingType to be set!
	    TypeDeclaration previousTeam = null;
		Parser parser = Config.getParser();
		if (parser != null) {
			previousTeam = parser.currentTeam;
			binaryEnclosingTeam.name = internalName();
			parser.currentTeam = binaryEnclosingTeam; // a dummy AST!!
		}
		try {
			if (this.teamPackage != null)
				return this.teamPackage.getRoleType(typeName);
		} finally {
			if (parser != null)
				parser.currentTeam = previousTeam;
		}
	}
// SH}
	return null;
}
//{ObjectTeams: ROFI intermediate solution:
// FIXME(SH): location in file and documentation why/whether needed!
public static final TypeDeclaration binaryEnclosingTeam = new TypeDeclaration(null);
// SH}

// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
@Override
public MethodBinding[] getMethods(char[] selector) {
	
	if (!isPrototype())
		return this.prototype.getMethods(selector);

	if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
		long range;
		if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
			int start = (int) range, end = (int) (range >> 32);
			int length = end - start + 1;
			if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
				// simply clone method subset
				MethodBinding[] result;
				System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
				return result;
			}
		}
		return Binding.NO_METHODS;
	}
	// lazily sort methods
	if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
		int length = this.methods.length;
		if (length > 1)
			ReferenceBinding.sortMethods(this.methods, 0, length);
		this.tagBits |= TagBits.AreMethodsSorted;
	}
	long range;
	if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
		int start = (int) range, end = (int) (range >> 32);
		int length = end - start + 1;
		MethodBinding[] result = new MethodBinding[length];
		// iterate methods to resolve them
		for (int i = start, index = 0; i <= end; i++, index++)
			result[index] = resolveTypesFor(this.methods[i]);
		return result;
	}
	return Binding.NO_METHODS;
}
// Answer methods named selector, which take no more than the suggestedParameterLength.
// The suggested parameter length is optional and may not be guaranteed by every type.
@Override
public MethodBinding[] getMethods(char[] selector, int suggestedParameterLength) {
	
	if (!isPrototype())
		return this.prototype.getMethods(selector, suggestedParameterLength);

	if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
		return getMethods(selector);
	// lazily sort methods
	if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
		int length = this.methods.length;
		if (length > 1)
			ReferenceBinding.sortMethods(this.methods, 0, length);
		this.tagBits |= TagBits.AreMethodsSorted;
	}
	long range;
	if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
		int start = (int) range, end = (int) (range >> 32);
		int length = end - start + 1;
		int count = 0;
		for (int i = start; i <= end; i++) {
			if (this.methods[i].doesParameterLengthMatch(suggestedParameterLength))
				count++;
		}
		if (count == 0) {
			MethodBinding[] result = new MethodBinding[length];
			// iterate methods to resolve them
			for (int i = start, index = 0; i <= end; i++)
				result[index++] = resolveTypesFor(this.methods[i]);
			return result;
		} else {
			MethodBinding[] result = new MethodBinding[count];
			// iterate methods to resolve them
			for (int i = start, index = 0; i <= end; i++) {
				if (this.methods[i].doesParameterLengthMatch(suggestedParameterLength))
					result[index++] = resolveTypesFor(this.methods[i]);
			}
			return result;
		}
	}
	return Binding.NO_METHODS;
}

@Override
public boolean hasMemberTypes() {
	if (!isPrototype())
		return this.prototype.hasMemberTypes();
    return this.memberTypes.length > 0;
}
// NOTE: member types of binary types are resolved when needed
@Override
public TypeVariableBinding getTypeVariable(char[] variableName) {
	if (!isPrototype())
		return this.prototype.getTypeVariable(variableName);

	TypeVariableBinding variable = super.getTypeVariable(variableName);
	variable.resolve();
	return variable;
}
@Override
public boolean hasTypeBit(int bit) {
	
	if (!isPrototype())
		return this.prototype.hasTypeBit(bit);
	
	// ensure hierarchy is resolved, which will propagate bits down to us
	boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType;
	this.environment.mayTolerateMissingType = true;
	try {
		superclass();
		superInterfaces();
	} finally {
		this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
	}
	return (this.typeBits & bit) != 0;
}
private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames, ITypeAnnotationWalker walker) {
	if (!isPrototype()) throw new IllegalStateException();
	// ParameterSignature = Identifier ':' TypeSignature
	//   or Identifier ':' TypeSignature(optional) InterfaceBound(s)
	// InterfaceBound = ':' TypeSignature
	int colon = CharOperation.indexOf(Util.C_COLON, wrapper.signature, wrapper.start);
	wrapper.start = colon + 1; // skip name + ':'
	ReferenceBinding type, firstBound = null;
	short rank = 0;
	if (wrapper.signature[wrapper.start] == Util.C_COLON) {
		type = this.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null);
		rank++;
	} else {
		TypeBinding typeFromTypeSignature = this.environment.getTypeFromTypeSignature(wrapper, existingVariables, this, missingTypeNames, walker.toTypeBound(rank++));
		if (typeFromTypeSignature instanceof ReferenceBinding) {
			type = (ReferenceBinding) typeFromTypeSignature;
		} else {
			// this should only happen if the signature is corrupted (332423)
			type = this.environment.getResolvedJavaBaseType(TypeConstants.JAVA_LANG_OBJECT, null);
		}
		firstBound = type;
	}

	// variable is visible to its bounds
	variable.modifiers |= ExtraCompilerModifiers.AccUnresolved;
	variable.setSuperClass(type);

	ReferenceBinding[] bounds = null;
	if (wrapper.signature[wrapper.start] == Util.C_COLON) {
		java.util.ArrayList types = new java.util.ArrayList(2);
		do {
			wrapper.start++; // skip ':'
			types.add(this.environment.getTypeFromTypeSignature(wrapper, existingVariables, this, missingTypeNames, walker.toTypeBound(rank++)));
		} while (wrapper.signature[wrapper.start] == Util.C_COLON);
		bounds = new ReferenceBinding[types.size()];
		types.toArray(bounds);
	}

	variable.setSuperInterfaces(bounds == null ? Binding.NO_SUPERINTERFACES : bounds);
	if (firstBound == null) {
		firstBound = variable.superInterfaces.length == 0 ? null : variable.superInterfaces[0];
	}
	variable.setFirstBound(firstBound);
}
/**
 * Returns true if a type is identical to another one,
 * or for generic types, true if compared to its raw type.
 */
@Override
public boolean isEquivalentTo(TypeBinding otherType) {
	
	if (TypeBinding.equalsEquals(this, otherType)) return true;
	if (otherType == null) return false;
	switch(otherType.kind()) {
		case Binding.WILDCARD_TYPE :
		case Binding.INTERSECTION_TYPE :
			return ((WildcardBinding) otherType).boundCheck(this);
		case Binding.PARAMETERIZED_TYPE:
		/* With the hybrid 1.4/1.5+ projects modes, while establishing type equivalence, we need to
	       be prepared for a type such as Map appearing in one of three forms: As (a) a ParameterizedTypeBinding 
	       e.g Map<String, String>, (b) as RawTypeBinding Map#RAW and finally (c) as a BinaryTypeBinding 
	       When the usage of a type lacks type parameters, whether we land up with the raw form or not depends
	       on whether the underlying type was "seen to be" a generic type in the particular build environment or
	       not. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=186565 && https://bugs.eclipse.org/bugs/show_bug.cgi?id=328827 
		*/ 
		case Binding.RAW_TYPE :
			return TypeBinding.equalsEquals(otherType.erasure(), this);
	}
	return false;
}
@Override
public boolean isGenericType() {
	
	if (!isPrototype())
		return this.prototype.isGenericType();
	
    return this.typeVariables != Binding.NO_TYPE_VARIABLES;
}
@Override
public boolean isHierarchyConnected() {
	
	if (!isPrototype())
		return this.prototype.isHierarchyConnected();
	
	return (this.tagBits & (TagBits.HasUnresolvedSuperclass | TagBits.HasUnresolvedSuperinterfaces)) == 0;
}
@Override
public boolean isRepeatableAnnotationType() {
	if (!isPrototype()) throw new IllegalStateException();
	return this.containerAnnotationType != null;
}
@Override
public int kind() {
	
	if (!isPrototype())
		return this.prototype.kind();
	
	if (this.typeVariables != Binding.NO_TYPE_VARIABLES)
		return Binding.GENERIC_TYPE;
	return Binding.TYPE;
}
// NOTE: member types of binary types are resolved when needed
@Override
public ReferenceBinding[] memberTypes() {
 	if (!isPrototype()) {
		if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0)
			return this.memberTypes;
		/*
		 * The members obtained from the prototype are already sorted
		 * thus we can safely assume that our local copy of the member types
		 * is sorted, too.
		 */
		ReferenceBinding [] members = this.prototype.memberTypes();
		int memberTypesLength = members == null ? 0 : members.length;
		if (memberTypesLength > 0) {
			this.memberTypes = new ReferenceBinding[memberTypesLength];
			for (int i = 0; i < memberTypesLength; i++)
				this.memberTypes[i] = this.environment.createMemberType(members[i], this);
		}
		this.tagBits &= ~TagBits.HasUnresolvedMemberTypes;
		this.memberTypesSorted = true;
		return this.memberTypes;
	}
	
	if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0) {
		return maybeSortedMemberTypes();
	}
	for (int i = this.memberTypes.length; --i >= 0;)
		this.memberTypes[i] = (ReferenceBinding) resolveType(this.memberTypes[i], this.environment, false /* no raw conversion for now */);
	this.tagBits &= ~TagBits.HasUnresolvedMemberTypes;
	return maybeSortedMemberTypes();
}

private ReferenceBinding[] maybeSortedMemberTypes() {
	// do not try to sort while we are still resolving
	if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) != 0) {
		return this.memberTypes;
	}
	if (!this.memberTypesSorted) {
		// lazily sort member types
		int length = this.memberTypes.length;
		if (length > 1)
			sortMemberTypes(this.memberTypes, 0, length);
		this.memberTypesSorted = true;
	}
	return this.memberTypes;
}

// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
@Override
public MethodBinding[] methods() {
	
	if (!isPrototype()) {
		return this.methods = this.prototype.methods();
	}
	
	if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
		return this.methods;

	// lazily sort methods
	if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
		int length = this.methods.length;
		if (length > 1)
			ReferenceBinding.sortMethods(this.methods, 0, length);
		this.tagBits |= TagBits.AreMethodsSorted;
	}
	for (int i = this.methods.length; --i >= 0;)
		resolveTypesFor(this.methods[i]);
	this.tagBits |= TagBits.AreMethodsComplete;
	return this.methods;
}
@Override
public void setHierarchyCheckDone() {
	this.tagBits |= TagBits.BeginHierarchyCheck | TagBits.EndHierarchyCheck;
}

@Override
public TypeBinding prototype() {
	return this.prototype;
}

private boolean isPrototype() {
	return this == this.prototype; //$IDENTITY-COMPARISON$
}

@Override
public ReferenceBinding containerAnnotationType() {
	if (!isPrototype()) throw new IllegalStateException();
	if (this.containerAnnotationType instanceof UnresolvedReferenceBinding) {
		this.containerAnnotationType = (ReferenceBinding) BinaryTypeBinding.resolveType(this.containerAnnotationType, this.environment, false);
	}
	return this.containerAnnotationType;
}

private FieldBinding resolveTypeFor(FieldBinding field) {
	
	if (!isPrototype())
		return this.prototype.resolveTypeFor(field);
	
	if ((field.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
		return field;

	TypeBinding resolvedType = resolveType(field.type, this.environment, true /* raw conversion */);
	field.type = resolvedType;
	if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
		field.tagBits |= TagBits.HasMissingType;
	}
//{ObjectTeams: does this field have a type anchor?
	char[] anchorName = null;
	if (field.model != null) {
		if (field.model.hasResolveAnchorStarted) {
			this.environment.problemReporter.cycleInFieldAnchor(field);
		} else {
			field.model.hasResolveAnchorStarted = true;
			anchorName = field.model.typeAnchor;
		}
	}
	if (anchorName != null)
		field.type = RoleTypeCreator.wrapTypeWithAnchorFromName(
										field.type, anchorName, this, this.environment);
	else
		// implicit anchor?
		field.type = RoleTypeCreator.maybeWrapUnqualifiedRoleType(
										field.type, this);
// SH}
	field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
	return field;
}
MethodBinding resolveTypesFor(MethodBinding method) {
	
	if (!isPrototype())
		return this.prototype.resolveTypesFor(method);
	
	if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
		return method;

	if (!method.isConstructor()) {
		TypeBinding resolvedType = resolveType(method.returnType, this.environment, true /* raw conversion */);
		method.returnType = resolvedType;
		if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
			method.tagBits |= TagBits.HasMissingType;
		}
	}
	for (int i = method.parameters.length; --i >= 0;) {
		TypeBinding resolvedType = resolveType(method.parameters[i], this.environment, true /* raw conversion */);
		method.parameters[i] = resolvedType;
		if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
			method.tagBits |= TagBits.HasMissingType;
		}
	}
	for (int i = method.thrownExceptions.length; --i >= 0;) {
		ReferenceBinding resolvedType = (ReferenceBinding) resolveType(method.thrownExceptions[i], this.environment, true /* raw conversion */);
		method.thrownExceptions[i] = resolvedType;
		if ((resolvedType.tagBits & TagBits.HasMissingType) != 0) {
			method.tagBits |= TagBits.HasMissingType;
		}
	}
	for (int i = method.typeVariables.length; --i >= 0;) {
		method.typeVariables[i].resolve();
	}
//{ObjectTeams: now that return type is resolved restore access modifiers for castto method
	// restore access flags for castTo-methods:
	// (see StandardElementGenerator.getCastMethod())
	if (   CharOperation.prefixEquals(IOTConstants.CAST_PREFIX, method.selector)
		&& !((ReferenceBinding)method.returnType).isPublic())
	{
		method.modifiers &= ~ExtraCompilerModifiers.AccVisibilityMASK;
		method.modifiers |= ClassFileConstants.AccProtected;
	}

	if (!method.isSynthetic())
		RoleTypeCreator.wrapTypesInMethodBindingSignature(method, this.environment);
// SH}
	method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
	return method;
}
//{ObjectTeams: accessible to classes in org.eclipse.objectteams...:
@Override
public
// SH}
AnnotationBinding[] retrieveAnnotations(Binding binding) {
	
	if (!isPrototype())
		return this.prototype.retrieveAnnotations(binding);
	
	return AnnotationBinding.addStandardAnnotations(super.retrieveAnnotations(binding), binding.getAnnotationTagBits(), this.environment);
}

@Override
public void setContainerAnnotationType(ReferenceBinding value) {
	if (!isPrototype()) throw new IllegalStateException();
	this.containerAnnotationType = value;
}

@Override
public void tagAsHavingDefectiveContainerType() {
	if (!isPrototype()) throw new IllegalStateException();
	if (this.containerAnnotationType != null && this.containerAnnotationType.isValidBinding())
		this.containerAnnotationType = new ProblemReferenceBinding(this.containerAnnotationType.compoundName, this.containerAnnotationType, ProblemReasons.DefectiveContainerAnnotationType);
}

@Override
SimpleLookupTable storedAnnotations(boolean forceInitialize, boolean forceStore) {
	
	if (!isPrototype())
		return this.prototype.storedAnnotations(forceInitialize, forceStore);
	
	if (forceInitialize && this.storedAnnotations == null) {
//{ObjectTeams: do support annotations for roles for the sake of copying:
	  if (!this.isRole())
// SH}
		if (!this.environment.globalOptions.storeAnnotations && !forceStore)
			return null; // not supported during this compile
		this.storedAnnotations = new SimpleLookupTable(3);
	}
	return this.storedAnnotations;
}

//pre: null annotation analysis is enabled
private void scanFieldForNullAnnotation(IBinaryField field, FieldBinding fieldBinding, boolean isEnum, ITypeAnnotationWalker externalAnnotationWalker) {
	if (!isPrototype()) throw new IllegalStateException();

	if (isEnum && (field.getModifiers() & ClassFileConstants.AccEnum) != 0) {
		fieldBinding.tagBits |= TagBits.AnnotationNonNull;
		return; // we know it's nonnull, no need to look for null *annotations* on enum constants.
	}

	if (!CharOperation.equals(this.fPackage.compoundName, TypeConstants.JAVA_LANG_ANNOTATION) // avoid dangerous re-entry via usesNullTypeAnnotations()
			&& this.environment.usesNullTypeAnnotations()) {
		TypeBinding fieldType = fieldBinding.type;
		if (fieldType != null
				&& !fieldType.isBaseType()
				&& (fieldType.tagBits & TagBits.AnnotationNullMASK) == 0
				&& fieldType.acceptsNonNullDefault()) {
				int nullDefaultFromField = getNullDefaultFrom(field.getAnnotations());
				if (nullDefaultFromField == Binding.NO_NULL_DEFAULT
						? hasNonNullDefaultFor(DefaultLocationField, -1)
						: (nullDefaultFromField & DefaultLocationField) != 0) {
					fieldBinding.type = this.environment.createAnnotatedType(fieldType,
							new AnnotationBinding[] { this.environment.getNonNullAnnotation() });
				}
		}
		return; // not using fieldBinding.tagBits when we have type annotations.
	}

	// global option is checked by caller

	if (fieldBinding.type == null || fieldBinding.type.isBaseType())
		return; // null annotations are only applied to reference types

	boolean explicitNullness = false;
	IBinaryAnnotation[] annotations = externalAnnotationWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER
											? externalAnnotationWalker.getAnnotationsAtCursor(fieldBinding.type.id, false) 
											: field.getAnnotations();
	if (annotations != null) {
		for (int i = 0; i < annotations.length; i++) {
			char[] annotationTypeName = annotations[i].getTypeName();
			if (annotationTypeName[0] != Util.C_RESOLVED)
				continue;
			int typeBit = this.environment.getNullAnnotationBit(signature2qualifiedTypeName(annotationTypeName));
			if (typeBit == TypeIds.BitNonNullAnnotation) {
				fieldBinding.tagBits |= TagBits.AnnotationNonNull;
				explicitNullness = true;
				break;
			}
			if (typeBit == TypeIds.BitNullableAnnotation) {
				fieldBinding.tagBits |= TagBits.AnnotationNullable;
				explicitNullness = true;
				break;
			}
		}
	}
	if (explicitNullness && this.externalAnnotationStatus.isPotentiallyUnannotatedLib())
		this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
	if (!explicitNullness) {
		int nullDefaultFromField = getNullDefaultFrom(field.getAnnotations());
		if (nullDefaultFromField == Binding.NO_NULL_DEFAULT ? hasNonNullDefaultFor(DefaultLocationField, -1)
				: (nullDefaultFromField & DefaultLocationField) != 0) {
			fieldBinding.tagBits |= TagBits.AnnotationNonNull;
		}
	}
}

private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding, ITypeAnnotationWalker externalAnnotationWalker, boolean useNullTypeAnnotations) {
	if (!isPrototype()) throw new IllegalStateException();
	if (isEnum()) {
		int purpose = 0;
		if (CharOperation.equals(TypeConstants.VALUEOF, method.getSelector())
				&& methodBinding.parameters.length == 1
				&& methodBinding.parameters[0].id == TypeIds.T_JavaLangString)
		{
			purpose = SyntheticMethodBinding.EnumValueOf;
		} else if (CharOperation.equals(TypeConstants.VALUES, method.getSelector())
				&& methodBinding.parameters == Binding.NO_PARAMETERS) {
			purpose = SyntheticMethodBinding.EnumValues;
		}
		if (purpose != 0) {
			boolean needToDefer = this.environment.globalOptions.useNullTypeAnnotations == null;
			if (needToDefer)
				this.environment.deferredEnumMethods.add(methodBinding);
			else
				SyntheticMethodBinding.markNonNull(methodBinding, purpose, this.environment);
			return;
		}
	}

	// return:
	ITypeAnnotationWalker returnWalker = externalAnnotationWalker.toMethodReturn();
	IBinaryAnnotation[] annotations = returnWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER
								? returnWalker.getAnnotationsAtCursor(methodBinding.returnType.id, false)
								: method.getAnnotations();
	if (annotations != null) {
		int methodDefaultNullness = NO_NULL_DEFAULT;
		for (int i = 0; i < annotations.length; i++) {
			char[] annotationTypeName = annotations[i].getTypeName();
			if (annotationTypeName[0] != Util.C_RESOLVED)
				continue;
			int typeBit = this.environment.getNullAnnotationBit(signature2qualifiedTypeName(annotationTypeName));
			if (typeBit == TypeIds.BitNonNullByDefaultAnnotation) {
				methodDefaultNullness |= getNonNullByDefaultValue(annotations[i], this.environment);
			} else if (typeBit == TypeIds.BitNonNullAnnotation) {
				methodBinding.tagBits |= TagBits.AnnotationNonNull;
				if (this.environment.usesNullTypeAnnotations()) {
					if (methodBinding.returnType != null && !methodBinding.returnType.hasNullTypeAnnotations()) {
						methodBinding.returnType = this.environment.createAnnotatedType(methodBinding.returnType,
								new AnnotationBinding[] { this.environment.getNonNullAnnotation() });
					}
				}
			} else if (typeBit == TypeIds.BitNullableAnnotation) {
				methodBinding.tagBits |= TagBits.AnnotationNullable;
				if (this.environment.usesNullTypeAnnotations()) {
					if (methodBinding.returnType != null && !methodBinding.returnType.hasNullTypeAnnotations()) {
						methodBinding.returnType = this.environment.createAnnotatedType(methodBinding.returnType,
								new AnnotationBinding[] { this.environment.getNullableAnnotation() });
					}
				}
			}
		}
		methodBinding.defaultNullness = methodDefaultNullness;
	}

	// parameters:
	TypeBinding[] parameters = methodBinding.parameters;
	int numVisibleParams = parameters.length;
	int numParamAnnotations = externalAnnotationWalker instanceof IMethodAnnotationWalker
							? ((IMethodAnnotationWalker) externalAnnotationWalker).getParameterCount()
							: method.getAnnotatedParametersCount();
	if (numParamAnnotations > 0) {
		for (int j = 0; j < numVisibleParams; j++) {
			if (numParamAnnotations > 0) {
				int startIndex = numParamAnnotations - numVisibleParams;
				ITypeAnnotationWalker parameterWalker = externalAnnotationWalker.toMethodParameter((short) (j+startIndex));
				IBinaryAnnotation[] paramAnnotations = parameterWalker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER
															? parameterWalker.getAnnotationsAtCursor(parameters[j].id, false)
															: method.getParameterAnnotations(j+startIndex, this.fileName);
				if (paramAnnotations != null) {
					for (int i = 0; i < paramAnnotations.length; i++) {
						char[] annotationTypeName = paramAnnotations[i].getTypeName();
						if (annotationTypeName[0] != Util.C_RESOLVED)
							continue;
						int typeBit = this.environment.getNullAnnotationBit(signature2qualifiedTypeName(annotationTypeName));
						if (typeBit == TypeIds.BitNonNullAnnotation) {
							if (methodBinding.parameterNonNullness == null)
								methodBinding.parameterNonNullness = new Boolean[numVisibleParams];
							methodBinding.parameterNonNullness[j] = Boolean.TRUE;
							if (this.environment.usesNullTypeAnnotations()) {
								if (methodBinding.parameters[j] != null
										&& !methodBinding.parameters[j].hasNullTypeAnnotations()) {
									methodBinding.parameters[j] = this.environment.createAnnotatedType(
											methodBinding.parameters[j],
											new AnnotationBinding[] { this.environment.getNonNullAnnotation() });
								}
							}
							break;
						} else if (typeBit == TypeIds.BitNullableAnnotation) {
							if (methodBinding.parameterNonNullness == null)
								methodBinding.parameterNonNullness = new Boolean[numVisibleParams];
							methodBinding.parameterNonNullness[j] = Boolean.FALSE;
							if (this.environment.usesNullTypeAnnotations()) {
								if (methodBinding.parameters[j] != null
										&& !methodBinding.parameters[j].hasNullTypeAnnotations()) {
									methodBinding.parameters[j] = this.environment.createAnnotatedType(
											methodBinding.parameters[j],
											new AnnotationBinding[] { this.environment.getNullableAnnotation() });
								}
							}
							break;
						}
					}
				}
			}
		}
	}
	if (useNullTypeAnnotations && this.externalAnnotationStatus.isPotentiallyUnannotatedLib()) {
		if (methodBinding.returnType.hasNullTypeAnnotations() 
				|| (methodBinding.tagBits & TagBits.AnnotationNullMASK) != 0 
				|| methodBinding.parameterNonNullness != null) {
			this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
		} else {
			for (TypeBinding parameter : parameters) {
				if (parameter.hasNullTypeAnnotations()) {
					this.externalAnnotationStatus = ExternalAnnotationStatus.TYPE_IS_ANNOTATED;
					break;
				}
			}
		}
	}
}
// pre: null annotation analysis is enabled
private void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBinding packageBinding) {
	if (!isPrototype()) throw new IllegalStateException();
	char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName();
	if (nonNullByDefaultAnnotationName == null)
		return; // not well-configured to use null annotations

	if (CharOperation.equals(CharOperation.splitOn('/', binaryType.getName()), nonNullByDefaultAnnotationName))
		return; // don't recursively apply @NNBD on @NNBD, neither directly nor via the 'enclosing' package-info.java
	for (String name : this.environment.globalOptions.nonNullByDefaultAnnotationSecondaryNames)
		if (CharOperation.toString(this.compoundName).equals(name))
			return;

	IBinaryAnnotation[] annotations = binaryType.getAnnotations();
	boolean isPackageInfo = CharOperation.equals(sourceName(), TypeConstants.PACKAGE_INFO_NAME);
	if (annotations != null) {
		int nullness = NO_NULL_DEFAULT;
		int length = annotations.length;
		for (int i = 0; i < length; i++) {
			char[] annotationTypeName = annotations[i].getTypeName();
			if (annotationTypeName[0] != Util.C_RESOLVED)
				continue;
			int typeBit = this.environment.getNullAnnotationBit(signature2qualifiedTypeName(annotationTypeName));
			if (typeBit == TypeIds.BitNonNullByDefaultAnnotation) {
				// using NonNullByDefault we need to inspect the details of the value() attribute:
				nullness |= getNonNullByDefaultValue(annotations[i], this.environment);
			}
		}
		this.defaultNullness = nullness;
		if (nullness != NO_NULL_DEFAULT) {
			if (isPackageInfo)
				packageBinding.setDefaultNullness(nullness);
			return;
		}
	}
	if (isPackageInfo) {
		// no default annotations found in package-info
		packageBinding.setDefaultNullness(Binding.NO_NULL_DEFAULT);
		return;
	}
	ReferenceBinding enclosingTypeBinding = this.enclosingType;
	if (enclosingTypeBinding != null) {
		if (setNullDefault(enclosingTypeBinding.getNullDefault()))
			return;
	}
	// no annotation found on the type or its enclosing types
	// check the package-info for default annotation if not already done before
	if (packageBinding.getDefaultNullness() == Binding.NO_NULL_DEFAULT && !isPackageInfo
			&& ((this.typeBits & (TypeIds.BitAnyNullAnnotation)) == 0))
	{
		// this will scan the annotations in package-info
		ReferenceBinding packageInfo = packageBinding.getType(TypeConstants.PACKAGE_INFO_NAME, packageBinding.enclosingModule);
		if (packageInfo == null) {
			packageBinding.setDefaultNullness(Binding.NO_NULL_DEFAULT);
		}
	}
	// no @NonNullByDefault at type level, check containing package:
	setNullDefault(packageBinding.getDefaultNullness());
}

boolean setNullDefault(int newNullDefault) {
	this.defaultNullness = newNullDefault;
	if (newNullDefault != Binding.NO_NULL_DEFAULT) {
		return true;
	}
	return false;
}

/** given an application of @NonNullByDefault convert the annotation argument (if any) into a bitvector a la {@link Binding#NullnessDefaultMASK} */
// pre: null annotation analysis is enabled
static int getNonNullByDefaultValue(IBinaryAnnotation annotation, LookupEnvironment environment) {

	char[] annotationTypeName = annotation.getTypeName();
	char[][] typeName = signature2qualifiedTypeName(annotationTypeName);
	IBinaryElementValuePair[] elementValuePairs = annotation.getElementValuePairs();
	if (elementValuePairs == null || elementValuePairs.length == 0 ) {
		// no argument: apply default default
		ReferenceBinding annotationType = environment.getType(typeName, environment.UnNamedModule); // TODO(SHMOD): null annotations from a module?
		if (annotationType == null) return 0;
		if (annotationType.isUnresolvedType())
			annotationType = ((UnresolvedReferenceBinding) annotationType).resolve(environment, false);
		int nullness = evaluateTypeQualifierDefault(annotationType);
		if (nullness != 0)
			return nullness;
		MethodBinding[] annotationMethods = annotationType.methods();
		if (annotationMethods != null && annotationMethods.length == 1) {
			Object value = annotationMethods[0].getDefaultValue();
			return Annotation.nullLocationBitsFromAnnotationValue(value);
		}
		return DefaultLocationsForTrueValue; // custom unconfigurable NNBD
	} else if (elementValuePairs.length > 0) {
		// evaluate the contained EnumConstantSignatures:
		int nullness = 0;
		for (int i = 0; i < elementValuePairs.length; i++)
			nullness |= Annotation.nullLocationBitsFromAnnotationValue(elementValuePairs[i].getValue());
		return nullness;
	} else {
		// empty argument: cancel all defaults from enclosing scopes
		return NULL_UNSPECIFIED_BY_DEFAULT;
	}
}

public static int evaluateTypeQualifierDefault(ReferenceBinding annotationType) {
	for (AnnotationBinding annotationOnAnnotation : annotationType.getAnnotations()) {
		if(CharOperation.equals(annotationOnAnnotation.getAnnotationType().compoundName[annotationOnAnnotation.type.compoundName.length-1], TYPE_QUALIFIER_DEFAULT)) {
			ElementValuePair[] pairs2 = annotationOnAnnotation.getElementValuePairs();
			if(pairs2 != null) {
				for (ElementValuePair elementValuePair : pairs2) {
					char[] name = elementValuePair.getName();
					if(CharOperation.equals(name, TypeConstants.VALUE)) {
						int nullness = 0;
						Object value = elementValuePair.getValue();
						if(value instanceof Object[]) {
							Object[] values = (Object[]) value;
							for (Object value1 : values)
								nullness |= Annotation.nullLocationBitsFromElementTypeAnnotationValue(value1);
						} else {
							nullness |= Annotation.nullLocationBitsFromElementTypeAnnotationValue(value);								
						}
						return nullness;
					}
				}
			}
		}
	}
	return 0;
}

static char[][] signature2qualifiedTypeName(char[] typeSignature) {
	return CharOperation.splitOn('/', typeSignature, 1, typeSignature.length-1); // cut off leading 'L' and trailing ';'
}

@Override
int getNullDefault() {
	return this.defaultNullness;
}

private void scanTypeForContainerAnnotation(IBinaryType binaryType, char[][][] missingTypeNames) {
	if (!isPrototype()) throw new IllegalStateException();
	IBinaryAnnotation[] annotations = binaryType.getAnnotations();
	if (annotations != null) {
		int length = annotations.length;
		for (int i = 0; i < length; i++) {
			char[] annotationTypeName = annotations[i].getTypeName();
			if (CharOperation.equals(annotationTypeName, ConstantPool.JAVA_LANG_ANNOTATION_REPEATABLE)) {
				IBinaryElementValuePair[] elementValuePairs = annotations[i].getElementValuePairs();
				if (elementValuePairs != null && elementValuePairs.length == 1) {
					Object value = elementValuePairs[0].getValue();
					if (value instanceof ClassSignature) {
						this.containerAnnotationType = (ReferenceBinding) this.environment.getTypeFromSignature(((ClassSignature)value).getTypeName(), 0, -1, false, null, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
					}
				}
				break;
			}
		}
	}
}

/* Answer the receiver's superclass... null if the receiver is Object or an interface.
*
* NOTE: superclass of a binary type is resolved when needed
*/
@Override
public ReferenceBinding superclass() {
	
	if (!isPrototype()) {
		return this.superclass = this.prototype.superclass();
	}
	
	if ((this.tagBits & TagBits.HasUnresolvedSuperclass) == 0)
		return this.superclass;

	// finish resolving the type
	this.superclass = (ReferenceBinding) resolveType(this.superclass, this.environment, true /* raw conversion */);
	this.tagBits &= ~TagBits.HasUnresolvedSuperclass;
	if (this.superclass.problemId() == ProblemReasons.NotFound) {
		this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
	} else {
		// make super-type resolving recursive for propagating typeBits downwards
		boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType;
		this.environment.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360164
		try {
			this.superclass.superclass();
			this.superclass.superInterfaces();
		} finally {
			this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
		}
	}
	this.typeBits |= (this.superclass.typeBits & TypeIds.InheritableBits);
	if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()! 
		this.typeBits |= applyCloseableClassWhitelists(this.environment.globalOptions);
	detectCircularHierarchy();
	return this.superclass;
}

private void breakLoop() {
	ReferenceBinding currentSuper = this.superclass;
	ReferenceBinding prevSuper = null;
	while (currentSuper != null) {
		if ((currentSuper.tagBits & TagBits.EndHierarchyCheck) != 0 && prevSuper instanceof BinaryTypeBinding) {
			((BinaryTypeBinding)prevSuper).superclass = this.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
			break;
		}
		currentSuper.tagBits |= TagBits.EndHierarchyCheck;
		prevSuper = currentSuper;
		currentSuper = currentSuper.superclass();
	}	
}

private void detectCircularHierarchy() {
	ReferenceBinding currentSuper = this.superclass;
	ReferenceBinding tempSuper = null;
	int count = 0;
	int skipCount = 20;
	while (currentSuper != null) {		
		if (currentSuper.hasHierarchyCheckStarted())
			break;
		if (TypeBinding.equalsEquals(currentSuper, this) || TypeBinding.equalsEquals(currentSuper, tempSuper)) {
			currentSuper.tagBits |= TagBits.HierarchyHasProblems;
			if (currentSuper.isBinaryBinding())
				breakLoop();
			
			return;
		}
		if (count == skipCount) {
			tempSuper = currentSuper; // for finding loops that only start after a linear chain
			skipCount *= 2;
			count = 0;
		}
		//Ignore if the super is not yet resolved..
		if (!currentSuper.isHierarchyConnected()) 
			return;
		currentSuper = currentSuper.superclass();	
		count++;
	}
	/* No loop detected and completely found that there is no loop
	 * So, set that info for all the classes 
	 */
	tempSuper = this;
	while (TypeBinding.notEquals(currentSuper, tempSuper)) {
		tempSuper.setHierarchyCheckDone();
		tempSuper=tempSuper.superclass();
	}	
}

//{ObjectTeams:
@Override
public ReferenceBinding baseclass () {
	if (this.baseclass == null) {
    	if (this.roleModel != null) {
    		// check if evaluation of a PlayedBy attribute had to be deferred:
    		AbstractAttribute attribute = this.roleModel.getAttribute(IOTConstants.PLAYEDBY_NAME);
    		if (attribute != null) {
    			attribute.evaluate(this, this.environment, null);
    			this.roleModel.removeAttribute(attribute);
    			return baseclass();
    		}
    	}
        return null;
    }
    if (this.baseclass instanceof UnresolvedReferenceBinding)
        this.baseclass = ((UnresolvedReferenceBinding) this.baseclass).resolve(this.environment, false);
    return this.baseclass;
}
/** Needed for confined types: class file says "j.l.Object", but we actually mean: __OT__Confined.*/
public void resetSuperclass(ReferenceBinding superClass) {
	if (CharOperation.equals(IOTConstants.ORG_OBJECTTEAMS_TEAM_CONFINED, this.compoundName))
		this.superclass= null;
	else if (isInterface())
		this.superclass= superClass;
}
// SH}

// NOTE: superInterfaces of binary types are resolved when needed
@Override
public ReferenceBinding[] superInterfaces() {
	
	if (!isPrototype()) {
		return this.superInterfaces = this.prototype.superInterfaces();
	}
	if ((this.tagBits & TagBits.HasUnresolvedSuperinterfaces) == 0)
		return this.superInterfaces;

	for (int i = this.superInterfaces.length; --i >= 0;) {
		this.superInterfaces[i] = (ReferenceBinding) resolveType(this.superInterfaces[i], this.environment, true /* raw conversion */);
		if (this.superInterfaces[i].problemId() == ProblemReasons.NotFound) {
			this.tagBits |= TagBits.HierarchyHasProblems; // propagate type inconsistency
		} else {
			// make super-type resolving recursive for propagating typeBits downwards
			boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType;
			this.environment.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360164
			try {
				this.superInterfaces[i].superclass();
				if (this.superInterfaces[i].isParameterizedType()) {
					ReferenceBinding superType = this.superInterfaces[i].actualType();
					if (TypeBinding.equalsEquals(superType, this)) {
						this.tagBits |= TagBits.HierarchyHasProblems;
						continue;
					}
				}
				this.superInterfaces[i].superInterfaces();
			} finally {
				this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations;
			}	
		}
		this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits);
		if ((this.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0) // avoid the side-effects of hasTypeBit()! 
			this.typeBits |= applyCloseableInterfaceWhitelists();
	}
	this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
	return this.superInterfaces;
}
@Override
public TypeVariableBinding[] typeVariables() {
	
	if (!isPrototype()) {
		return this.typeVariables = this.prototype.typeVariables();
	}
 	if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0)
		return this.typeVariables;

 	for (int i = this.typeVariables.length; --i >= 0;)
		this.typeVariables[i].resolve();
	this.tagBits &= ~TagBits.HasUnresolvedTypeVariables;
	return this.typeVariables;
}
@Override
public String toString() {
	
	if (this.hasTypeAnnotations())
		return annotatedDebugName();
	
	StringBuffer buffer = new StringBuffer();

	if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
	if (isPublic()) buffer.append("public "); //$NON-NLS-1$
	if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
	if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
	if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
	if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
	if (isFinal()) buffer.append("final "); //$NON-NLS-1$
//	{ObjectTeams
	if (isTeam()) buffer.append("team "); //$NON-NLS-1$
//	Markus Witte}

	if (isEnum()) buffer.append("enum "); //$NON-NLS-1$
	else if (isAnnotationType()) buffer.append("@interface "); //$NON-NLS-1$
	else if (isClass()) buffer.append("class "); //$NON-NLS-1$
	else buffer.append("interface "); //$NON-NLS-1$
	buffer.append((this.compoundName != null) ? CharOperation.toString(this.compoundName) : "UNNAMED TYPE"); //$NON-NLS-1$

	if (this.typeVariables == null) {
		buffer.append("<NULL TYPE VARIABLES>"); //$NON-NLS-1$
	} else if (this.typeVariables != Binding.NO_TYPE_VARIABLES) {
		buffer.append("<"); //$NON-NLS-1$
		for (int i = 0, length = this.typeVariables.length; i < length; i++) {
			if (i  > 0) buffer.append(", "); //$NON-NLS-1$
			if (this.typeVariables[i] == null) {
				buffer.append("NULL TYPE VARIABLE"); //$NON-NLS-1$
				continue;
			}
			char[] varChars = this.typeVariables[i].toString().toCharArray();
			buffer.append(varChars, 1, varChars.length - 2);
		}
		buffer.append(">"); //$NON-NLS-1$
	}
	buffer.append("\n\textends "); //$NON-NLS-1$
	buffer.append((this.superclass != null) ? this.superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$

	if (this.superInterfaces != null) {
		if (this.superInterfaces != Binding.NO_SUPERINTERFACES) {
			buffer.append("\n\timplements : "); //$NON-NLS-1$
			for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
				if (i  > 0)
					buffer.append(", "); //$NON-NLS-1$
				buffer.append((this.superInterfaces[i] != null) ? this.superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
			}
		}
	} else {
		buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
	}

//{ObjectTeams
    if (baseclass() != null) {
        buffer.append("\n\tplayedBy "); //$NON-NLS-1$
        buffer.append(baseclass().debugName());
    }
// SH}

	if (this.enclosingType != null) {
		buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
		buffer.append(this.enclosingType.debugName());
	}

	if (this.fields != null) {
		if (this.fields != Binding.NO_FIELDS) {
			buffer.append("\n/*   fields   */"); //$NON-NLS-1$
			for (int i = 0, length = this.fields.length; i < length; i++)
				buffer.append((this.fields[i] != null) ? "\n" + this.fields[i].toString() : "\nNULL FIELD"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	} else {
		buffer.append("NULL FIELDS"); //$NON-NLS-1$
	}

	if (this.methods != null) {
		if (this.methods != Binding.NO_METHODS) {
			buffer.append("\n/*   methods   */"); //$NON-NLS-1$
			for (int i = 0, length = this.methods.length; i < length; i++)
				buffer.append((this.methods[i] != null) ? "\n" + this.methods[i].toString() : "\nNULL METHOD"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	} else {
		buffer.append("NULL METHODS"); //$NON-NLS-1$
	}

	if (this.memberTypes != null) {
		if (this.memberTypes != Binding.NO_MEMBER_TYPES) {
			buffer.append("\n/*   members   */"); //$NON-NLS-1$
			for (int i = 0, length = this.memberTypes.length; i < length; i++)
				buffer.append((this.memberTypes[i] != null) ? "\n" + this.memberTypes[i].toString() : "\nNULL TYPE"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	} else {
		buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
	}

	buffer.append("\n\n\n"); //$NON-NLS-1$
	return buffer.toString();
}

@Override
public TypeBinding unannotated() {
	return this.prototype;
}
@Override
public TypeBinding withoutToplevelNullAnnotation() {
	if (!hasNullTypeAnnotations())
		return this;
	AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations);
	if (newAnnotations.length > 0)
		return this.environment.createAnnotatedType(this.prototype, newAnnotations);
	return this.prototype;
}
@Override
MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
	
	if (!isPrototype())
		return this.prototype.unResolvedMethods();
	
	return this.methods;
}

@Override
public FieldBinding[] unResolvedFields() {
	
	if (!isPrototype())
		return this.prototype.unResolvedFields();
	
	return this.fields;
}
//{ObjectTeams: for use by TypeModel:
public ReferenceBinding[] unresolvedMemberTypes() {
	return this.memberTypes;
}
// SH}
@Override
public ModuleBinding module() {
	if (!isPrototype())
		return this.prototype.module;
	return this.module;
}
}
