/*******************************************************************************
 * Copyright (c) 2000, 2020 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 ReferenceBinding[] permittedSubtypes;
	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.permittedSubtypes = prototype.permittedSubtypes;
	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;
		this.permittedSubtypes = Binding.NO_PERMITTEDTYPES;

//{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)  {
			char[] superclassName = binaryType.getSuperclassName();
//{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:
			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;
				if (CharOperation.equals(superclassName, TypeConstants.CharArray_JAVA_LANG_RECORD_SLASH)){
					this.modifiers |= ExtraCompilerModifiers.AccRecord;
				}
			}
// :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;
				}
			}

			this.permittedSubtypes = Binding.NO_PERMITTEDTYPES;
			char[][] permittedSubtypeNames = binaryType.getPermittedSubtypeNames();
			if (permittedSubtypeNames != null) {
				this.modifiers |= ExtraCompilerModifiers.AccSealed;
				int size = permittedSubtypeNames.length;
				if (size > 0) {
					this.permittedSubtypes = 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.permittedSubtypes[i] = this.environment.getTypeFromConstantPoolName(permittedSubtypeNames[i], 0, -1, false, missingTypeNames, toplevelWalker.toSupertype(i, superclassName));
					this.extendedTagBits |= ExtendedTagBits.HasUnresolvedPermittedSubtypes;
				}
			}
		} 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;
			}

			this.permittedSubtypes = Binding.NO_PERMITTEDTYPES;
			if (!wrapper.atEnd()) {
				// attempt to find each permitted type if it exists in the cache (otherwise - resolve it when requested)
				java.util.ArrayList types = new java.util.ArrayList(2);
				short rank = 0;
				do {
					types.add(this.environment.getTypeFromTypeSignature(wrapper, typeVars, this, missingTypeNames, toplevelWalker.toSupertype(rank++, wrapper.peekFullType())));
				} while (!wrapper.atEnd());
				this.permittedSubtypes = new ReferenceBinding[types.size()];
				types.toArray(this.permittedSubtypes);
				this.extendedTagBits |= ExtendedTagBits.HasUnresolvedPermittedSubtypes;
			}

		}
		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;
					}
				}
				for (TypeBinding permsub : this.permittedSubtypes) {
					if (permsub.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);
		}
		// NOTE: not adding permitted types here since the search is up the hierarchy while permitted ones are down.
	}
	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 boolean isRecord() {
	return (this.modifiers & ExtraCompilerModifiers.AccRecord) != 0;
}

@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 ReferenceBinding[] permittedTypes() {

	if (!isPrototype()) {
		return this.permittedSubtypes = this.prototype.permittedTypes();
	}
	for (int i = this.permittedSubtypes.length; --i >= 0;)
		this.permittedSubtypes[i] = (ReferenceBinding) resolveType(this.permittedSubtypes[i], this.environment, false);

	// Note: unlike for superinterfaces() hierarchy check not required here since these are subtypes
	return this.permittedSubtypes;
}
@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 (isRecord()) buffer.append("record "); //$NON-NLS-1$
	else 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.permittedSubtypes != null) {
		if (this.permittedSubtypes != Binding.NO_PERMITTEDTYPES) {
			buffer.append("\n\tpermits : "); //$NON-NLS-1$
			for (int i = 0, length = this.permittedSubtypes.length; i < length; i++) {
				if (i  > 0)
					buffer.append(", "); //$NON-NLS-1$
				buffer.append((this.permittedSubtypes[i] != null) ? this.permittedSubtypes[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
			}
		}
	} else {
		buffer.append("NULL PERMITTEDSUBTYPES"); //$NON-NLS-1$
	}

	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;
}
}
