Bug 397182 - Prepare OTDT for new (dynamic) weaver
- more complete handling of OTSpecialAccessAttribute
- consolidate handling of accessId for OTDyn
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 582281c..99bce3d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -60,6 +60,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ConstructorDecapsulationException;
 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.control.StateMemento;
@@ -67,6 +68,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CallinImplementorDyn;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.AstGenerator;
@@ -635,8 +637,12 @@
 	  {
 		this.binding = ((ProblemMethodBinding)this.binding).closestMatch;
 		if (baseclassDecapsulationAllowed) {
-			state.scope.enclosingSourceType().roleModel.addInaccessibleBaseMethod(this.binding);
+			int accessId = state.scope.enclosingSourceType().roleModel.addInaccessibleBaseMethod(this.binding);
 			state.scope.problemReporter().decapsulation(this, state.scope);
+			if (CallinImplementorDyn.DYNAMIC_WEAVING) {
+				this.resolvedType = allocationType;
+				throw new ConstructorDecapsulationException(accessId);
+			}
 		}
 	  } else {
 //  orig:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index 0d2f6a3..54b6c66 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -41,6 +41,8 @@
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.BaseAllocationExpression;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ConstructorDecapsulationException;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.Lowering;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
@@ -232,7 +234,18 @@
 	if (localVariableBinding != null && (localVariableBinding.isCatchParameter() || localVariableBinding.isParameter())) { 
 		localVariableBinding.tagBits &= ~TagBits.IsEffectivelyFinal;  // as it is already definitely assigned, we can conclude already. Also note: catch parameter cannot be compound assigned.
 	}
+//{ObjectTeams:
+/* orig:
 	TypeBinding rhsType = this.expression.resolveType(scope);
+  :giro */
+	TypeBinding rhsType;
+	try {
+		rhsType = this.expression.resolveType(scope);
+	} catch (ConstructorDecapsulationException e) {
+		this.expression = BaseAllocationExpression.convertToDynAccess(scope, (AllocationExpression) this.expression, e.accessId);
+		rhsType = this.expression.resolvedType;
+	}
+// SH}
 	if (lhsType == null || rhsType == null) {
 		return null;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
index a35abbb..f5b3c1d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
@@ -41,6 +41,8 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 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.ast.ConstructorDecapsulationException;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TsuperReference;
 import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.BytecodeTransformer;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
@@ -492,9 +494,21 @@
 						argsContainCast = true;
 					}
 					argument.setExpressionContext(INVOCATION_CONTEXT);
+//{ObjectTeams: OTDyn may need to translate super(base(..)) if decapsulation is involved:
+				  try {
+// orig:
 					if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
 						argHasError = true;
 					}
+// giro:
+				  } catch (ConstructorDecapsulationException cde) {
+					  argument = BaseAllocationExpression.convertToDynAccess(scope, (AllocationExpression) argument, cde.accessId);
+					  if (argument.resolvedType == null)
+						  argHasError = true;
+					  else
+						  argumentTypes[i] = argument.resolvedType;
+				  }
+// SH}
 					if (sourceLevel >= ClassFileConstants.JDK1_8 && argument.isPolyExpression()) {
 						if (this.innerInferenceHelper == null)
 							this.innerInferenceHelper = new InnerInferenceHelper();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index a180bf2..fae834c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -112,6 +112,7 @@
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.WeakenedTypeBinding;
 import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CallinImplementorDyn;
 import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CalloutImplementor;
+import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CalloutImplementorDyn;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance.RoleConstructorCall;
@@ -194,6 +195,7 @@
 
 //{ObjectTeams:
 	private boolean isDecapsulation = false;
+	public int accessId; // for decaps access under OTREDyn
 	// special case: the role method call in a method pushed out to the enclosing team needs special resolving
 	public boolean isPushedOutRoleMethodCall = false;
 	public boolean isGenerated = false;
@@ -1040,16 +1042,16 @@
 		{
 			this.binding = ((ProblemMethodBinding)this.binding).closestMatch;
 			if (!this.binding.declaringClass.isRole()) { // access via interface is possible anyway, no access wrapper needed.
-				// instruct the OTRE to generate an accessor method:
-				int accessId = scope.enclosingSourceType().roleModel.addInaccessibleBaseMethod(this.binding);
+				// need an accessor method that will be generated by the OTRE / OTREDyn
+				if (this.accessId == -1) // happens for BaseAllocationExpression with role-as-base
+					this.accessId = scope.enclosingSourceType().roleModel.addInaccessibleBaseMethod(this.binding);
 				// pretend that accessor method were already there:
 				this.binding = new MethodBinding(this.binding, this.binding.declaringClass.getRealClass());
 				if (CallinImplementorDyn.DYNAMIC_WEAVING) {
-					MethodModel.recordMethodAccessId(this.binding, accessId);
 					if (this.binding.isStatic())
-						this.binding.selector = CallinImplementorDyn.OT_ACCESS_STATIC;
+						this.binding.selector = CalloutImplementorDyn.OT_ACCESS_STATIC;
 					else
-						this.binding.selector = CallinImplementorDyn.OT_ACCESS;
+						this.binding.selector = CalloutImplementorDyn.OT_ACCESS;
 					TypeBinding originalReturnType = this.binding.returnType;
 					if (originalReturnType.id != TypeIds.T_void) {
 						if (originalReturnType.isBaseType()) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index 66828b9..53e9cd2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -65,10 +65,12 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ConstructorDecapsulationException;
 import org.eclipse.objectteams.otdt.internal.core.compiler.ast.OTQualifiedAllocationExpression;
 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.mappings.CallinImplementorDyn;
 import org.eclipse.objectteams.otdt.internal.core.compiler.util.RoleTypeCreator;
 
 
@@ -602,8 +604,12 @@
 //{ObjectTeams: decapsulating base constructor call?
 			  if (this.type.getBaseclassDecapsulation().isAllowed()) {
 				  this.binding = ((ProblemMethodBinding)this.binding).closestMatch;
-				  scope.enclosingSourceType().roleModel.addInaccessibleBaseMethod(this.binding);
+				  int accessId = scope.enclosingSourceType().roleModel.addInaccessibleBaseMethod(this.binding);
 				  scope.problemReporter().decapsulation(this, scope);
+				  if (CallinImplementorDyn.DYNAMIC_WEAVING) {
+					  this.resolvedType = allocationType;
+					  throw new ConstructorDecapsulationException(accessId);
+				  }
 			  } else {
 // orig:
 				  scope.problemReporter().invalidConstructor(this, this.binding);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index e4c53df..7aef0a6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -45,8 +45,6 @@
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
-import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CallinImplementorDyn;
-import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
 import org.eclipse.objectteams.otdt.internal.core.compiler.model.TeamModel;
 
 /**
@@ -311,40 +309,6 @@
 			codeStream.newArray(codeGenVarArgsType); // create a mono-dimensional array
 		}
 	} else if (arguments != null) { // standard generation for method arguments
-//{ObjectTeams: decapsulation under OTREDyn requires packing into an array etc.:
-		if (   CharOperation.equals(CallinImplementorDyn.OT_ACCESS, binding.selector)
-			|| CharOperation.equals(CallinImplementorDyn.OT_ACCESS_STATIC, binding.selector)) 
-		{
-			SourceTypeBinding roleType = currentScope.enclosingSourceType();
-			// adjust the target method binding
-			binding.parameters = new TypeBinding[] {
-											TypeBinding.INT,
-											TypeBinding.INT,
-											currentScope.createArrayType(currentScope.getJavaLangObject(), 1),
-											currentScope.getOrgObjectteamsITeam() 
-									};
-			binding.returnType = currentScope.getJavaLangObject();
-			// accessId:
-			codeStream.generateInlinedValue(MethodModel.getMethodAccessId(binding));
-			// opkind (not used for method access):
-			codeStream.iconst_0();
-			// pack original arguments into a new Object[]
-			codeStream.generateInlinedValue(arguments.length);
-			codeStream.anewarray(currentScope.getJavaLangObject());
-			for (int i = 0, max = arguments.length; i < max; i++) {
-				codeStream.dup();
-				codeStream.generateInlinedValue(i);
-				arguments[i].generateCode(currentScope, codeStream, true);
-				if (arguments[i].resolvedType.isBaseType())
-					codeStream.generateBoxingConversion(arguments[i].resolvedType.id);
-				codeStream.aastore();
-			}
-			// pass enclosing team:
-			Object[] path = currentScope.getEmulationPath(roleType.enclosingType(), true, false);
-			codeStream.generateOuterAccess(path, null, roleType.enclosingType(), currentScope);
-			return;
-		}
-// SH}
 		for (int i = 0, max = arguments.length; i < max; i++)
 //{ObjectTeams: check for need for role-ifc to plain-class cast:
 		{
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java
index 1e750cf..0817561 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/BaseAllocationExpression.java
@@ -27,31 +27,43 @@
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
 import org.eclipse.jdt.internal.compiler.ast.Assignment;
+import org.eclipse.jdt.internal.compiler.ast.CastExpression;
 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.Reference;
 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.MemberTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
 import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.Lifting;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
 import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
+import org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CalloutImplementorDyn;
 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.util.AstGenerator;
@@ -186,6 +198,7 @@
         	allocSend.receiver = receiver;
         	allocSend.selector = selector;
         	allocSend.arguments = this.arguments;
+        	allocSend.accessId = -1; // request that MessageSend.resolveType() assigns a fresh accessId if decapsulation is detected
         	allocation = allocSend;
         } else {
             AllocationExpression alloc = newAllocation(baseclass, gen);
@@ -239,8 +252,94 @@
     		}
         }
     }
-    
-    private boolean isArgOfOtherCtor(ConstructorDeclaration constructorDecl, BlockScope scope) {
+
+	public static Expression convertToDynAccess(BlockScope scope, AllocationExpression expression, int accessId) {
+		AstGenerator gen = new AstGenerator(expression);
+    	Expression receiver;
+    	char[] selector;
+    	int modifiers = ClassFileConstants.AccPublic;
+		TypeBinding baseclass = expression.resolvedType;
+		if (expression instanceof QualifiedAllocationExpression) {
+			receiver = ((QualifiedAllocationExpression) expression).enclosingInstance;
+			selector = CalloutImplementorDyn.OT_ACCESS;
+			// FIXME: here we should call a non-static outer._OT$access() which must invoke this.new Inner().
+		} else {
+			receiver = gen.typeReference(baseclass);
+			selector = CalloutImplementorDyn.OT_ACCESS_STATIC;
+			modifiers |= ClassFileConstants.AccStatic;
+		}
+		MessageSend allocSend = new MessageSend() {
+    		@Override
+			public boolean isDecapsulationAllowed(Scope scope2) {
+    			// this message send can decapsulate independent of scope
+    			return true;
+    		}
+    		@Override
+    		public DecapsulationState getBaseclassDecapsulation() {
+    			return DecapsulationState.ALLOWED;
+    		}
+    	};
+    	gen.setPositions(allocSend);
+    	allocSend.receiver = receiver;
+    	allocSend.selector = selector;
+    	allocSend.arguments = expression.arguments;
+    	allocSend.constant = Constant.NotAConstant;
+    	allocSend.actualReceiverType = baseclass;
+    	allocSend.accessId = accessId;
+   		allocSend.arguments = createResolvedAccessArguments(gen, accessId, expression.arguments, scope);
+    	allocSend.binding = new MethodBinding(modifiers, new TypeBinding[] {
+    			TypeBinding.INT,
+    			TypeBinding.INT,
+    			scope.createArrayType(scope.getJavaLangObject(), 1),
+    			scope.getOrgObjectteamsITeam() 
+    		}, 
+    		Binding.NO_EXCEPTIONS,
+    		(ReferenceBinding) baseclass);
+    	allocSend.binding.returnType = scope.getJavaLangObject();
+    	allocSend.binding.selector = selector;
+    	return gen.resolvedCastExpression(allocSend, baseclass, CastExpression.RAW);
+	}
+
+	private static Expression[] createResolvedAccessArguments(AstGenerator gen, int accessId, Expression[] arguments, BlockScope scope) {
+		IntLiteral accessIdLiteral = gen.intLiteral(accessId);
+		accessIdLiteral.resolveType(scope);
+
+		IntLiteral opKindLiteral = gen.intLiteral(0);
+		opKindLiteral.resolveType(scope);
+		
+		Expression[] boxedArgs = null;
+		if (arguments != null) {
+			boxedArgs = new Expression[arguments.length];
+			for (int i = 0; i < arguments.length; i++) {
+				Expression argument = arguments[i];
+				if (argument.resolvedType.isPrimitiveType()) {
+					BaseTypeBinding baseType = (BaseTypeBinding) argument.resolvedType;
+					AllocationExpression boxingAllocation = gen.createBoxing(argument, baseType);
+					boxingAllocation.resolvedType = scope.environment().computeBoxingType(baseType);
+					boxingAllocation.binding = scope.getConstructor((ReferenceBinding) boxingAllocation.resolvedType, new TypeBinding[]{baseType}, boxingAllocation);
+					boxingAllocation.constant = Constant.NotAConstant;
+					argument = boxingAllocation;
+				}
+				boxedArgs[i] = argument;
+			}
+		}
+		ArrayAllocationExpression packedArgs = gen.arrayAllocation(gen.qualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT), 
+				boxedArgs != null ? 1 : 0, boxedArgs); // arguments are already resolved at this point
+		ArrayBinding objectArray = scope.createArrayType(scope.getJavaLangObject(), 1);
+		if (packedArgs.initializer != null)
+			packedArgs.initializer.binding = objectArray;
+		else
+			packedArgs.dimensions[0].resolveType(scope);
+		packedArgs.resolvedType = objectArray;
+		packedArgs.constant = Constant.NotAConstant;
+
+		Reference teamReference = gen.qualifiedThisReference(scope.enclosingSourceType().enclosingType());
+		teamReference.resolveType(scope);
+		
+		return new Expression[] { accessIdLiteral, opKindLiteral, packedArgs, teamReference };
+	}
+
+	private boolean isArgOfOtherCtor(ConstructorDeclaration constructorDecl, BlockScope scope) {
     	// two marker exception types:
     	@SuppressWarnings("serial") class FoundException extends RuntimeException { /*empty*/}
     	@SuppressWarnings("serial") class NotFoundException extends RuntimeException { /*empty*/ }
@@ -359,9 +458,9 @@
         }
 		if (this.isExpression) // don't treat as assignment
 			return this.resolvedType = this.expression.resolveType(scope);
-        if (!scope.methodScope().referenceContext.hasErrors())
-            return super.resolveType(scope);
-        return null;
+		if (!scope.methodScope().referenceContext.hasErrors())
+			return super.resolveType(scope);
+		return null;
     }
     
     @Override
@@ -397,5 +496,4 @@
     		return super.printExpressionNoParenthesis(indent, output);
     	return output.append("<no expression yet>"); //$NON-NLS-1$
 	}
-
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/ConstructorDecapsulationException.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/ConstructorDecapsulationException.java
new file mode 100644
index 0000000..f184e17
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/ConstructorDecapsulationException.java
@@ -0,0 +1,33 @@
+/**********************************************************************
+ * This file is part of "Object Teams Development Tooling"-Software
+ *
+ * Copyright 2014, GK Software AG and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Please visit http://www.eclipse.org/objectteams for updates and contact.
+ *
+ * Contributors:
+ * 			Stephan Herrmann - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.objectteams.otdt.internal.core.compiler.ast;
+
+/**
+ * Thrown when during resolving of an AllocationExpression we detect that
+ * decapsulation is involved, which in OTREDyn requires redirection to
+ * an _OT$access or _OT$accessStatic method.
+ * @since 2.3
+ */
+@SuppressWarnings("serial")
+public class ConstructorDecapsulationException extends RuntimeException {
+
+	public int accessId;
+
+	public ConstructorDecapsulationException(int accessId) {
+		this.accessId = accessId;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/FieldAccessSpec.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/FieldAccessSpec.java
index 4e79132..e507f7e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/FieldAccessSpec.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/FieldAccessSpec.java
@@ -178,7 +178,11 @@
 		{
 			// record this field access for Attribute generation:
 			RoleModel roleModel = scope.enclosingSourceType().roleModel;
-			ReferenceBinding targetClass =  roleModel.addAccessedBaseField(this.resolvedField, this.calloutModifier);
+			// find appropriate target class
+			FieldBinding field = this.resolvedField;
+			ReferenceBinding targetClass = field.declaringClass; // default: the class declaring the field (could be super of bound base)
+			if (!field.isStatic() && (field.isProtected() || field.isPublic()))
+				targetClass = roleModel.getBaseTypeBinding();	// use the specific declared bound class (avoids weaving into possibly inaccessible super base)
 
 			// create accessor method:
 			result = createMethod(targetClass, accessorSelector);
@@ -288,8 +292,10 @@
 
 	@Override
 	void checkDecapsulation(ReferenceBinding baseClass, Scope scope) {
-		if (this.implementationStrategy != ImplementationStrategy.DIRECT)
+		if (this.implementationStrategy != ImplementationStrategy.DIRECT) {
+    		this.accessId = createAccessAttribute(scope.enclosingSourceType().roleModel);
 			scope.problemReporter().decapsulation(this, baseClass, scope, isSetter());
+		}
 	}
 
 	public boolean checkBaseReturnType(CallinCalloutScope scope, int bindDir)
@@ -393,8 +399,8 @@
 		return this.resolvedField.canBeSeenBy(receiverType, this, scope);
 	}
 
-	public void createAccessAttribute(RoleModel roleModel) {		
-		roleModel.addAccessedBaseField(this.resolvedField, this.calloutModifier);
+	public int createAccessAttribute(RoleModel roleModel) {		
+		return roleModel.addAccessedBaseField(this.resolvedField, this.calloutModifier);
 	}
 
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/MethodSpec.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/MethodSpec.java
index fc0b42c..cb8cbb5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/MethodSpec.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/MethodSpec.java
@@ -101,6 +101,7 @@
 	public boolean isDeclaration = false;
 //{OTDyn:
 	public int callinID = -1;
+	public int accessId;
 // SH}
 
 	public enum ImplementationStrategy {
@@ -503,6 +504,7 @@
 		if (!this.resolvedMethod.canBeSeenBy(baseClass, this, scope)) {
 			this.implementationStrategy = CallinImplementorDyn.DYNAMIC_WEAVING 
 					? ImplementationStrategy.DYN_ACCESS : ImplementationStrategy.DECAPS_WRAPPER;
+    		this.accessId = createAccessAttribute(scope.enclosingSourceType().roleModel);
    			scope.problemReporter().decapsulation(this, baseClass, scope);
 		} else {
 			this.implementationStrategy = ImplementationStrategy.DIRECT;
@@ -788,7 +790,7 @@
 		throw new InternalCompilerError("Method not applicable"); //$NON-NLS-1$
 	}
 	
-	public void createAccessAttribute(RoleModel roleModel) {
-		roleModel.addInaccessibleBaseMethod(this.resolvedMethod);		
+	public int createAccessAttribute(RoleModel roleModel) {
+		return roleModel.addInaccessibleBaseMethod(this.resolvedMethod);		
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java
index ba800da..916f876 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java
@@ -1,7 +1,7 @@
 /**********************************************************************
  * This file is part of "Object Teams Development Tooling"-Software
  *
- * Copyright 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2006, 2014 Fraunhofer Gesellschaft, Munich, Germany,
  * for its Fraunhofer Institute for Computer Architecture and Software
  * Technology (FIRST), Berlin, Germany and Technical University Berlin,
  * Germany.
@@ -10,7 +10,6 @@
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
- * $Id: $
  *
  * Please visit http://www.eclipse.org/objectteams for updates and contact.
  *
@@ -61,8 +60,24 @@
 	private static final int DYN_CALLOUT_FIELD_ACCESS = 5;
 	private static final int DYN_SUPER_METHOD_ACCESS = 6;
 	private static final int M_SIZE = CallinImplementorDyn.DYNAMIC_WEAVING ? 8 : 6;
-	private static final int F_SIZE = CallinImplementorDyn.DYNAMIC_WEAVING ? 8 : 7;
+	private static final int F_SIZE = CallinImplementorDyn.DYNAMIC_WEAVING ? 9 : 7;
 
+	/*
+	 * For OTREDyn, each attribute of this type maintains a set of locally unique (per team) access IDs.
+	 * These IDs are consumed and translated by OTREDyn to obtain those IDs that uniquely identify the
+	 * base feature within a generated _OT$access or _OT$accessStatic method.
+	 * 
+	 * AccessIds are generated during resolve and stored in these AST nodes:
+	 * - MethodSpec / FieldAccessSpec
+	 *   - From here it is directly picked up by CallinImplementorDyn to insert
+	 *     the accessId as an argument for the generated _OT$access[Static] call.
+	 * - MessageSend; accessId is preset for message sends implementing decapsulating BaseAllocationExpression
+	 *   - regular base class:
+	 *     - detected during AllocationExpression.resolveType, throws ConstructorDecapsulationExpression
+	 *     - allocation is then replaced by a MessageSend to the _OT$access method
+	 *   - base is role:
+	 *     - generated AST has accessId = -1 to be updated during MessageSend.resolveType() if decaps needed
+	 */
 	int nextAccessId = 0;
 	
 	/** Descriptor for a decapsulated base-method. */
@@ -76,8 +91,15 @@
 			if (CopyInheritance.isCreator(method))
 				// creator is declared in the enclosing team
 				this.boundBaseclass = this.boundBaseclass.enclosingType();
-			if (CallinImplementorDyn.DYNAMIC_WEAVING)
+			if (CallinImplementorDyn.DYNAMIC_WEAVING) {
+				for (DecapsulatedMethodDesc methodDesc : OTSpecialAccessAttribute.this._decapsulatedMethods) {
+					if (methodDesc.method == method) {
+						this.accessId = methodDesc.accessId; // share the accessId from another callout to the same method
+						return;
+					}
+				}
 				this.accessId = OTSpecialAccessAttribute.this.nextAccessId++;
+			}
 		}
 
 		void write() {
@@ -100,16 +122,16 @@
 				writeName(this.boundBaseclass.attributeName()); // where to weave into
 				writeName(encodedName);
 				writeName(this.method.signature());
-				if (CallinImplementorDyn.DYNAMIC_WEAVING)
-					writeUnsignedShort(this.accessId);
 			}
+			if (CallinImplementorDyn.DYNAMIC_WEAVING)
+				writeUnsignedShort(this.accessId);
 		}
 
 		public String toString() {
 			return new String(this.method.readableName());
 		}
 	}
-	private List<DecapsulatedMethodDesc> _decapsulatedMethods = new ArrayList<DecapsulatedMethodDesc>();
+	List<DecapsulatedMethodDesc> _decapsulatedMethods = new ArrayList<DecapsulatedMethodDesc>();
 
 	/** Descriptor for a callout-bound base field. */
 	private class CalloutToFieldDesc {
@@ -121,7 +143,7 @@
 		FieldBinding field;
 		ReferenceBinding targetClass;
 		int flags; // use the above constants
-		private int accessId;
+		int accessId;
 		CalloutToFieldDesc(FieldBinding field, ReferenceBinding targetClass, int calloutModifier)
 		{
 			this.field = field;
@@ -130,8 +152,15 @@
 							CALLOUT_GET_FIELD : CALLOUT_SET_FIELD;
 			if (field.isStatic())
 				this.flags |= CALLOUT_STATIC_FIELD;
-			if (CallinImplementorDyn.DYNAMIC_WEAVING)
+			if (CallinImplementorDyn.DYNAMIC_WEAVING) {
+				for (CalloutToFieldDesc ctf : OTSpecialAccessAttribute.this._calloutToFields) {
+					if (ctf.field == field) {
+						this.accessId = ctf.accessId; // share the accessId from another callout to the same field
+						return;
+					}
+				}
 				this.accessId = OTSpecialAccessAttribute.this.nextAccessId++;
+			}
 		}
 
 		public int calloutModifier() {
@@ -143,7 +172,7 @@
 		void write() {
 			if (CallinImplementorDyn.DYNAMIC_WEAVING) {
 				writeByte((byte)DYN_CALLOUT_FIELD_ACCESS);
-				writeByte((byte)this.accessId);
+				writeUnsignedShort(this.accessId);
 			} else {
 				writeByte((byte)CALLOUT_FIELD_ACCESS);
 			}
@@ -166,7 +195,7 @@
 			return  result.toString();
 		}
 	}
-	private List<CalloutToFieldDesc> _calloutToFields = new ArrayList<CalloutToFieldDesc>();
+	List<CalloutToFieldDesc> _calloutToFields = new ArrayList<CalloutToFieldDesc>();
 
 	/** Descriptor for base.super.m() special method access. */
 	public class SuperMethodDesc
@@ -177,7 +206,7 @@
 		}
 
 		void write() {
-			writeByte((byte)SUPER_METHOD_ACCESS);
+			writeByte((byte)(CallinImplementorDyn.DYNAMIC_WEAVING ? DYN_SUPER_METHOD_ACCESS : SUPER_METHOD_ACCESS));
 			writeName(this.method.declaringClass.attributeName());
 			writeName(this.method.declaringClass.superclass().attributeName());
 			writeName(this.method.selector);
@@ -215,8 +244,10 @@
 		return accessId;
 	}
 
-	public void addCalloutFieldAccess(FieldBinding field, ReferenceBinding targetClass, int calloutModifier) {
-		this._calloutToFields.add(new CalloutToFieldDesc(field, targetClass, calloutModifier));
+	public int addCalloutFieldAccess(FieldBinding field, ReferenceBinding targetClass, int calloutModifier) {
+		CalloutToFieldDesc calloutToFieldDesc = new CalloutToFieldDesc(field, targetClass, calloutModifier);
+		this._calloutToFields.add(calloutToFieldDesc);
+		return calloutToFieldDesc.accessId;
 	}
 
 	public void addSuperMethodAccess(MethodBinding method) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
index c74ab26..52273f8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CallinImplementorDyn.java
@@ -99,10 +99,6 @@
 	//  - both the team version (II[Object;) and the base version (I[Object;)
 	public static final char[] OT_CALL_ORIG_STATIC = "_OT$callOrigStatic".toCharArray(); //$NON-NLS-1$
 	
-	// for decapsulation:
-	public static final char[] OT_ACCESS 		= "_OT$access".toCharArray(); //$NON-NLS-1$
-	public static final char[] OT_ACCESS_STATIC = "_OT$accessStatic".toCharArray(); //$NON-NLS-1$
-	
 	// variable names (arguments ...)
 	static final char[] TEAMS 			= "teams".toCharArray(); //$NON-NLS-1$
 	static final char[] INDEX			= "index".toCharArray(); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
index 406d2b2..ee076c3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementor.java
@@ -1,7 +1,7 @@
 /**********************************************************************
  * This file is part of "Object Teams Development Tooling"-Software
  *
- * Copyright 2003, 2011 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2003, 2014 Fraunhofer Gesellschaft, Munich, Germany,
  * for its Fraunhofer Institute for Computer Architecture and Software
  * Technology (FIRST), Berlin, Germany and Technical University Berlin,
  * Germany.
@@ -571,8 +571,10 @@
 
     		boolean isCalloutToField = calloutDecl.isCalloutToField();
     		MethodBinding targetMethod = calloutDecl.baseMethodSpec.resolvedMethod;
-	    	baseAccess = new PrivateRoleMethodCall(receiver, selector, arguments, isCalloutToField,
+	    	MessageSend baseSend = new PrivateRoleMethodCall(receiver, selector, arguments, isCalloutToField,
 	    										   calloutDecl.scope, baseType, targetMethod, gen);
+    		baseSend.accessId = calloutDecl.baseMethodSpec.accessId;
+    		baseAccess = baseSend;
     	} else {
     		if (calloutDecl.baseMethodSpec.isStatic())
     			// we thought we should use an instance
@@ -589,8 +591,7 @@
 						else
 							baseAccess = gen.qualifiedNameReference(new char[][] {IOTConstants._OT_BASE, baseField.name });
 						if (fieldSpec.isSetter()) {
-							int pos = fieldSpec.isStatic() ? 0 : 1;
-							baseAccess = gen.assignment((NameReference)baseAccess, arguments[pos]);
+							baseAccess = gen.assignment((NameReference)baseAccess, arguments[0]);
 							returnType = TypeBinding.VOID; // signal that no result processing is necessary
 						}
 					} else {
@@ -602,7 +603,9 @@
 						// we thought we should use an instance
 						// but decapsulating c-t-f (non-role-base) is sent to the base *class*
 						receiver = gen.baseNameReference(baseType.getRealClass());
-		    		baseAccess = gen.messageSend(receiver, selector, arguments);
+		    		MessageSend baseSend = gen.messageSend(receiver, selector, arguments);
+		    		baseSend.accessId = calloutDecl.baseMethodSpec.accessId;
+		    		baseAccess = baseSend;
 		    		break;
 				case DYN_ACCESS:
 					baseAccess = CalloutImplementorDyn.baseAccessExpression(calloutDecl.scope, this._role, baseType, receiver, calloutDecl.baseMethodSpec, arguments, gen);
@@ -674,7 +677,7 @@
 				minArguments = 1;
 			else
 				minArguments = 0;
-        	if (!baseMethodSpec.isStatic()) {
+        	if (!baseMethodSpec.isStatic() && !CallinImplementorDyn.DYNAMIC_WEAVING) { // OTREDyn uses non-static accessor for non-static fields
         		arguments = new Expression[minArguments+1];
 	        	// cast needed against weakened _OT$base reference
         		//   and if base is a role, to go to the class type (FIXME)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java
index c4ecf8b..9912b55 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/CalloutImplementorDyn.java
@@ -16,6 +16,7 @@
 package org.eclipse.objectteams.otdt.internal.core.compiler.mappings;
 
 import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -39,19 +40,17 @@
 public class CalloutImplementorDyn {
 
 	// wrapper methods for decapsulating callout
-	public static final char[] ACCESS = "_OT$access".toCharArray(); //$NON-NLS-1$
-	public static final char[] ACCESS_STATIC = "_OT$accessStatic".toCharArray(); //$NON-NLS-1$
+	public static final char[] OT_ACCESS = "_OT$access".toCharArray(); //$NON-NLS-1$
+	public static final char[] OT_ACCESS_STATIC = "_OT$accessStatic".toCharArray(); //$NON-NLS-1$
 	
 
 	public static Expression baseAccessExpression(Scope scope, RoleModel roleModel, ReferenceBinding baseType, 
 												  Expression receiver, MethodSpec baseSpec, Expression[] arguments,
 												  AstGenerator gen) 
 	{
-		baseSpec.createAccessAttribute(roleModel);
-
 		char[] selector = ensureAccessor(scope, baseType, baseSpec.isStatic());
 		TeamModel teamModel = roleModel.getTeamModel();
-		Expression memberIdArg = gen.intLiteral(teamModel.getNewCallinId(baseSpec));
+		Expression accessIdArg = gen.intLiteral(baseSpec.accessId);
 		int opKind = 0;
 		if (baseSpec instanceof FieldAccessSpec)
 			if (((FieldAccessSpec) baseSpec).calloutModifier == TerminalTokens.TokenNameset)
@@ -59,7 +58,7 @@
 		Expression opKindArg = gen.intLiteral(opKind);
 		Expression packagedArgs = gen.arrayAllocation(gen.qualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT), 1, arguments);
 		Expression callerArg = gen.qualifiedThisReference(gen.typeReference(teamModel.getBinding()));
-		Expression messageSend = gen.messageSend(receiver, selector, new Expression[] {memberIdArg, opKindArg, packagedArgs, callerArg});
+		MessageSend messageSend = gen.messageSend(receiver, selector, new Expression[] {accessIdArg, opKindArg, packagedArgs, callerArg});
 		if (baseSpec.resolvedType() == TypeBinding.VOID)
 			return messageSend;
 		else
@@ -69,7 +68,7 @@
 	private static char[] ensureAccessor(Scope scope, ReferenceBinding baseType, boolean isStatic) {
 		if (baseType.isRoleType())
 			baseType = baseType.getRealClass();
-		char[] selector = isStatic ? ACCESS_STATIC : ACCESS;
+		char[] selector = isStatic ? OT_ACCESS_STATIC : OT_ACCESS;
 		MethodBinding[] methods = baseType.getMethods(selector);
 		if (methods == null || methods.length != 1) {
 			int modifiers = ClassFileConstants.AccPublic|ClassFileConstants.AccSynthetic;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/MethodMappingImplementor.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/MethodMappingImplementor.java
index 3e72516..39791ac 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/MethodMappingImplementor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/mappings/MethodMappingImplementor.java
@@ -114,7 +114,7 @@
     	int implementationArgLen = implParameters.length;
 
 		int expressionsOffset = 0;
-        if (isFieldAccess) {
+        if (isFieldAccess && !CallinImplementorDyn.DYNAMIC_WEAVING) { // OTREDyn uses non-static accessor for non-static fields
         	// field access is mapped to static method with additional first parameter _OT$base (unless static):
         	if (!((FieldAccessSpec)methodMapping.getBaseMethodSpecs()[0]).isStatic())
         		expressionsOffset = 1;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/MethodModel.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/MethodModel.java
index b2984e0..8a1a400 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/MethodModel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/MethodModel.java
@@ -132,9 +132,6 @@
     // offset between byte code line number and source code line number
     public int _lineOffset;
 
-    // this id is used by OTREDyn to select decapsulated method:
-    private int _accessId;
-
 	// for a callin method record all exceptions declared by bound base methods:
     public Set<ReferenceBinding> _baseExceptions;
     public void addBaseExceptions(ReferenceBinding[] exceptions) {
@@ -726,24 +723,7 @@
 		}
 		return handledRoles;
 	}
-	/**
-	 * Record an accessId as used by OTREDyn to select a decapsulated method within _OT$access.
-	 * This assumes that different teams decapsulating the same base method keep distinct
-	 * method bindings for the loadtime-generated target method.
-	 * @param method
-	 * @param accessId
-	 */
-	public static void recordMethodAccessId(MethodBinding method, int accessId) {
-		getModel(method)._accessId = accessId;
-	}
-	/**
-	 * Retrieve the accessId previously recorded using {@link #recordByteCode(ClassFile, int)}.
-	 * @param method
-	 * @return the accessId
-	 */
-	public static int getMethodAccessId(MethodBinding method) {
-		return getModel(method)._accessId;
-	}
+
 	/** 
 	 * Try to create an AST generator that assigns remapped positions (SMAP).
 	 * @param hostTypeDecl type declaration that will hold the generated byte code
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/RoleModel.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/RoleModel.java
index 439c681..315c302 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/RoleModel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/RoleModel.java
@@ -1171,9 +1171,9 @@
 	 * Record that a given field is accessed using callout.
 	 * @param field
 	 * @param calloutModifier either TokenNameget or TokenNameset (from TerminalTokens).
-	 * @return the target class into which the OTRE will insert the accessor method
+	 * @return the accessId (per team) for this field
 	 */
-	public ReferenceBinding addAccessedBaseField(FieldBinding field, int calloutModifier) {
+	public int addAccessedBaseField(FieldBinding field, int calloutModifier) {
 		// find appropriate target class
 		ReferenceBinding targetClass = field.declaringClass; // default: the class declaring the field (could be super of bound base)
 		if (!field.isStatic() && (field.isProtected() || field.isPublic()))
@@ -1181,9 +1181,9 @@
 
 		// push out to the team to ensure early evaluation by the OTRE:
 		OTSpecialAccessAttribute specialAccess = getTeamModel().getSpecialAccessAttribute();
-		specialAccess.addCalloutFieldAccess(field, targetClass, calloutModifier);
+		int accessId = specialAccess.addCalloutFieldAccess(field, targetClass, calloutModifier);
 		specialAccess.addAdaptedBaseClass(field.declaringClass);
-		return targetClass;
+		return accessId;
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
index 1666391..ff6074a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/AstGenerator.java
@@ -1283,7 +1283,7 @@
 	 * @param resultExpr
 	 * @return an allocation expression for the boxed value.
 	 */
-	public Expression createBoxing(Expression resultExpr, BaseTypeBinding type)
+	public AllocationExpression createBoxing(Expression resultExpr, BaseTypeBinding type)
 	{
 		char[][] boxedType = boxTypeName(type);
 		return allocation(qualifiedTypeReference(boxedType), new Expression[]{resultExpr});
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddInterfaceAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddInterfaceAdapter.java
index 7115028..6220908 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddInterfaceAdapter.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AddInterfaceAdapter.java
@@ -1,7 +1,7 @@
 /**********************************************************************

  * This file is part of "Object Teams Dynamic Runtime Environment"

  * 

- * Copyright 2009, 2012 Oliver Frank and others.

+ * Copyright 2009, 2014 Oliver Frank and others.

  * 

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

@@ -19,6 +19,7 @@
 import org.objectweb.asm.ClassAdapter;

 import org.objectweb.asm.ClassVisitor;

 import org.objectweb.asm.MethodVisitor;

+import org.objectweb.asm.Opcodes;

 

 /**

  * Adds an interface to the bytecode of a class

@@ -39,6 +40,9 @@
 		String[] newInterfaces = new String[interfaces.length + 1];

 		System.arraycopy(interfaces, 0, newInterfaces, 0, interfaces.length);

 		newInterfaces[interfaces.length] = interfaceName;

+		// Assumption: when it should potentially be a bound baseclass it may have to be public, too:

+		access &= ~(Opcodes.ACC_PRIVATE|Opcodes.ACC_PROTECTED);

+		access |= Opcodes.ACC_PUBLIC;

 		super.visit(version, access, name, signature, superName, newInterfaces);

 	}

 	

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java
index 4c56ef3..e53a3f7 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java
@@ -1,7 +1,7 @@
 /**********************************************************************

  * This file is part of "Object Teams Dynamic Runtime Environment"

  * 

- * Copyright 2009, 2012 Oliver Frank and others.

+ * Copyright 2009, 2014 Oliver Frank and others.

  * 

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

@@ -259,6 +259,7 @@
 

 		List<DecapsMethod> methods = new ArrayList<DecapsMethod>();

 		List<DecapsField> fields = new ArrayList<DecapsField>();

+		List<String> decapsulatedBaseClasses = new ArrayList<String>(); // not currently used, see AddInterfaceAdapter for brute force solution

 		

 		protected OTSpecialAccessAttribute() {

 			super(ATTRIBUTE_OT_SPECIAL_ACCESS);

@@ -273,14 +274,26 @@
 				int kind = cr.readByte(off++);

 				switch (kind) {

 				case DECAPSULATION_METHOD_ACCESS:

-					attr.readMethodAccess(cr, off, buf);	off+=6;

+					attr.readMethodAccess(cr, off, buf);	off+=8;

 					break;

 				case CALLOUT_FIELD_ACCESS:

 					attr.readFieldAccess(cr, off, buf); 	off+=8;

+					break;

+				case SUPER_METHOD_ACCESS:

+					throw new IllegalStateException("Not yet handled: OTSpecialAccess for SUPER_METHOD_ACCESS");

+//					off+=8;

+//					break;

 				default:

-					// FIXME(SH): handle!

+					throw new IllegalStateException("Unexpected kind in OTSpecialAccess attribute: "+kind);

 				}

 			}

+			size = cr.readUnsignedShort(off);				off+=2;

+			for (int i = 0; i < size; i++) {

+				String baseClass = cr.readUTF8(off, buf);	off+=2;

+				int flag = cr.readByte(off++);

+				if (flag == 1)

+					decapsulatedBaseClasses.add(baseClass);

+			}

 			return attr;

 		}

 		private void readMethodAccess(ClassReader cr, int off, char[] buf) {

@@ -291,13 +304,20 @@
 			boolean isStatic = false;

 			String baseClass;

 			String methodName;

-			int pos = encodedName.indexOf('?');

-			if (pos == -1) {

-				pos = encodedName.indexOf('!');

-				isStatic = true;

+			if (encodedName.charAt(0) == '<') {

+				// constructor

+				baseClass = className;

+				methodName = encodedName;

+				isStatic = true; // use static accessor

+			} else {

+				int pos = encodedName.indexOf('?');

+				if (pos == -1) {

+					pos = encodedName.indexOf('!');

+					isStatic = true;

+				}

+				baseClass = encodedName.substring(0, pos);

+				methodName = encodedName.substring(pos+1);

 			}

-			baseClass = encodedName.substring(0, pos);

-			methodName = encodedName.substring(pos+1);

 			this.methods.add(new DecapsMethod(baseClass, methodName, methodDesc, id, isStatic));

 		}

 		private void readFieldAccess(ClassReader cr, int off, char[] buf) {

diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateMethodAccessAdapter.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateMethodAccessAdapter.java
index acd1005..4035760 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateMethodAccessAdapter.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/CreateMethodAccessAdapter.java
@@ -1,7 +1,7 @@
 /**********************************************************************

  * This file is part of "Object Teams Dynamic Runtime Environment"

  * 

- * Copyright 2009, 2012 Oliver Frank and others.

+ * Copyright 2009, 2014 Oliver Frank and others.

  * 

  * All rights reserved. This program and the accompanying materials

  * are made available under the terms of the Eclipse Public License v1.0

@@ -42,11 +42,13 @@
 	private int accessId;

 	private Method access;

 	private int firstArgIndex;

+	private boolean isConstructor;

 

 	public CreateMethodAccessAdapter(Method method, int accessId) {

 		this.method = method;

 		this.accessId = accessId;

-		if (method.isStatic()) {

+		isConstructor = method.getName().equals("<init>");

+		if (method.isStatic() || isConstructor) {

 			access = ConstantMembers.accessStatic;

 			firstArgIndex = 0;

 		} else {

@@ -60,8 +62,12 @@
 		MethodNode methodNode = getMethod(method);

 		InsnList instructions = new InsnList();

 		

-		//put "this" on the stack for a non-static method 

-		if (!method.isStatic()) {

+		if (isConstructor) {

+			// create empty object for constructor invocation:

+			instructions.add(new TypeInsnNode(Opcodes.NEW, name));

+			instructions.add(new InsnNode(Opcodes.DUP));

+		} else if (!method.isStatic()) {

+			//put "this" on the stack for a non-static method

 			instructions.add(new IntInsnNode(Opcodes.ALOAD, 0));

 		}

 		

@@ -93,6 +99,8 @@
 		int opcode = Opcodes.INVOKEVIRTUAL;

 		if (method.isStatic()) {

 			opcode = Opcodes.INVOKESTATIC;

+		} else if (isConstructor) {

+			opcode = Opcodes.INVOKESPECIAL;

 		}

 		instructions.add(new MethodInsnNode(opcode, name, method.getName(), method.getSignature()));

 		

@@ -106,7 +114,7 @@
 			

 				instructions.add(AsmTypeHelper.getBoxingInstructionForType(returnType));

 				instructions.add(new InsnNode(Opcodes.ARETURN));

-		} else if (returnType.getSort() == Type.VOID) {

+		} else if (returnType.getSort() == Type.VOID && !isConstructor) {

 			instructions.add(new InsnNode(Opcodes.ACONST_NULL));

 			instructions.add(new InsnNode(Opcodes.ARETURN));

 		} else {