1 /*
   2  * Copyright (C) 2006 Dan Carpenter.
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU General Public License
   6  * as published by the Free Software Foundation; either version 2
   7  * of the License, or (at your option) any later version.
   8  *
   9  * This program is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  * GNU General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU General Public License
  15  * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
  16  */
  17 
  18 /*
  19  * You have a lists of states.  kernel = locked, foo = NULL, ...
  20  * When you hit an if {} else {} statement then you swap the list
  21  * of states for a different list of states.  The lists are stored
  22  * on stacks.
  23  *
  24  * At the beginning of this file there are list of the stacks that
  25  * we use.  Each function in this file does something to one of
  26  * of the stacks.
  27  *
  28  * So the smatch_flow.c understands code but it doesn't understand states.
  29  * smatch_flow calls functions in this file.  This file calls functions
  30  * in smatch_slist.c which just has boring generic plumbing for handling
  31  * state lists.  But really it's this file where all the magic happens.
  32  */
  33 
  34 #include <stdlib.h>
  35 #include <stdio.h>
  36 #include "smatch.h"
  37 #include "smatch_slist.h"
  38 #include "smatch_extra.h"
  39 
  40 struct smatch_state undefined = { .name = "undefined" };
  41 struct smatch_state ghost = { .name = "ghost" };
  42 struct smatch_state merged = { .name = "merged" };
  43 struct smatch_state true_state = { .name = "true" };
  44 struct smatch_state false_state = { .name = "false" };
  45 
  46 static struct stree *cur_stree; /* current states */
  47 static struct stree *fast_overlay;
  48 
  49 static struct stree_stack *true_stack; /* states after a t/f branch */
  50 static struct stree_stack *false_stack;
  51 static struct stree_stack *pre_cond_stack; /* states before a t/f branch */
  52 
  53 static struct stree_stack *cond_true_stack; /* states affected by a branch */
  54 static struct stree_stack *cond_false_stack;
  55 
  56 static struct stree_stack *fake_cur_stree_stack;
  57 static int read_only;
  58 
  59 static struct stree_stack *break_stack;
  60 static struct stree_stack *fake_break_stack;
  61 static struct stree_stack *switch_stack;
  62 static struct range_list_stack *remaining_cases;
  63 static struct stree_stack *default_stack;
  64 static struct stree_stack *continue_stack;
  65 
  66 static struct named_stree_stack *goto_stack;
  67 
  68 static struct ptr_list *backup;
  69 
  70 int option_debug;
  71 
  72 void __print_cur_stree(void)
  73 {
  74         __print_stree(cur_stree);
  75 }
  76 
  77 int unreachable(void)
  78 {
  79         if (!cur_stree)
  80                 return 1;
  81         return 0;
  82 }
  83 
  84 void __set_cur_stree_readonly(void)
  85 {
  86         read_only++;
  87 }
  88 
  89 void __set_cur_stree_writable(void)
  90 {
  91         read_only--;
  92 }
  93 
  94 struct sm_state *set_state(int owner, const char *name, struct symbol *sym, struct smatch_state *state)
  95 {
  96         struct sm_state *ret;
  97 
  98         if (!name || !state)
  99                 return NULL;
 100 
 101         if (read_only)
 102                 sm_perror("cur_stree is read only.");
 103 
 104         if (option_debug || strcmp(check_name(owner), option_debug_check) == 0) {
 105                 struct smatch_state *s;
 106 
 107                 s = __get_state(owner, name, sym);
 108                 if (!s)
 109                         sm_msg("%s new [%s] '%s' %s", __func__,
 110                                check_name(owner), name, show_state(state));
 111                 else
 112                         sm_msg("%s change [%s] '%s' %s => %s",
 113                                 __func__, check_name(owner), name, show_state(s),
 114                                 show_state(state));
 115         }
 116 
 117         if (owner != -1 && unreachable())
 118                 return NULL;
 119 
 120         if (fake_cur_stree_stack)
 121                 set_state_stree_stack(&fake_cur_stree_stack, owner, name, sym, state);
 122 
 123         ret = set_state_stree(&cur_stree, owner, name, sym, state);
 124 
 125         return ret;
 126 }
 127 
 128 struct sm_state *set_state_expr(int owner, struct expression *expr, struct smatch_state *state)
 129 {
 130         char *name;
 131         struct symbol *sym;
 132         struct sm_state *ret = NULL;
 133 
 134         expr = strip_expr(expr);
 135         name = expr_to_var_sym(expr, &sym);
 136         if (!name || !sym)
 137                 goto free;
 138         ret = set_state(owner, name, sym, state);
 139 free:
 140         free_string(name);
 141         return ret;
 142 }
 143 
 144 struct stree *__swap_cur_stree(struct stree *stree)
 145 {
 146         struct stree *orig = cur_stree;
 147 
 148         cur_stree = stree;
 149         return orig;
 150 }
 151 
 152 void __push_fake_cur_stree(void)
 153 {
 154         push_stree(&fake_cur_stree_stack, NULL);
 155         __save_pre_cond_states();
 156 }
 157 
 158 struct stree *__pop_fake_cur_stree(void)
 159 {
 160         if (!fake_cur_stree_stack)
 161                 sm_perror("popping too many fake cur strees.");
 162         __use_pre_cond_states();
 163         return pop_stree(&fake_cur_stree_stack);
 164 }
 165 
 166 void __free_fake_cur_stree(void)
 167 {
 168         struct stree *stree;
 169 
 170         stree = __pop_fake_cur_stree();
 171         free_stree(&stree);
 172 }
 173 
 174 void __set_fake_cur_stree_fast(struct stree *stree)
 175 {
 176         if (fast_overlay) {
 177                 sm_perror("cannot nest fast overlay");
 178                 return;
 179         }
 180         fast_overlay = stree;
 181         set_fast_math_only();
 182 }
 183 
 184 void __pop_fake_cur_stree_fast(void)
 185 {
 186         fast_overlay = NULL;
 187         clear_fast_math_only();
 188 }
 189 
 190 void __merge_stree_into_cur(struct stree *stree)
 191 {
 192         struct sm_state *sm;
 193         struct sm_state *orig;
 194         struct sm_state *merged;
 195 
 196         FOR_EACH_SM(stree, sm) {
 197                 orig = get_sm_state(sm->owner, sm->name, sm->sym);
 198                 if (orig)
 199                         merged = merge_sm_states(orig, sm);
 200                 else
 201                         merged = sm;
 202                 __set_sm(merged);
 203         } END_FOR_EACH_SM(sm);
 204 }
 205 
 206 void __set_sm(struct sm_state *sm)
 207 {
 208         if (read_only)
 209                 sm_perror("cur_stree is read only.");
 210 
 211         if (option_debug ||
 212             strcmp(check_name(sm->owner), option_debug_check) == 0) {
 213                 struct smatch_state *s;
 214 
 215                 s = __get_state(sm->owner, sm->name, sm->sym);
 216                 if (!s)
 217                         sm_msg("%s new %s", __func__, show_sm(sm));
 218                 else
 219                         sm_msg("%s change %s (was %s)", __func__, show_sm(sm),
 220                                show_state(s));
 221         }
 222 
 223         if (unreachable())
 224                 return;
 225 
 226         if (fake_cur_stree_stack)
 227                 overwrite_sm_state_stree_stack(&fake_cur_stree_stack, sm);
 228 
 229         overwrite_sm_state_stree(&cur_stree, sm);
 230 }
 231 
 232 void __set_sm_cur_stree(struct sm_state *sm)
 233 {
 234         if (read_only)
 235                 sm_perror("cur_stree is read only.");
 236 
 237         if (option_debug ||
 238             strcmp(check_name(sm->owner), option_debug_check) == 0) {
 239                 struct smatch_state *s;
 240 
 241                 s = __get_state(sm->owner, sm->name, sm->sym);
 242                 if (!s)
 243                         sm_msg("%s new %s", __func__, show_sm(sm));
 244                 else
 245                         sm_msg("%s change %s (was %s)",
 246                                 __func__, show_sm(sm), show_state(s));
 247         }
 248 
 249         if (unreachable())
 250                 return;
 251 
 252         overwrite_sm_state_stree(&cur_stree, sm);
 253 }
 254 
 255 void __set_sm_fake_stree(struct sm_state *sm)
 256 {
 257         if (read_only)
 258                 sm_perror("cur_stree is read only.");
 259 
 260         if (option_debug ||
 261             strcmp(check_name(sm->owner), option_debug_check) == 0) {
 262                 struct smatch_state *s;
 263 
 264                 s = __get_state(sm->owner, sm->name, sm->sym);
 265                 if (!s)
 266                         sm_msg("%s new %s", __func__, show_sm(sm));
 267                 else
 268                         sm_msg("%s change %s (was %s)",
 269                                 __func__, show_sm(sm), show_state(s));
 270         }
 271 
 272         if (unreachable())
 273                 return;
 274 
 275         overwrite_sm_state_stree_stack(&fake_cur_stree_stack, sm);
 276 }
 277 
 278 
 279 typedef void (get_state_hook)(int owner, const char *name, struct symbol *sym);
 280 DECLARE_PTR_LIST(fn_list, get_state_hook *);
 281 static struct fn_list *get_state_hooks;
 282 
 283 void add_get_state_hook(get_state_hook *fn)
 284 {
 285         get_state_hook **p = malloc(sizeof(get_state_hook *));
 286         *p = fn;
 287         add_ptr_list(&get_state_hooks, p);
 288 }
 289 
 290 static void call_get_state_hooks(int owner, const char *name, struct symbol *sym)
 291 {
 292         static int recursion;
 293         get_state_hook **fn;
 294 
 295         if (recursion)
 296                 return;
 297         recursion = 1;
 298 
 299         FOR_EACH_PTR(get_state_hooks, fn) {
 300                 (*fn)(owner, name, sym);
 301         } END_FOR_EACH_PTR(fn);
 302 
 303         recursion = 0;
 304 }
 305 
 306 struct smatch_state *__get_state(int owner, const char *name, struct symbol *sym)
 307 {
 308         struct sm_state *sm;
 309 
 310         sm = get_sm_state(owner, name, sym);
 311         if (!sm)
 312                 return NULL;
 313         return sm->state;
 314 }
 315 
 316 struct smatch_state *get_state(int owner, const char *name, struct symbol *sym)
 317 {
 318         call_get_state_hooks(owner, name, sym);
 319 
 320         return __get_state(owner, name, sym);
 321 }
 322 
 323 struct smatch_state *get_state_expr(int owner, struct expression *expr)
 324 {
 325         char *name;
 326         struct symbol *sym;
 327         struct smatch_state *ret = NULL;
 328 
 329         expr = strip_expr(expr);
 330         name = expr_to_var_sym(expr, &sym);
 331         if (!name || !sym)
 332                 goto free;
 333         ret = get_state(owner, name, sym);
 334 free:
 335         free_string(name);
 336         return ret;
 337 }
 338 
 339 struct state_list *get_possible_states(int owner, const char *name, struct symbol *sym)
 340 {
 341         struct sm_state *sms;
 342 
 343         sms = get_sm_state_stree(cur_stree, owner, name, sym);
 344         if (sms)
 345                 return sms->possible;
 346         return NULL;
 347 }
 348 
 349 struct state_list *get_possible_states_expr(int owner, struct expression *expr)
 350 {
 351         char *name;
 352         struct symbol *sym;
 353         struct state_list *ret = NULL;
 354 
 355         expr = strip_expr(expr);
 356         name = expr_to_var_sym(expr, &sym);
 357         if (!name || !sym)
 358                 goto free;
 359         ret = get_possible_states(owner, name, sym);
 360 free:
 361         free_string(name);
 362         return ret;
 363 }
 364 
 365 struct sm_state *get_sm_state(int owner, const char *name, struct symbol *sym)
 366 {
 367         struct sm_state *ret;
 368 
 369         ret = get_sm_state_stree(fast_overlay, owner, name, sym);
 370         if (ret)
 371                 return ret;
 372 
 373         return get_sm_state_stree(cur_stree, owner, name, sym);
 374 }
 375 
 376 struct sm_state *get_sm_state_expr(int owner, struct expression *expr)
 377 {
 378         char *name;
 379         struct symbol *sym;
 380         struct sm_state *ret = NULL;
 381 
 382         expr = strip_expr(expr);
 383         name = expr_to_var_sym(expr, &sym);
 384         if (!name || !sym)
 385                 goto free;
 386         ret = get_sm_state(owner, name, sym);
 387 free:
 388         free_string(name);
 389         return ret;
 390 }
 391 
 392 void delete_state(int owner, const char *name, struct symbol *sym)
 393 {
 394         delete_state_stree(&cur_stree, owner, name, sym);
 395         if (cond_true_stack) {
 396                 delete_state_stree_stack(&pre_cond_stack, owner, name, sym);
 397                 delete_state_stree_stack(&cond_true_stack, owner, name, sym);
 398                 delete_state_stree_stack(&cond_false_stack, owner, name, sym);
 399         }
 400 }
 401 
 402 void delete_state_expr(int owner, struct expression *expr)
 403 {
 404         char *name;
 405         struct symbol *sym;
 406 
 407         expr = strip_expr(expr);
 408         name = expr_to_var_sym(expr, &sym);
 409         if (!name || !sym)
 410                 goto free;
 411         delete_state(owner, name, sym);
 412 free:
 413         free_string(name);
 414 }
 415 
 416 static void delete_all_states_stree_sym(struct stree **stree, struct symbol *sym)
 417 {
 418         struct state_list *slist = NULL;
 419         struct sm_state *sm;
 420 
 421         FOR_EACH_SM(*stree, sm) {
 422                 if (sm->sym == sym)
 423                         add_ptr_list(&slist, sm);
 424         } END_FOR_EACH_SM(sm);
 425 
 426         FOR_EACH_PTR(slist, sm) {
 427                 delete_state_stree(stree, sm->owner, sm->name, sm->sym);
 428         } END_FOR_EACH_PTR(sm);
 429 
 430         free_slist(&slist);
 431 }
 432 
 433 static void delete_all_states_stree_stack_sym(struct stree_stack **stack, struct symbol *sym)
 434 {
 435         struct stree *stree;
 436 
 437         if (!*stack)
 438                 return;
 439 
 440         stree = pop_stree(stack);
 441         delete_all_states_stree_sym(&stree, sym);
 442         push_stree(stack, stree);
 443 }
 444 
 445 void __delete_all_states_sym(struct symbol *sym)
 446 {
 447         delete_all_states_stree_sym(&cur_stree, sym);
 448 
 449         delete_all_states_stree_stack_sym(&true_stack, sym);
 450         delete_all_states_stree_stack_sym(&true_stack, sym);
 451         delete_all_states_stree_stack_sym(&false_stack, sym);
 452         delete_all_states_stree_stack_sym(&pre_cond_stack, sym);
 453         delete_all_states_stree_stack_sym(&cond_true_stack, sym);
 454         delete_all_states_stree_stack_sym(&cond_false_stack, sym);
 455         delete_all_states_stree_stack_sym(&fake_cur_stree_stack, sym);
 456         delete_all_states_stree_stack_sym(&break_stack, sym);
 457         delete_all_states_stree_stack_sym(&fake_break_stack, sym);
 458         delete_all_states_stree_stack_sym(&switch_stack, sym);
 459         delete_all_states_stree_stack_sym(&continue_stack, sym);
 460 
 461         /*
 462          * deleting from the goto stack is problematic because we don't know
 463          * if the label is in scope and also we need the value for --two-passes.
 464          */
 465 }
 466 
 467 struct stree *get_all_states_from_stree(int owner, struct stree *source)
 468 {
 469         struct stree *ret = NULL;
 470         struct sm_state *tmp;
 471 
 472         FOR_EACH_SM(source, tmp) {
 473                 if (tmp->owner == owner)
 474                         avl_insert(&ret, tmp);
 475         } END_FOR_EACH_SM(tmp);
 476 
 477         return ret;
 478 }
 479 
 480 struct stree *get_all_states_stree(int owner)
 481 {
 482         return get_all_states_from_stree(owner, cur_stree);
 483 }
 484 
 485 struct stree *__get_cur_stree(void)
 486 {
 487         return cur_stree;
 488 }
 489 
 490 int is_reachable(void)
 491 {
 492         if (cur_stree)
 493                 return 1;
 494         return 0;
 495 }
 496 
 497 void set_true_false_states(int owner, const char *name, struct symbol *sym,
 498                            struct smatch_state *true_state,
 499                            struct smatch_state *false_state)
 500 {
 501         if (read_only)
 502                 sm_perror("cur_stree is read only.");
 503 
 504         if (option_debug || strcmp(check_name(owner), option_debug_check) == 0) {
 505                 struct smatch_state *tmp;
 506 
 507                 tmp = __get_state(owner, name, sym);
 508                 sm_msg("%s [%s] '%s'.  Was %s.  Now T:%s F:%s", __func__,
 509                        check_name(owner),  name, show_state(tmp),
 510                        show_state(true_state), show_state(false_state));
 511         }
 512 
 513         if (unreachable())
 514                 return;
 515 
 516         if (!cond_false_stack || !cond_true_stack) {
 517                 sm_perror("missing true/false stacks");
 518                 return;
 519         }
 520 
 521         if (true_state)
 522                 set_state_stree_stack(&cond_true_stack, owner, name, sym, true_state);
 523         if (false_state)
 524                 set_state_stree_stack(&cond_false_stack, owner, name, sym, false_state);
 525 }
 526 
 527 void set_true_false_states_expr(int owner, struct expression *expr,
 528                            struct smatch_state *true_state,
 529                            struct smatch_state *false_state)
 530 {
 531         char *name;
 532         struct symbol *sym;
 533 
 534         expr = strip_expr(expr);
 535         name = expr_to_var_sym(expr, &sym);
 536         if (!name || !sym)
 537                 goto free;
 538         set_true_false_states(owner, name, sym, true_state, false_state);
 539 free:
 540         free_string(name);
 541 }
 542 
 543 void __set_true_false_sm(struct sm_state *true_sm, struct sm_state *false_sm)
 544 {
 545         int owner;
 546         const char *name;
 547         struct symbol *sym;
 548 
 549         if (!true_sm && !false_sm)
 550                 return;
 551 
 552         if (unreachable())
 553                 return;
 554 
 555         owner = true_sm ? true_sm->owner : false_sm->owner;
 556         name = true_sm ? true_sm->name : false_sm->name;
 557         sym = true_sm ? true_sm->sym : false_sm->sym;
 558         if (option_debug || strcmp(check_name(owner), option_debug_check) == 0) {
 559                 struct smatch_state *tmp;
 560 
 561                 tmp = __get_state(owner, name, sym);
 562                 sm_msg("%s [%s] '%s'.  Was %s.  Now T:%s F:%s", __func__,
 563                        check_name(owner),  name, show_state(tmp),
 564                        show_state(true_sm ? true_sm->state : NULL),
 565                        show_state(false_sm ? false_sm->state : NULL));
 566         }
 567 
 568         if (!cond_false_stack || !cond_true_stack) {
 569                 sm_perror("missing true/false stacks");
 570                 return;
 571         }
 572 
 573         if (true_sm)
 574                 overwrite_sm_state_stree_stack(&cond_true_stack, true_sm);
 575         if (false_sm)
 576                 overwrite_sm_state_stree_stack(&cond_false_stack, false_sm);
 577 }
 578 
 579 void nullify_path(void)
 580 {
 581         if (fake_cur_stree_stack) {
 582                 __free_fake_cur_stree();
 583                 __push_fake_cur_stree();
 584         }
 585         free_stree(&cur_stree);
 586 }
 587 
 588 void __match_nullify_path_hook(const char *fn, struct expression *expr,
 589                                void *unused)
 590 {
 591         nullify_path();
 592 }
 593 
 594 /*
 595  * At the start of every function we mark the path
 596  * as unnull.  That way there is always at least one state
 597  * in the cur_stree until nullify_path is called.  This
 598  * is used in merge_slist() for the first null check.
 599  */
 600 void __unnullify_path(void)
 601 {
 602         if (!cur_stree)
 603                 set_state(-1, "unnull_path", NULL, &true_state);
 604 }
 605 
 606 int __path_is_null(void)
 607 {
 608         if (cur_stree)
 609                 return 0;
 610         return 1;
 611 }
 612 
 613 static void check_stree_stack_free(struct stree_stack **stack)
 614 {
 615         if (*stack) {
 616                 sm_perror("stack not empty");
 617                 free_stack_and_strees(stack);
 618         }
 619 }
 620 
 621 void save_all_states(void)
 622 {
 623         __add_ptr_list(&backup, cur_stree);
 624         cur_stree = NULL;
 625 
 626         __add_ptr_list(&backup, true_stack);
 627         true_stack = NULL;
 628         __add_ptr_list(&backup, false_stack);
 629         false_stack = NULL;
 630         __add_ptr_list(&backup, pre_cond_stack);
 631         pre_cond_stack = NULL;
 632 
 633         __add_ptr_list(&backup, cond_true_stack);
 634         cond_true_stack = NULL;
 635         __add_ptr_list(&backup, cond_false_stack);
 636         cond_false_stack = NULL;
 637 
 638         __add_ptr_list(&backup, fake_cur_stree_stack);
 639         fake_cur_stree_stack = NULL;
 640 
 641         __add_ptr_list(&backup, break_stack);
 642         break_stack = NULL;
 643         __add_ptr_list(&backup, fake_break_stack);
 644         fake_break_stack = NULL;
 645 
 646         __add_ptr_list(&backup, switch_stack);
 647         switch_stack = NULL;
 648         __add_ptr_list(&backup, remaining_cases);
 649         remaining_cases = NULL;
 650         __add_ptr_list(&backup, default_stack);
 651         default_stack = NULL;
 652         __add_ptr_list(&backup, continue_stack);
 653         continue_stack = NULL;
 654 
 655         __add_ptr_list(&backup, goto_stack);
 656         goto_stack = NULL;
 657 }
 658 
 659 static void *pop_backup(void)
 660 {
 661         void *ret;
 662 
 663         ret = last_ptr_list(backup);
 664         delete_ptr_list_last(&backup);
 665         return ret;
 666 }
 667 
 668 void restore_all_states(void)
 669 {
 670         goto_stack = pop_backup();
 671 
 672         continue_stack = pop_backup();
 673         default_stack = pop_backup();
 674         remaining_cases = pop_backup();
 675         switch_stack = pop_backup();
 676         fake_break_stack = pop_backup();
 677         break_stack = pop_backup();
 678 
 679         fake_cur_stree_stack = pop_backup();
 680 
 681         cond_false_stack = pop_backup();
 682         cond_true_stack = pop_backup();
 683 
 684         pre_cond_stack = pop_backup();
 685         false_stack = pop_backup();
 686         true_stack = pop_backup();
 687 
 688         cur_stree = pop_backup();
 689 }
 690 
 691 void free_goto_stack(void)
 692 {
 693         struct named_stree *named_stree;
 694 
 695         FOR_EACH_PTR(goto_stack, named_stree) {
 696                 free_stree(&named_stree->stree);
 697         } END_FOR_EACH_PTR(named_stree);
 698         __free_ptr_list((struct ptr_list **)&goto_stack);
 699 }
 700 
 701 void clear_all_states(void)
 702 {
 703         nullify_path();
 704         check_stree_stack_free(&true_stack);
 705         check_stree_stack_free(&false_stack);
 706         check_stree_stack_free(&pre_cond_stack);
 707         check_stree_stack_free(&cond_true_stack);
 708         check_stree_stack_free(&cond_false_stack);
 709         check_stree_stack_free(&break_stack);
 710         check_stree_stack_free(&fake_break_stack);
 711         check_stree_stack_free(&switch_stack);
 712         check_stree_stack_free(&continue_stack);
 713         check_stree_stack_free(&fake_cur_stree_stack);
 714 
 715         free_goto_stack();
 716 
 717         free_every_single_sm_state();
 718         free_tmp_expressions();
 719 }
 720 
 721 void __push_cond_stacks(void)
 722 {
 723         push_stree(&cond_true_stack, NULL);
 724         push_stree(&cond_false_stack, NULL);
 725         __push_fake_cur_stree();
 726 }
 727 
 728 void __fold_in_set_states(void)
 729 {
 730         struct stree *new_states;
 731         struct sm_state *sm;
 732 
 733         new_states = __pop_fake_cur_stree();
 734         FOR_EACH_SM(new_states, sm) {
 735                 __set_sm(sm);
 736                 __set_true_false_sm(sm, sm);
 737         } END_FOR_EACH_SM(sm);
 738         free_stree(&new_states);
 739 }
 740 
 741 void __free_set_states(void)
 742 {
 743         struct stree *new_states;
 744 
 745         new_states = __pop_fake_cur_stree();
 746         free_stree(&new_states);
 747 }
 748 
 749 struct stree *__copy_cond_true_states(void)
 750 {
 751         struct stree *ret;
 752 
 753         ret = pop_stree(&cond_true_stack);
 754         push_stree(&cond_true_stack, clone_stree(ret));
 755         return ret;
 756 }
 757 
 758 struct stree *__copy_cond_false_states(void)
 759 {
 760         struct stree *ret;
 761 
 762         ret = pop_stree(&cond_false_stack);
 763         push_stree(&cond_false_stack, clone_stree(ret));
 764         return ret;
 765 }
 766 
 767 struct stree *__pop_cond_true_stack(void)
 768 {
 769         return pop_stree(&cond_true_stack);
 770 }
 771 
 772 struct stree *__pop_cond_false_stack(void)
 773 {
 774         return pop_stree(&cond_false_stack);
 775 }
 776 
 777 /*
 778  * This combines the pre cond states with either the true or false states.
 779  * For example:
 780  * a = kmalloc() ; if (a !! foo(a)
 781  * In the pre state a is possibly null.  In the true state it is non null.
 782  * In the false state it is null.  Combine the pre and the false to get
 783  * that when we call 'foo', 'a' is null.
 784  */
 785 static void __use_cond_stack(struct stree_stack **stack)
 786 {
 787         struct stree *stree;
 788 
 789         free_stree(&cur_stree);
 790 
 791         cur_stree = pop_stree(&pre_cond_stack);
 792         push_stree(&pre_cond_stack, clone_stree(cur_stree));
 793 
 794         stree = pop_stree(stack);
 795         overwrite_stree(stree, &cur_stree);
 796         push_stree(stack, stree);
 797 }
 798 
 799 void __use_pre_cond_states(void)
 800 {
 801         free_stree(&cur_stree);
 802         cur_stree = pop_stree(&pre_cond_stack);
 803 }
 804 
 805 void __use_cond_true_states(void)
 806 {
 807         __use_cond_stack(&cond_true_stack);
 808 }
 809 
 810 void __use_cond_false_states(void)
 811 {
 812         __use_cond_stack(&cond_false_stack);
 813 }
 814 
 815 void __negate_cond_stacks(void)
 816 {
 817         struct stree *old_false, *old_true;
 818 
 819         old_false = pop_stree(&cond_false_stack);
 820         old_true = pop_stree(&cond_true_stack);
 821         push_stree(&cond_false_stack, old_true);
 822         push_stree(&cond_true_stack, old_false);
 823 }
 824 
 825 void __and_cond_states(void)
 826 {
 827         and_stree_stack(&cond_true_stack);
 828         or_stree_stack(&pre_cond_stack, cur_stree, &cond_false_stack);
 829 }
 830 
 831 void __or_cond_states(void)
 832 {
 833         or_stree_stack(&pre_cond_stack, cur_stree, &cond_true_stack);
 834         and_stree_stack(&cond_false_stack);
 835 }
 836 
 837 void __save_pre_cond_states(void)
 838 {
 839         push_stree(&pre_cond_stack, clone_stree(cur_stree));
 840 }
 841 
 842 void __discard_pre_cond_states(void)
 843 {
 844         struct stree *tmp;
 845 
 846         tmp = pop_stree(&pre_cond_stack);
 847         free_stree(&tmp);
 848 }
 849 
 850 struct stree *__get_true_states(void)
 851 {
 852         return clone_stree(top_stree(cond_true_stack));
 853 }
 854 
 855 struct stree *__get_false_states(void)
 856 {
 857         return clone_stree(top_stree(cond_false_stack));
 858 }
 859 
 860 void __use_cond_states(void)
 861 {
 862         struct stree *pre, *pre_clone, *true_states, *false_states;
 863 
 864         pre = pop_stree(&pre_cond_stack);
 865         pre_clone = clone_stree(pre);
 866 
 867         true_states = pop_stree(&cond_true_stack);
 868         overwrite_stree(true_states, &pre);
 869         free_stree(&true_states);
 870         /* we use the true states right away */
 871         free_stree(&cur_stree);
 872         cur_stree = pre;
 873 
 874         false_states = pop_stree(&cond_false_stack);
 875         overwrite_stree(false_states, &pre_clone);
 876         free_stree(&false_states);
 877         push_stree(&false_stack, pre_clone);
 878 }
 879 
 880 void __push_true_states(void)
 881 {
 882         push_stree(&true_stack, clone_stree(cur_stree));
 883 }
 884 
 885 void __use_false_states(void)
 886 {
 887         free_stree(&cur_stree);
 888         cur_stree = pop_stree(&false_stack);
 889 }
 890 
 891 void __discard_false_states(void)
 892 {
 893         struct stree *stree;
 894 
 895         stree = pop_stree(&false_stack);
 896         free_stree(&stree);
 897 }
 898 
 899 void __merge_false_states(void)
 900 {
 901         struct stree *stree;
 902 
 903         stree = pop_stree(&false_stack);
 904         merge_stree(&cur_stree, stree);
 905         free_stree(&stree);
 906 }
 907 
 908 /*
 909  * This function probably seemed common sensical when I wrote it but, oh wow,
 910  * does it look subtle in retrospect.  Say we set a state on one side of the if
 911  * else path but not on the other, then what we should record in the fake stree
 912  * is the merged state.
 913  *
 914  * This function relies on the fact that the we always set the cur_stree as well
 915  * and we already have the infrastructure to merge things correctly into the
 916  * cur_stree.
 917  *
 918  * So instead of merging fake strees together which is probably a lot of work,
 919  * we just use it as a list of set states and look up the actual current values
 920  * in the cur_stree.
 921  *
 922  */
 923 static void update_stree_with_merged(struct stree **stree)
 924 {
 925         struct state_list *slist = NULL;
 926         struct sm_state *sm, *new;
 927 
 928         FOR_EACH_SM(*stree, sm) {
 929                 new = get_sm_state(sm->owner, sm->name, sm->sym);
 930                 if (!new)  /* This can happen if we go out of scope */
 931                         continue;
 932                 add_ptr_list(&slist, new);
 933         } END_FOR_EACH_SM(sm);
 934 
 935         FOR_EACH_PTR(slist, sm) {
 936                 overwrite_sm_state_stree(stree, sm);
 937         } END_FOR_EACH_PTR(sm);
 938 
 939         free_slist(&slist);
 940 }
 941 
 942 static void update_fake_stree_with_merged(void)
 943 {
 944         struct stree *stree;
 945 
 946         if (!fake_cur_stree_stack)
 947                 return;
 948         stree = pop_stree(&fake_cur_stree_stack);
 949         update_stree_with_merged(&stree);
 950         push_stree(&fake_cur_stree_stack, stree);
 951 }
 952 
 953 void __merge_true_states(void)
 954 {
 955         struct stree *stree;
 956 
 957         stree = pop_stree(&true_stack);
 958         merge_stree(&cur_stree, stree);
 959         update_fake_stree_with_merged();
 960         free_stree(&stree);
 961 }
 962 
 963 void __push_continues(void)
 964 {
 965         push_stree(&continue_stack, NULL);
 966 }
 967 
 968 void __discard_continues(void)
 969 {
 970         struct stree *stree;
 971 
 972         stree = pop_stree(&continue_stack);
 973         free_stree(&stree);
 974 }
 975 
 976 void __process_continues(void)
 977 {
 978         struct stree *stree;
 979 
 980         stree = pop_stree(&continue_stack);
 981         if (!stree)
 982                 stree = clone_stree(cur_stree);
 983         else
 984                 merge_stree(&stree, cur_stree);
 985 
 986         push_stree(&continue_stack, stree);
 987 }
 988 
 989 void __merge_continues(void)
 990 {
 991         struct stree *stree;
 992 
 993         stree = pop_stree(&continue_stack);
 994         merge_stree(&cur_stree, stree);
 995         free_stree(&stree);
 996 }
 997 
 998 void __push_breaks(void)
 999 {
1000         push_stree(&break_stack, NULL);
1001         if (fake_cur_stree_stack)
1002                 push_stree(&fake_break_stack, NULL);
1003 }
1004 
1005 void __process_breaks(void)
1006 {
1007         struct stree *stree;
1008 
1009         stree = pop_stree(&break_stack);
1010         if (!stree)
1011                 stree = clone_stree(cur_stree);
1012         else
1013                 merge_stree(&stree, cur_stree);
1014         push_stree(&break_stack, stree);
1015 
1016         if (!fake_cur_stree_stack)
1017                 return;
1018 
1019         stree = pop_stree(&fake_break_stack);
1020         if (!stree)
1021                 stree = clone_stree(top_stree(fake_cur_stree_stack));
1022         else
1023                 merge_stree(&stree, top_stree(fake_cur_stree_stack));
1024         push_stree(&fake_break_stack, stree);
1025 }
1026 
1027 int __has_breaks(void)
1028 {
1029         struct stree *stree;
1030         int ret;
1031 
1032         stree = pop_stree(&break_stack);
1033         ret = !!stree;
1034         push_stree(&break_stack, stree);
1035         return ret;
1036 }
1037 
1038 void __merge_breaks(void)
1039 {
1040         struct stree *stree;
1041         struct sm_state *sm;
1042 
1043         stree = pop_stree(&break_stack);
1044         merge_stree(&cur_stree, stree);
1045         free_stree(&stree);
1046 
1047         if (!fake_cur_stree_stack)
1048                 return;
1049 
1050         stree = pop_stree(&fake_break_stack);
1051         update_stree_with_merged(&stree);
1052         FOR_EACH_SM(stree, sm) {
1053                 overwrite_sm_state_stree_stack(&fake_cur_stree_stack, sm);
1054         } END_FOR_EACH_SM(sm);
1055         free_stree(&stree);
1056 }
1057 
1058 void __use_breaks(void)
1059 {
1060         struct stree *stree;
1061         struct sm_state *sm;
1062 
1063         free_stree(&cur_stree);
1064         cur_stree = pop_stree(&break_stack);
1065 
1066         if (!fake_cur_stree_stack)
1067                 return;
1068         stree = pop_stree(&fake_break_stack);
1069         FOR_EACH_SM(stree, sm) {
1070                 overwrite_sm_state_stree_stack(&fake_cur_stree_stack, sm);
1071         } END_FOR_EACH_SM(sm);
1072         free_stree(&stree);
1073 
1074 
1075 }
1076 
1077 void __save_switch_states(struct expression *switch_expr)
1078 {
1079         struct range_list *rl;
1080 
1081         get_absolute_rl(switch_expr, &rl);
1082 
1083         push_rl(&remaining_cases, rl);
1084         push_stree(&switch_stack, clone_stree(cur_stree));
1085 }
1086 
1087 int have_remaining_cases(void)
1088 {
1089         return !!top_rl(remaining_cases);
1090 }
1091 
1092 void __merge_switches(struct expression *switch_expr, struct range_list *case_rl)
1093 {
1094         struct stree *stree;
1095         struct stree *implied_stree;
1096 
1097         stree = pop_stree(&switch_stack);
1098         implied_stree = __implied_case_stree(switch_expr, case_rl, &remaining_cases, &stree);
1099         merge_stree(&cur_stree, implied_stree);
1100         free_stree(&implied_stree);
1101         push_stree(&switch_stack, stree);
1102 }
1103 
1104 void __discard_switches(void)
1105 {
1106         struct stree *stree;
1107 
1108         pop_rl(&remaining_cases);
1109         stree = pop_stree(&switch_stack);
1110         free_stree(&stree);
1111 }
1112 
1113 void __push_default(void)
1114 {
1115         push_stree(&default_stack, NULL);
1116 }
1117 
1118 void __set_default(void)
1119 {
1120         set_state_stree_stack(&default_stack, 0, "has_default", NULL, &true_state);
1121 }
1122 
1123 int __pop_default(void)
1124 {
1125         struct stree *stree;
1126 
1127         stree = pop_stree(&default_stack);
1128         if (stree) {
1129                 free_stree(&stree);
1130                 return 1;
1131         }
1132         return 0;
1133 }
1134 
1135 static struct named_stree *alloc_named_stree(const char *name, struct symbol *sym, struct stree *stree)
1136 {
1137         struct named_stree *named_stree = __alloc_named_stree(0);
1138 
1139         named_stree->name = (char *)name;
1140         named_stree->stree = stree;
1141         named_stree->sym = sym;
1142         return named_stree;
1143 }
1144 
1145 void __save_gotos(const char *name, struct symbol *sym)
1146 {
1147         struct stree **stree;
1148         struct stree *clone;
1149 
1150         stree = get_named_stree(goto_stack, name, sym);
1151         if (stree) {
1152                 merge_stree(stree, cur_stree);
1153                 return;
1154         } else {
1155                 struct named_stree *named_stree;
1156 
1157                 clone = clone_stree(cur_stree);
1158                 named_stree = alloc_named_stree(name, sym, clone);
1159                 add_ptr_list(&goto_stack, named_stree);
1160         }
1161 }
1162 
1163 void __merge_gotos(const char *name, struct symbol *sym)
1164 {
1165         struct stree **stree;
1166 
1167         stree = get_named_stree(goto_stack, name, sym);
1168         if (stree)
1169                 merge_stree(&cur_stree, *stree);
1170 }