Branch: Tag:

2007-03-31

2007-03-31 15:08:42 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Fixed several reference-count bugs in the new function call checking code.
Implemented a working new_check_call().

Rev: src/pike_types.c:1.272

2:   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: pike_types.c,v 1.271 2007/03/30 15:26:35 grubba Exp $ + || $Id: pike_types.c,v 1.272 2007/03/31 15:08:42 grubba Exp $   */      #include "global.h"
984:    }   #endif /* 0 */    if ((marker_set & (PT_FLAG_MARKER_0 << m)) && markers[m]) { -  type = markers[m]; +  type = dmalloc_touch(struct pike_type *, markers[m]);    if (marker_set & (PT_FLAG_ASSIGN_0 << m)) {    /* There's a corresponding assignment,    * so we need to keep the marker as well.
994:    marker_set & ~(PT_FLAG_MARKER_0 << m));    push_type('0' + m);    push_type(T_OR); -  markers[m] = type; +  markers[m] = dmalloc_touch(struct pike_type *, type);    } else {    /* It's a marker we're cleared to replace. */    marker_set &= ~(PT_FLAG_MARKER_0 << m);
1681: Inside #if defined(PIKE_DEBUG)
  void simple_describe_type(struct pike_type *s)   {    if (s) { +  /* fprintf(stderr, "[[[%p]]]", s); */    switch(s->type) {    case '0': case '1': case '2': case '3': case '4':    case '5': case '6': case '7': case '8': case '9':
1816: Inside #if defined(PIKE_DEBUG)
   default:    fprintf(stderr, "Unknown type node: %d, %p:%p",    s->type, s->car, s->cdr); + #ifdef DEBUG_MALLOC +  debug_malloc_dump_references(s, 0, 2, 0); + #endif    break;    }    if (s->flags) {
3283:    low_or_pike_types(b_markers[m], tmp, 0);    if(b_markers[m]) free_type(b_markers[m]);    free_type(tmp); -  b_markers[m]=pop_unfinished_type(); +  b_markers[m] = pop_unfinished_type();   #ifdef PIKE_TYPE_DEBUG    if (l_flag>2) {    dynamic_buffer save_buf;
4587:    struct pike_type *tmp2;    INT32 array_cnt = 0;    - #ifdef PIKE_TYPE_DEBUG + #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "%*slower_new_check_call(", indent*2, "");    simple_describe_type(fun_type);
4595: Inside #if defined(PIKE_TYPE_DEBUG)
   simple_describe_type(arg_type);    fprintf(stderr, ", 0x%04x)...\n", flags);    } - #endif /* PIKE_TYPE_DEBUG */ + #endif /* PIKE_DEBUG */       loop:    /* Count the number of array levels. */
4661:       case T_NOT:    if (arg_type->type == T_NOT) { -  /* Both sides are inverted. Pop both. */ +  /* Both sides are inverted. Pop both inversions. */    arg_type = arg_type->car;    fun_type = fun_type->car;    goto loop;
4691:    * with current types.    * FIXME: What about the limited number of args case?    */ -  push_finished_type(res->cdr); +     push_finished_type(mixed_type_string); -  push_type(T_MANY); +     free_type(res);    } else {    /* More arguments to check. */
4722:    */       /* No create() -- No arguments. */ -  return NULL; +  /* return NULL; */ +  copy_pike_type(res, mixed_type_string); +  break;    } else {    fun_type = zzap_function_return(tmp, CDR_TO_INT(fun_type->car)); -  free_type(tmp); +     }    res = lower_new_check_call(fun_type, arg_type, flags CHECK_CALL_ARGS);    free_type(fun_type);
4743:       /* FALL_THROUGH */    case PIKE_T_MIXED: -  add_ref(mixed_type_string); -  res = mixed_type_string; +  copy_pike_type(res, mixed_type_string);    break;       case PIKE_T_FUNCTION:
4773:    }    /* Note: Use the low variants of pike_types_le and match_types,    * so that markers get set and kept. */ - #ifdef PIKE_TYPE_DEBUG + #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "%*sChecking argument type ", indent*2+2, "");    simple_describe_type(arg_type);
4781: Inside #if defined(PIKE_TYPE_DEBUG)
   simple_describe_type(fun_type);    fprintf(stderr, ".\n");    } - #endif /* PIKE_TYPE_DEBUG */ + #endif /* PIKE_DEBUG */    if (!low_pike_types_le(arg_type, fun_type->car, 0, 0) &&    ((flags & CALL_STRICT) || -  !low_match_types(arg_type, fun_type->car, 0))) { +  !low_match_types(arg_type, fun_type->car, NO_SHORTCUTS))) {    /* No match. */ - #ifdef PIKE_TYPE_DEBUG + #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "%*sNo match.\n", indent*2+2, "");    } - #endif /* PIKE_TYPE_DEBUG */ + #endif /* PIKE_DEBUG */    res = NULL;    if (tmp) free_type(tmp);    break;
4802:    if ((flags & CALL_LAST_ARG) &&    (fun_type->type == PIKE_T_FUNCTION)) {    /* There are more required arguments. */ - #ifdef PIKE_TYPE_DEBUG + #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "%*sMore arguments required.\n", indent*2+2, "");    } - #endif /* PIKE_TYPE_DEBUG */ + #endif /* PIKE_DEBUG */    res = NULL;    if (tmp) free_type(tmp);    break;    }    } - #ifdef PIKE_TYPE_DEBUG + #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "%*sSuccess.\n", indent*2+2, "");    } - #endif /* PIKE_TYPE_DEBUG */ + #endif /* PIKE_DEBUG */    type_stack_mark();    push_finished_type_with_markers(fun_type, b_markers, PT_FLAG_MARKER);    res = pop_unfinished_type();
4827:    break;    }    if (!array_cnt || !res) { - #ifdef PIKE_TYPE_DEBUG + #ifdef PIKE_DEBUG    if (l_flag>2) {    if (res) {    fprintf(stderr, "%*s==> ", indent*2, "");
4837: Inside #if defined(PIKE_TYPE_DEBUG)
   }    fprintf(stderr, "\n");    } - #endif /* PIKE_TYPE_DEBUG */ + #endif /* PIKE_DEBUG */    return res;    }   
4849:    }    res = pop_type();    - #ifdef PIKE_TYPE_DEBUG + #ifdef PIKE_DEBUG    if (l_flag>2) {    fprintf(stderr, "%*s==> ", indent*2, "");    simple_describe_type(res);    fprintf(stderr, "\n");    } - #endif /* PIKE_TYPE_DEBUG */ + #endif /* PIKE_DEBUG */       return res;   }
4956:    struct pike_type *tmp2;    INT32 array_cnt = 0;    + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, " Getting return type for "); +  simple_describe_type(fun_type); +  fprintf(stderr, "... "); +  } + #endif /* PIKE_DEBUG */ +     loop:    /* Count the number of array levels. */    while(fun_type->type == PIKE_T_ARRAY) {
4982:    if (!(tmp = new_get_return_type(fun_type->cdr, flags))) {    break;    } -  res = or_pike_types(res, tmp, 1); +  res = or_pike_types(tmp2 = res, tmp, 1); +  free_type(tmp2); +  free_type(tmp);    break;    case T_AND:    if (!(res = new_get_return_type(fun_type->car, flags))) {
5009:    break;    } else {    fun_type = zzap_function_return(tmp, CDR_TO_INT(fun_type->car)); -  free_type(tmp); +     }    res = new_get_return_type(fun_type, flags);    free_type(fun_type);
5025:       /* FALL_THROUGH */    case PIKE_T_MIXED: -  add_ref(mixed_type_string); -  res = mixed_type_string; +  copy_pike_type(res, mixed_type_string);    break;       case PIKE_T_FUNCTION: -  +  do { +  if (!match_types(fun_type->car, void_type_string)) {    /* Too few arguments. */    break; -  +  } +  fun_type = fun_type->cdr; +  } while(fun_type->type == PIKE_T_FUNCTION); +  if (fun_type->type != T_MANY) { +  /* Still too few arguments. */ +  break; +  }    case T_MANY: -  add_ref(fun_type->cdr); -  res = fun_type->cdr; +  copy_pike_type(res, fun_type->cdr);    break;       default:
5042:    break;    }    -  if (!res) return NULL; +  if (!res) { + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, "Failed.\n"); +  } + #endif /* PIKE_DEBUG */ +  return NULL; +  }    -  + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, "Ok, cleaning up markers... "); +  } + #endif /* PIKE_DEBUG */ +     type_stack_mark();       /* Get rid of any remaining markers. */
5055:    while(array_cnt--) {    push_type(PIKE_T_ARRAY);    } +  + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, "Done.\n"); +  } + #endif /* PIKE_DEBUG */ +     return pop_unfinished_type();   }   
5218:    break;    }    if (res->type == T_NOT) { -  add_ref(res->car); -  tmp = res->car; +  copy_pike_type(tmp, res->car);    free_type(res);    res = tmp;    } else {
5247:    break;    case PIKE_T_OBJECT:    fun_type = low_object_lfun_type(fun_type, LFUN_CALL); -  if (fun_type) goto loop; +  if (fun_type) { +  goto loop; +  }    /* FIXME: Multiple cases:    * Untyped object.    * Failed to lookup program id.
5256:       /* FALL_THROUGH */    case PIKE_T_MIXED: -  add_ref(mixed_type_string); -  res = mixed_type_string; +  copy_pike_type(res, mixed_type_string);    break;       case PIKE_T_FUNCTION:
5277:    return res;   }    - /* NOTE: type loses a reference. */ - struct pike_type *new_check_call(node *fun, int *argno, -  struct pike_type *type, node *args) + /* NOTE: fun_type loses a reference. */ + struct pike_type *new_check_call(struct pike_string *fun_name, +  struct pike_type *fun_type, +  node *args, INT32 *argno)   { -  struct pike_type *tmp_type = NULL; +  struct pike_type *tmp = NULL;    -  while (args && (args->token == F_ARG_LIST)) { -  type = new_check_call(fun, argno, type, CAR(args)); +  debug_malloc_touch(fun_type); +  +  while (args && (args->token == F_ARG_LIST) && fun_type) { +  fun_type = new_check_call(fun_name, fun_type, CAR(args), argno); +  debug_malloc_touch(fun_type);    args = CDR(args);    } -  if (!args) { -  return type; +  +  if (!args || !fun_type) { +  debug_malloc_touch(fun_type); +  return fun_type;    }    -  switch(type->type) { -  case T_NOT: -  break; +  (*argno)++;    -  case T_FUNCTION: -  if (!pike_types_le(args->type, type->car)) { -  if (!match_types(args->type, type->car)) { -  /* Bad arg */ -  } else { -  /* Not strict arg */ + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, " Checking argument #%d... ", *argno); +  simple_describe_type(args->type); +  fprintf(stderr, " fun_type: "); +  simple_describe_type(fun_type);    } -  + #endif /* PIK_DEBUG */ +  +  if (args->token == F_PUSH_ARRAY) { +  struct pike_type *prev = NULL; +  int cnt = 256; +  /* This token can expand to anything between zero and MAX_ARGS args. */ +  +  /* Loop until we get a stable fun_type, or it's an invalid argument. */ +  while ((tmp = low_new_check_call(fun_type, args->type, 0)) && +  (tmp != prev) && --cnt) { +  if (prev) { +  free_type(prev);    } -  copy_pike_type(tmp_type, type->cdr); -  free_type(type); -  type = tmp_type; -  (*argno)++; -  break; +  prev = tmp; +  tmp = or_pike_types(fun_type, prev, 1); +  free_type(fun_type); +  fun_type = tmp; +  } +  if (cnt == 256) { +  yywarning("The slice operator argument must be an empty array."); +  } +  return fun_type; +  } else if ((tmp = low_new_check_call(fun_type, args->type, 0))) { +  /* OK. */ + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, " OK.\n"); +  } + #endif /* PIKE_DEBUG */ +  free_type(fun_type); +  return tmp; +  }    -  case T_MANY: -  if (!pike_types_le(args->type, type->car)) { -  if (!match_types(args->type, type->car)) { -  /* Bad arg */ +  if ((tmp = get_first_arg_type(fun_type, 0))) { + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, " Bad argument.\n"); +  } + #endif /* PIKE_DEBUG */ +  my_yyerror("Bad argument %d to %S.", +  *argno, fun_name); +  yytype_error(NULL, tmp, args->type, 0); +  free_type(tmp);    } else { -  /* Not strict arg */ + #ifdef PIKE_DEBUG +  if (l_flag>2) { +  fprintf(stderr, " Too many arguments.\n");    } -  + #endif /* PIKE_DEBUG */ +  my_yyerror("Too many arguments to %S (expected %d arguments).", +  fun_name, *argno - 1); +  yytype_error(NULL, NULL, args->type, 0);    } -  (*argno)++; -  break; +  free_type(fun_type); +  return NULL;   }    -  return type; - } -  +    struct pike_type *zzap_function_return(struct pike_type *a, INT32 id)   {    switch(a->type)