diff --git a/src/encode.c b/src/encode.c index 520d18361b5c09fdcb3364c496b8314893e26381..4a5786023db71d785fd76c73a0954d94b8e601e3 100644 --- a/src/encode.c +++ b/src/encode.c @@ -1082,8 +1082,10 @@ static void encode_value2(struct svalue *val, struct encode_data *data, int forc ref_push_program(p); f_function_name(1); +#if 0 if(TYPEOF(Pike_sp[-1]) == PIKE_T_INT) Pike_error("Cannot encode C programs.\n"); +#endif encode_value2(Pike_sp-1, data, 0); pop_n_elems(2); @@ -1094,7 +1096,9 @@ static void encode_value2(struct svalue *val, struct encode_data *data, int forc } if( p->event_handler ) Pike_error("Cannot encode programs with event handlers.\n"); +#if 0 Pike_error("Cannot encode C programs.\n"); +#endif } #ifdef OLD_PIKE_ENCODE_PROGRAM @@ -1414,7 +1418,27 @@ static void encode_value2(struct svalue *val, struct encode_data *data, int forc struct identifier *id = ID_FROM_PTR(p, ref); /* Skip identifiers that haven't been overloaded. */ - if (ref->id_flags & ID_INHERITED) continue; + if (ref->id_flags & ID_INHERITED) { + if ((ref->id_flags & (ID_VARIANT|ID_HIDDEN)) == ID_VARIANT) { + /* Find the dispatcher. */ + int i = really_low_find_shared_string_identifier(id->name, p, + SEE_PROTECTED|SEE_PRIVATE); + /* NB: We use the id_dumped flag for the + * dispatcher to mark whether we have + * dumped the first variant of this + * name in this program. + */ + if ((i >= 0) && !is_variant_dispatcher(p, i) && + !PTR_FROM_INT(p, i)->inherit_offset) { + /* Overloaded in this program. + * + * Make sure later variants don't clear this one. + */ + id_dumped[PTR_FROM_INT(p, i)->identifier_offset] = 1; + } + } + continue; + } /* Skip getter/setter variables; they get pulled in * by their respective functions. @@ -1529,6 +1553,30 @@ static void encode_value2(struct svalue *val, struct encode_data *data, int forc } free_string(symbol); } + } else if (ref->id_flags & ID_VARIANT) { + /* Find the dispatcher. */ + int i = really_low_find_shared_string_identifier(id->name, p, + SEE_PROTECTED|SEE_PRIVATE); + /* NB: We use the id_dumped flag for the + * dispatcher to mark whether we have + * dumped the first variant of this + * name in this program. + */ + if ((i < 0) || !is_variant_dispatcher(p, i)) { + Pike_error("Failed to find dispatcher for inherited " + "variant function: %S\n", id->name); + } + if (PTR_FROM_INT(p, i)->inherit_offset) { + Pike_error("Dispatcher for variant function %S " + "is inherited.\n", id->name); + } + gs_flags = ref->id_flags & PTR_FROM_INT(p, i)->id_flags; + if (id_dumped[PTR_FROM_INT(p, i)->identifier_offset]) { + gs_flags |= ID_VARIANT; + } else { + /* First variant. */ + id_dumped[PTR_FROM_INT(p, i)->identifier_offset] = 1; + } } if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) { @@ -1662,6 +1710,17 @@ static void encode_value2(struct svalue *val, struct encode_data *data, int forc break; case IDENTIFIER_C_FUNCTION: + if (is_variant_dispatcher(p, d)) { + /* This is handled by end_first_pass() et all. */ + /* NB: This can be reached even though id_dumped + * for it gets set by the variant functions, + * if it is overriding an old definition. + * + * We thus need to make sure id_dumped stays cleared. + */ + id_dumped[ref->identifier_offset] = 0; + continue; + } /* Not supported. */ Pike_error("Cannot encode functions implemented in C " "(identifier=\"%S\").\n", diff --git a/src/program.c b/src/program.c index d204724864b60685ba694c100488e56d7ca8369c..abf0d0973d9716fa32cb3c4d6d04d61281b9c0eb 100644 --- a/src/program.c +++ b/src/program.c @@ -3793,7 +3793,7 @@ void check_program(struct program *p) static void f_dispatch_variant(INT32 args); -static int is_variant_dispatcher(struct program *prog, int fun) +int is_variant_dispatcher(struct program *prog, int fun) { struct reference *ref; struct identifier *id; diff --git a/src/program.h b/src/program.h index 0c7192b451b56d873a8dc09f933d2ce1fbd65af6..79b7fcb0118f74c0ee807f15ad380020d40effc9 100644 --- a/src/program.h +++ b/src/program.h @@ -801,6 +801,7 @@ PMOD_EXPORT void debug_start_new_program(INT_TYPE line, const char *file); void dump_program_desc(struct program *p); int sizeof_variable(int run_time_type); void check_program(struct program *p); +int is_variant_dispatcher(struct program *prog, int fun); struct program *end_first_pass(int finish); PMOD_EXPORT struct program *debug_end_program(void); PMOD_EXPORT size_t low_add_storage(size_t size, size_t alignment,