pike.git / src / program.c

version» Context lines:

pike.git/src/program.c:2369:    continue;    }       if ((ref->id_flags & (ID_INHERITED|ID_USED)) == (ID_INHERITED|ID_USED)) {    struct inherit *inh = INHERIT_FROM_PTR(Pike_compiler->new_program, ref);    struct reference *sub_ref;       /* Find the inherit one level away. */    while (inh->inherit_level > 1) inh--;    + #if 0   #ifdef PIKE_DEBUG    if (!inh->inherit_level) { -  +  /* FIXME: This is valid for references that are about to be +  * overridden by the variant dispatcher. +  */    Pike_fatal("Inherit without intermediate levels.\n");    }   #endif -  + #endif       sub_ref = PTR_FROM_INT(inh->prog, cur_id - inh->identifier_level);       /* Check if the symbol was used before it was inherited. */    if ((c->lex.pragmas & ID_STRICT_TYPES) &&    (sub_ref->id_flags & ID_USED)) {    struct identifier *sub_id = ID_FROM_PTR(inh->prog, sub_ref);    if (IDENTIFIER_IS_FUNCTION(sub_id->identifier_flags)) {    if ((Pike_compiler->compiler_pass == 2) &&    !pike_types_le(ID_FROM_PTR(Pike_compiler->new_program,
pike.git/src/program.c:2743:    struct pike_string *name,    int flags,    int *idp)   {    struct compilation *c = THIS_COMPILATION;    int id=0;    struct svalue tmp;       CHECK_COMPILER();    - #ifdef WITH_FACETS -  if(Pike_compiler->compiler_pass == 1 && p) { -  p->facet_index = -1; -  p->facet_group = NULL; -  } - #endif -  +     /* We don't want to change thread, but we don't want to    * wait for the other threads to complete either.    */    low_init_threads_disable();       c->compilation_depth++;       if (!Pike_compiler->compiler_frame) {    new_node_s_context();    }
pike.git/src/program.c:3119:    {    if(p->inherits[e].prog)    free_program(p->inherits[e].prog);    }    if(p->inherits[e].parent)    free_object(p->inherits[e].parent);    }       DOUBLEUNLINK(first_program, p);    - #ifdef WITH_FACETS -  if(p->facet_group) -  { -  free_object(p->facet_group); -  } - #endif -  +     if(p->flags & PROGRAM_OPTIMIZED)    {   #ifdef PIKE_USE_MACHINE_CODE    do {    /* NOTE: Assumes all BAR's are before any FOO. */   #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \    if (p->NAME) mexec_free(p->NAME);   #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \    if (p->NAME) { \    dmfree(p->NAME); \
pike.git/src/program.c:3791:    "Program->identifier_index[%ld]\n",    (long)(e-1), (long)e);    }    }      }   #endif      static void f_dispatch_variant(INT32 args);    + static int is_variant_dispatcher(struct program *prog, int fun) + { +  struct reference *ref; +  struct identifier *id; +  if (fun < 0) return 0; +  ref = PTR_FROM_INT(prog, fun); +  id = ID_FROM_PTR(prog, ref); +  return (IDENTIFIER_IS_C_FUNCTION(id->identifier_flags) && +  (id->func.c_fun == f_dispatch_variant)); + } +  + static int add_variant_dispatcher(struct pike_string *name, +  struct pike_type *type, +  int id_flags) + { +  union idptr dispatch_fun; +  dispatch_fun.c_fun = f_dispatch_variant; +  return define_function(name, type, id_flags & ~(ID_VARIANT|ID_LOCAL), +  IDENTIFIER_C_FUNCTION, &dispatch_fun, 0); + } +    /* Note: This function is misnamed, since it's run after both passes. /mast */   /* finish-states:    *    * 0: First pass.    * 1: Last pass.    * 2: Called from decode_value().    */   struct program *end_first_pass(int finish)   {    struct compilation *c = THIS_COMPILATION;
pike.git/src/program.c:3819:    /* Collect variant functions that have been defined in this program,    * and add the corresponding dispatchers.    */    for (e = 0; e < num_refs; e++) {    struct identifier *id;    struct pike_string *name;    struct pike_type *type;    int id_flags;    int j;    if (prog->identifier_references[e].inherit_offset) continue; -  if (!((id_flags = prog->identifier_references[e].id_flags) & ID_VARIANT)) { -  /* Not a variant function. */ -  continue; -  } +  if (!is_variant_dispatcher(prog, e)) continue; +  /* Found a dispatcher. */ +     id = ID_FROM_INT(prog, e);    name = id->name; -  type = id->type; +  type = NULL; +  id_flags = 0;       CDFPRINTF((stderr, "Collecting variants of \"%s\"...\n", name->str));    -  /* Check whether we've added a dispatcher for this function already. */ -  j = isidentifier(name); -  if ((j >= 0) && (!prog->identifier_references[j].inherit_offset)) { -  /* Already handled. */ -  CDFPRINTF((stderr, "Dispatcher present!\n")); -  goto next_ref; -  } -  - #ifdef COMPILER_DEBUG -  fprintf(stderr, "type: "); -  simple_describe_type(type); -  fprintf(stderr, "\n"); - #endif -  -  /* Collect the other variants of the function. */ -  for (j = e+1; j < num_refs; j++) { -  if (prog->identifier_references[j].inherit_offset) continue; -  if (!(prog->identifier_references[j].id_flags & ID_VARIANT)) continue; +  /* Collect the variants of the function. */ +  j = prog->num_identifier_references; +  while ((j = really_low_find_variant_identifier(name, prog, NULL, j, +  SEE_PROTECTED|SEE_PRIVATE)) >= 0) { +  struct reference *ref = prog->identifier_references + j;    id = ID_FROM_INT(prog, j); -  if (name != id->name) continue; -  id_flags |= prog->identifier_references[j].id_flags; +  id_flags |= ref->id_flags; +  /* NB: The dispatcher needs the variant references to +  * not get overloaded for the ::-operator to work. +  */ +  prog->identifier_references[j].id_flags |= ID_LOCAL;    type = or_pike_types(type, id->type, 1);   #ifdef COMPILER_DEBUG    fprintf(stderr, "type: ");    simple_describe_type(id->type);    fprintf(stderr, "\n");   #endif    } -  /* Include the directly inherited variants as well. */ -  for (j = 1; j < prog->num_inherits; j++) { -  struct inherit *inh = &prog->inherits[j]; -  if (inh->inherit_level != 1) continue; -  e = really_low_find_shared_string_identifier(name, inh->prog, -  SEE_PROTECTED); -  if (e == -1) continue; -  id = ID_FROM_INT(inh->prog, e); -  id_flags |= inh->prog->identifier_references[e].id_flags; -  type = or_pike_types(type, id->type, 1); -  } +    #ifdef COMPILER_DEBUG    fprintf(stderr, "Dispatcher type: ");    simple_describe_type(type);    fprintf(stderr, "\n");   #endif -  define_function(name, type, id_flags & ~ID_VARIANT, -  IDENTIFIER_C_FUNCTION, &dispatch_fun, 0); +  /* Update the type of the dispatcher. */ +  id = ID_FROM_INT(prog, e); +  free_type(id->type); +  id->type = type; +  prog->identifier_references->id_flags |= id_flags & ~(ID_VARIANT|ID_LOCAL);    next_ref:    ;    }       debug_malloc_touch(Pike_compiler->fake_object);    debug_malloc_touch(Pike_compiler->fake_object->storage);       MAKE_CONST_STRING(s,"__INIT");      
pike.git/src/program.c:4528: Inside #if 0
   parent_offset+=i->parent_offset;   #endif       return locate_parent_state(&state,    &i,    &parent_identifier,    depth);   }   #endif    - #ifdef WITH_FACETS - void check_for_facet_inherit(struct program *p) - { -  /* If the inherit statement comes before the facet keyword in the -  * class declaration the class will be temporarily marked as a -  * product-class, but this will be taken care of when the facet -  * keyword is found. */ -  if (!p) return; -  if (Pike_compiler->new_program->facet_group && -  p->facet_group != Pike_compiler->new_program->facet_group) -  yyerror("A class can not belong to two facet-groups."); -  if (p->flags & PROGRAM_IS_FACET) { -  if (Pike_compiler->new_program->flags & PROGRAM_IS_FACET) { -  if(Pike_compiler->new_program->facet_index != p->facet_index) -  yyerror("Facet class can't inherit from class in different facet."); -  } -  /* Otherwise this is a product class */ -  else { -  if( !Pike_compiler->new_program->facet_group ) { -  Pike_compiler->new_program->flags |= PROGRAM_IS_PRODUCT; -  add_ref(p->facet_group); -  Pike_compiler->new_program->facet_group = p->facet_group; -  } -  push_int(Pike_compiler->new_program->id); -  push_int(p->facet_index); -  push_int(p->id); -  safe_apply(p->facet_group, "add_product_class", 3); -  pop_stack(); -  } -  } -  /* The inherited class is not a facet class */ -  else if (p->flags & PROGRAM_IS_PRODUCT) { -  if (Pike_compiler->new_program->flags & PROGRAM_IS_FACET) { -  yyerror("Facet class can't inherit from product class."); -  } -  else if(Pike_compiler->new_program->flags & PROGRAM_IS_PRODUCT){ -  yyerror("Product class can't inherit from other product class."); -  } -  /* A class that inherits from a product class is also a product class */ -  else { -  Pike_compiler->new_program->flags |= PROGRAM_IS_PRODUCT; -  add_ref(p->facet_group); -  Pike_compiler->new_program->facet_group = p->facet_group; -  } -  } - } - #endif -  -  +    static void lower_inherit(struct program *p,    struct object *parent,    int parent_identifier,    int parent_offset,    INT32 flags,    struct pike_string *name)   {    int e;    ptrdiff_t inherit_offset, storage_offset;    struct inherit inherit;
pike.git/src/program.c:4664:    }       if (!(p->flags & (PROGRAM_FINISHED | PROGRAM_PASS_1_DONE))) {    yyerror ("Cannot inherit program in pass 1 "    "which is only a placeholder.");    yyerror ("(You probably have a cyclic symbol dependency that the "    "compiler cannot handle.)");    return;    }    - #ifdef WITH_FACETS -  /* Check if inherit is a facet inherit. */ -  check_for_facet_inherit(p); - #endif -  +     if (p == placeholder_program) {    yyerror("Trying to inherit placeholder program (resolver problem).");    return;    }       /* parent offset was increased by 42 for above test.. */    if(parent_offset)    parent_offset-=42;       inherit_offset = Pike_compiler->new_program->num_inherits;
pike.git/src/program.c:5022:   /*    * Return the index of the identifier found, otherwise -1.    */   int isidentifier(struct pike_string *s)   {    return really_low_find_shared_string_identifier(s,    Pike_compiler->new_program,    SEE_PROTECTED|SEE_PRIVATE);   }    - /** -  * Return the index of the identifier if found, otherwise -1. -  * -  * If id_flags indicates a variant function, the index for a -  * variant function with the same type and name is returned -  * if found, otherwise -1. -  */ - int isidentifier_variant(struct pike_string *name, -  unsigned id_flags, -  struct pike_type *type) - { -  if (id_flags & ID_VARIANT) { -  return really_low_find_variant_identifier(name, -  Pike_compiler->new_program, -  type, -  Pike_compiler->new_program-> -  num_identifier_references, -  SEE_PROTECTED|SEE_PRIVATE); -  } else { -  return isidentifier(name); -  } - } -  +    /*    * Definition of identifiers.    *    * Pike has three plus one classes of identifiers:    *    * IDENTIFIER_VARIABLE - A value stored in object->storage    * IDENTIFIER_CONSTANT - A value stored in program->constants    * IDENTIFIER_FUNCTION - Either a C function or a Pike function    * and    * IDENTIFIER_ALIAS - An alias for a different identifier.
pike.git/src/program.c:5633:    id=ID_FROM_INT(Pike_compiler->new_program,n);    if(id->func.const_info.offset>=0) {    /* Update the stored constant. */    assign_svalue (&PROG_FROM_INT(Pike_compiler->new_program,n)->    constants[id->func.const_info.offset].sval, c);    } else {    id->run_time_type = (unsigned char) TYPEOF(*c);    id->func.const_info.offset = store_constant(c, 0, 0);    }    free_type(id->type); -  if ((TYPEOF(*c) == T_INT) && !(flags & ID_INLINE)) { -  if (c->u.integer) { -  copy_pike_type(id->type, int_type_string); -  } else { -  copy_pike_type(id->type, zero_type_string); -  } -  } else { -  id->type = get_type_of_svalue(c); -  } +  if( !(flags & ID_INLINE) ) +  id->type = get_lax_type_of_svalue( c ); +  else +  id->type = get_type_of_svalue( c );   #ifdef PROGRAM_BUILD_DEBUG    fprintf (stderr, "%.*sstored constant #%d at %d\n",    cc->compilation_depth, "",    n, id->func.const_info.offset);   #endif    }    return n;    }      #ifdef PIKE_DEBUG
pike.git/src/program.c:5671:   #endif       copy_shared_string(dummy.name, name);    dummy.identifier_flags = IDENTIFIER_CONSTANT;    dummy.filename_strno = store_prog_string(cc->lex.current_file);    dummy.linenumber = cc->lex.current_line;      #if 1    if (c) {   #endif -  if ((TYPEOF(*c) == T_INT) && !(flags & ID_INLINE)) { -  if (c->u.integer) { -  copy_pike_type(dummy.type, int_type_string); -  } else { -  copy_pike_type(dummy.type, zero_type_string); -  } -  } else { -  dummy.type = get_type_of_svalue(c); -  } +  if( !(flags & ID_INLINE) ) +  dummy.type = get_lax_type_of_svalue( c ); +  else +  dummy.type = get_type_of_svalue( c );    dummy.run_time_type = (unsigned char) TYPEOF(*c);    dummy.func.const_info.offset = store_constant(c, 0, 0);    dummy.opt_flags=OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND;    if(TYPEOF(*c) == PIKE_T_PROGRAM && (c->u.program->flags & PROGRAM_CONSTANT))    dummy.opt_flags=0;   #if 1    }    else {    copy_pike_type(dummy.type, mixed_type_string);    dummy.run_time_type=T_MIXED;
pike.git/src/program.c:5905:    * if func isn't given, it is supposed to be a prototype.    */   INT32 define_function(struct pike_string *name,    struct pike_type *type,    unsigned flags,    unsigned function_flags,    union idptr *func,    unsigned opt_flags)   {    struct compilation *c = THIS_COMPILATION; +  struct program *prog = Pike_compiler->new_program;    struct identifier *funp,fun;    struct reference ref;    struct svalue *lfun_type;    int run_time_type = T_FUNCTION;    INT32 i;    int getter_setter = -1;    int is_setter = 0;       CHECK_COMPILER();   
pike.git/src/program.c:5998:    int level = REPORT_NOTICE;    if (!match_types(type, gs_type)) {    level = REPORT_ERROR;    } else if (c->lex.pragmas & ID_STRICT_TYPES) {    level = REPORT_WARNING;    }    yytype_report(level, NULL, 0, gs_type,    NULL, 0, type, 0,    "Type mismatch for callback function %S:", name);    } +  if (flags & ID_VARIANT) { +  my_yyerror("Variants not supported for getter/setters: %S", name); +  flags &= ~ID_VARIANT; +  }    i = isidentifier(symbol);    if ((i >= 0) && -  !((ref = PTR_FROM_INT(Pike_compiler->new_program, i))-> -  id_flags & ID_INHERITED)) { +  !((ref = PTR_FROM_INT(prog, i))->id_flags & ID_INHERITED)) {    /* Not an inherited symbol. */ -  struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, i); +  struct identifier *id = ID_FROM_INT(prog, i);    if (!IDENTIFIER_IS_VARIABLE(id->identifier_flags)) {    my_yyerror("Illegal to redefine function %S with variable.", symbol);    } else if (id->run_time_type != PIKE_T_GET_SET) {    my_yyerror("Illegal to redefine a current variable with a getter/setter: %S.", symbol);    } else {    if ((ref->id_flags | ID_USED) != (flags | ID_USED)) {    if (Pike_compiler->compiler_pass == 1) {    yywarning("Modifier mismatch for variable %S.", symbol);    }    ref->id_flags &= flags | ID_USED;    }    getter_setter = i;    }    /* FIXME: Update id->type here. */    } else {    struct identifier *id;    i = low_define_variable(symbol, symbol_type, flags,    ~0, PIKE_T_GET_SET); -  id = ID_FROM_INT(Pike_compiler->new_program, i); +  id = ID_FROM_INT(prog, i);       /* Paranoia. */    id->func.gs_info.getter = -1;    id->func.gs_info.setter = -1;       getter_setter = i;    }    /* NOTE: The function needs to have the same PRIVATE/INLINE    * behaviour as the variable for overloading to behave    * as expected.    *    * FIXME: Force PRIVATE?    */    flags |= ID_PROTECTED /* | ID_PRIVATE | ID_INLINE | ID_USED */;    free_type(symbol_type);    free_string(symbol);    }    }       if(IDENTIFIER_IS_C_FUNCTION(function_flags)) -  Pike_compiler->new_program->flags |= PROGRAM_HAS_C_METHODS; +  prog->flags |= PROGRAM_HAS_C_METHODS;       if (Pike_compiler->compiler_pass == 1) {    /* Mark the type as tentative by setting the runtime-type    * to T_MIXED.    *    * NOTE: This should be reset to T_FUNCTION in pass 2.    */    run_time_type = T_MIXED;    }    -  i = isidentifier_variant(name, flags, type); +  i = isidentifier(name); +  if (Pike_compiler->compiler_pass == 1) { +  if (flags & ID_VARIANT) { +  if (i >= 0) { +  if (!is_variant_dispatcher(prog, i)) { +  /* This function will be the termination function for +  * our variant dispatcher. +  */ +  struct reference ref = prog->identifier_references[i]; +  /* Make sure to not get complaints about multiple +  * definitions when adding the variant dispatcher. +  */ +  prog->identifier_references[i].id_flags |= ID_INHERITED; +  add_variant_dispatcher(name, type, flags); +  /* Restore the termination function as a variant. */ +  ref.id_flags |= ID_VARIANT; +  if (is_variant_dispatcher(prog, i)) { +  /* The termination function got replaced with +  * the variant dispatcher. +  */ +  add_to_identifier_references(ref); +  } else { +  /* The termination function is still in the same place. */ +  prog->identifier_references[i].id_flags = ref.id_flags; +  } +  } else if (prog->identifier_references[i].inherit_offset) { +  /* NB: If we are overriding an inherited dispatcher, there's +  * no need to go via it, since our new dispatcher can +  * just continue on with the old ones variant functions. +  */ +  add_variant_dispatcher(name, type, flags); +  } +  } else { +  add_variant_dispatcher(name, type, flags); +  } +  i = really_low_find_variant_identifier(name, prog, type, +  prog->num_identifier_references, +  SEE_PROTECTED|SEE_PRIVATE); +  } else if (is_variant_dispatcher(prog, i) && +  !prog->identifier_references[i].inherit_offset) { +  if (!func || (func->c_fun != f_dispatch_variant) || +  !IDENTIFIER_IS_C_FUNCTION(function_flags)) { +  /* FIXME: What about the case +  * +  * non-variant prototype; +  * +  * variant; +  * +  * non-variant definition. +  */ +  my_yyerror("Overriding variant function %S() with " +  "non-variant in the same class.", +  name); +  } +  } +  } else if (i >= 0) { +  /* Pass 2 */ +  if (is_variant_dispatcher(prog, i)) { +  if (!func || (func->c_fun != f_dispatch_variant) || +  !IDENTIFIER_IS_C_FUNCTION(function_flags)) { +  /* Variant or variant termination function in second pass. */ +  flags |= ID_VARIANT; +  i = really_low_find_variant_identifier(name, prog, type, +  prog->num_identifier_references, +  SEE_PROTECTED|SEE_PRIVATE); +  } +  } +  }       if(i >= 0)    {    int overridden;       /* already defined */      #ifdef PROGRAM_BUILD_DEBUG    fprintf(stderr, "%.*sexisted as identifier #%d\n",    c->compilation_depth, "", i);   #endif    -  funp=ID_FROM_INT(Pike_compiler->new_program, i); -  ref=Pike_compiler->new_program->identifier_references[i]; +  funp = ID_FROM_INT(prog, i); +  ref = prog->identifier_references[i];       if (funp->identifier_flags & IDENTIFIER_HAS_BODY)    /* Keep this flag. */    function_flags |= IDENTIFIER_HAS_BODY;       if(!(ref.id_flags & ID_INHERITED)) /* not inherited */    {       if( !( IDENTIFIER_IS_FUNCTION(funp->identifier_flags) &&    ( (!func || func->offset == -1) || (funp->func.offset == -1))))    {    my_yyerror("Identifier %S defined twice.", name);       if (getter_setter != -1) { -  struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, -  getter_setter); +  struct identifier *id = ID_FROM_INT(prog, getter_setter);    (&id->func.gs_info.getter)[is_setter] = i;    }    return i;    }       /* Note: The type from pass 1 may be incompatible with the one from    * pass 2. Only do this in pass 2, and only if the previous    * type isn't from pass 1.    */    if ((Pike_compiler->compiler_pass == 2) &&
pike.git/src/program.c:6135:       if((ref.id_flags & ID_FINAL)   #if 0    && !(funp->func.offset == -1)   #endif    )    {    my_yyerror("Illegal to redefine 'final' function %S.", name);    }    +  if (!(flags & ID_VARIANT) && (Pike_compiler->compiler_pass == 1) && +  (funp->func.c_fun == f_dispatch_variant) && +  (!func || (func->c_fun != f_dispatch_variant) || +  !IDENTIFIER_IS_C_FUNCTION(function_flags)) && +  IDENTIFIER_IS_C_FUNCTION(funp->identifier_flags)) { +  /* Overriding a variant function dispatcher with +  * a non-variant function in pass 1. +  * +  * Hide the corresponding variant functions. +  */ +  int j = prog->num_identifier_references; +  while ((j = really_low_find_variant_identifier(name, prog, NULL, j, +  SEE_PROTECTED|SEE_PRIVATE)) != -1) { +  if (!prog->identifier_references[j].inherit_offset) { +  /* FIXME: This doesn't catch all cases, and should probably +  * be moved to a place where it does. +  */ +  my_yyerror("Overloading variant function %S with non-variant in same class.", +  name); +  } +  prog->identifier_references[j].id_flags |= ID_HIDDEN; +  } +  }       if(ref.id_flags & ID_INLINE)    {   #ifdef PROGRAM_BUILD_DEBUG    fprintf(stderr, "%.*sidentifier is local\n",    c->compilation_depth, "");   #endif    /* Hide the previous definition, and make a new definition. */ -  Pike_compiler->new_program->identifier_references[i].id_flags |= -  ID_PROTECTED; +  prog->identifier_references[i].id_flags |= ID_PROTECTED;    goto make_a_new_def;    }       /* Otherwise we alter the existing definition */   #ifdef PROGRAM_BUILD_DEBUG    fprintf(stderr, "%.*saltering the existing definition\n",    c->compilation_depth, "");   #endif       copy_shared_string(fun.name, name);
pike.git/src/program.c:6170:       fun.identifier_flags=function_flags;       if(func)    fun.func = *func;    else    fun.func.offset = -1;       fun.opt_flags = opt_flags;    -  ref.identifier_offset=Pike_compiler->new_program->num_identifiers; +  ref.identifier_offset = prog->num_identifiers;    debug_add_to_identifiers(fun);    }       if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;       ref.inherit_offset = 0;    ref.id_flags = flags;    if (flags & ID_VARIANT) {    ref.id_flags |= ID_USED; -  Pike_compiler->new_program->identifier_references[i] = ref; +  prog->identifier_references[i] = ref;    overridden = i;    } else {    overridden = override_identifier(&ref, name);    }    if (overridden >= 0) {   #ifdef PIKE_DEBUG -  struct reference *oref = -  Pike_compiler->new_program->identifier_references+overridden; +  struct reference *oref = prog->identifier_references+overridden;    if((oref->inherit_offset != ref.inherit_offset) ||    (oref->identifier_offset != ref.identifier_offset) ||    ((oref->id_flags | ID_USED) != (ref.id_flags | ID_USED))) {    fprintf(stderr,    "ref: %d:%d 0x%04x\n"    "got: %d:%d 0x%04x (%d)\n",    ref.inherit_offset, ref.identifier_offset,    ref.id_flags,    oref->inherit_offset,    oref->identifier_offset,    oref->id_flags,    overridden);    Pike_fatal("New function overloading algorithm failed!\n");    }   #endif       if (getter_setter != -1) { -  struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, -  getter_setter); +  struct identifier *id = ID_FROM_INT(prog, getter_setter);    INT32 old_i = (&id->func.gs_info.getter)[is_setter];    if ((old_i >= 0) && (old_i != overridden)) {    my_yyerror("Multiple definitions for %S.", name);    }    (&id->func.gs_info.getter)[is_setter] = overridden;    }    return overridden;    }    /* NOTE: At this point we already have the identifier in the    * new program, and just need to add the reference.
pike.git/src/program.c:6249:    else    fun.func.offset = -1;       fun.opt_flags = opt_flags;      #ifdef PIKE_DEBUG    if (a_flag > 5) {    fprintf(stderr,    "Adding new function #%d: '%s'\n"    " identifier_flags:0x%02x opt_flags:0x%04x\n", -  Pike_compiler->new_program->num_identifiers, +  prog->num_identifiers,    fun.name->str,    fun.identifier_flags, fun.opt_flags);    }   #endif /* PIKE_DEBUG */    -  i=Pike_compiler->new_program->num_identifiers; +  i = prog->num_identifiers;       debug_add_to_identifiers(fun);       if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;       ref.id_flags = flags;    ref.identifier_offset = i;    ref.inherit_offset = 0;    }       ref.run_time_type = PIKE_T_UNKNOWN;       /* Add the reference. */    -  i=Pike_compiler->new_program->num_identifier_references; +  i = prog->num_identifier_references;    add_to_identifier_references(ref);      #ifdef PROGRAM_BUILD_DEBUG    fprintf(stderr, "%.*sadded new definition #%d\n",    c->compilation_depth, "", i);   #endif       if (getter_setter != -1) { -  struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, -  getter_setter); +  struct identifier *id = ID_FROM_INT(prog, getter_setter);    INT32 old_i = (&id->func.gs_info.getter)[is_setter];    if (old_i >= 0) {    my_yyerror("Multiple definitions for %S.", name);    }    (&id->func.gs_info.getter)[is_setter] = i;    }       return i;   }   
pike.git/src/program.c:6557:   }      /**    * This is the dispatcher function for variant functions.    *    * cf end_first_pass().    */   static void f_dispatch_variant(INT32 args)   {    struct pike_frame *fp = Pike_fp; -  int fun_num = fp->fun; +     struct program *prog = fp->context->prog; -  struct identifier *id = ID_FROM_INT(prog, fun_num); +  struct reference *funp = PTR_FROM_INT(fp->current_program, fp->fun); +  struct identifier *id = ID_FROM_PTR(fp->current_program, funp);    struct pike_string *name = id->name; -  while (fun_num--) { +  int fun_num = prog->num_identifier_references; +  int flags = 0; +  +  /* NB: The following is mostly to support a potential future +  * case where a mixed set of protections would cause +  * multiple dispatchers with the same name to be added +  * (but different protection (and types)). +  */ +  if (funp->id_flags & ID_PRIVATE) { +  flags = SEE_PRIVATE|SEE_PROTECTED; +  } else if (funp->id_flags & ID_PROTECTED) { +  flags = SEE_PROTECTED; +  } +  +  while ((fun_num = really_low_find_variant_identifier(name, prog, NULL, +  fun_num, flags)) != -1) {    int i;    struct pike_type *t;    struct pike_type *ret;    -  if (!(prog->identifier_references[fun_num].id_flags & ID_VARIANT)) { -  continue; -  } +     id = ID_FROM_INT(prog, fun_num); -  if (id->name != name) continue; -  +     add_ref(t = id->type);       /* Check whether the type is compatible with our arguments. */    for (i = 0; i < args; i++) {    struct pike_type *cont = check_call_svalue(t, 0, Pike_sp+i - args);    free_type(t);    if (!(t = cont)) break;    }    if (!t) continue;    ret = new_get_return_type(t, 0);