/*******************************************************************************
 * 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 343713 - [compiler] bogus line number in constructor of inner class in 1.5 compliance
 *     							bug 349326 - [1.7] new warning for missing try-with-resources
 *								bug 186342 - [compiler][null] Using annotations for null checking
 *								bug 361407 - Resource leak warning when resource is assigned to a field outside of constructor
 *								bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
 *								bug 383690 - [compiler] location of error re uninitialized final field should be aligned
 *								bug 331649 - [compiler][null] consider null annotations for fields
 *								bug 383368 - [compiler][null] syntactic null analysis for field references
 *								bug 400421 - [compiler] Null analysis for fields does not take @com.google.inject.Inject into account
 *								Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *								Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables
 *								Bug 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
 *        Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
 *                          Bug 415399 - [1.8][compiler] Type annotations on constructor results dropped by the code generator
 *     Ulrich Grave <ulrich.grave@gmx.de> - Contributions for
 *                              bug 386692 - Missing "unused" warning on "autowired" fields
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationCollector;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.parser.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseAllocationExpression;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.BytecodeTransformer;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.Lifting;
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.TypeModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel.ProblemDetail;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.InsertTypeAdjustmentsVisitor;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.TSuperHelper;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.TypeAnalyzer;

/**
 * OTDT changes:
 *
 * What: analyze base constructor (exactly one) call.
 *
 * What: translate base() ctor calls into constructorCall (cf. BaseAllocationExpression)
 *
 * What: block some operations on generated/copied constructors.
 *
 * BYTE CODE:
 * What:
 * 		1) store the completed byte code in RoleModel
 * 		1b) mark erroneous methods to prevent byte code copy (have not byte code)
 * 		2) switch between actual generateCode and adjusting copy
 *
 * What: Refuse to generate field initialization for roles (see RoleInitializationMethod).
 * Why:  normal field initialization cannot be copy-inherited.
 *
 * What: generate code for valueParamSynthArgs.
 *
 * What: create statements for throwing an IllegalRoleCreationException at run-time
 * Why:  specializing an unbound role to a bound role renders existing new-expressions illegal.
 *
 * What: write OT-specific byte code attributes.
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class ConstructorDeclaration extends AbstractMethodDeclaration {

	public ExplicitConstructorCall constructorCall;

	public TypeParameter[] typeParameters;
//{ObjectTeams: more flags
	// we need to control the order of analyseCode, but prevent double analysis:
	private boolean isCodeAnalyzed = false;
	public boolean needsLifting = false;
// SH}

public ConstructorDeclaration(CompilationResult compilationResult){
	super(compilationResult);
}
/**
 * The flowInfo corresponds to non-static field initialization infos. It may be unreachable (155423), but still the explicit constructor call must be
 * analyzed as reachable, since it will be generated in the end.
 */
public void analyseCode(ClassScope classScope, InitializationFlowContext initializerFlowContext, FlowInfo flowInfo, int initialReachMode) {
	if (this.ignoreFurtherInvestigation)
		return;

	int nonStaticFieldInfoReachMode = flowInfo.reachMode();
	flowInfo.setReachMode(initialReachMode);

//{ObjectTeams:
	// already processed? (see below "force called constructor to be analyzed")
	if (this.isCodeAnalyzed)
		return;
	this.isCodeAnalyzed = true;

	ReferenceBinding roleType = this.scope.enclosingSourceType();
	// don't analyze copied:
    if (this.isCopied) {
    	// ... except for base ctor issues:
    	if (MethodModel.callsBaseCtor(this.binding.copyInheritanceSrc))
    		MethodModel.setCallsBaseCtor(this);
    	if (   this.arguments == null
    		&& !MethodModel.callsBaseCtor(this.binding)
    		&& roleType.baseclass() != null)
    	{
    		MethodModel.getModel(this).problemDetail = ProblemDetail.IllegalDefaultCtor;
    		this.isGenerated = true; // prevent conversion to DOM AST
    	}
        return;
    }
	// still waiting for statements to be generated?
	if (this.isGenerated && this.statements == null)
		return;
    // ctor of bound role needs exactly one base ctor call
    if (   roleType.baseclass() != null
    	&& this.constructorCall != null)
    {
    	// force called constructor to be analyzed:
    	MethodBinding selfCall = this.constructorCall.binding;
    	if (TypeBinding.equalsEquals(selfCall.declaringClass, this.binding.declaringClass))
    		((ConstructorDeclaration)selfCall.sourceMethod()).analyseCode(classScope, initializerFlowContext, flowInfo.copy(), flowInfo.reachMode());

        boolean calledHere = MethodModel.callsBaseCtor(this.binding);
        boolean calledIndirectly = MethodModel.callsBaseCtor(selfCall);
		if (calledIndirectly) {
			ReferenceBinding requiredBase = roleType.baseclass();
			ReferenceBinding createdBase = selfCall.declaringClass.baseclass();
			if (TypeBinding.notEquals(requiredBase, createdBase))
				this.scope.problemReporter().
					callsCtorWithMismatchingBaseCtor(this.constructorCall,
													 selfCall.declaringClass,
													 requiredBase,
													 createdBase);
		}

        calledIndirectly |= (  !Lifting.isLiftToConstructor(this.binding, this.binding.declaringClass)
						    && Lifting.isLiftToConstructor(selfCall, selfCall.declaringClass));
                	       // if a non-lift ctor calls a lift-ctor this accounts for a base-ctor call.

        if (Lifting.isLiftToConstructor(this, this.binding.declaringClass)){
            if (calledHere || calledIndirectly)
                this.scope.problemReporter().baseConstructorCallInLiftingConstructor(this);
        } else {
            if (!calledHere && !calledIndirectly && !Lifting.isLiftingCtor(selfCall)) {
            	if (!(isDefaultConstructor() && roleType.roleModel != null && roleType.roleModel.hasBaseclassProblem())) // ignore if wrong def.ctor was created
            		this.scope.problemReporter().missingCallToBaseConstructor(
            				this, this.binding.declaringClass);
            } else if (calledHere && calledIndirectly) {
                this.scope.problemReporter().
                        tooManyCallsToBaseConstructor(this.statements[0], this.constructorCall);
            }
            if (!calledHere) {
            	// if this is an error, it is already reported. Don't complain again.
            	FieldBinding baseField = this.scope.enclosingSourceType().getField(IOTConstants._OT_BASE, true);
            	if (baseField != null)
					flowInfo.markAsDefinitelyAssigned(baseField);
            }
        }
        if (calledIndirectly)
        	MethodModel.setCallsBaseCtor(this);
    }
// SH}

//{ObjectTeams: don't report against role constructors (could be accessed by tsub role):
  if (   !classScope.referenceContext.isRole()
	  || (classScope.referenceContext.binding.isAnonymousType() && !classScope.referenceContext.isPurelyCopied)) // do report against non-copied anonymous types
//SH}
	checkUnused: {
		MethodBinding constructorBinding;
		if ((constructorBinding = this.binding) == null) break checkUnused;
		if ((this.bits & ASTNode.IsDefaultConstructor) != 0) break checkUnused;
		if (constructorBinding.isUsed()) break checkUnused;
		if (constructorBinding.isPrivate()) {
			if ((this.binding.declaringClass.tagBits & TagBits.HasNonPrivateConstructor) == 0)
				break checkUnused; // tolerate as known pattern to block instantiation
		} else if (!constructorBinding.isOrEnclosedByPrivateType()) {
			break checkUnused;
 		}
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=270446, When the AST built is an abridged version
		// we don't have all tree nodes we would otherwise expect. (see ASTParser.setFocalPosition)
		if (this.constructorCall == null)
			break checkUnused;
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=264991, Don't complain about this
		// constructor being unused if the base class doesn't have a no-arg constructor.
		// See that a seemingly unused constructor that chains to another constructor with a
		// this(...) can be flagged as being unused without hesitation.
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=265142
		if (this.constructorCall.accessMode != ExplicitConstructorCall.This) {
			ReferenceBinding superClass = constructorBinding.declaringClass.superclass();
			if (superClass == null)
				break checkUnused;
			// see if there is a no-arg super constructor
			MethodBinding methodBinding = superClass.getExactConstructor(Binding.NO_PARAMETERS);
			if (methodBinding == null)
				break checkUnused;
			if (!methodBinding.canBeSeenBy(SuperReference.implicitSuperConstructorCall(), this.scope))
				break checkUnused;
			ReferenceBinding declaringClass = constructorBinding.declaringClass;
			if (constructorBinding.isPublic() && constructorBinding.parameters.length == 0 &&
					declaringClass.isStatic() &&
					declaringClass.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoExternalizable, false) != null)
				break checkUnused;
			// otherwise default super constructor exists, so go ahead and complain unused.
		}
		// complain unused
		if ((this.bits & ASTNode.IsImplicit) == 0)
			this.scope.problemReporter().unusedPrivateConstructor(this);
	}

	// check constructor recursion, once all constructor got resolved
	if (isRecursive(null /*lazy initialized visited list*/)) {
		this.scope.problemReporter().recursiveConstructorInvocation(this.constructorCall);
	}
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=385780
	if (this.typeParameters != null  &&
			!this.scope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
		for (int i = 0, length = this.typeParameters.length; i < length; ++i) {
			TypeParameter typeParameter = this.typeParameters[i];
			if ((typeParameter.binding.modifiers & ExtraCompilerModifiers.AccLocallyUsed) == 0) {
				this.scope.problemReporter().unusedTypeParameter(typeParameter);
			}
		}
	}
	try {
		ExceptionHandlingFlowContext constructorContext =
			new ExceptionHandlingFlowContext(
				initializerFlowContext.parent,
				this,
				this.binding.thrownExceptions,
				initializerFlowContext,
				this.scope,
				FlowInfo.DEAD_END);
		initializerFlowContext.checkInitializerExceptions(
			this.scope,
			constructorContext,
			flowInfo);

		// anonymous constructor can gain extra thrown exceptions from unhandled ones
		if (this.binding.declaringClass.isAnonymousType()) {
			List computedExceptions = constructorContext.extendedExceptions;
			if (computedExceptions != null){
				int size;
				if ((size = computedExceptions.size()) > 0){
					ReferenceBinding[] actuallyThrownExceptions;
					computedExceptions.toArray(actuallyThrownExceptions = new ReferenceBinding[size]);
					this.binding.thrownExceptions = actuallyThrownExceptions;
				}
			}
		}

		// nullity and mark as assigned
		analyseArguments(classScope.environment(), flowInfo, this.arguments, this.binding);

		// propagate to constructor call
		if (this.constructorCall != null) {
			// if calling 'this(...)', then flag all non-static fields as definitely
			// set since they are supposed to be set inside other local constructor
			if (this.constructorCall.accessMode == ExplicitConstructorCall.This) {
//{ObjectTeams: calls to copied super ctors are not relevant here:
			  if (!TSuperHelper.isTSuper(this.constructorCall.binding)) {
// orig:
				FieldBinding[] fields = this.binding.declaringClass.fields();
				for (int i = 0, count = fields.length; i < count; i++) {
					FieldBinding field;
					if (!(field = fields[i]).isStatic()) {
						flowInfo.markAsDefinitelyAssigned(field);
					}
				}
// :giro
			  }
// SH}
			}
			flowInfo = this.constructorCall.analyseCode(this.scope, constructorContext, flowInfo);
		}

		// reuse the reachMode from non static field info
		flowInfo.setReachMode(nonStaticFieldInfoReachMode);

		// propagate to statements
		if (this.statements != null) {
			CompilerOptions compilerOptions = this.scope.compilerOptions();
			boolean enableSyntacticNullAnalysisForFields = compilerOptions.enableSyntacticNullAnalysisForFields;
			int complaintLevel = (nonStaticFieldInfoReachMode & FlowInfo.UNREACHABLE) == 0 ? Statement.NOT_COMPLAINED : Statement.COMPLAINED_FAKE_REACHABLE;
			for (int i = 0, count = this.statements.length; i < count; i++) {
				Statement stat = this.statements[i];
				if ((complaintLevel = stat.complainIfUnreachable(flowInfo, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
					flowInfo = stat.analyseCode(this.scope, constructorContext, flowInfo);
				}
				if (enableSyntacticNullAnalysisForFields) {
					constructorContext.expireNullCheckedFieldInfo();
				}
				if (compilerOptions.analyseResourceLeaks) {
					FakedTrackingVariable.cleanUpUnassigned(this.scope, stat, flowInfo);
				}
			}
		}
		// check for missing returning path
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) {
			this.bits |= ASTNode.NeedFreeReturn;
		}

		// reuse the initial reach mode for diagnosing missing blank finals
		// no, we should use the updated reach mode for diagnosing uninitialized blank finals.
		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=235781
		// flowInfo.setReachMode(initialReachMode);

		// check missing blank final field initializations (plus @NonNull)
		if ((this.constructorCall != null)
//{ObjectTeams: no checking for some more cases:
			// don't need to check tsuper ctors:
			&& !TSuperHelper.isTSuper(this.binding)
			// tsuper() is implemented as this(), too (already containing field inits):
			&& (this.constructorCall.accessMode != ExplicitConstructorCall.Tsuper)
// SH}
			&& (this.constructorCall.accessMode != ExplicitConstructorCall.This)) {
			flowInfo = flowInfo.mergedWith(constructorContext.initsOnReturn);
			FieldBinding[] fields = this.binding.declaringClass.fields();
			checkAndGenerateFieldAssignment(initializerFlowContext, flowInfo, fields);
			doFieldReachAnalysis(flowInfo, fields);
//{ObjectTeams: mandatory tsuper() call?
			if (roleType.isRole()
					&& !TSuperHelper.isTSuper(this.binding)
					&& this.constructorCall.accessMode != ExplicitConstructorCall.Tsuper) {
				for (ReferenceBinding tsuperRole : roleType.roleModel.getTSuperRoleBindings()) {
					RoleModel tsuperModel = tsuperRole.roleModel;
					if (tsuperModel != null && tsuperModel.hasFinalFieldInit()) {
						classScope.problemReporter().needToCallTSuper(this.constructorCall, tsuperRole);
						break;
					}
				}
			}
// SH}
		}
		// check unreachable catch blocks
		constructorContext.complainIfUnusedExceptionHandlers(this);
		// check unused parameters
		this.scope.checkUnusedParameters(this.binding);
		this.scope.checkUnclosedCloseables(flowInfo, null, null/*don't report against a specific location*/, null);
	} catch (AbortMethod e) {
		this.ignoreFurtherInvestigation = true;
	}
}
protected void doFieldReachAnalysis(FlowInfo flowInfo, FieldBinding[] fields) {
	for (int i = 0, count = fields.length; i < count; i++) {
		FieldBinding field = fields[i];
		if (!field.isStatic() && !flowInfo.isDefinitelyAssigned(field)) {
			if (field.isFinal()) {
				this.scope.problemReporter().uninitializedBlankFinalField(
						field,
						((this.bits & ASTNode.IsDefaultConstructor) != 0)
							? (ASTNode) this.scope.referenceType().declarationOf(field.original())
							: this);
			} else if (field.isNonNull() || field.type.isFreeTypeVariable()) {
				FieldDeclaration fieldDecl = this.scope.referenceType().declarationOf(field.original());
				if (!isValueProvidedUsingAnnotation(fieldDecl))
					this.scope.problemReporter().uninitializedNonNullField(
						field,
						((this.bits & ASTNode.IsDefaultConstructor) != 0)
							? (ASTNode) fieldDecl
							: this);
			}
		}
	}
}

protected void checkAndGenerateFieldAssignment(FlowContext flowContext, FlowInfo flowInfo, FieldBinding[] fields) {
	return;
}
boolean isValueProvidedUsingAnnotation(FieldDeclaration fieldDecl) {
	// a member field annotated with @Inject is considered to be initialized by the injector
	if (fieldDecl.annotations != null) {
		int length = fieldDecl.annotations.length;
		for (int i = 0; i < length; i++) {
			Annotation annotation = fieldDecl.annotations[i];
			if (annotation.resolvedType.id == TypeIds.T_JavaxInjectInject) {
				return true; // no concept of "optional"
			} else if (annotation.resolvedType.id == TypeIds.T_ComGoogleInjectInject) {
				MemberValuePair[] memberValuePairs = annotation.memberValuePairs();
				if (memberValuePairs == Annotation.NoValuePairs)
					return true;
				for (int j = 0; j < memberValuePairs.length; j++) {
					// if "optional=false" is specified, don't rely on initialization by the injector:
					if (CharOperation.equals(memberValuePairs[j].name, TypeConstants.OPTIONAL))
						return memberValuePairs[j].value instanceof FalseLiteral;
				}
			} else if (annotation.resolvedType.id == TypeIds.T_OrgSpringframeworkBeansFactoryAnnotationAutowired) {
				MemberValuePair[] memberValuePairs = annotation.memberValuePairs();
				if (memberValuePairs == Annotation.NoValuePairs)
					return true;
				for (int j = 0; j < memberValuePairs.length; j++) {
					if (CharOperation.equals(memberValuePairs[j].name, TypeConstants.REQUIRED))
						return memberValuePairs[j].value instanceof TrueLiteral;
				}
			}
		}
	}
	return false;
}

/**
 * Bytecode generation for a constructor
 *
 * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope
 * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
 */
@Override
public void generateCode(ClassScope classScope, ClassFile classFile) {
//{ObjectTeams: if copied for implicit inheritance just adjust and write out
    if(isRelevantCopied())
    {
        new BytecodeTransformer().checkCopyMethodCode(classFile, this);
        if (this.binding.bytecodeMissing && !Config.getConfig().ignoreMissingBytecode) { // copy did not succeed
			int problemsLength;
			CategorizedProblem[] problems =
				this.scope.referenceCompilationUnit().compilationResult.getProblems();
			CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
			System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
			classFile.addProblemConstructor(this, this.binding, problemsCopy);
        }
        return;
    }
    if (areStatementsMissing() && (this.bits & (ASTNode.IsDefaultConstructor|ASTNode.IsCanonicalConstructor)) == 0 ) {
    	this.binding.bytecodeMissing = true;
    	return;
    }
// SH}
	int problemResetPC = 0;
	if (this.ignoreFurtherInvestigation) {
		if (this.binding == null)
			return; // Handle methods with invalid signature or duplicates
		int problemsLength;
		CategorizedProblem[] problems =
			this.scope.referenceCompilationUnit().compilationResult.getProblems();
		CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
		System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
		classFile.addProblemConstructor(this, this.binding, problemsCopy);
//{ObjectTeams: mark this erroneous, so we don't try to copy the byte code later:
        this.binding.bytecodeMissing = true;
// SH}
		return;
	}
	boolean restart = false;
	boolean abort = false;
	CompilationResult unitResult = null;
	int problemCount = 0;
	if (classScope != null) {
		TypeDeclaration referenceContext = classScope.referenceContext;
		if (referenceContext != null) {
			unitResult = referenceContext.compilationResult();
			problemCount = unitResult.problemCount;
		}
	}
	do {
		try {
			problemResetPC = classFile.contentsOffset;
			internalGenerateCode(classScope, classFile);
			restart = false;
		} catch (AbortMethod e) {
			if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
				// a branch target required a goto_w, restart code gen in wide mode.
				classFile.contentsOffset = problemResetPC;
				classFile.methodCount--;
				classFile.codeStream.resetInWideMode(); // request wide mode
				// reset the problem count to prevent reporting the same warning twice
				if (unitResult != null) {
					unitResult.problemCount = problemCount;
				}
				restart = true;
			} else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
				classFile.contentsOffset = problemResetPC;
				classFile.methodCount--;
				classFile.codeStream.resetForCodeGenUnusedLocals();
				// reset the problem count to prevent reporting the same warning twice
				if (unitResult != null) {
					unitResult.problemCount = problemCount;
				}
				restart = true;
			} else {
				restart = false;
				abort = true;
			}
		}
	} while (restart);
	if (abort) {
		int problemsLength;
		CategorizedProblem[] problems =
				this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
		CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
		System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
		classFile.addProblemConstructor(this, this.binding, problemsCopy, problemResetPC);
	}
}

public void generateSyntheticFieldInitializationsIfNecessary(MethodScope methodScope, CodeStream codeStream, ReferenceBinding declaringClass) {
//{ObjectTeams: new kind of synthetics, may occur in non-nested types, too:
	SyntheticArgumentBinding[] syntheticArgs = declaringClass.valueParamSynthArgs();
	if (syntheticArgs != null) {
		for (int i = 0, max = syntheticArgs.length; i < max; i++) {
			SyntheticArgumentBinding syntheticArg;
			if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
				codeStream.aload_0();
				codeStream.load(syntheticArg);
				codeStream.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, declaringClass);
			}
		}
	}
// SH}
	if (!declaringClass.isNestedType()) return;

	NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;

//{ObjectTeams: variable already declared above.
/* orig:
	SyntheticArgumentBinding[] syntheticArgs = nestedType.syntheticEnclosingInstances();
  :giro */
	syntheticArgs = nestedType.syntheticEnclosingInstances();
//SH}
	if (syntheticArgs != null) {
		for (int i = 0, max = syntheticArgs.length; i < max; i++) {
			SyntheticArgumentBinding syntheticArg;
			if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
				codeStream.aload_0();
				codeStream.load(syntheticArg);
				codeStream.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */);
			}
		}
	}
	syntheticArgs = nestedType.syntheticOuterLocalVariables();
	if (syntheticArgs != null) {
		for (int i = 0, max = syntheticArgs.length; i < max; i++) {
			SyntheticArgumentBinding syntheticArg;
			if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
				codeStream.aload_0();
				codeStream.load(syntheticArg);
				codeStream.fieldAccess(Opcodes.OPC_putfield, syntheticArg.matchingField, null /* default declaringClass */);
			}
		}
	}
}

private void internalGenerateCode(ClassScope classScope, ClassFile classFile) {
	classFile.generateMethodInfoHeader(this.binding);
	int methodAttributeOffset = classFile.contentsOffset;
	int attributeNumber = classFile.generateMethodInfoAttributes(this.binding);
//{ObjectTeams: write OT-specific byte code attributes
    if (this.model != null)
        attributeNumber += this.model.writeAttributes(classFile);
// SH}
	if ((!this.binding.isNative()) && (!this.binding.isAbstract())) {

		TypeDeclaration declaringType = classScope.referenceContext;
		int codeAttributeOffset = classFile.contentsOffset;
		classFile.generateCodeAttributeHeader();
		CodeStream codeStream = classFile.codeStream;
		codeStream.reset(this, classFile);

		// initialize local positions - including initializer scope.
		ReferenceBinding declaringClass = this.binding.declaringClass;

		int enumOffset = declaringClass.isEnum() ? 2 : 0; // String name, int ordinal
		int argSlotSize = 1 + enumOffset; // this==aload0

		if (declaringClass.isNestedType()){
			this.scope.extraSyntheticArguments = declaringClass.syntheticOuterLocalVariables();
			this.scope.computeLocalVariablePositions(// consider synthetic arguments if any
					declaringClass.getEnclosingInstancesSlotSize() + 1 + enumOffset,
				codeStream);
			argSlotSize += declaringClass.getEnclosingInstancesSlotSize();
			argSlotSize += declaringClass.getOuterLocalVariablesSlotSize();
		} else {
//{ObjectTeams:	treat value parameters similar to enclosing instances:
			VariableBinding[] syntheticArguments = declaringClass.valueParamSynthArgs();
			argSlotSize += syntheticArguments.length;
/* orig:
			this.scope.computeLocalVariablePositions(1 + enumOffset,  codeStream);
  :giro */
			this.scope.computeLocalVariablePositions(1 + enumOffset + syntheticArguments.length,  codeStream);
// SH}
		}

		if (this.arguments != null) {
			for (int i = 0, max = this.arguments.length; i < max; i++) {
				// arguments initialization for local variable debug attributes
				LocalVariableBinding argBinding;
				codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding);
				argBinding.recordInitializationStartPC(0);
				switch(argBinding.type.id) {
					case TypeIds.T_long :
					case TypeIds.T_double :
						argSlotSize += 2;
						break;
					default :
						argSlotSize++;
						break;
				}
			}
		}

		MethodScope initializerScope = declaringType.initializerScope;
		initializerScope.computeLocalVariablePositions(argSlotSize, codeStream); // offset by the argument size (since not linked to method scope)

		boolean needFieldInitializations = this.constructorCall == null || this.constructorCall.accessMode != ExplicitConstructorCall.This;
//{ObjectTeams: some deviations regarding field initialization:
		// copied team constructors (due to arg lifting) do not initialize fields
		if (   !needFieldInitializations
			&& this.constructorCall != null
			&& this.constructorCall.binding.model != null
			&& this.constructorCall.binding.model.liftedParams != null)
		{
			needFieldInitializations = true;
		}
		// top confined types have no fields to initialize nor have they initFields methods:
		if (needFieldInitializations && TypeAnalyzer.isTopConfined(this.scope.enclosingReceiverType()))
			needFieldInitializations= false;
// SH}

		// post 1.4 target level, synthetic initializations occur prior to explicit constructor call
		boolean preInitSyntheticFields = this.scope.compilerOptions().targetJDK >= ClassFileConstants.JDK1_4;

		if (needFieldInitializations && preInitSyntheticFields){
			generateSyntheticFieldInitializationsIfNecessary(this.scope, codeStream, declaringClass);
			codeStream.recordPositionsFrom(0, this.bodyStart > 0 ? this.bodyStart : this.sourceStart);
		}
		// generate constructor call
		if (this.constructorCall != null) {
			this.constructorCall.generateCode(this.scope, codeStream);
		}
		// generate field initialization - only if not invoking another constructor call of the same class
		if (needFieldInitializations) {
			if (!preInitSyntheticFields){
				generateSyntheticFieldInitializationsIfNecessary(this.scope, codeStream, declaringClass);
			}
//{ObjectTeams: if a role can make use of _OT$InitFields, that is where all fields are initialized (only if all are non-final):
		  if (!isRoleUsingInitFields(declaringType, declaringClass)) {
// orig:
			// generate user field initialization
			if (declaringType.fields != null) {
				for (int i = 0, max = declaringType.fields.length; i < max; i++) {
					FieldDeclaration fieldDecl;
					if (!(fieldDecl = declaringType.fields[i]).isStatic()) {
						fieldDecl.generateCode(initializerScope, codeStream);
					}
				}
			}
// :giro
		  } else
			callInit:
		  {
				// lifting ctor already contains the invoke statement
				MethodBinding[] initMethods = declaringType.binding.getMethods(IOTConstants.INIT_METHOD_NAME);
				if (initMethods.length >= 1)
				{
					int argCount = TSuperHelper.isTSuper(this.binding) ?  1 : 0;
					for (int i = 0; i < initMethods.length; i++) {
						if (initMethods[i].parameters.length == argCount) {
							codeStream.aload_0(); // this
							codeStream.invoke(Opcodes.OPC_invokevirtual, initMethods[i], declaringType.binding);
							break callInit;
						}
					}
				}
				// no matching role init method should mean we had errors.
				assert    TypeModel.isIgnoreFurtherInvestigation(classScope.referenceContext)
				       || RoleModel.hasTagBit(declaringClass, RoleModel.BaseclassHasProblems)
				       || declaringClass.isTeam(); // might be the "turning constructor" of a nested team (see 2.1.11-otjld-*-1f)
		  }
// SH}
		}
		// generate statements
		if (this.statements != null) {
			for (int i = 0, max = this.statements.length; i < max; i++) {
				this.statements[i].generateCode(this.scope, codeStream);
			}
		}
		// if a problem got reported during code gen, then trigger problem method creation
		if (this.ignoreFurtherInvestigation) {
			throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null);
		}
		if ((this.bits & ASTNode.NeedFreeReturn) != 0) {
			codeStream.return_();
		}
		// local variable attributes
		codeStream.exitUserScope(this.scope);
		codeStream.recordPositionsFrom(0, this.bodyEnd > 0 ? this.bodyEnd : this.sourceStart);
		try {
			classFile.completeCodeAttribute(codeAttributeOffset, this.scope);
		} catch(NegativeArraySizeException e) {
			throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null);
		}
//{ObjectTeams
		maybeRecordByteCode(classFile, methodAttributeOffset-6); // include method header
// SH}
		attributeNumber++;
		if ((codeStream instanceof StackMapFrameCodeStream)
				&& needFieldInitializations
				&& declaringType.fields != null) {
			((StackMapFrameCodeStream) codeStream).resetSecretLocals();
		}
	}
	classFile.completeMethodInfo(this.binding, methodAttributeOffset, attributeNumber);
}
private boolean isRoleUsingInitFields(TypeDeclaration typeDecl, ReferenceBinding typeBinding) {
	if (!typeDecl.isRole()
		  || (   typeBinding.enclosingType() != null // also accept roles of o.o.Team
			  && typeBinding.enclosingType().id == IOTConstants.T_OrgObjectTeamsTeam))
		return false;
	boolean hasInitialization = false;
	if (typeDecl.fields != null) {
		for (FieldDeclaration fieldDeclaration : typeDecl.fields) {
			if (fieldDeclaration.initialization != null) {
				if (fieldDeclaration.isFinal())
					return false; // needs to be set inside a proper constructor!
				hasInitialization = true;
			}
		}
	}
	for (ReferenceBinding tsuperRole : typeDecl.getRoleModel().getTSuperRoleBindings()) {
		if (tsuperRole.fields() != Binding.NO_FIELDS && !tsuperRole.roleModel.hasFinalFieldInit()) {
			hasInitialization = true; // conservative, would need another flag to test if tsuper has field init
		}
	}
	return hasInitialization;
}

@Override
protected AnnotationBinding[][] getPropagatedRecordComponentAnnotations() {

	if ((this.bits & (ASTNode.IsCanonicalConstructor | ASTNode.IsImplicit)) == 0)
		return null;
	if (this.binding == null)
		return null;
	AnnotationBinding[][] paramAnnotations = null;
	ReferenceBinding declaringClass = this.binding.declaringClass;
	if (declaringClass instanceof SourceTypeBinding) {
		assert declaringClass.isRecord();
		RecordComponentBinding[] rcbs = ((SourceTypeBinding) declaringClass).components();
		for (int i = 0, length = rcbs.length; i < length; i++) {
			RecordComponentBinding rcb = rcbs[i];
			RecordComponent recordComponent = rcb.sourceRecordComponent();
			long rcMask = TagBits.AnnotationForParameter | TagBits.AnnotationForTypeUse;
			List<AnnotationBinding> relevantAnnotationBindings = new ArrayList<>();
			Annotation[] relevantAnnotations = ASTNode.getRelevantAnnotations(recordComponent.annotations, rcMask, relevantAnnotationBindings);
			if (relevantAnnotations != null) {
				if (paramAnnotations == null) {
					paramAnnotations = new AnnotationBinding[length][];
					for (int j=0; j<i; j++) {
						paramAnnotations[j] = Binding.NO_ANNOTATIONS;
					}
				}
				this.binding.tagBits |= TagBits.HasParameterAnnotations;
				paramAnnotations[i] = relevantAnnotationBindings.toArray(new AnnotationBinding[0]);
			} else if (paramAnnotations != null) {
				paramAnnotations[i] = Binding.NO_ANNOTATIONS;
			}
		}
	}
	return paramAnnotations;
}

//{ObjectTeams: ctors are copied for roles and teams:
@Override
public void maybeRecordByteCode(ClassFile classFile, int methodAttributeOffset) {
	RoleModel.maybeRecordByteCode(
	            this,
	            classFile,
	            methodAttributeOffset);
	if (this.binding.declaringClass.isTeam()) {
	   	// TODO (SH): could we optimize this, e.g., not copy the whole
	   	// class' byte code, but 'only' method and constant pool?
	   	MethodModel methodModel = MethodModel.getModel(this);
	   	methodModel.recordByteCode(classFile, methodAttributeOffset);
	}
}
// SH}

@Override
public void getAllAnnotationContexts(int targetType, List allAnnotationContexts) {
	TypeReference fakeReturnType = new SingleTypeReference(this.selector, 0);
	fakeReturnType.resolvedType = this.binding.declaringClass;
	AnnotationCollector collector = new AnnotationCollector(fakeReturnType, targetType, allAnnotationContexts);
	for (int i = 0, max = this.annotations.length; i < max; i++) {
		Annotation annotation = this.annotations[i];
		annotation.traverse(collector, (BlockScope) null);
	}
}

@Override
public boolean isConstructor() {
	return true;
}

@Override
public boolean isCanonicalConstructor() {
	return (this.bits & ASTNode.IsCanonicalConstructor) != 0;
}

@Override
public boolean isDefaultConstructor() {
	return (this.bits & ASTNode.IsDefaultConstructor) != 0;
}

@Override
public boolean isInitializationMethod() {
	return true;
}

/*
 * Returns true if the constructor is directly involved in a cycle.
 * Given most constructors aren't, we only allocate the visited list
 * lazily.
 */
public boolean isRecursive(ArrayList visited) {
	if (this.binding == null
			|| this.constructorCall == null
			|| this.constructorCall.binding == null
			|| this.constructorCall.isSuperAccess()
// {ObjectTeams
			|| this.constructorCall.isTsuperAccess()
// Markus Witte}
			|| !this.constructorCall.binding.isValidBinding()) {
		return false;
	}

	ConstructorDeclaration targetConstructor =
		((ConstructorDeclaration)this.scope.referenceType().declarationOf(this.constructorCall.binding.original()));
	if (targetConstructor == null) return false; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=358762
	if (this == targetConstructor) return true; // direct case

	if (visited == null) { // lazy allocation
		visited = new ArrayList(1);
	} else {
		int index = visited.indexOf(this);
		if (index >= 0) return index == 0; // only blame if directly part of the cycle
	}
	visited.add(this);

	return targetConstructor.isRecursive(visited);
}

@Override
public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
	//fill up the constructor body with its statements
	if (((this.bits & ASTNode.IsDefaultConstructor) != 0) && this.constructorCall == null){
		this.constructorCall = SuperReference.implicitSuperConstructorCall();
		this.constructorCall.sourceStart = this.sourceStart;
		this.constructorCall.sourceEnd = this.sourceEnd;
		return;
	}
//{ObjectTeams: generated don't have source code:
	if (this.isCopied || this.isGenerated)
		return;
// SH}
	parser.parse(this, unit, false);
	this.containsSwitchWithTry = parser.switchWithTry;
}

//{ObjectTeams: create statements for throwing an IllegalRoleCreationException at run-time:
void createExceptionStatements() {
	AstGenerator gen = new AstGenerator(this.sourceStart, this.sourceEnd);
	this.constructorCall = gen.explicitConstructorCall(ExplicitConstructorCall.Super);
	this.statements = new Statement[] {
		gen.throwStatement(
				gen.allocation(
						gen.qualifiedTypeReference(IOTConstants.ILLEGAL_ROLE_CREATION_EXCEPTION),
						null))
	};
	this.hasParsedStatements = true;
	this.isCopied = false;
	resolve(this.scope.classScope());
}
// SH}

@Override
public StringBuffer printBody(int indent, StringBuffer output) {
	output.append(" {"); //$NON-NLS-1$
	if (this.constructorCall != null) {
		output.append('\n');
		this.constructorCall.printStatement(indent, output);
	}
	if (this.statements != null) {
		for (int i = 0; i < this.statements.length; i++) {
			output.append('\n');
			this.statements[i].printStatement(indent, output);
		}
	}
//{ObjectTeams: signal missing body for copy inherited methods
	else
	{
		if(this.isCopied==true && this.statements == null){
			output.append("\n"); //$NON-NLS-1$
			printIndent(indent == 0 ? 0 : indent - 1,output);
			output.append("     /* CopyInheritance */"); //$NON-NLS-1$
		}
	}
//Markus Witte}
	output.append('\n');
	printIndent(indent == 0 ? 0 : indent - 1, output).append('}');
	return output;
}

@Override
public void resolveJavadoc() {
	if (this.binding == null || this.javadoc != null) {
		super.resolveJavadoc();
	} else if ((this.bits & ASTNode.IsDefaultConstructor) == 0 ) {
		if((this.bits & ASTNode.IsImplicit) != 0 ) return;
		if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
			// Set javadoc visibility
			int javadocVisibility = this.binding.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
			ClassScope classScope = this.scope.classScope();
			ProblemReporter reporter = this.scope.problemReporter();
			int severity = reporter.computeSeverity(IProblem.JavadocMissing);
			if (severity != ProblemSeverities.Ignore) {
				if (classScope != null) {
					javadocVisibility = Util.computeOuterMostVisibility(classScope.referenceType(), javadocVisibility);
				}
				int javadocModifiers = (this.binding.modifiers & ~ExtraCompilerModifiers.AccVisibilityMASK) | javadocVisibility;
				reporter.javadocMissing(this.sourceStart, this.sourceEnd, severity, javadocModifiers);
			}
		}
	}
}

/*
 * Type checking for constructor, just another method, except for special check
 * for recursive constructor invocations.
 */
@Override
public void resolveStatements() {
	SourceTypeBinding sourceType = this.scope.enclosingSourceType();
	if (!CharOperation.equals(sourceType.sourceName, this.selector)){
		this.scope.problemReporter().missingReturnType(this);
	}
//{ObjectTeams: don't resolve any thing for copied (not even generated super().
    if (this.isCopied)
        return;
// SH}
	// typeParameters are already resolved from Scope#connectTypeVariables()
	if (this.binding != null && !this.binding.isPrivate()) {
		sourceType.tagBits |= TagBits.HasNonPrivateConstructor;
	}
	// if null ==> an error has occurs at parsing time ....
	if (this.constructorCall != null) {
		if (sourceType.id == TypeIds.T_JavaLangObject
				&& this.constructorCall.accessMode != ExplicitConstructorCall.This) {
			// cannot use super() in java.lang.Object
			if (this.constructorCall.accessMode == ExplicitConstructorCall.Super) {
				this.scope.problemReporter().cannotUseSuperInJavaLangObject(this.constructorCall);
			}
			this.constructorCall = null;
		} else if (sourceType.isRecord() &&
				!(this instanceof CompactConstructorDeclaration) && // compact constr should be marked as canonical?
				(this.binding != null && (this.binding.tagBits & TagBits.IsCanonicalConstructor) == 0) &&
				this.constructorCall.accessMode != ExplicitConstructorCall.This) {
			this.scope.problemReporter().recordMissingExplicitConstructorCallInNonCanonicalConstructor(this);
			this.constructorCall = null;
		}
		else {
//{ObjectTeams: some transformations:
		  // base() might replace existing constructorCall:
		  if (   this.statements != null
			  && this.statements.length > 0
			  && (this.statements[0] instanceof BaseAllocationExpression))
		  {
			 ((BaseAllocationExpression)this.statements[0]).checkGenerate(this.scope);
		  }
		  // prepare for resolving a special statement: constructorCall.
	      Config oldConfig = Config.createOrResetConfig(this);
		  try {
// orig:
			this.constructorCall.resolve(this.scope);
// :giro
			// order in this condition is relevant, first part resets flags!
			if (   Config.requireTypeAdjustment()
			    && !this.scope.problemReporter().referenceContext.hasErrors())
			{
				this.constructorCall.traverse(new InsertTypeAdjustmentsVisitor(), this.scope);
			}
		  } finally {
		    Config.removeOrRestore(oldConfig, this);
		  }
// SH}
		}
	}
	if ((this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) {
		this.scope.problemReporter().methodNeedBody(this);
	}
	super.resolveStatements();
}

@Override
public void traverse(ASTVisitor visitor, ClassScope classScope) {
	if (visitor.visit(this, classScope)) {
		if (this.javadoc != null) {
			this.javadoc.traverse(visitor, this.scope);
		}
		if (this.annotations != null) {
			int annotationsLength = this.annotations.length;
			for (int i = 0; i < annotationsLength; i++)
				this.annotations[i].traverse(visitor, this.scope);
		}
		if (this.typeParameters != null) {
			int typeParametersLength = this.typeParameters.length;
			for (int i = 0; i < typeParametersLength; i++) {
				this.typeParameters[i].traverse(visitor, this.scope);
			}
		}
		if (this.arguments != null) {
			int argumentLength = this.arguments.length;
			for (int i = 0; i < argumentLength; i++)
				this.arguments[i].traverse(visitor, this.scope);
		}
		if (this.thrownExceptions != null) {
			int thrownExceptionsLength = this.thrownExceptions.length;
			for (int i = 0; i < thrownExceptionsLength; i++)
				this.thrownExceptions[i].traverse(visitor, this.scope);
		}
		if (this.constructorCall != null)
			this.constructorCall.traverse(visitor, this.scope);
		if (this.statements != null) {
			int statementsLength = this.statements.length;
			for (int i = 0; i < statementsLength; i++)
				this.statements[i].traverse(visitor, this.scope);
		}
	}
	visitor.endVisit(this, classScope);
}
@Override
public TypeParameter[] typeParameters() {
    return this.typeParameters;
}
}
