Program: 82822
Project: 82822
Buggy source:
/** 
 * Weird: we used to have JConstructor (and JConstructorCall) in our AST, but we got rid of them completely and instead model them as instance methods whose qualifier is a naked no-argument new operation. There are several reasons we do it this way: 1) When spitting our AST back to Java code (for verification purposes), we found it was impossible to correctly emulate nested classes as non-nested classes using traditional constructor syntax. It boiled down to the fact that you really HAVE to assign your synthetic arguments to your synthetic fields BEFORE calling your superclass constructor (because it might call you back polymorphically). And trying to do that in straight Java is a semantic error, a super call must be the first statement of your constructor. 2) It's a lot more like how we'll be generating JavaScript eventually. 3) It's a lot easier to optimize; the same optimizations work on our synthetic fields as work on any user fields. In fact, once we're past AST generation, we throw away all information about what's synthetic. The order of emulation is: - assign all synthetic fields from synthetic args - call our super constructor emulation method - call our instance initializer emulation method - run user code - return this
 */
void processConstructor(ConstructorDeclaration x){
  JMethod ctor=(JMethod)typeMap.get(x.binding);
  try {
    SourceInfo info=ctor.getSourceInfo();
    currentMethod=ctor;
    currentMethodBody=(JMethodBody)ctor.getBody();
    currentMethodScope=x.scope;
    JMethodCall superOrThisCall=null;
    ExplicitConstructorCall ctorCall=x.constructorCall;
    if (ctorCall != null) {
      superOrThisCall=(JMethodCall)dispatch("String_Node_Str",ctorCall);
    }
    boolean hasExplicitThis=(ctorCall != null) && !ctorCall.isSuperAccess();
    JClassType enclosingType=(JClassType)ctor.getEnclosingType();
    JMethod clinitMethod=enclosingType.methods.get(0);
    JMethodCall clinitCall=new JMethodCall(program,info,null,clinitMethod);
    JMethodBody body=(JMethodBody)ctor.getBody();
    List<JStatement> statements=body.getStatements();
    statements.add(clinitCall.makeStatement());
    if (!hasExplicitThis) {
      ReferenceBinding declaringClass=x.binding.declaringClass;
      if (declaringClass instanceof NestedTypeBinding) {
        Iterator<JParameter> paramIt=getSyntheticsIterator(ctor);
        NestedTypeBinding nestedBinding=(NestedTypeBinding)declaringClass;
        if (nestedBinding.enclosingInstances != null) {
          for (int i=0; i < nestedBinding.enclosingInstances.length; ++i) {
            SyntheticArgumentBinding arg=nestedBinding.enclosingInstances[i];
            JParameter param=paramIt.next();
            if (arg.matchingField != null) {
              JField field=(JField)typeMap.get(arg);
              statements.add(program.createAssignmentStmt(info,createVariableRef(info,field),createVariableRef(info,param)));
            }
          }
        }
        if (nestedBinding.outerLocalVariables != null) {
          for (int i=0; i < nestedBinding.outerLocalVariables.length; ++i) {
            SyntheticArgumentBinding arg=nestedBinding.outerLocalVariables[i];
            JParameter param=paramIt.next();
            JField field=(JField)typeMap.get(arg);
            statements.add(program.createAssignmentStmt(info,createVariableRef(info,field),createVariableRef(info,param)));
          }
        }
      }
    }
    if (enclosingType.isEnumOrSubclass() != null) {
      assert(superOrThisCall != null);
      JVariableRef enumNameRef=createVariableRef(superOrThisCall.getSourceInfo(),ctor.params.get(0));
      superOrThisCall.getArgs().add(0,enumNameRef);
      JVariableRef enumOrdinalRef=createVariableRef(superOrThisCall.getSourceInfo(),ctor.params.get(1));
      superOrThisCall.getArgs().add(1,enumOrdinalRef);
    }
    if (superOrThisCall != null) {
      statements.add(superOrThisCall.makeStatement());
    }
    JExpression thisRef=createThisRef(info,enclosingType);
    if (!hasExplicitThis) {
      JMethod initMethod=enclosingType.methods.get(1);
      JMethodCall initCall=new JMethodCall(program,info,thisRef,initMethod);
      statements.add(initCall.makeStatement());
    }
    if (x.statements != null) {
      for (int i=0, n=x.statements.length; i < n; ++i) {
        Statement origStmt=x.statements[i];
        JStatement jstmt=dispProcessStatement(origStmt);
        if (jstmt != null) {
          statements.add(jstmt);
        }
      }
    }
    currentMethodScope=null;
    currentMethod=null;
    statements.add(new JReturnStatement(program,null,thisRef));
  }
 catch (  Throwable e) {
    throw translateException(ctor,e);
  }
}

Fixed version (ground truth):
/** 
 * Weird: we used to have JConstructor (and JConstructorCall) in our AST, but we got rid of them completely and instead model them as instance methods whose qualifier is a naked no-argument new operation. There are several reasons we do it this way: 1) When spitting our AST back to Java code (for verification purposes), we found it was impossible to correctly emulate nested classes as non-nested classes using traditional constructor syntax. It boiled down to the fact that you really HAVE to assign your synthetic arguments to your synthetic fields BEFORE calling your superclass constructor (because it might call you back polymorphically). And trying to do that in straight Java is a semantic error, a super call must be the first statement of your constructor. 2) It's a lot more like how we'll be generating JavaScript eventually. 3) It's a lot easier to optimize; the same optimizations work on our synthetic fields as work on any user fields. In fact, once we're past AST generation, we throw away all information about what's synthetic. The order of emulation is: - assign all synthetic fields from synthetic args - call our super constructor emulation method - call our instance initializer emulation method - run user code - return this
 */
void processConstructor(ConstructorDeclaration x){
  JMethod ctor=(JMethod)typeMap.get(x.binding);
  try {
    SourceInfo info=ctor.getSourceInfo();
    currentMethod=ctor;
    currentMethodBody=(JMethodBody)ctor.getBody();
    currentMethodScope=x.scope;
    JMethodCall superOrThisCall=null;
    ExplicitConstructorCall ctorCall=x.constructorCall;
    if (ctorCall != null) {
      superOrThisCall=(JMethodCall)dispatch("String_Node_Str",ctorCall);
    }
    boolean hasExplicitThis=(ctorCall != null) && !ctorCall.isSuperAccess();
    JClassType enclosingType=(JClassType)ctor.getEnclosingType();
    JMethod clinitMethod=enclosingType.methods.get(0);
    JMethodCall clinitCall=new JMethodCall(program,info,null,clinitMethod);
    JMethodBody body=(JMethodBody)ctor.getBody();
    List<JStatement> statements=body.getStatements();
    statements.add(clinitCall.makeStatement());
    if (!hasExplicitThis) {
      ReferenceBinding declaringClass=x.binding.declaringClass;
      if (declaringClass instanceof NestedTypeBinding) {
        Iterator<JParameter> paramIt=getSyntheticsIterator();
        NestedTypeBinding nestedBinding=(NestedTypeBinding)declaringClass;
        if (nestedBinding.enclosingInstances != null) {
          for (int i=0; i < nestedBinding.enclosingInstances.length; ++i) {
            SyntheticArgumentBinding arg=nestedBinding.enclosingInstances[i];
            JParameter param=paramIt.next();
            if (arg.matchingField != null) {
              JField field=(JField)typeMap.get(arg);
              statements.add(program.createAssignmentStmt(info,createVariableRef(info,field),createVariableRef(info,param)));
            }
          }
        }
        if (nestedBinding.outerLocalVariables != null) {
          for (int i=0; i < nestedBinding.outerLocalVariables.length; ++i) {
            SyntheticArgumentBinding arg=nestedBinding.outerLocalVariables[i];
            JParameter param=paramIt.next();
            JField field=(JField)typeMap.get(arg);
            statements.add(program.createAssignmentStmt(info,createVariableRef(info,field),createVariableRef(info,param)));
          }
        }
      }
    }
    if (enclosingType.isEnumOrSubclass() != null) {
      assert(superOrThisCall != null);
      JVariableRef enumNameRef=createVariableRef(superOrThisCall.getSourceInfo(),ctor.params.get(0));
      superOrThisCall.getArgs().add(0,enumNameRef);
      JVariableRef enumOrdinalRef=createVariableRef(superOrThisCall.getSourceInfo(),ctor.params.get(1));
      superOrThisCall.getArgs().add(1,enumOrdinalRef);
    }
    if (superOrThisCall != null) {
      statements.add(superOrThisCall.makeStatement());
    }
    JExpression thisRef=createThisRef(info,enclosingType);
    if (!hasExplicitThis) {
      JMethod initMethod=enclosingType.methods.get(1);
      JMethodCall initCall=new JMethodCall(program,info,thisRef,initMethod);
      statements.add(initCall.makeStatement());
    }
    if (x.statements != null) {
      for (int i=0, n=x.statements.length; i < n; ++i) {
        Statement origStmt=x.statements[i];
        JStatement jstmt=dispProcessStatement(origStmt);
        if (jstmt != null) {
          statements.add(jstmt);
        }
      }
    }
    currentMethodScope=null;
    currentMethod=null;
    statements.add(new JReturnStatement(program,null,thisRef));
  }
 catch (  Throwable e) {
    throw translateException(ctor,e);
  }
}