pike.git / src / las.c

version» Context lines:

pike.git/src/las.c:1:   /*   || 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$ +    */      #include "global.h"   #include "interpret.h"   #include "las.h"   #include "array.h"   #include "object.h"   #include "stralloc.h"   #include "dynamic_buffer.h"   #include "lex.h"
pike.git/src/las.c:24:   #include "operators.h"   #include "callback.h"   #include "pike_macros.h"   #include "peep.h"   #include "builtin_functions.h"   #include "cyclic.h"   #include "opcodes.h"   #include "pikecode.h"   #include "gc.h"   #include "pike_compiler.h" - #include "block_alloc.h" + #include "block_allocator.h"      /* Define this if you want the optimizer to be paranoid about aliasing    * effects to to indexing.    */   /* #define PARANOID_INDEXING */    - /* #define NEW_ARG_CHECK */ -  +    static node *eval(node *);   static void optimize(node *n); - static node *localopt(node *n); +       int cumulative_parse_error=0;   extern char *get_type_name(int);      #define MAX_GLOBAL 2048      /* #define yywarning my_yyerror */      int car_is_node(node *n)   {    switch(n->token)    {    case F_EXTERNAL:    case F_GET_SET: -  case F_IDENTIFIER: +     case F_TRAMPOLINE:    case F_CONSTANT:    case F_LOCAL:    case F_THIS:    case F_VERSION:    return 0;       default:    return !!_CAR(n);    }   }      int cdr_is_node(node *n)   {    switch(n->token)    {    case F_EXTERNAL:    case F_GET_SET: -  case F_IDENTIFIER: +     case F_TRAMPOLINE:    case F_CONSTANT:    case F_LOCAL:    case F_THIS:    case F_VERSION:    return 0;       default:    return !!_CDR(n);    }   }      int node_is_leaf(node *n)   {    switch(n->token)    {    case F_EXTERNAL:    case F_GET_SET: -  case F_IDENTIFIER: +     case F_TRAMPOLINE:    case F_CONSTANT:    case F_LOCAL:    case F_VERSION:    return 1;    }    return 0;   }      #ifdef PIKE_DEBUG
pike.git/src/las.c:212: Inside #if defined(PIKE_DEBUG)
   fputs("n:", stderr);    print_tree(n);    fputs("orig_n:", stderr);    print_tree(orig_n);    Pike_fatal("check_tree() lost track.\n");    }    n->parent = parent;   }   #endif    - /* FIXME: Ought to use parent pointer to avoid recursion. */ - INT32 count_args(node *n) + static int low_count_args(node *n)   {    int a,b; -  check_tree(n,0); +     -  fatal_check_c_stack(16384); -  +     if(!n) return 0;    switch(n->token)    {    case F_COMMA_EXPR:    case F_VAL_LVAL:    case F_ARG_LIST:    a=count_args(CAR(n));    if(a==-1) return -1;    b=count_args(CDR(n));    if(b==-1) return -1;    return a+b;       case F_CAST:    if(n->type == void_type_string)    return 0; -  else +     return count_args(CAR(n));       case F_SOFT_CAST:    return count_args(CAR(n));       case F_CASE:    case F_CASE_RANGE:    case F_FOR:    case F_DO:    case F_LOOP:
pike.git/src/las.c:261:    case F_RETURN:    case F_CONTINUE:    case F_FOREACH:    return 0;       case '?':    {    int tmp1,tmp2;    tmp1=count_args(CADR(n));    tmp2=count_args(CDDR(n)); -  if(tmp1==-1 || tmp2==-1) return -1; +     if(tmp1 < tmp2) return tmp1;    return tmp2;    }       case F_PUSH_ARRAY:    return -1;       case F_APPLY:    if(CAR(n)->token == F_CONSTANT &&    TYPEOF(CAR(n)->u.sval) == T_FUNCTION &&
pike.git/src/las.c:287:    case F_RANGE_FROM_BEG:    case F_RANGE_FROM_END:    return 1;    case F_RANGE_OPEN:    return 0;       default:    if(n->type == void_type_string) return 0;    return 1;    } +  UNREACHABLE();   }    -  + INT32 count_args(node *n) + { +  int total = 0; +  int a,b; +  node *orig = n; +  node *orig_parent; +  node *prev = NULL; +  check_tree(n,0); +  +  fatal_check_c_stack(16384); +  +  if(!n) return 0; +  +  orig_parent = n->parent; +  n->parent = NULL; +  +  while(1) { +  int val; +  while ((n->token == F_COMMA_EXPR) || +  (n->token == F_VAL_LVAL) || +  (n->token == F_ARG_LIST)) { +  if (CAR(n)) { +  CAR(n)->parent = n; +  n = CAR(n); +  } else if (CDR(n)) { +  CDR(n)->parent = n; +  n = CDR(n); +  } else { +  /* Unlikely, but... */ +  goto backtrack; +  } +  } +  +  /* Leaf. */ +  val = low_count_args(n); +  if (val == -1) { +  total = -1; +  break; +  } +  if (n->parent && (CAR(n->parent) == CDR(n->parent))) { +  /* Same node in both CDR and CAR ==> count twice. */ +  val *= 2; +  } +  total += val; +  +  backtrack: +  while (n->parent && +  (!CDR(n->parent) || (n == CDR(n->parent)))) { +  n = n->parent; +  } +  if (!(n = n->parent)) break; +  /* Found a parent where we haven't visited CDR. */ +  CDR(n)->parent = n; +  n = CDR(n); +  } +  +  orig->parent = orig_parent; +  +  return total; + } +    /* FIXME: Ought to use parent pointer to avoid recursion. */   struct pike_type *find_return_type(node *n)   {    struct pike_type *a, *b;       check_tree(n,0);       fatal_check_c_stack(16384);       if(!n) return 0;
pike.git/src/las.c:381:    if (!match_types(n->type, t)) {    yytype_report(REPORT_ERROR, NULL, 0, t, NULL, 0, n->type, 0, msg);    return 0;    }    if (THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES) {    yytype_report(REPORT_WARNING, NULL, 0, t, NULL, 0, n->type, 0, msg);    }    if (runtime_options & RUNTIME_CHECK_TYPES) {    node *p = n->parent;    if (CAR(p) == n) { -  (_CAR(p) = mksoftcastnode(t, n))->parent = p; +  (_CAR(p) = mksoftcastnode(t, mkcastnode(mixed_type_string, n))) +  ->parent = p;    } else if (CDR(p) == n) { -  (_CDR(p) = mksoftcastnode(t, n))->parent = p; +  (_CDR(p) = mksoftcastnode(t, mkcastnode(mixed_type_string, n))) +  ->parent = p;    } else {    yywarning("Failed to find place to insert soft cast.");    }    }    return 1;   }    - #undef BLOCK_ALLOC_NEXT - #define BLOCK_ALLOC_NEXT u.node.a + void init_node_s_blocks() { }    - #undef PRE_INIT_BLOCK - #define PRE_INIT_BLOCK(NODE) do { \ -  NODE->token = USHRT_MAX; \ -  } while (0) + void really_free_node_s(node * n) { +  ba_free(&Pike_compiler->node_allocator, n); + }    - BLOCK_ALLOC_FILL_PAGES(node_s, 2) + MALLOC_FUNCTION + node * alloc_node_s() { +  return ba_alloc(&Pike_compiler->node_allocator); + }    - #define NODES (sizeof (((struct node_s_block *) NULL)->x) / sizeof (struct node_s)) + void count_memory_in_node_ss(size_t * num, size_t * size) { +  struct program_state * state = Pike_compiler;    - #undef BLOCK_ALLOC_NEXT - #define BLOCK_ALLOC_NEXT next +  *num = 0; +  *size = 0;    - void free_all_nodes(void) - { -  if(!Pike_compiler->previous) -  { -  node *tmp; -  struct node_s_block *tmp2; -  size_t e=0; +  while (state) { +  size_t _num, _size; +  ba_count_all(&state->node_allocator, &_num, &_size); +  *num += _num; +  *size += _size; +  state = state->previous; +  } + }    - #ifndef PIKE_DEBUG -  if(cumulative_parse_error) -  { - #endif + void node_walker(struct ba_iterator * it, void * UNUSED(data)) { +  do { +  node * tmp = ba_it_val(it);    -  for(tmp2=node_s_blocks;tmp2;tmp2=tmp2->next) e+=tmp2->used; -  if(e) -  { -  size_t e2=e; -  struct node_s_block *nextblk; -  for(tmp2=node_s_blocks;tmp2;tmp2=nextblk) -  { -  int n = tmp2->used; -  nextblk = tmp2->next; -  /* We want to be able to access the token field of all -  * the blocks... +  /* +  * since we free nodes from here, we might iterate over them again. +  * to avoid that we check for the free mark.    */ -  PIKE_MEM_RW(tmp2->x); -  for(e=0;n && e<NODES;e++) -  { -  if (tmp2->x[e].token != USHRT_MAX) -  { -  tmp=tmp2->x+e; +  if (tmp->token == USHRT_MAX) continue; +    #ifdef PIKE_DEBUG    if(!cumulative_parse_error)    { -  fprintf(stderr,"Free node at %p, (%s:%d) (token=%d).\n", -  (void *)tmp, tmp->current_file->str, tmp->line_number, +  fprintf(stderr,"Free node at %p, (%s:%ld) (token=%d).\n", +  (void *)tmp, +  tmp->current_file->str, (long)tmp->line_number,    tmp->token);       debug_malloc_dump_references(tmp,0,2,0);       if(tmp->token==F_CONSTANT)    print_tree(tmp);    }    /* else */   #endif    {
pike.git/src/las.c:466: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if (l_flag > 3) {    fprintf(stderr, "Freeing node that had %d refs.\n",    tmp->refs);    }   #endif /* PIKE_DEBUG */    /* Force the node to be freed. */    tmp->refs = 1;    debug_malloc_touch(tmp->type);    free_node(tmp); -  --n; +     } -  +  } while (ba_it_step(it));   } -  } -  } - #ifdef PIKE_DEBUG -  if(!cumulative_parse_error) -  Pike_fatal("Failed to free %"PRINTSIZET"d nodes when compiling!\n",e2); +  + void free_all_nodes(void) + { +  node *tmp; +  + #ifndef PIKE_DEBUG +  if(cumulative_parse_error) {   #endif -  +  ba_walk(&Pike_compiler->node_allocator, &node_walker, NULL); + #ifdef PIKE_DEBUG +  if(!cumulative_parse_error) { +  size_t n, s; +  ba_count_all(&Pike_compiler->node_allocator, &n, &s); +  if (n) +  Pike_fatal("Failed to free %"PRINTSIZET"d nodes when compiling!\n",n);    } - #ifndef PIKE_DEBUG + #else    }   #endif -  free_all_node_s_blocks(); +     cumulative_parse_error=0;   } - } +       void debug_free_node(node *n)   {    if(!n) return;       if (sub_ref(n)) {   #ifdef PIKE_DEBUG    if(l_flag>9)    print_tree(n);   #endif /* PIKE_DEBUG */
pike.git/src/las.c:623:         /* here starts routines to make nodes */   static node *debug_mkemptynode(void)   {    node *res=alloc_node_s();       CHECK_COMPILER();      #ifdef __CHECKER__ -  MEMSET(res, 0, sizeof(node)); +  memset(res, 0, sizeof(node));   #endif /* __CHECKER__ */       res->refs = 0;    add_ref(res); /* For DMALLOC... */    res->token=0;    res->line_number=THIS_COMPILATION->lex.current_line;    copy_shared_string(res->current_file, THIS_COMPILATION->lex.current_file);    res->type=0;    res->name=0;    res->node_info=0;
pike.git/src/las.c:695:    break;      #ifdef PIKE_DEBUG    case F_CAST:    case F_SOFT_CAST:    Pike_fatal("Attempt to create a cast-node with mknode()!\n");    case F_CONSTANT:    Pike_fatal("Attempt to create an F_CONSTANT-node with mknode()!\n");    case F_LOCAL:    Pike_fatal("Attempt to create an F_LOCAL-node with mknode()!\n"); -  case F_IDENTIFIER: -  Pike_fatal("Attempt to create an F_IDENTIFIER-node with mknode()!\n"); +     case F_TRAMPOLINE:    Pike_fatal("Attempt to create an F_TRAMPOLINE-node with mknode()!\n");    case F_EXTERNAL:    Pike_fatal("Attempt to create an F_EXTERNAL-node with mknode()!\n");    case F_GET_SET:    Pike_fatal("Attempt to create an F_GET_SET-node with mknode()!\n");   #endif /* PIKE_DEBUG */ -  +  + #define OPERNODE(X,Y) case X: return mkopernode(("`" #Y), a, b ) +  OPERNODE(F_LT,<); +  OPERNODE(F_GT,>); +  OPERNODE(F_LE,<=); +  OPERNODE(F_GE,>=); +  OPERNODE(F_EQ,==); +  OPERNODE(F_NE,!=); +  OPERNODE(F_ADD,+); +  OPERNODE(F_SUBTRACT,-); +  OPERNODE(F_DIVIDE,/); +  OPERNODE(F_MULTIPLY,*); +  OPERNODE(F_MOD,%); +  OPERNODE(F_LSH,<<); +  OPERNODE(F_RSH,>>); +  OPERNODE(F_OR,|); +  OPERNODE(F_AND,&); +  OPERNODE(F_XOR,^); +  OPERNODE(F_NOT,!); +  OPERNODE(F_COMPL,~); + #if 0 +  OPERNODE(F_NEGATE,-); + #endif + #undef OPERNODE    }       check_tree(a,0);    check_tree(b,0);       res = mkemptynode();    _CAR(res) = dmalloc_touch(node *, a);    _CDR(res) = dmalloc_touch(node *, b);    if(a) {    a->parent = res;
pike.git/src/las.c:865:    res->tree_info |= (b->tree_info & ~(OPT_BREAK|OPT_CONTINUE));    }    break;       case F_SSCANF:    if(!b || count_args(b) == 0) break;    res->node_info |= OPT_ASSIGNMENT;    break;       case F_APPEND_ARRAY: +  case F_APPEND_MAPPING:    case F_MULTI_ASSIGN:    case F_ASSIGN: -  case F_MOD_EQ: -  case F_AND_EQ: -  case F_MULT_EQ: -  case F_ADD_EQ: -  case F_SUB_EQ: -  case F_DIV_EQ: -  case F_LSH_EQ: -  case F_RSH_EQ: -  case F_XOR_EQ: -  case F_OR_EQ: +  case F_ASSIGN_SELF:    res->node_info |= OPT_ASSIGNMENT;    if (a) {    res->tree_info |= a->tree_info;    }    if (b) {    res->tree_info |= b->tree_info;    }    break;       case F_INC:
pike.git/src/las.c:1064:    res->u.integer.b = 0;    } else {    res->u.integer.b = depth;    }       return res;   }      node *debug_mkidentifiernode(int i)   { - #if 1 +     node *res = mkexternalnode(Pike_compiler->new_program, i);    check_tree(res,0);    return res; - #else -  node *res = mkemptynode(); -  res->token = F_IDENTIFIER; -  copy_shared_string(res->type, ID_FROM_INT(Pike_compiler->new_program, i)->type); -  -  /* FIXME */ -  if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(Pike_compiler->new_program, i)->identifier_flags)) -  { -  res->node_info = OPT_EXTERNAL_DEPEND; -  }else{ -  res->node_info = OPT_NOT_CONST; +    } -  res->tree_info=res->node_info; +     - #ifdef __CHECKER__ -  _CDR(res) = 0; - #endif -  res->u.id.number = i; - #ifdef SHARED_NODES -  res->u.id.prog = Pike_compiler->new_program; - #endif /* SHARED_NODES */ -  -  check_tree(res,0); -  return res; - #endif - } -  +    node *debug_mktrampolinenode(int i, struct compiler_frame *frame)   {    struct compiler_frame *f;    node *res = mkemptynode();       res->token = F_TRAMPOLINE;    copy_pike_type(res->type, ID_FROM_INT(Pike_compiler->new_program, i)->type);       /* FIXME */    if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(Pike_compiler->new_program, i)->identifier_flags))
pike.git/src/las.c:1151:    push_object_type (0, parent_prog->id);    res->type = pop_unfinished_type();    res->node_info = OPT_NOT_CONST;    Pike_compiler->compiler_frame->opt_flags |= OPT_EXTERNAL_DEPEND;    }    else {    struct identifier *id = ID_FROM_INT(parent_prog, i);   #ifdef PIKE_DEBUG    if(d_flag)    { -  check_type_string(id->type); +     check_string(id->name);    }   #endif       /* Mark the identifier reference as used. */    PTR_FROM_INT(parent_prog, i)->id_flags |= ID_USED;       copy_pike_type(res->type, id->type);    -  /* FIXME */ +  /* FIXME: The IDENTIFIER_IS_ALIAS case isn't handled! */    if(IDENTIFIER_IS_CONSTANT(id->identifier_flags))    {    if (!(PTR_FROM_INT(parent_prog, i)->id_flags & ID_LOCAL)) {    /* It's possible to overload the identifier. */    res->node_info = OPT_EXTERNAL_DEPEND;    } else if (id->func.const_info.offset != -1) { -  struct svalue *s = &parent_prog->constants[id->func.const_info.offset].sval; +  struct program *p = PROG_FROM_INT(parent_prog, i); +  struct svalue *s = &p->constants[id->func.const_info.offset].sval;    if ((TYPEOF(*s) == T_PROGRAM) &&    (s->u.program->flags & PROGRAM_USES_PARENT)) {    /* The constant program refers to its parent, so we need as well. */    res->node_info = OPT_EXTERNAL_DEPEND;    }    }    }else{    res->node_info = OPT_NOT_CONST;    if (IDENTIFIER_IS_VARIABLE(id->identifier_flags) &&    (id->run_time_type == PIKE_T_GET_SET)) {
pike.git/src/las.c:1331:    }       if(type==n->type) {    struct pike_string *t1 = describe_type(type);    yywarning("Soft cast to %S is a noop.", t1);    free_string(t1);    return n;    }       if (n->type) { - #ifdef NEW_ARG_CHECK +     if (!(result_type = soft_cast(type, n->type, 0))) {    ref_push_type_value(n->type);    ref_push_type_value(type);    yytype_report(REPORT_ERROR, -  NULL, 0, NULL, -  NULL, 0, NULL, +  NULL, 0, type, +  NULL, 0, n->type,    2, "Soft cast of %O to %O isn't a valid cast.");    } else if (result_type == n->type) {    ref_push_type_value(n->type);    ref_push_type_value(type);    yytype_report(REPORT_WARNING,    NULL, 0, NULL,    NULL, 0, NULL,    2, "Soft cast of %O to %O is a noop.");    } - #else /* !NEW_ARG_CHECK */ -  if (!check_soft_cast(type, n->type)) { -  ref_push_type_value(type); -  ref_push_type_value(n->type); -  yytype_report(REPORT_WARNING, -  NULL, 0, NULL, -  NULL, 0, NULL, -  2, "Soft cast to %S isn't a restriction of %S."); +     } -  /* FIXME: check_soft_cast() is weaker than pike_types_le() -  * The resulting type should probably be the and between the old -  * and the new type. -  */ - #endif +     } -  } +        res = mkemptynode();    res->token = F_SOFT_CAST;    if (result_type) {    res->type = result_type;    } else {    copy_pike_type(res->type, type);    }       res->tree_info |= n->tree_info;
pike.git/src/las.c:1424:    {    yyerror("Failed to resolve external constant.");    push_int(0);    return;    }    p = state->new_program;    numid=n->u.integer.b;    }    break;    -  case F_IDENTIFIER: -  p=Pike_compiler->new_program; -  numid=n->u.id.number; -  break; -  +     case F_LOCAL:    /* FIXME: Ought to have the name of the identifier in the message. */    yyerror("Expected constant, got local variable.");    push_int(0);    return;       case F_GLOBAL:    /* FIXME: Ought to have the name of the identifier in the message. */    yyerror("Expected constant, got global variable.");    push_int(0);
pike.git/src/las.c:1463:    ptrdiff_t args=eval_low(n,1);    if(args==1) return;       if(args!=-1)    {    if(!args)    {    yyerror("Expected constant, got void expression.");    }else{    yyerror("Possible internal error!!!"); -  pop_n_elems(DO_NOT_WARN(args-1)); +  pop_n_elems(args-1);    return;    }    } else {    yyerror("Failed to evaluate constant expression.");    }    } else {    yyerror("Expected constant expression.");    }    push_int(0);    return;
pike.git/src/las.c:1531:       resolv_constant(n);    switch(TYPEOF(Pike_sp[-1]))    {    case T_OBJECT:    if(!Pike_sp[-1].u.object->prog)    {    pop_stack();    push_int(0);    }else{ -  f_object_program(1); +  o_cast(program_type_string, T_PROGRAM);    }    break;       default:    if (Pike_compiler->compiler_pass!=1)    yyerror("Illegal program identifier");    pop_stack();    push_int(0);       case T_FUNCTION:    case T_PROGRAM:    break;    }   }      /* This one always leaves a program if possible */   void resolv_program(node *n)   { -  +  if (!n) { +  push_int(0); +  return; +  } +     check_tree(n,0);    -  +  fix_type_field(n); +  +  if (!pike_types_le(n->type, inheritable_type_string) && +  (THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES)) { +  yytype_report(REPORT_WARNING, +  n->current_file, n->line_number, inheritable_type_string, +  n->current_file, n->line_number, n->type, +  0, "Not a valid object type.\n"); +  } +     resolv_class(n);    switch(TYPEOF(Pike_sp[-1]))    {    case T_FUNCTION:    if(program_from_function(Pike_sp-1))    break;       default:    if (Pike_compiler->compiler_pass!=1)    yyerror("Illegal program identifier");
pike.git/src/las.c:1577:    }   }      node *index_node(node *n, char *node_name, struct pike_string *id)   {    node *ret;    JMP_BUF tmp;       check_tree(n,0);    -  if (!is_const(n) && !TEST_COMPAT(7, 6)) { +  if (!is_const(n)) {    /* Index dynamically. */    return mknode(F_INDEX, copy_node(n), mkstrnode(id));    }       if(SETJMP(tmp))    {    if (node_name) {    handle_compile_exception ("Couldn't index module %s.", node_name);    } else {    handle_compile_exception ("Couldn't index module.");
pike.git/src/las.c:1791:   #endif    return a->u.trampoline.ident == b->u.trampoline.ident &&    a->u.trampoline.frame == b->u.trampoline.frame;       case F_EXTERNAL:    case F_GET_SET:    case F_LOCAL:    return a->u.integer.a == b->u.integer.a &&    a->u.integer.b == b->u.integer.b;    -  case F_IDENTIFIER: -  return a->u.id.number == b->u.id.number; -  +     case F_CAST:    case F_SOFT_CAST:    return a->type == b->type && node_is_eq(CAR(a), CAR(b));       case F_CONSTANT:    return is_equal(&(a->u.sval), &(b->u.sval));       default:    if( a->type != b->type ) return 0;    if(car_is_node(a) && !node_is_eq(CAR(a), CAR(b))) return 0;
pike.git/src/las.c:1937:   node *copy_node(node *n)   {    node *b;    debug_malloc_touch(n);    debug_malloc_touch(n->type);    check_tree(n,0);    if(!n) return n;    switch(n->token)    {    case F_LOCAL: -  case F_IDENTIFIER: +     case F_TRAMPOLINE:    b=mknewintnode(0);    if(b->type) free_type(b->type);    *b=*n;    copy_pike_type(b->type, n->type);    return b;       default:    add_ref(n);    return n;
pike.git/src/las.c:2101:    if(CAR(n) &&    CAR(n)->token == F_CONSTANT &&    TYPEOF(CAR(n)->u.sval) == T_FUNCTION &&    SUBTYPEOF(CAR(n)->u.sval) == FUNCTION_BUILTIN &&    CAR(n)->u.sval.u.efun->function == f)    return &_CDR(n);    }    return 0;   }    -  + #ifdef PIKE_DEBUG   /* FIXME: Ought to use parent pointer to avoid recursion. */   static void low_print_tree(node *foo,int needlval)   {    if(!foo) return;    if(l_flag>9)    {    fprintf(stderr, "/*%x*/",foo->tree_info);    }       fatal_check_c_stack(16384);
pike.git/src/las.c:2142:    if (_CDR(foo)) {    low_print_tree(_CADR(foo),0);    fputs("):(", stderr);    low_print_tree(_CDDR(foo),0);    } else {    fputs("0:0", stderr);    }    fputc(')', stderr);    break;    -  case F_IDENTIFIER: -  if(needlval) fputc('&', stderr); -  if (Pike_compiler->new_program) { -  fprintf(stderr, "id(%s)",ID_FROM_INT(Pike_compiler->new_program, foo->u.id.number)->name->str); -  } else { -  fputs("unknown identifier", stderr); -  } -  break; -  +     case F_EXTERNAL:    case F_GET_SET:    if(needlval) fputc('&', stderr);    {    struct program_state *state = Pike_compiler;    char *name = "?";    int program_id = foo->u.integer.a;    int level = 0;    int id_no = foo->u.integer.b;    while(state && (state->new_program->id != program_id)) {
pike.git/src/las.c:2191:    fputs("trampoline<unknown identifier>", stderr);    }    break;       case F_ASSIGN:    low_print_tree(_CDR(foo),1);    fputc('=', stderr);    low_print_tree(_CAR(foo),0);    break;    +  case F_ASSIGN_SELF: +  low_print_tree(_CDR(foo),1); +  fputc(':', stderr); +  fputc('=', stderr); +  low_print_tree(_CAR(foo),0); +  break; +     case F_POP_VALUE:    fputc('{', stderr);    low_print_tree(_CAR(foo), 0);    fputc('}', stderr);    break;       case F_CAST:    { -  dynamic_buffer save_buf; -  char *s; -  init_buf(&save_buf); -  my_describe_type(foo->type); -  s=simple_free_buf(&save_buf); -  fprintf(stderr, "(%s){",s); -  free(s); +  fputc('(', stderr); +  simple_describe_type(foo->type); +  fprintf(stderr, "){");    low_print_tree(_CAR(foo),0);    fputc('}', stderr);    break;    }       case F_SOFT_CAST:    { -  dynamic_buffer save_buf; -  char *s; -  init_buf(&save_buf); -  my_describe_type(foo->type); -  s=simple_free_buf(&save_buf); -  fprintf(stderr, "[%s(", s); -  free(s); +  fputc('[', stderr); +  simple_describe_type(foo->type); +  fputc('(', stderr);    low_print_tree(_CDR(foo), 0);    fprintf(stderr, ")]{");    low_print_tree(_CAR(foo),0);    fputc('}', stderr);    break;    }       case F_COMMA_EXPR:    low_print_tree(_CAR(foo),0);    if(_CAR(foo) && _CDR(foo))
pike.git/src/las.c:2343:    return;    }   }      void print_tree(node *n)   {    check_tree(n,0);    low_print_tree(n,0);    fputc('\n', stderr);   } + #endif    -  +    /* The following routines need much better commenting. */   /* They also needed to support lexical scoping and external variables.    * /grubba 2000-08-27    */      /*    * Known bugs:    * * Aliasing is not handled.    * * Called functions are assumed not to use lexical scoping.    */
pike.git/src/las.c:2433:   }      /* Makes a copy of a.    * Note: Can throw errors on out of memory.    */   static struct used_vars *copy_vars(struct used_vars *a)   {    struct used_vars *ret;    struct scope_info *src;    struct scope_info **dst; -  ret=(struct used_vars *)xalloc(sizeof(struct used_vars)); +  ret=xalloc(sizeof(struct used_vars));    src = a->locals;    dst = &(ret->locals);    *dst = NULL;    while (src) {    *dst = malloc(sizeof(struct scope_info));    if (!*dst) {    src = ret->locals;    while(src) {    struct scope_info *tmp = src->next;    free(src);    src = tmp;    }    free(ret);    Pike_error("Out of memory in copy_vars.\n");    return NULL; /* Make sure that the optimizer knows we exit here. */    } -  MEMCPY(*dst, src, sizeof(struct scope_info)); +  memcpy(*dst, src, sizeof(struct scope_info));    src = src->next;    dst = &((*dst)->next);    *dst = NULL;    }    src = a->externals;    dst = &(ret->externals);    *dst = NULL;    while (src) {    *dst = malloc(sizeof(struct scope_info));    if (!*dst) {
pike.git/src/las.c:2477:    src = ret->externals;    while(src) {    struct scope_info *tmp = src->next;    free(src);    src = tmp;    }    free(ret);    Pike_error("Out of memory in copy_vars.\n");    return NULL; /* Make sure that the optimizer knows we exit here. */    } -  MEMCPY(*dst, src, sizeof(struct scope_info)); +  memcpy(*dst, src, sizeof(struct scope_info));    src = src->next;    dst = &((*dst)->next);    *dst = NULL;    }       ret->err = a->err;    ret->ext_flags = a->ext_flags;    return ret;   }   
pike.git/src/las.c:2518:    }   #endif /* PIKE_DEBUG */    return (*a)->vars + num;    }   #ifdef PIKE_DEBUG    if (l_flag > 4) {    fputs("Creating new scope.\n", stderr);    }   #endif /* PIKE_DEBUG */    new = (struct scope_info *)xalloc(sizeof(struct scope_info)); -  MEMSET(new, VAR_UNUSED, sizeof(struct scope_info)); +  memset(new, VAR_UNUSED, sizeof(struct scope_info));    new->next = *a;    new->scope_id = scope_id;    *a = new;    return new->vars + num;   }      /* FIXME: Ought to use parent pointer to avoid recursion. */   /* Find the variables that are used in the tree n. */   /* noblock: Don't mark unused variables that are written to as blocked.    * overwrite: n is an lvalue that is overwritten.
pike.git/src/las.c:2563:       case F_EXTERNAL:    case F_GET_SET:    q = find_q(&(p->externals), n->u.integer.b, n->u.integer.a);   #ifdef PIKE_DEBUG    if (l_flag > 2) {    fprintf(stderr, "external %d:%d is ",    n->u.integer.a, n->u.integer.b);    }   #endif /* PIKE_DEBUG */ -  goto set_pointer; -  -  case F_IDENTIFIER: -  q = find_q(&(p->externals), n->u.id.number, -  Pike_compiler->new_program->id); -  if(n->u.id.number > MAX_GLOBAL) -  { -  p->err=1; -  return 0; -  } - #ifdef PIKE_DEBUG -  if (l_flag > 2) { -  fprintf(stderr, "external %d:%d is ", -  Pike_compiler->new_program->id, n->u.id.number); -  } - #endif /* PIKE_DEBUG */ -  +     set_pointer:    if(overwrite)    {    if(*q == VAR_UNUSED && !noblock) {    *q = VAR_BLOCKED;   #ifdef PIKE_DEBUG    if (l_flag > 2) {    fputs("blocked\n", stderr);    }    } else {
pike.git/src/las.c:2624: Inside #if defined(PARANOID_INDEXING)
   case F_INDEX:   #ifdef PARANOID_INDEXING    /* Be paranoid, and assume aliasing. */    p->ext_flags = VAR_USED;   #endif /* PARANOID_INDEXING */    if(car_is_node(n)) find_used_variables(CAR(n),p,noblock,0);    if(cdr_is_node(n)) find_used_variables(CDR(n),p,noblock,0);    break;       case F_ASSIGN: +  case F_ASSIGN_SELF:    find_used_variables(CAR(n),p,noblock,0);    find_used_variables(CDR(n),p,noblock,1);    break;       case '?':    find_used_variables(CAR(n),p,noblock,0);    a=copy_vars(p);    find_used_variables(CADR(n),a,noblock,0);    find_used_variables(CDDR(n),p,noblock,0);    do_and_vars(p, a);
pike.git/src/las.c:2707: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if (l_flag > 2) {    fprintf(stderr, "external %d:%d is written\n",    n->u.integer.a, n->u.integer.b);    }   #endif /* PIKE_DEBUG */    *find_q(&(p->externals), n->u.integer.b, n->u.integer.a) = VAR_USED;    }    break;    -  case F_IDENTIFIER: -  if(lvalue) -  { -  if(n->u.id.number >= MAX_VAR) -  { -  p->err=1; -  return; -  } - #ifdef PIKE_DEBUG -  if (l_flag > 2) { -  fprintf(stderr, "external %d:%d is written\n", -  Pike_compiler->new_program->id, n->u.id.number); -  } - #endif /* PIKE_DEBUG */ -  *find_q(&(p->externals), n->u.id.number, -  Pike_compiler->new_program->id) = VAR_USED; -  } -  break; -  +     case F_APPLY:    case F_AUTO_MAP:    if(n->tree_info & OPT_SIDE_EFFECT) {    p->ext_flags = VAR_USED;    }    find_written_vars(CAR(n), p, 0);    find_written_vars(CDR(n), p, 0);    break;       case F_AUTO_MAP_MARKER:
pike.git/src/las.c:2767:    break;       case F_INC:    case F_DEC:    case F_POST_INC:    case F_POST_DEC:    find_written_vars(CAR(n), p, 1);    break;       case F_ASSIGN: +  case F_ASSIGN_SELF:    case F_MULTI_ASSIGN:    find_written_vars(CAR(n), p, 0);    find_written_vars(CDR(n), p, 1);    break;    -  +  case F_APPEND_MAPPING:    case F_APPEND_ARRAY: -  case F_AND_EQ: -  case F_OR_EQ: -  case F_XOR_EQ: -  case F_LSH_EQ: -  case F_RSH_EQ: -  case F_ADD_EQ: -  case F_SUB_EQ: -  case F_MULT_EQ: -  case F_MOD_EQ: -  case F_DIV_EQ: +     find_written_vars(CAR(n), p, 1);    find_written_vars(CDR(n), p, 0);    break;       case F_SSCANF:    find_written_vars(CAR(n), p, 0);    /* FIXME: Marks arg 2 as written for now.    */    find_written_vars(CDR(n), p, 1);    break;
pike.git/src/las.c:2971:    aaa = aaa->next;    }    }    free_vars(&aa);    free_vars(&bb);    return 0;   }      static int depend_p3(node *a,node *b)   { -  if(!b) return 0; +  if(!b || !a) return 0;   #if 0    if(!(b->tree_info & OPT_SIDE_EFFECT) &&    (b->tree_info & OPT_EXTERNAL_DEPEND))    return 1;   #endif       if((a->tree_info & OPT_EXTERNAL_DEPEND)) return 1;       return depend_p2(a,b);   }
pike.git/src/las.c:3023:    /* Make a temporary node (lval = 0), so that we can use depend_p(). */    ADD_NODE_REF2(lval,    tmp = mknode(F_ASSIGN, mkintnode(0), lval));    ret = depend_p(n, tmp);    free_node(tmp);    return ret;   }      static int function_type_max=0;    - /* FIXME: Ought to use parent pointer to avoid recursion. */ - static void low_build_function_type(node *n) - { -  if(!n) return; -  if(function_type_max++ > 999) -  { -  reset_type_stack(); -  -  push_type(T_MIXED); -  push_type(T_VOID); -  push_type(T_OR); /* return type is void or mixed */ -  -  push_type(T_MIXED); -  push_type(T_VOID); -  push_type(T_OR); /* varargs */ -  -  push_type(T_MANY); -  return; -  } -  switch(n->token) -  { -  case F_COMMA_EXPR: -  case F_ARG_LIST: -  fatal_check_c_stack(16384); -  -  low_build_function_type(CDR(n)); -  low_build_function_type(CAR(n)); -  break; -  -  case F_PUSH_ARRAY: -  { -  struct pike_type *so_far; -  struct pike_type *arg_type; -  struct pike_type *tmp; -  -  so_far = pop_type(); -  -  copy_pike_type(arg_type, void_type_string); -  -  /* Convert fun(a,b,c...:d) to fun(a|b|c|void...:d) -  */ -  -  while(so_far->type == T_FUNCTION) { -  tmp = or_pike_types(arg_type, so_far->car, 1); -  free_type(arg_type); -  arg_type = tmp; -  copy_pike_type(tmp, so_far->cdr); -  free_type(so_far); -  so_far = tmp; -  } -  -  tmp = or_pike_types(arg_type, so_far->car, 1); -  free_type(arg_type); -  arg_type = tmp; -  -  push_finished_type(so_far->cdr); /* Return type */ -  -  free_type(so_far); -  -  so_far = index_type(CAR(n)->type, int_type_string, n); -  tmp = or_pike_types(arg_type, so_far, 1); -  push_finished_type(tmp); -  if (tmp == mixed_type_string) { -  /* Ensure "or void"... */ -  push_type(T_VOID); -  push_type(T_OR); -  } -  free_type(arg_type); -  free_type(so_far); -  free_type(tmp); -  push_type(T_MANY); -  } -  return; -  -  default: -  if(n->type) -  { -  if(n->type == void_type_string) return; -  push_finished_type(n->type); -  }else{ -  push_type(T_MIXED); -  } -  push_type(T_FUNCTION); -  } - } -  +    static struct pike_string *get_name_of_function(node *n)   {    struct pike_string *name = NULL;    if (!n) {    MAKE_CONST_STRING(name, "NULL");    return name;    }    switch(n->token)    {   #if 0 /* FIXME */    case F_TRAMPOLINE:   #endif -  case F_IDENTIFIER: -  name = ID_FROM_INT(Pike_compiler->new_program, n->u.id.number)->name; -  break; -  +     case F_ARROW:    case F_INDEX: -  if(CDR(n)->token == F_CONSTANT && +  if(!CDR(n)) +  { +  MAKE_CONST_STRING(name, "NULL"); +  } +  else if(CDR(n)->token == F_CONSTANT &&    TYPEOF(CDR(n)->u.sval) == T_STRING)    {    name = CDR(n)->u.sval.u.string;    }else{    MAKE_CONST_STRING(name, "dynamically resolved function");    }    break;       case F_CONSTANT:    switch(TYPEOF(n->u.sval))
pike.git/src/las.c:3262:   #endif    return name;   }      void fix_type_field(node *n)   {    struct compilation *c = THIS_COMPILATION;    struct pike_type *type_a, *type_b;    struct pike_type *old_type;    -  if (n->type && !(n->node_info & OPT_TYPE_NOT_FIXED)) +  if (!n || (n->type && !(n->node_info & OPT_TYPE_NOT_FIXED)))    return; /* assume it is correct */       old_type = n->type;    n->type = 0;    n->node_info &= ~OPT_TYPE_NOT_FIXED;    -  +  /* +  These two are needed if we want to extract types +  from nodes while building the tree. +  */ +  if( CAR(n) ) fix_type_field(CAR(n)); +  if( CDR(n) ) fix_type_field(CDR(n)); +     switch(n->token)    {    case F_SOFT_CAST:    if (CAR(n) && CAR(n)->type) { - #ifdef NEW_ARG_CHECK +     struct pike_type *soft_type = NULL;    if (CDR(n) && (CDR(n)->token == F_CONSTANT) &&    (TYPEOF(CDR(n)->u.sval) == T_TYPE)) {    soft_type = CDR(n)->u.sval.u.type;    if ((n->type = soft_cast(soft_type, CAR(n)->type, 0))) {    /* Success. */    break;    }    ref_push_type_value(CAR(n)->type);    ref_push_type_value(soft_type);    yytype_report(REPORT_ERROR, NULL, 0, NULL, NULL, 0, NULL,    2, "Soft cast of %O to %O isn't a valid cast.");    } else {    yytype_report(REPORT_ERROR, NULL, 0, type_type_string,    NULL, 0, CDR(n)->type, 0,    "Soft cast with non-type.");    } -  /* Failure: Fall through to the old code. */ - #else /* !NEW_ARG_CHECK */ -  if (!check_soft_cast(old_type, CAR(n)->type)) { -  ref_push_type_value(old_type); -  ref_push_type_value(CAR(n)->type); -  yytype_report(REPORT_ERROR, NULL, 0, NULL, NULL, 0, NULL, -  2, "Soft cast to %S isn't a restriction of %S.", -  t1, t2); +     } -  /* FIXME: check_soft_cast() is weaker than pike_types_le() -  * The resulting type should probably be the AND between the old -  * and the new type. -  */ - #endif /* NEW_ARG_CHECK */ -  } +     /* FALL_THROUGH */    case F_CAST:    /* Type-field is correct by definition. */    copy_pike_type(n->type, old_type);    break;       case F_LAND:    case F_LOR:    if (!CAR(n) || CAR(n)->type == void_type_string) {    yyerror("Conditional uses void expression.");    copy_pike_type(n->type, mixed_type_string);    break;    } -  +     if(!match_types(CAR(n)->type, mixed_type_string))    yyerror("Bad conditional expression.");       if (!CDR(n) || CDR(n)->type == void_type_string)    copy_pike_type(n->type, void_type_string);    else if(n->token == F_LAND || CAR(n)->type == CDR(n)->type)    {    copy_pike_type(n->type, CDR(n)->type);    }else{    n->type = or_pike_types(CAR(n)->type, CDR(n)->type, 0);    }    break;    -  +  case F_APPEND_MAPPING: +  if (!CAR(n) || (CAR(n)->type == void_type_string)) { +  yyerror("Assigning a void expression."); +  copy_pike_type(n->type, void_type_string); +  } +  else +  /* FIXME: Not really correct, should calculate type of RHS. */ +  copy_pike_type(n->type, CAR(n)->type); +  break; +     case F_APPEND_ARRAY:    if (!CAR(n) || (CAR(n)->type == void_type_string)) {    yyerror("Assigning a void expression.");    copy_pike_type(n->type, void_type_string);    } else if (!CDR(n)) {    copy_pike_type(n->type, CAR(n)->type);    } else {    struct pike_type *tmp;    /* Ensure that the type-fields are up to date. */    fix_type_field(CAR(n));    fix_type_field(CDR(n));    type_stack_mark();    push_finished_type(CDR(n)->type);    push_type(T_ARRAY);    n->type = and_pike_types(CAR(n)->type, tmp = pop_unfinished_type());    free_type(tmp);    }    break;       case F_ASSIGN: -  +  case F_ASSIGN_SELF:    if (!CAR(n) || (CAR(n)->type == void_type_string)) {    yyerror("Assigning a void expression.");    copy_pike_type(n->type, void_type_string);    } else if (!CDR(n)) {    copy_pike_type(n->type, CAR(n)->type);    } else {    /* Ensure that the type-fields are up to date. */    fix_type_field(CAR(n));    fix_type_field(CDR(n));   #if 0
pike.git/src/las.c:3377:    *    * FIXME: Exactly what case is the problem?    * /grubba 2005-02-15    *    * Example:    * array tmp = ({([]),([])});    * tmp->foo = 7; // Multi-assign.    * /grubba 2007-04-27    */    if (((CDR(n)->token != F_INDEX && CDR(n)->token != F_ARROW) || -  !((TEST_COMPAT (7, 6) && /* Bug compatibility. */ -  match_types(array_type_string, CDR(n)->type)) || -  match_types(array_type_string, CADR(n)->type))) && +  !(match_types(array_type_string, CADR(n)->type))) &&    !match_types(CDR(n)->type,CAR(n)->type)) {    yytype_report(REPORT_ERROR, NULL, 0, CDR(n)->type,    NULL, 0, CAR(n)->type,    0, "Bad type in assignment.");    } else {    if (c->lex.pragmas & ID_STRICT_TYPES) {    struct pike_string *t1 = describe_type(CAR(n)->type);    struct pike_string *t2 = describe_type(CDR(n)->type);   #ifdef PIKE_DEBUG    if (l_flag > 0) {    fputs("Warning: Invalid assignment: ", stderr);    print_tree(n);    }   #endif /* PIKE_DEBUG */    yywarning("An expression of type %S cannot be assigned to "    "a variable of type %S.", t1, t2);    free_string(t2);    free_string(t1);    }    if (runtime_options & RUNTIME_CHECK_TYPES) { -  _CAR(n) = mksoftcastnode(CDR(n)->type, CAR(n)); +  _CAR(n) = mksoftcastnode(CDR(n)->type, +  mkcastnode(mixed_type_string, CAR(n)));    }    }    }   #endif /* 0 */    n->type = and_pike_types(CAR(n)->type, CDR(n)->type);    }    break;       case F_ARRAY_LVALUE:    {
pike.git/src/las.c:3538:    break;       case F_AUTO_MAP:    case F_APPLY:    if (!CAR(n) || (CAR(n)->type == void_type_string)) {    yyerror("Calling a void expression.");    } else {    struct pike_type *f; /* Expected type. */    struct pike_type *s; /* Actual type */    struct pike_string *name = NULL; - #ifndef NEW_ARG_CHECK -  char *alternate_name = NULL; - #endif +     INT32 args;    - #ifdef NEW_ARG_CHECK -  +     args = 0; -  +     name = get_name_of_function(CAR(n));      #ifdef PIKE_DEBUG    if (l_flag>2) -  safe_pike_fprintf (stderr, "Checking call to %S at %S:%d.\n", name, -  n->current_file, n->line_number); +  safe_pike_fprintf (stderr, "Checking call to %S at %S:%ld.\n", name, +  n->current_file, (long)n->line_number);   #endif /* PIKE_DEBUG */       /* NOTE: new_check_call() steals a reference from f! */    copy_pike_type(f, CAR(n)->type);    f = debug_malloc_pass(new_check_call(name, f, CDR(n), &args, 0));       if (!f) {    /* Errors have been generated. */    copy_pike_type(n->type, mixed_type_string);    break;
pike.git/src/las.c:3584: Inside #if defined(NEW_ARG_CHECK)
   push_type(T_ARRAY);    free_type(n->type);    n->type = pop_type();    }    break;    }       /* Too few arguments or similar. */    copy_pike_type(n->type, mixed_type_string);    -  if ((s = get_first_arg_type(dmalloc_touch(struct pike_type *, f), 0))) { +  if ((s = get_first_arg_type(dmalloc_touch(struct pike_type *, f), +  CALL_NOT_LAST_ARG))) {    yytype_report(REPORT_ERROR, NULL, 0, s,    NULL, 0, NULL,    0, "Too few arguments to %S (got %d).",    name, args);    free_type(s);    yytype_report(REPORT_ERROR, NULL, 0, NULL,    NULL, 0, CAR(n)->type,    0, "Function type:");    } else {    yytype_report(REPORT_ERROR, NULL, 0, function_type_string,    NULL, 0, f,    0, "Attempt to call a non function value %S.",    name);    }    free_type(f);    break; - #else /* !NEW_ARG_CHECK */ -  -  if (!match_types(CAR(n)->type, function_type_string) && -  !match_types(CAR(n)->type, array_type_string)) { -  yytype_report(REPORT_ERROR, NULL, 0, function_type_string, -  NULL, 0, CAR(n)->type, -  0, "Calling non function value."); -  copy_pike_type(n->type, mixed_type_string); -  -  /* print_tree(n); */ -  break; +     } -  -  push_type(T_MIXED); /* match any return type */ -  push_type(T_VOID); /* even void */ -  push_type(T_OR); -  -  push_type(T_VOID); /* not varargs */ -  push_type(T_MANY); -  function_type_max=0; -  low_build_function_type(CDR(n)); -  s = pop_type(); -  f = CAR(n)->type?CAR(n)->type:mixed_type_string; -  n->type = check_call(s, f, -  (c->lex.pragmas & ID_STRICT_TYPES) && -  !(n->node_info & OPT_WEAK_TYPE)); -  args = count_arguments(s); -  max_args = count_arguments(f); -  if(max_args<0) max_args = 0x7fffffff; -  -  -  if (n->type) { -  /* Type/argument-check OK. */ -  free_type(s); -  -  if(n->token == F_AUTO_MAP) -  { -  push_finished_type(n->type); -  push_type(T_ARRAY); -  free_type(n->type); -  n->type = pop_type(); -  } -  -  break; -  } -  -  switch(CAR(n)->token) -  { - #if 0 /* FIXME */ -  case F_TRAMPOLINE: - #endif -  case F_IDENTIFIER: -  name=ID_FROM_INT(Pike_compiler->new_program, CAR(n)->u.id.number)->name; -  break; -  -  case F_ARROW: -  case F_INDEX: -  if(CDAR(n)->token == F_CONSTANT && -  TYPEOF(CDAR(n)->u.sval) == T_STRING) -  { -  name=CDAR(n)->u.sval.u.string; -  }else{ -  alternate_name="dynamically resolved function"; -  } -  break; -  -  case F_CONSTANT: -  switch(TYPEOF(CAR(n)->u.sval)) -  { -  case T_FUNCTION: -  if(SUBTYPEOF(CAR(n)->u.sval) == FUNCTION_BUILTIN) -  { -  name=CAR(n)->u.sval.u.efun->name; -  }else{ -  name=ID_FROM_INT(CAR(n)->u.sval.u.object->prog, -  SUBTYPEOF(CAR(n)->u.sval))->name; -  } -  break; -  -  case T_ARRAY: -  alternate_name="array call"; -  break; -  -  case T_PROGRAM: -  alternate_name="clone call"; -  break; -  -  default: -  alternate_name="`() (function call)"; -  break; -  } -  break; -  -  case F_EXTERNAL: -  case F_GET_SET: -  { -  int id_no = CAR(n)->u.integer.b; -  -  if (id_no == IDREF_MAGIC_THIS) -  alternate_name = "this"; /* Should perhaps qualify it. */ -  -  else { -  int program_id = CAR(n)->u.integer.a; -  struct program_state *state = Pike_compiler; -  -  alternate_name="external symbol"; -  -  while (state && (state->new_program->id != program_id)) { -  state = state->previous; -  } -  -  if (state) { -  struct identifier *id = ID_FROM_INT(state->new_program, id_no); -  if (id && id->name) { -  name = id->name; - #if 0 - #ifdef PIKE_DEBUG -  /* FIXME: This test crashes on valid code because the type of the -  * identifier can change in pass 2 -Hubbe -  */ -  if(id->type != f) -  { -  printf("Type of external node is not matching it's identifier.\nid->type: "); -  simple_describe_type(id->type); -  printf("\nf : "); -  simple_describe_type(f); -  printf("\n"); -  -  Pike_fatal("Type of external node is not matching it's identifier.\n"); -  } - #endif - #endif -  } -  } -  } -  } -  break; -  -  default: -  alternate_name="unknown function"; -  } -  -  if(max_args < args) -  { -  if(TEST_COMPAT(0,6)) -  { -  free_type(s); +     copy_pike_type(n->type, mixed_type_string);    break; -  } -  if (name) { -  my_yyerror("Too many arguments to %S.", name); -  } else { -  my_yyerror("Too many arguments to %s.", alternate_name); -  } -  } -  else if(max_correct_args == args) -  { -  if (name) { -  my_yyerror("Too few arguments to %S.", name); -  } else { -  my_yyerror("Too few arguments to %s.", alternate_name); -  } -  } else if (name) { -  my_yyerror("Bad argument %d to %S.", max_correct_args+1, name); -  } else { -  my_yyerror("Bad argument %d to %s.", -  max_correct_args+1, alternate_name); -  } +     -  yytype_error(NULL, f, s, 0); -  -  /* print_tree(n); */ -  -  free_type(s); - #endif /* NEW_ARG_CHECK */ -  } -  copy_pike_type(n->type, mixed_type_string); -  break; -  +     case '?':    if (!CAR(n) || (CAR(n)->type == void_type_string)) {    yyerror("Conditional expression is void.");    } else if(!match_types(CAR(n)->type, mixed_type_string))    yyerror("Bad conditional expression.");       if(!CDR(n) || !CADR(n) || !CDDR(n) ||    CADR(n)->type == void_type_string ||    CDDR(n)->type == void_type_string)    {
pike.git/src/las.c:3804:       if(CADR(n)->type == CDDR(n)->type)    {    copy_pike_type(n->type, CADR(n)->type);    break;    }       n->type = or_pike_types(CADR(n)->type, CDDR(n)->type, 0);    break;    -  case F_AND_EQ: -  case F_OR_EQ: -  case F_XOR_EQ: -  case F_LSH_EQ: -  case F_RSH_EQ: -  case F_ADD_EQ: -  case F_SUB_EQ: -  case F_MULT_EQ: -  case F_MOD_EQ: -  case F_DIV_EQ: -  if (CAR(n)) { -  struct pike_string *op_string = NULL; -  struct pike_type *call_type; -  node *op_node; -  -  /* Go via var = OP(var, expr); -  * -  * FIXME: To restrict the type further: -  * type = typeof(OP(var, expr)) AND typeof(var); -  */ -  switch(n->token) { -  case F_AND_EQ: -  MAKE_CONST_STRING(op_string, "`&"); -  break; -  case F_OR_EQ: -  MAKE_CONST_STRING(op_string, "`|"); -  break; -  case F_XOR_EQ: -  MAKE_CONST_STRING(op_string, "`^"); -  break; -  case F_LSH_EQ: -  MAKE_CONST_STRING(op_string, "`<<"); -  break; -  case F_RSH_EQ: -  MAKE_CONST_STRING(op_string, "`>>"); -  break; -  case F_ADD_EQ: -  MAKE_CONST_STRING(op_string, "`+"); -  break; -  case F_SUB_EQ: -  MAKE_CONST_STRING(op_string, "`-"); -  break; -  case F_MULT_EQ: -  MAKE_CONST_STRING(op_string, "`*"); -  break; -  case F_MOD_EQ: -  MAKE_CONST_STRING(op_string, "`%"); -  break; -  case F_DIV_EQ: -  MAKE_CONST_STRING(op_string, "`/"); -  break; -  default: -  Pike_fatal("fix_type_field(): Unhandled token: %d\n", n->token); -  break; -  } -  if (!(op_node = find_module_identifier(op_string, 0))) { -  my_yyerror("Internally used efun undefined for token %d: %S", -  n->token, op_string); -  copy_pike_type(n->type, mixed_type_string); -  break; -  } -  -  if (!op_node->type) { -  fix_type_field(op_node); -  } -  -  push_finished_type(CAR(n)->type); -  push_type(T_VOID); -  push_type(T_MANY); -  push_finished_type(CDR(n)?CDR(n)->type:mixed_type_string); -  push_type(T_FUNCTION); -  push_finished_type(CAR(n)->type); -  push_type(T_FUNCTION); -  -  call_type = pop_type(); -  -  n->type = check_call(call_type, -  op_node->type ? op_node->type : mixed_type_string, -  (c->lex.pragmas & ID_STRICT_TYPES) && -  !(op_node->node_info & OPT_WEAK_TYPE)); -  if (n->type) { -  /* Type check ok. */ -  free_node(op_node); -  free_type(call_type); -  break; -  } -  yytype_report(REPORT_ERROR, NULL, 0, -  op_node->type ? op_node->type : mixed_type_string, -  NULL, 0, call_type, -  0, "Bad arguments to %S.", op_string); -  free_node(op_node); -  free_type(call_type); -  } -  copy_pike_type(n->type, mixed_type_string); -  break; -  +     case F_INC:    case F_DEC:    case F_POST_INC:    case F_POST_DEC:    if (CAR(n)) {    /* The expression gets the type from the variable. */    /* FIXME: Ought to strip non-applicable subtypes from the type. */    copy_pike_type(n->type, CAR(n)->type);    } else {    copy_pike_type(n->type, mixed_type_string);
pike.git/src/las.c:3939:    !SAFE_IS_ZERO(& CAR(n)->u.sval)) {    check_node_type(CAR(n),    Pike_compiler->compiler_frame->current_return_type,    "Wrong return type.");    }    }    copy_pike_type(n->type, void_type_string);    break;       case F_CASE_RANGE: -  if (CDR(n) && CAR(n) && !TEST_COMPAT(0,6)) { +  if (CDR(n) && CAR(n)) { +  fix_type_field(CAR(n)); +  fix_type_field(CDR(n));    /* case 1 .. 2: */    if (!match_types(CAR(n)->type, CDR(n)->type)) {    if (!match_types(CAR(n)->type, int_type_string) ||    !match_types(CDR(n)->type, int_type_string)) {    yytype_report(REPORT_ERROR,    NULL, 0, CAR(n)->type,    NULL, 0, CDR(n)->type,    0, "Type mismatch in case range.");    }    } else if ((c->lex.pragmas & ID_STRICT_TYPES) &&
pike.git/src/las.c:3972:    if (!(CDR(n)->type == zero_type_string) ||    !(pike_types_le(CAR(n)->type, int_type_string))) {    yytype_report(REPORT_WARNING,    NULL, 0, CAR(n)->type,    NULL, 0, CDR(n)->type,    0, "Type mismatch in case range.");    }    }    }    } +  if (CDR(n) && (Pike_compiler->compiler_pass == 2)) { +  fix_type_field(CDR(n)); +  if (!match_types(CDR(n)->type, enumerable_type_string)) { +  yytype_report(REPORT_WARNING, +  NULL, 0, enumerable_type_string, +  NULL, 0, CDR(n)->type, +  0, "Case value is not an enumerable type."); +  } +  }    /* FALL_THROUGH */    case F_CASE: -  +  if (CAR(n) && (Pike_compiler->compiler_pass == 2)) { +  fix_type_field(CAR(n)); +  if (!match_types(CAR(n)->type, enumerable_type_string)) { +  yytype_report(REPORT_WARNING, +  NULL, 0, enumerable_type_string, +  NULL, 0, CAR(n)->type, +  0, "Case value is not an enumerable type."); +  } +  } +  /* FALL_THROUGH */    case F_INC_LOOP:    case F_DEC_LOOP:    case F_DEC_NEQ_LOOP:    case F_INC_NEQ_LOOP:    case F_LOOP:    case F_CONTINUE:    case F_BREAK:    case F_DEFAULT:    case F_POP_VALUE:    copy_pike_type(n->type, void_type_string);
pike.git/src/las.c:4166:    }    free_type(array_zero);    }    }    }    foreach_type_check_done:    copy_pike_type(n->type, void_type_string);    break;       case F_SSCANF: -  if (!CAR(n) || (CAR(n)->token != ':') || -  !CDAR(n) || (CDAR(n)->token != F_ARG_LIST) || -  !CADAR(n) || !CDDAR(n)) { +  if (!CAR(n) || (CAR(n)->token != F_ARG_LIST) || !CAAR(n)) +  {    yyerror("Too few arguments to sscanf().");    MAKE_CONSTANT_TYPE(n->type, tIntPos);    } else {    struct pike_string *sscanf_name;    struct pike_type *sscanf_type;    node *args;    INT32 argno = 0; -  if (CAAR(n)->u.sval.u.integer & SSCANF_FLAG_76_COMPAT) { -  MAKE_CONST_STRING(sscanf_name, "sscanf_76"); -  add_ref(sscanf_type = sscanf_76_type_string); -  } else { +     MAKE_CONST_STRING(sscanf_name, "sscanf");    add_ref(sscanf_type = sscanf_type_string); -  } -  args = mknode(F_ARG_LIST, CDAR(n), CDR(n)); -  add_ref(CDAR(n)); +  args = mknode(F_ARG_LIST, CAR(n), CDR(n)); +  add_ref(CAR(n));    if (CDR(n)) add_ref(CDR(n));    sscanf_type = new_check_call(sscanf_name, sscanf_type, args, &argno, 0);    free_node(args);    if (sscanf_type) {    if (!(n->type = new_get_return_type(sscanf_type, 0))) {    struct pike_type *expected; -  if ((expected = get_first_arg_type(sscanf_type, 0))) { +  if ((expected = get_first_arg_type(sscanf_type, CALL_NOT_LAST_ARG))) {    yytype_report(REPORT_ERROR,    NULL, 0, expected,    NULL, 0, NULL, -  0, "Too few arguments to %S (got %d).", -  sscanf_name, argno); +  0, "Too few arguments to sscanf (got %d).", +  argno);    free_type(expected);    } else {    /* Most likely not reached. */    yytype_report(REPORT_ERROR,    NULL, 0, function_type_string,    NULL, 0, sscanf_type, -  0, "Attempt to call a non function value %S.", -  sscanf_name); +  0, "Attempt to call a non function value sscanf.");    }    }    free_type(sscanf_type);    }    if (!n->type) {    MAKE_CONSTANT_TYPE(n->type, tIntPos);    }    }    break;   
pike.git/src/las.c:4253:    if (n->token == F_ARG_LIST) {    n->type = or_pike_types(CAR(n)->type, CDR(n)->type, 0);    } else {    copy_pike_type(n->type, CDR(n)->type);    }    break;       case F_MAGIC_INDEX:    /* FIXME: Could have a stricter type for ::`->(). */    /* FIXME: */ -  MAKE_CONSTANT_TYPE(n->type, tFunc(tMix tOr(tVoid,tInt),tMix)); +  MAKE_CONSTANT_TYPE(n->type, tFunc(tStr tOr3(tVoid,tObj,tDeprecated(tInt)) +  tOr(tVoid,tInt), tMix));    break;    case F_MAGIC_SET_INDEX:    /* FIXME: Could have a stricter type for ::`->=(). */    /* FIXME: */    MAKE_CONSTANT_TYPE(n->type, tFunc(tMix tSetvar(0,tMix) tOr(tVoid,tInt), tVar(0)));    break;    case F_MAGIC_INDICES:    MAKE_CONSTANT_TYPE(n->type, tFunc(tOr(tVoid,tInt), tArr(tString)));    break;    case F_MAGIC_VALUES:
pike.git/src/las.c:4286:    }       if (n->type != old_type) {    if (n->parent) {    n->parent->node_info |= OPT_TYPE_NOT_FIXED;    }    }    if (old_type) {    free_type(old_type);    } - #ifdef PIKE_DEBUG -  check_type_string(n->type); - #endif /* PIKE_DEBUG */ +    }      static void zapp_try_optimize(node *n)   {    node *parent;    node *orig_n = n;       if(!n) return;       parent = n->parent;
pike.git/src/las.c:4334:    break;    }   #ifdef PIKE_DEBUG    if (n != orig_n) {    Pike_fatal("zzap_try_optimize() lost track of parent.\n");    }   #endif /* PIKE_DEBUG */    n->parent = parent;   }    - #if defined(SHARED_NODES) + #if defined(SHARED_NODES) && 0   /* FIXME: Ought to use parent pointer to avoid recursion. */   static void find_usage(node *n, unsigned char *usage,    unsigned char *switch_u,    const unsigned char *cont_u,    const unsigned char *break_u,    const unsigned char *catch_u)   {    if (!n)    return;       fatal_check_c_stack(16384);       switch(n->token) {    case F_ASSIGN: -  +  case F_ASSIGN_SELF:    if ((CDR(n)->token == F_LOCAL) && (!CDR(n)->u.integer.b)) {    usage[CDR(n)->u.integer.a] = 0;    } else if (CDR(n)->token == F_ARRAY_LVALUE) {    find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);    }    find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);    return;       case F_SSCANF:    {    int i;       /* catch_usage is restored if sscanf throws an error. */    for (i=0; i < MAX_LOCAL; i++) {    usage[i] |= catch_u[i];    }    /* Only the first two arguments are evaluated. */ -  if (CAR(n) && CDAR(n)) { -  find_usage(CDDAR(n), usage, switch_u, cont_u, break_u, catch_u); -  find_usage(CADAR(n), usage, switch_u, cont_u, break_u, catch_u); +  if (CAR(n)) { +  find_usage(CDAR(n), usage, switch_u, cont_u, break_u, catch_u); +  find_usage(CAAR(n), usage, switch_u, cont_u, break_u, catch_u);    }    return;    }       case F_CATCH:    {    unsigned char catch_usage[MAX_LOCAL];    int i;    -  MEMCPY(catch_usage, usage, MAX_LOCAL); +  memcpy(catch_usage, usage, MAX_LOCAL);    find_usage(CAR(n), usage, switch_u, cont_u, catch_usage, catch_usage);    for(i=0; i < MAX_LOCAL; i++) {    usage[i] |= catch_usage[i];    }    return;    }       case F_AUTO_MAP:    case F_APPLY:    {
pike.git/src/las.c:4414: Inside #if defined(SHARED_NODES)
   usage[CAR(n)->u.integer.a] = 0;    }    }    return;       case F_ARRAY_LVALUE:    find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);    return;       case F_CONTINUE: -  MEMCPY(usage, cont_u, MAX_LOCAL); +  memcpy(usage, cont_u, MAX_LOCAL);    return;       case F_BREAK: -  MEMCPY(usage, break_u, MAX_LOCAL); +  memcpy(usage, break_u, MAX_LOCAL);    return;       case F_DEFAULT:    case F_CASE:    case F_CASE_RANGE:    {    int i;       find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);    find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);
pike.git/src/las.c:4441: Inside #if defined(SHARED_NODES)
   }    return;    }       case F_SWITCH:    {    unsigned char break_usage[MAX_LOCAL];    unsigned char switch_usage[MAX_LOCAL];    int i;    -  MEMSET(switch_usage, 0, MAX_LOCAL); -  MEMCPY(break_usage, usage, MAX_LOCAL); +  memset(switch_usage, 0, MAX_LOCAL); +  memcpy(break_usage, usage, MAX_LOCAL);       find_usage(CDR(n), usage, switch_usage, cont_u, break_usage, catch_u);       for(i = 0; i < MAX_LOCAL; i++) {    usage[i] |= switch_usage[i];    }       find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);    return;    }       case F_RETURN: -  MEMSET(usage, 0, MAX_LOCAL); +  memset(usage, 0, MAX_LOCAL);    /* FIXME: The function arguments should be marked "used", since    * they are seen in backtraces.    */    return;       case F_LOR:    case F_LAND:    {    unsigned char trail_usage[MAX_LOCAL];    int i;    -  MEMCPY(trail_usage, usage, MAX_LOCAL); +  memcpy(trail_usage, usage, MAX_LOCAL);       find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);       for(i=0; i < MAX_LOCAL; i++) {    usage[i] |= trail_usage[i];    }       find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);    return;    }       case '?':    {    unsigned char cadr_usage[MAX_LOCAL];    unsigned char cddr_usage[MAX_LOCAL];    int i;    -  MEMCPY(cadr_usage, usage, MAX_LOCAL); -  MEMCPY(cddr_usage, usage, MAX_LOCAL); +  memcpy(cadr_usage, usage, MAX_LOCAL); +  memcpy(cddr_usage, usage, MAX_LOCAL);       find_usage(CADR(n), cadr_usage, switch_u, cont_u, break_u, catch_u);    find_usage(CDDR(n), cddr_usage, switch_u, cont_u, break_u, catch_u);       for (i=0; i < MAX_LOCAL; i++) {    usage[i] = cadr_usage[i] | cddr_usage[i];    }    find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);    return;    }       case F_DO:    {    unsigned char break_usage[MAX_LOCAL];    unsigned char continue_usage[MAX_LOCAL];    -  MEMCPY(break_usage, usage, MAX_LOCAL); +  memcpy(break_usage, usage, MAX_LOCAL);       find_usage(CDR(n), usage, switch_u, cont_u, break_usage, catch_u);    -  MEMCPY(continue_usage, usage, MAX_LOCAL); +  memcpy(continue_usage, usage, MAX_LOCAL);       find_usage(CAR(n), usage, switch_u, break_usage, continue_usage,    catch_u);    return;    }       case F_FOR:    {    unsigned char loop_usage[MAX_LOCAL];    unsigned char break_usage[MAX_LOCAL];    unsigned char continue_usage[MAX_LOCAL];    int i;    -  MEMCPY(break_usage, usage, MAX_LOCAL); +  memcpy(break_usage, usage, MAX_LOCAL);       /* for(;a;b) c; is handled like:    *    * if (a) { do { c; b; } while(a); }    */    -  MEMSET(loop_usage, 0, MAX_LOCAL); +  memset(loop_usage, 0, MAX_LOCAL);       find_usage(CAR(n), loop_usage, switch_u, cont_u, break_u, catch_u);    if (CDR(n)) {    find_usage(CDDR(n), loop_usage, switch_u, cont_u, break_usage,    catch_u);    -  MEMCPY(continue_usage, loop_usage, MAX_LOCAL); +  memcpy(continue_usage, loop_usage, MAX_LOCAL);       find_usage(CADR(n), loop_usage, switch_u, continue_usage, break_usage,    catch_u);    }       for (i = 0; i < MAX_LOCAL; i++) {    usage[i] |= loop_usage[i];    }       find_usage(CAR(n), usage, switch_u, cont_u, break_u, catch_u);    return;    }       case F_FOREACH:    {    unsigned char loop_usage[MAX_LOCAL];    unsigned char break_usage[MAX_LOCAL];    unsigned char continue_usage[MAX_LOCAL];    int i;    -  MEMCPY(break_usage, usage, MAX_LOCAL); +  memcpy(break_usage, usage, MAX_LOCAL);       /* Find the usage from the loop */    -  MEMSET(loop_usage, 0, MAX_LOCAL); +  memset(loop_usage, 0, MAX_LOCAL);    -  MEMCPY(continue_usage, usage, MAX_LOCAL); +  memcpy(continue_usage, usage, MAX_LOCAL);       find_usage(CDR(n), loop_usage, switch_u, continue_usage, break_usage,    catch_u);    if (CDAR(n)->token == F_LOCAL) {    if (!(CDAR(n)->u.integer.b)) {    loop_usage[CDAR(n)->u.integer.a] = 0;    }    } else if (CDAR(n)->token == F_LVALUE_LIST) {    find_usage(CDAR(n), loop_usage, switch_u, cont_u, break_u, catch_u);    }
pike.git/src/las.c:4617: Inside #if defined(SHARED_NODES)
   const unsigned char *catch_u)   {    node *car, *cdr;       if (!n)    return NULL;       switch(n->token) {    /* FIXME: Does not support F_LOOP yet. */    case F_ASSIGN: +  case F_ASSIGN_SELF:    if ((CDR(n)->token == F_LOCAL) && (!CDR(n)->u.integer.b)) {    /* Assignment of local variable */    if (!(usage[CDR(n)->u.integer.a] & 1)) {    /* Value isn't used. */    struct pike_type *ref_type;    MAKE_CONSTANT_TYPE(ref_type, tOr(tComplex, tString));    if (!match_types(CDR(n)->type, ref_type)) {    /* The variable doesn't hold a refcounted value. */    free_type(ref_type);    return low_localopt(CAR(n), usage, switch_u, cont_u,
pike.git/src/las.c:4640: Inside #if defined(SHARED_NODES)
   }    usage[CDR(n)->u.integer.a] = 0;    cdr = CDR(n);    ADD_NODE_REF(cdr);    } else if (CDR(n)->token == F_ARRAY_LVALUE) {    cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);    } else {    cdr = CDR(n);    ADD_NODE_REF(cdr);    } -  return mknode(F_ASSIGN, low_localopt(CAR(n), usage, switch_u, cont_u, +  return mknode(n->token, low_localopt(CAR(n), usage, switch_u, cont_u,    break_u, catch_u), cdr);       case F_SSCANF:    {    int i;       /* catch_usage is restored if sscanf throws an error. */    for (i=0; i < MAX_LOCAL; i++) {    usage[i] |= catch_u[i];    }    /* Only the first two arguments are evaluated. */ -  if (CAR(n) && CDAR(n)) { -  cdr = low_localopt(CDDAR(n), usage, switch_u, cont_u, break_u, catch_u); -  car = low_localopt(CADAR(n), usage, switch_u, cont_u, break_u, catch_u); +  if (CAR(n)) { +  cdr = low_localopt(CDAR(n), usage, switch_u, cont_u, break_u, catch_u); +  car = low_localopt(CAAR(n), usage, switch_u, cont_u, break_u, catch_u);       if (CDR(n)) {    ADD_NODE_REF(CDR(n));    } -  return mknode(F_SSCANF, mknode(':', CAAR(n), -  mknode(F_ARG_LIST, car, cdr)), CDR(n)); +  return mknode(F_SSCANF, mknode(F_ARG_LIST, car, cdr), CDR(n));    }    ADD_NODE_REF(n);    return n;    }       case F_CATCH:    {    unsigned char catch_usage[MAX_LOCAL];    int i;    -  MEMCPY(catch_usage, usage, MAX_LOCAL); +  memcpy(catch_usage, usage, MAX_LOCAL);    car = low_localopt(CAR(n), usage, switch_u, cont_u, catch_usage,    catch_usage);    for(i=0; i < MAX_LOCAL; i++) {    usage[i] |= catch_usage[i];    }    return mknode(F_CATCH, car, 0);    }    break;       case F_AUTO_MAP:
pike.git/src/las.c:4725: Inside #if defined(SHARED_NODES)
      case F_CAST:    return mkcastnode(n->type, low_localopt(CAR(n), usage, switch_u, cont_u,    break_u, catch_u));       case F_SOFT_CAST:    return mksoftcastnode(n->type, low_localopt(CAR(n), usage, switch_u,    cont_u, break_u, catch_u));       case F_CONTINUE: -  MEMCPY(usage, cont_u, MAX_LOCAL); +  memcpy(usage, cont_u, MAX_LOCAL);    ADD_NODE_REF(n);    return n;       case F_BREAK: -  MEMCPY(usage, break_u, MAX_LOCAL); +  memcpy(usage, break_u, MAX_LOCAL);    ADD_NODE_REF(n);    return n;       case F_DEFAULT:    case F_CASE:    case F_CASE_RANGE:    {    int i;       cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);
pike.git/src/las.c:4754: Inside #if defined(SHARED_NODES)
   }    return mknode(n->token, car, cdr);    }       case F_SWITCH:    {    unsigned char break_usage[MAX_LOCAL];    unsigned char switch_usage[MAX_LOCAL];    int i;    -  MEMSET(switch_usage, 0, MAX_LOCAL); -  MEMCPY(break_usage, usage, MAX_LOCAL); +  memset(switch_usage, 0, MAX_LOCAL); +  memcpy(break_usage, usage, MAX_LOCAL);       cdr = low_localopt(CDR(n), usage, switch_usage, cont_u, break_usage,    catch_u);       for(i = 0; i < MAX_LOCAL; i++) {    usage[i] |= switch_usage[i];    }       car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);    return mknode(F_SWITCH, car, cdr);    }       case F_RETURN: -  MEMSET(usage, 0, MAX_LOCAL); +  memset(usage, 0, MAX_LOCAL);    /* FIXME: The function arguments should be marked "used", since    * they are seen in backtraces.    */    return mknode(F_RETURN, low_localopt(CAR(n), usage, switch_u, cont_u,    break_u, catch_u), 0);       case F_LOR:    case F_LAND:    {    unsigned char trail_usage[MAX_LOCAL];    int i;    -  MEMCPY(trail_usage, usage, MAX_LOCAL); +  memcpy(trail_usage, usage, MAX_LOCAL);       cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_u, catch_u);       for(i=0; i < MAX_LOCAL; i++) {    usage[i] |= trail_usage[i];    }       car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);       return mknode(n->token, car, cdr);    }       case '?':    {    unsigned char cadr_usage[MAX_LOCAL];    unsigned char cddr_usage[MAX_LOCAL];    int i;    -  MEMCPY(cadr_usage, usage, MAX_LOCAL); -  MEMCPY(cddr_usage, usage, MAX_LOCAL); +  memcpy(cadr_usage, usage, MAX_LOCAL); +  memcpy(cddr_usage, usage, MAX_LOCAL);       car = low_localopt(CADR(n), cadr_usage, switch_u, cont_u, break_u,    catch_u);    cdr = low_localopt(CDDR(n), cddr_usage, switch_u, cont_u, break_u,    catch_u);       for (i=0; i < MAX_LOCAL; i++) {    usage[i] = cadr_usage[i] | cddr_usage[i];    }    cdr = mknode(':', car, cdr);    car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);    return mknode('?', car, cdr);    }       case F_DO:    {    unsigned char break_usage[MAX_LOCAL];    unsigned char continue_usage[MAX_LOCAL];    int i;    -  MEMCPY(break_usage, usage, MAX_LOCAL); +  memcpy(break_usage, usage, MAX_LOCAL);       /* Find the usage from the loop */    find_usage(CDR(n), usage, switch_u, cont_u, break_u, catch_u);    -  MEMCPY(continue_usage, usage, MAX_LOCAL); +  memcpy(continue_usage, usage, MAX_LOCAL);       find_usage(CAR(n), usage, switch_u, continue_usage, break_usage,    catch_u);       for (i = 0; i < MAX_LOCAL; i++) {    usage[i] |= break_usage[i];    }       cdr = low_localopt(CDR(n), usage, switch_u, cont_u, break_usage,    catch_u);    -  MEMCPY(continue_usage, usage, MAX_LOCAL); +  memcpy(continue_usage, usage, MAX_LOCAL);       car = low_localopt(CAR(n), usage, switch_u, continue_usage, break_usage,    catch_u);       return mknode(F_DO, car, cdr);    }       case F_FOR:    {    unsigned char loop_usage[MAX_LOCAL];    unsigned char break_usage[MAX_LOCAL];    unsigned char continue_usage[MAX_LOCAL];    int i;    -  MEMCPY(break_usage, usage, MAX_LOCAL); +  memcpy(break_usage, usage, MAX_LOCAL);       /*    * if (a A|B) {    * B    * do {    * B    * c;    * continue:    * D    * b;    * C    * } while (a A|B);    * A    * }    * break:    * A    */       /* Find the usage from the loop. */    -  MEMSET(loop_usage, 0, MAX_LOCAL); +  memset(loop_usage, 0, MAX_LOCAL);       find_usage(CAR(n), loop_usage, switch_u, cont_u, break_u, catch_u);    if (CDR(n)) {    find_usage(CDDR(n), loop_usage, switch_u, cont_u, break_usage,    catch_u);    -  MEMCPY(continue_usage, loop_usage, MAX_LOCAL); +  memcpy(continue_usage, loop_usage, MAX_LOCAL);       find_usage(CADR(n), loop_usage, switch_u, continue_usage, break_usage,    catch_u);    }       for (i = 0; i < MAX_LOCAL; i++) {    usage[i] |= loop_usage[i];    }       /* The last thing to be evaluated is the conditional */    car = low_localopt(CAR(n), usage, switch_u, cont_u, break_u, catch_u);       if (CDR(n)) {    node *cadr, *cddr;       /* The incrementor */    cddr = low_localopt(CDDR(n), usage, switch_u, cont_u, break_usage,    catch_u);    -  MEMCPY(continue_usage, usage, MAX_LOCAL); +  memcpy(continue_usage, usage, MAX_LOCAL);       /* The body */    cadr = low_localopt(CADR(n), usage, switch_u, continue_usage,    break_usage, catch_u);    cdr = mknode(':', cadr, cddr);    } else {    cdr = 0;    }       for (i = 0; i < MAX_LOCAL; i++) {
pike.git/src/las.c:4930: Inside #if defined(SHARED_NODES)
   return mknode(F_FOR, car, cdr);    }       case F_FOREACH:    {    unsigned char loop_usage[MAX_LOCAL];    unsigned char break_usage[MAX_LOCAL];    unsigned char continue_usage[MAX_LOCAL];    int i;    -  MEMCPY(break_usage, usage, MAX_LOCAL); +  memcpy(break_usage, usage, MAX_LOCAL);       /*    * D    * arr = copy_value(arr);    * int i = 0;    * A|B    * while (i < sizeof(arr)) {    * B    * loopvar = arr[i];    * C    * body;    * continue:    * A|B    * }    * break:    * A    */       /* Find the usage from the loop */ -  MEMSET(loop_usage, 0, MAX_LOCAL); +  memset(loop_usage, 0, MAX_LOCAL);    -  MEMCPY(continue_usage, usage, MAX_LOCAL); +  memcpy(continue_usage, usage, MAX_LOCAL);       find_usage(CDR(n), loop_usage, switch_u, continue_usage, break_usage,    catch_u);    if (CDAR(n)->token == F_LOCAL) {    if (!(CDAR(n)->u.integer.b)) {    loop_usage[CDAR(n)->u.integer.a] = 0;    }    } else if (CDAR(n)->token == F_LVALUE_LIST) {    find_usage(CDAR(n), loop_usage, switch_u, cont_u, break_u, catch_u);    }       for (i = 0; i < MAX_LOCAL; i++) {    usage[i] |= loop_usage[i];    }    -  MEMCPY(continue_usage, usage, MAX_LOCAL); +  memcpy(continue_usage, usage, MAX_LOCAL);    cdr = low_localopt(CDR(n), usage, switch_u, continue_usage, break_usage,    catch_u);    if (CDAR(n)->token == F_LOCAL) {    if (!(CDAR(n)->u.integer.b)) {    usage[CDAR(n)->u.integer.a] = 0;    }    } else if (CDAR(n)->token == F_LVALUE_LIST) {    find_usage(CDAR(n), usage, switch_u, cont_u, break_u, catch_u);    }   
pike.git/src/las.c:5024: Inside #if defined(SHARED_NODES)
     static node *localopt(node *n)   {    unsigned char usage[MAX_LOCAL];    unsigned char b_usage[MAX_LOCAL];    unsigned char c_usage[MAX_LOCAL];    unsigned char s_usage[MAX_LOCAL];    unsigned char catch_usage[MAX_LOCAL];    node *n2;    -  MEMSET(usage, 0, MAX_LOCAL); -  MEMSET(b_usage, 0, MAX_LOCAL); -  MEMSET(c_usage, 0, MAX_LOCAL); -  MEMSET(s_usage, 0, MAX_LOCAL); -  MEMSET(catch_usage, 0, MAX_LOCAL); +  memset(usage, 0, MAX_LOCAL); +  memset(b_usage, 0, MAX_LOCAL); +  memset(c_usage, 0, MAX_LOCAL); +  memset(s_usage, 0, MAX_LOCAL); +  memset(catch_usage, 0, MAX_LOCAL);       n2 = low_localopt(n, usage, s_usage, c_usage, b_usage, catch_usage);      #ifdef PIKE_DEBUG    if (l_flag > 0) {    if ((n2 != n) || (l_flag > 4)) {    fputs("\nBefore localopt: ", stderr);    print_tree(n);       fputs("After localopt: ", stderr);    print_tree(n2);    }    }   #endif /* PIKE_DEBUG */       free_node(n);    return n2;   } - #endif /* SHARED_NODES */ + #endif /* SHARED_NODES && 0 */      static void optimize(node *n)   {    node *tmp1, *tmp2, *tmp3;    struct compilation *c = THIS_COMPILATION;    struct pike_string *save_file =    dmalloc_touch(struct pike_string *, c->lex.current_file); -  INT32 save_line = c->lex.current_line; +  INT_TYPE save_line = c->lex.current_line;       do    {    if(car_is_node(n) && !(CAR(n)->node_info & OPT_OPTIMIZED))    {    CAR(n)->parent = n;    n = CAR(n);    continue;    }    if(cdr_is_node(n) && !(CDR(n)->node_info & OPT_OPTIMIZED))
pike.git/src/las.c:5133: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if(l_flag > 3 && n)    {    fprintf(stderr,"Optimizing (tree info=%04x):",n->tree_info);    print_tree(n);    }   #endif       switch(n->token)    { + /* Unfortunately GCC doesn't ignore #pragma clang yet. */ + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wparentheses-equality"   #include "treeopt.h" -  + #pragma clang diagnostic pop + #else + #include "treeopt.h" + #endif    use_car:    ADD_NODE_REF2(CAR(n), tmp1 = CAR(n));    goto use_tmp1;       use_cdr:    ADD_NODE_REF2(CDR(n), tmp1 = CDR(n));    goto use_tmp1;       zap_node:    tmp1 = 0;
pike.git/src/las.c:5208:    check_tree(n,0);    }   }      struct timer_oflo   {    INT32 counter;    int yes;   };    - static void check_evaluation_time(struct callback *cb,void *tmp,void *ignored) + static void check_evaluation_time(struct callback *UNUSED(cb), void *tmp, void *UNUSED(ignored))   {    struct timer_oflo *foo=(struct timer_oflo *)tmp;    if(foo->counter-- < 0)    {    foo->yes=1;    pike_throw();    }   }      ptrdiff_t eval_low(node *n,int print_error)
pike.git/src/las.c:5238:   #endif /* PIKE_USE_MACHINE_CODE */      #ifdef PIKE_DEBUG    if(l_flag > 3 && n)    {    fprintf(stderr,"Evaluating (tree info=%x):",n->tree_info);    print_tree(n);    }   #endif    +  fix_type_field(n); +     if(Pike_compiler->num_parse_error) {    return -1;    }       num_strings = prog->num_strings;    num_constants = prog->num_constants;    num_program = prog->num_program;   #ifdef PIKE_USE_MACHINE_CODE    num_relocations = prog->num_relocations;   #endif /* PIKE_USE_MACHINE_CODE */
pike.git/src/las.c:5512:   }      int dooptcode(struct pike_string *name,    node *n,    struct pike_type *type,    int modifiers)   {    union idptr tmp;    int args, vargs, ret;    struct svalue *foo; + #ifdef PIKE_DEBUG +  struct compilation *c = THIS_COMPILATION; + #endif       CHECK_COMPILER();       optimize_node(n);       check_tree(n, 0);      #ifdef PIKE_DEBUG -  if(a_flag > 1) +  if((a_flag > 1) || (c->lex.pragmas & ID_DISASSEMBLE))    fprintf(stderr, "Doing function '%s' at %lx\n", name->str, -  DO_NOT_WARN((unsigned long)PIKE_PC)); +  (unsigned long)PIKE_PC);   #endif       args=count_arguments(type);    if(args < 0)    {    args=~args;    vargs=IDENTIFIER_VARARGS;    }else{    vargs=0;    }
pike.git/src/las.c:5574:    if((foo=is_stupid_func(n, args, vargs, type)))    {    if(TYPEOF(*foo) == T_FUNCTION && SUBTYPEOF(*foo) == FUNCTION_BUILTIN)    {    tmp.c_fun=foo->u.efun->function;    if(tmp.c_fun != f_destruct &&    tmp.c_fun != f_this_object &&    tmp.c_fun != f_backtrace)    {   #ifdef PIKE_DEBUG -  struct compilation *c = THIS_COMPILATION; -  +     if(a_flag > 1) -  fprintf(stderr,"%s:%d: IDENTIFIER OPTIMIZATION %s == %s\n", +  fprintf(stderr,"%s:%ld: IDENTIFIER OPTIMIZATION %s == %s\n",    c->lex.current_file->str, -  c->lex.current_line, +  (long)c->lex.current_line,    name->str,    foo->u.efun->name->str);   #endif    ret=define_function(name,    type,    (unsigned INT16)modifiers,    (unsigned INT8)(IDENTIFIER_C_FUNCTION |    IDENTIFIER_HAS_BODY |    vargs),    &tmp,