Program: 27672
Project: 27672
Buggy source:
private LValueResultFwd analyzePropLValFwd(Node obj,QualifiedName pname,TypeEnv inEnv,JSType type,boolean insideQualifiedName){
  Preconditions.checkArgument(pname.isIdentifier());
  String pnameAsString=pname.getLeftmostName();
  JSType reqObjType=pickReqObjType(obj).withLoose().withProperty(pname,type);
  LValueResultFwd lvalue=analyzeLValueFwd(obj,inEnv,reqObjType,true);
  TypeEnv lvalueEnv=lvalue.env;
  JSType lvalueType=lvalue.type;
  if (!lvalueType.isSubtypeOf(JSType.TOP_OBJECT)) {
    warnPropAccessOnNonobject(obj,pnameAsString,lvalueType);
    return new LValueResultFwd(lvalueEnv,type,null,null);
  }
  Node propAccessNode=obj.getParent();
  if (propAccessNode.isGetProp() && propAccessNode.getParent().isAssign() && mayWarnAboutPropCreation(pname,propAccessNode,lvalueType)) {
    return new LValueResultFwd(lvalueEnv,type,null,null);
  }
  if (!insideQualifiedName && mayWarnAboutConstProp(propAccessNode,lvalueType,pname)) {
    return new LValueResultFwd(lvalueEnv,type,null,null);
  }
  if (!lvalueType.mayHaveProp(pname)) {
    if (insideQualifiedName && lvalueType.isLoose()) {
      lvalueType=lvalueType.withProperty(pname,JSType.TOP_OBJECT.withLoose());
      if (lvalueType.isDict() && propAccessNode.isGetProp()) {
        lvalueType=lvalueType.specialize(JSType.TOP_STRUCT);
      }
 else       if (lvalueType.isStruct() && propAccessNode.isGetElem()) {
        lvalueType=lvalueType.specialize(JSType.TOP_DICT);
      }
      lvalueEnv=updateLvalueTypeInEnv(lvalueEnv,obj,lvalue.ptr,lvalueType);
    }
 else {
      boolean warnForInexistentProp=insideQualifiedName || propAccessNode.getParent().getType() != Token.ASSIGN;
      if (warnForInexistentProp && !lvalueType.isUnknown() && !lvalueType.isDict()) {
        warnings.add(JSError.make(obj,TypeCheck.INEXISTENT_PROPERTY,pnameAsString,lvalueType.toString()));
        return new LValueResultFwd(lvalueEnv,type,null,null);
      }
    }
  }
  if (propAccessNode.isGetElem()) {
    mayWarnAboutStructPropAccess(obj,lvalueType);
  }
 else   if (propAccessNode.isGetProp()) {
    mayWarnAboutDictPropAccess(obj,lvalueType);
  }
  QualifiedName setterPname=new QualifiedName(SETTER_PREFIX + pnameAsString);
  if (lvalueType.hasProp(setterPname)) {
    FunctionType funType=lvalueType.getProp(setterPname).getFunType();
    Preconditions.checkNotNull(funType);
    JSType formalType=funType.getFormalType(0);
    Preconditions.checkState(!formalType.isBottom());
    return new LValueResultFwd(lvalueEnv,formalType,formalType,null);
  }
  return new LValueResultFwd(lvalueEnv,lvalueType.mayHaveProp(pname) ? lvalueType.getProp(pname) : JSType.UNKNOWN,lvalueType.mayHaveProp(pname) ? lvalueType.getDeclaredProp(pname) : null,lvalue.ptr == null ? null : QualifiedName.join(lvalue.ptr,pname));
}

Fixed version (ground truth):
private LValueResultFwd analyzePropLValFwd(Node obj,QualifiedName pname,TypeEnv inEnv,JSType type,boolean insideQualifiedName){
  Preconditions.checkArgument(pname.isIdentifier());
  String pnameAsString=pname.getLeftmostName();
  JSType reqObjType=pickReqObjType(obj.getParent()).withLoose().withProperty(pname,type);
  LValueResultFwd lvalue=analyzeLValueFwd(obj,inEnv,reqObjType,true);
  TypeEnv lvalueEnv=lvalue.env;
  JSType lvalueType=lvalue.type;
  if (!lvalueType.isSubtypeOf(JSType.TOP_OBJECT)) {
    warnPropAccessOnNonobject(obj,pnameAsString,lvalueType);
    return new LValueResultFwd(lvalueEnv,type,null,null);
  }
  Node propAccessNode=obj.getParent();
  if (propAccessNode.isGetProp() && propAccessNode.getParent().isAssign() && mayWarnAboutPropCreation(pname,propAccessNode,lvalueType)) {
    return new LValueResultFwd(lvalueEnv,type,null,null);
  }
  if (!insideQualifiedName && mayWarnAboutConstProp(propAccessNode,lvalueType,pname)) {
    return new LValueResultFwd(lvalueEnv,type,null,null);
  }
  if (!lvalueType.mayHaveProp(pname)) {
    if (insideQualifiedName && lvalueType.isLoose()) {
      lvalueType=lvalueType.withProperty(pname,JSType.TOP_OBJECT.withLoose());
      if (lvalueType.isDict() && propAccessNode.isGetProp()) {
        lvalueType=lvalueType.specialize(JSType.TOP_STRUCT);
      }
 else       if (lvalueType.isStruct() && propAccessNode.isGetElem()) {
        lvalueType=lvalueType.specialize(JSType.TOP_DICT);
      }
      lvalueEnv=updateLvalueTypeInEnv(lvalueEnv,obj,lvalue.ptr,lvalueType);
    }
 else {
      boolean warnForInexistentProp=insideQualifiedName || propAccessNode.getParent().getType() != Token.ASSIGN;
      if (warnForInexistentProp && !lvalueType.isUnknown() && !lvalueType.isDict()) {
        warnings.add(JSError.make(obj,TypeCheck.INEXISTENT_PROPERTY,pnameAsString,lvalueType.toString()));
        return new LValueResultFwd(lvalueEnv,type,null,null);
      }
    }
  }
  if (propAccessNode.isGetElem()) {
    mayWarnAboutStructPropAccess(obj,lvalueType);
  }
 else   if (propAccessNode.isGetProp()) {
    mayWarnAboutDictPropAccess(obj,lvalueType);
  }
  QualifiedName setterPname=new QualifiedName(SETTER_PREFIX + pnameAsString);
  if (lvalueType.hasProp(setterPname)) {
    FunctionType funType=lvalueType.getProp(setterPname).getFunType();
    Preconditions.checkNotNull(funType);
    JSType formalType=funType.getFormalType(0);
    Preconditions.checkState(!formalType.isBottom());
    return new LValueResultFwd(lvalueEnv,formalType,formalType,null);
  }
  return new LValueResultFwd(lvalueEnv,lvalueType.mayHaveProp(pname) ? lvalueType.getProp(pname) : JSType.UNKNOWN,lvalueType.mayHaveProp(pname) ? lvalueType.getDeclaredProp(pname) : null,lvalue.ptr == null ? null : QualifiedName.join(lvalue.ptr,pname));
}