Refactored packagename to net.sourceforge.phpdt.internal.compiler.ast
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / compiler / ast / ConstructorDeclaration.java
index d6a9244..0bf4ad0 100644 (file)
@@ -1,25 +1,29 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v0.5 
+ * are made available under the terms of the Common Public License v1.0
  * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v05.html
+ * http://www.eclipse.org/legal/cpl-v10.html
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
- ******************************************************************************/
+ *******************************************************************************/
 package net.sourceforge.phpdt.internal.compiler.ast;
 
 import java.util.ArrayList;
 
-import net.sourceforge.phpdt.core.compiler.*;
-import net.sourceforge.phpdt.internal.compiler.*;
-import net.sourceforge.phpdt.internal.compiler.codegen.*;
-import net.sourceforge.phpdt.internal.compiler.flow.*;
-import net.sourceforge.phpdt.internal.compiler.lookup.*;
-import net.sourceforge.phpdt.internal.compiler.parser.*;
-import net.sourceforge.phpdt.internal.compiler.problem.*;
-import net.sourceforge.phpdt.internal.compiler.util.*;
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.flow.ExceptionHandlingFlowContext;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
+import net.sourceforge.phpdt.internal.compiler.flow.InitializationFlowContext;
+import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.parser.UnitParser;
+import net.sourceforge.phpdt.internal.compiler.problem.AbortMethod;
+
 
 public class ConstructorDeclaration extends AbstractMethodDeclaration {
 
@@ -27,9 +31,6 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
        public final static char[] ConstantPoolName = "<init>".toCharArray(); //$NON-NLS-1$
        public boolean isDefaultConstructor = false;
 
-       public int referenceCount = 0;
-       // count how many times this constructor is referenced from other local constructors
-
        public ConstructorDeclaration(CompilationResult compilationResult){
                super(compilationResult);
        }
@@ -41,6 +42,18 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
 
                if (ignoreFurtherInvestigation)
                        return;
+
+               if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
+                       if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
+                               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);
+               }
+                       
                try {
                        ExceptionHandlingFlowContext constructorContext =
                                new ExceptionHandlingFlowContext(
@@ -48,7 +61,7 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                                        this,
                                        binding.thrownExceptions,
                                        scope,
-                                       FlowInfo.DeadEnd);
+                                       FlowInfo.DEAD_END);
                        initializerFlowContext.checkInitializerExceptions(
                                scope,
                                constructorContext,
@@ -84,21 +97,23 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                        }
                        // propagate to statements
                        if (statements != null) {
+                               boolean didAlreadyComplain = false;
                                for (int i = 0, count = statements.length; i < count; i++) {
                                        Statement stat;
-                                       if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) {
+                                       if (!flowInfo.complainIfUnreachable(stat = statements[i], scope, didAlreadyComplain)) {
                                                flowInfo = stat.analyseCode(scope, constructorContext, flowInfo);
+                                       } else {
+                                               didAlreadyComplain = true;
                                        }
                                }
                        }
                        // check for missing returning path
-                       needFreeReturn =
-                               !((flowInfo == FlowInfo.DeadEnd) || flowInfo.isFakeReachable());
+                       this.needFreeReturn = flowInfo.isReachable();
 
                        // check missing blank final field initializations
                        if ((constructorCall != null)
                                && (constructorCall.accessMode != ExplicitConstructorCall.This)) {
-                               flowInfo = flowInfo.mergedWith(initializerFlowContext.initsOnReturn);
+                               flowInfo = flowInfo.mergedWith(constructorContext.initsOnReturn);
                                FieldBinding[] fields = binding.declaringClass.fields();
                                for (int i = 0, count = fields.length; i < count; i++) {
                                        FieldBinding field;
@@ -107,7 +122,7 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                                                && (!flowInfo.isDefinitelyAssigned(fields[i]))) {
                                                scope.problemReporter().uninitializedBlankFinalField(
                                                        field,
-                                                       isDefaultConstructor ? (AstNode) scope.referenceType() : this);
+                                                       isDefaultConstructor ? (ASTNode) scope.referenceType() : this);
                                        }
                                }
                        }
@@ -119,157 +134,183 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
        /**
         * Bytecode generation for a constructor
         *
-        * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope
-        * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
+        * @param classScope net.sourceforge.phpdt.internal.compiler.lookup.ClassScope
+        * @param classFile net.sourceforge.phpdt.internal.compiler.codegen.ClassFile
         */
-       public void generateCode(ClassScope classScope, ClassFile classFile) {
-               int problemResetPC = 0;
-               if (ignoreFurtherInvestigation) {
-                       if (this.binding == null)
-                               return; // Handle methods with invalid signature or duplicates
-                       int problemsLength;
-                       IProblem[] problems =
-                               scope.referenceCompilationUnit().compilationResult.getProblems();
-                       IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
-                       System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
-                       classFile.addProblemConstructor(this, binding, problemsCopy);
-                       return;
-               }
-               try {
-                       problemResetPC = classFile.contentsOffset;
-                       this.internalGenerateCode(classScope, classFile);
-               } catch (AbortMethod e) {
-                       if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
-                               // a branch target required a goto_w, restart code gen in wide mode.
-                               try {
-                                       if (statements != null) {
-                                               for (int i = 0, max = statements.length; i < max; i++)
-                                                       statements[i].resetStateForCodeGeneration();
-                                       }
-                                       classFile.contentsOffset = problemResetPC;
-                                       classFile.methodCount--;
-                                       classFile.codeStream.wideMode = true; // request wide mode 
-                                       this.internalGenerateCode(classScope, classFile); // restart method generation
-                               } catch (AbortMethod e2) {
-                                       int problemsLength;
-                                       IProblem[] problems =
-                                               scope.referenceCompilationUnit().compilationResult.getProblems();
-                                       IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
-                                       System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
-                                       classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC);
-                               }
-                       } else {
-                               int problemsLength;
-                               IProblem[] problems =
-                                       scope.referenceCompilationUnit().compilationResult.getProblems();
-                               IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
-                               System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
-                               classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC);
-                       }
-               }
-       }
-
-       private void internalGenerateCode(ClassScope classScope, ClassFile classFile) {
-               classFile.generateMethodInfoHeader(binding);
-               int methodAttributeOffset = classFile.contentsOffset;
-               int attributeNumber = classFile.generateMethodInfoAttribute(binding);
-               if ((!binding.isNative()) && (!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 = binding.declaringClass;
-                       int argSize = 0;
-                       scope.computeLocalVariablePositions(// consider synthetic arguments if any
-                       argSize =
-                               declaringClass.isNestedType()
-                                       ? ((NestedTypeBinding) declaringClass).syntheticArgumentsOffset
-                                       : 1,
-                               codeStream);
-                       if (arguments != null) {
-                               for (int i = 0, max = arguments.length; i < max; i++) {
-                                       // arguments initialization for local variable debug attributes
-                                       LocalVariableBinding argBinding;
-                                       codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding);
-                                       argBinding.recordInitializationStartPC(0);
-                                       TypeBinding argType;
-                                       if ((argType = argBinding.type) == LongBinding || (argType == DoubleBinding)) {
-                                               argSize += 2;
-                                       } else {
-                                               argSize++;
-                                       }
-                               }
-                       }
-                       MethodScope initializerScope = declaringType.initializerScope;
-                       initializerScope.computeLocalVariablePositions(argSize, codeStream);
-                       // offset by the argument size (since not linked to method scope)
-
-                       // generate constructor call
-                       if (constructorCall != null) {
-                               constructorCall.generateCode(scope, codeStream);
-                       }
-                       // generate field initialization - only if not invoking another constructor call of the same class
-                       if ((constructorCall != null)
-                               && (constructorCall.accessMode != ExplicitConstructorCall.This)) {
-                               // generate synthetic fields initialization
-                               if (declaringClass.isNestedType()) {
-                                       NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
-                                       SyntheticArgumentBinding[] syntheticArgs =
-                                               nestedType.syntheticEnclosingInstances();
-                                       for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length;
-                                               i < max;
-                                               i++) {
-                                               if (syntheticArgs[i].matchingField != null) {
-                                                       codeStream.aload_0();
-                                                       codeStream.load(syntheticArgs[i]);
-                                                       codeStream.putfield(syntheticArgs[i].matchingField);
-                                               }
-                                       }
-                                       syntheticArgs = nestedType.syntheticOuterLocalVariables();
-                                       for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length;
-                                               i < max;
-                                               i++) {
-                                               if (syntheticArgs[i].matchingField != null) {
-                                                       codeStream.aload_0();
-                                                       codeStream.load(syntheticArgs[i]);
-                                                       codeStream.putfield(syntheticArgs[i].matchingField);
-                                               }
-                                       }
-                               }
-                               // 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);
-                                               }
-                                       }
-                               }
-                       }
-                       // generate statements
-                       if (statements != null) {
-                               for (int i = 0, max = statements.length; i < max; i++) {
-                                       statements[i].generateCode(scope, codeStream);
-                               }
-                       }
-                       if (needFreeReturn) {
-                               codeStream.return_();
-                       }
-                       // local variable attributes
-                       codeStream.exitUserScope(scope);
-                       codeStream.recordPositionsFrom(0, this.bodyEnd);
-                       classFile.completeCodeAttribute(codeAttributeOffset);
-                       attributeNumber++;
-               }
-               classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
-
-               // if a problem got reported during code gen, then trigger problem method creation
-               if (ignoreFurtherInvestigation) {
-                       throw new AbortMethod(scope.referenceCompilationUnit().compilationResult);
-               }
-       }
+//     public void generateCode(ClassScope classScope, ClassFile classFile) {
+//             
+//             int problemResetPC = 0;
+//             if (ignoreFurtherInvestigation) {
+//                     if (this.binding == null)
+//                             return; // Handle methods with invalid signature or duplicates
+//                     int problemsLength;
+//                     IProblem[] problems =
+//                             scope.referenceCompilationUnit().compilationResult.getProblems();
+//                     IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+//                     System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+//                     classFile.addProblemConstructor(this, binding, problemsCopy);
+//                     return;
+//             }
+//             try {
+//                     problemResetPC = classFile.contentsOffset;
+//                     this.internalGenerateCode(classScope, classFile);
+//             } catch (AbortMethod e) {
+//                     if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
+//                             // a branch target required a goto_w, restart code gen in wide mode.
+//                             try {
+//                                     if (statements != null) {
+//                                             for (int i = 0, max = statements.length; i < max; i++)
+//                                                     statements[i].resetStateForCodeGeneration();
+//                                     }
+//                                     classFile.contentsOffset = problemResetPC;
+//                                     classFile.methodCount--;
+//                                     classFile.codeStream.wideMode = true; // request wide mode 
+//                                     this.internalGenerateCode(classScope, classFile); // restart method generation
+//                             } catch (AbortMethod e2) {
+//                                     int problemsLength;
+//                                     IProblem[] problems =
+//                                             scope.referenceCompilationUnit().compilationResult.getAllProblems();
+//                                     IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+//                                     System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+//                                     classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC);
+//                             }
+//                     } else {
+//                             int problemsLength;
+//                             IProblem[] problems =
+//                                     scope.referenceCompilationUnit().compilationResult.getAllProblems();
+//                             IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+//                             System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+//                             classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC);
+//                     }
+//             }
+//     }
+//
+//     public void generateSyntheticFieldInitializationsIfNecessary(
+//             MethodScope scope,
+//             CodeStream codeStream,
+//             ReferenceBinding declaringClass) {
+//                     
+//             if (!declaringClass.isNestedType()) return;
+//             
+//             NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
+//
+//             SyntheticArgumentBinding[] syntheticArgs = nestedType.syntheticEnclosingInstances();
+//             for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i < max; i++) {
+//                     SyntheticArgumentBinding syntheticArg;
+//                     if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
+//                             codeStream.aload_0();
+//                             codeStream.load(syntheticArg);
+//                             codeStream.putfield(syntheticArg.matchingField);
+//                     }
+//             }
+//             syntheticArgs = nestedType.syntheticOuterLocalVariables();
+//             for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i < max; i++) {
+//                     SyntheticArgumentBinding syntheticArg;
+//                     if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
+//                             codeStream.aload_0();
+//                             codeStream.load(syntheticArg);
+//                             codeStream.putfield(syntheticArg.matchingField);
+//                     }
+//             }
+//     }
+//
+//     private void internalGenerateCode(ClassScope classScope, ClassFile classFile) {
+//             
+//             classFile.generateMethodInfoHeader(binding);
+//             int methodAttributeOffset = classFile.contentsOffset;
+//             int attributeNumber = classFile.generateMethodInfoAttribute(binding);
+//             if ((!binding.isNative()) && (!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 = binding.declaringClass;
+//
+//                     int argSlotSize = 1; // this==aload0
+//                     
+//                     if (declaringClass.isNestedType()){
+//                             NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
+//                             this.scope.extraSyntheticArguments = nestedType.syntheticOuterLocalVariables();
+//                             scope.computeLocalVariablePositions(// consider synthetic arguments if any
+//                                     nestedType.enclosingInstancesSlotSize + 1,
+//                                     codeStream);
+//                             argSlotSize += nestedType.enclosingInstancesSlotSize;
+//                             argSlotSize += nestedType.outerLocalVariablesSlotSize;
+//                     } else {
+//                             scope.computeLocalVariablePositions(1,  codeStream);
+//                     }
+//                             
+//                     if (arguments != null) {
+//                             for (int i = 0, max = arguments.length; i < max; i++) {
+//                                     // arguments initialization for local variable debug attributes
+//                                     LocalVariableBinding argBinding;
+//                                     codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding);
+//                                     argBinding.recordInitializationStartPC(0);
+//                                     TypeBinding argType;
+//                                     if ((argType = argBinding.type) == LongBinding || (argType == DoubleBinding)) {
+//                                             argSlotSize += 2;
+//                                     } else {
+//                                             argSlotSize++;
+//                                     }
+//                             }
+//                     }
+//                     
+//                     MethodScope initializerScope = declaringType.initializerScope;
+//                     initializerScope.computeLocalVariablePositions(argSlotSize, codeStream); // offset by the argument size (since not linked to method scope)
+//
+//                     boolean needFieldInitializations = constructorCall == null || constructorCall.accessMode != ExplicitConstructorCall.This;
+//
+//                     // post 1.4 source level, synthetic initializations occur prior to explicit constructor call
+//                     boolean preInitSyntheticFields = scope.environment().options.targetJDK >= CompilerOptions.JDK1_4;
+//
+//                     if (needFieldInitializations && preInitSyntheticFields){
+//                             generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, declaringClass);
+//                     }                       
+//                     // generate constructor call
+//                     if (constructorCall != null) {
+//                             constructorCall.generateCode(scope, codeStream);
+//                     }
+//                     // generate field initialization - only if not invoking another constructor call of the same class
+//                     if (needFieldInitializations) {
+//                             if (!preInitSyntheticFields){
+//                                     generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, declaringClass);
+//                             }
+//                             // 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);
+//                                             }
+//                                     }
+//                             }
+//                     }
+//                     // generate statements
+//                     if (statements != null) {
+//                             for (int i = 0, max = statements.length; i < max; i++) {
+//                                     statements[i].generateCode(scope, codeStream);
+//                             }
+//                     }
+//                     if (this.needFreeReturn) {
+//                             codeStream.return_();
+//                     }
+//                     // local variable attributes
+//                     codeStream.exitUserScope(scope);
+//                     codeStream.recordPositionsFrom(0, this.bodyEnd);
+//                     classFile.completeCodeAttribute(codeAttributeOffset);
+//                     attributeNumber++;
+//             }
+//             classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
+//
+//             // if a problem got reported during code gen, then trigger problem method creation
+//             if (ignoreFurtherInvestigation) {
+//                     throw new AbortMethod(scope.referenceCompilationUnit().compilationResult);
+//             }
+//     }
 
        public boolean isConstructor() {
 
@@ -286,14 +327,43 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                return true;
        }
 
-       public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
+       /**
+        * 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()
+                               || !this.constructorCall.binding.isValidBinding()) {
+                       return false;
+               }
+               
+               ConstructorDeclaration targetConstructor = 
+                       ((ConstructorDeclaration)this.scope.referenceType().declarationOf(constructorCall.binding));
+               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);
+       }
+       
+       public void parseStatements(UnitParser parser, CompilationUnitDeclaration unit) {
 
                //fill up the constructor body with its statements
                if (ignoreFurtherInvestigation)
                        return;
                if (isDefaultConstructor){
-                       constructorCall =
-                               new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+                       constructorCall = SuperReference.implicitSuperConstructorCall();
                        constructorCall.sourceStart = sourceStart;
                        constructorCall.sourceEnd = sourceEnd; 
                        return;
@@ -306,45 +376,28 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
         * Type checking for constructor, just another method, except for special check
         * for recursive constructor invocations.
         */
-       public void resolveStatements(ClassScope upperScope) {
-/*
-               // checking for recursive constructor call (protection)
-               if (!ignoreFurtherInvestigation && constructorCall == null){
-                       constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
-                       constructorCall.sourceStart = sourceStart;
-                       constructorCall.sourceEnd = sourceEnd;
-               }
-*/
+       public void resolveStatements() {
+
                if (!CharOperation.equals(scope.enclosingSourceType().sourceName, selector)){
                        scope.problemReporter().missingReturnType(this);
                }
 
                // if null ==> an error has occurs at parsing time ....
-               if (constructorCall != null) {
+               if (this.constructorCall != null) {
                        // e.g. using super() in java.lang.Object
-                       if (binding != null
-                               && binding.declaringClass.id == T_Object
-                               && constructorCall.accessMode != ExplicitConstructorCall.This) {
-                                       if (constructorCall.accessMode == ExplicitConstructorCall.Super) {
-                                               scope.problemReporter().cannotUseSuperInJavaLangObject(constructorCall);
+                       if (this.binding != null
+                               && this.binding.declaringClass.id == T_Object
+                               && this.constructorCall.accessMode != ExplicitConstructorCall.This) {
+                                       if (this.constructorCall.accessMode == ExplicitConstructorCall.Super) {
+                                               scope.problemReporter().cannotUseSuperInJavaLangObject(this.constructorCall);
                                        }
-                                       constructorCall = null;
+                                       this.constructorCall = null;
                        } else {
-                               constructorCall.resolve(scope);
+                               this.constructorCall.resolve(this.scope);
                        }
                }
                
-               super.resolveStatements(upperScope);
-
-               // indirect reference: increment target constructor reference count
-               if (constructorCall != null){
-                       if (constructorCall.binding != null
-                               && !constructorCall.isSuperAccess()
-                               && constructorCall.binding.isValidBinding()) {
-                               ((ConstructorDeclaration)
-                                               (upperScope.referenceContext.declarationOf(constructorCall.binding))).referenceCount++;
-                       }
-               }
+               super.resolveStatements();
        }
 
        public String toStringStatements(int tab) {
@@ -367,7 +420,7 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
        }
 
        public void traverse(
-               IAbstractSyntaxTreeVisitor visitor,
+           ASTVisitor visitor,
                ClassScope classScope) {
 
                if (visitor.visit(this, classScope)) {
@@ -391,4 +444,4 @@ public class ConstructorDeclaration extends AbstractMethodDeclaration {
                }
                visitor.endVisit(this, classScope);
        }
-}
\ No newline at end of file
+}