When we had code like this in a header unifdef failed to deduct that the expression was always false - and we had code exported that was not intended for userspace. #if defined(__KERNEL__) && !defined(__ASSEMBLY__) int a; #endif This commit implment support in unidef which allows it to work out if an #if expression always evaluates true or false for symbols which are being undefined/always defined. The patch is slightly more complicated than I'd hoped because unifdef needs to see lines fully evaluated - doing otherwise causes it to mark the line as "dirty" and copy it over no matter what.
Unified · Split
| @@ -678,8 +678,10 @@ eval_unary(const struct ops *ops, int *valp, const char **cpp) · 677 unmodified lines | ||
| 678 | 678 | if (*cp == '!') { |
| 679 | 679 | debug("eval%d !", ops - eval_ops); |
| 680 | 680 | cp++; |
| 681 | − if (eval_unary(ops, valp, &cp) == LT_IF) | |
| 681 | + if (eval_unary(ops, valp, &cp) == LT_IF) { | |
| 682 | + *cpp = cp; | |
| 682 | 683 | return (LT_IF); |
| 684 | + } | |
| 683 | 685 | *valp = !*valp; |
| 684 | 686 | } else if (*cp == '(') { |
| 685 | 687 | cp++; |
| @@ -700,13 +702,16 @@ eval_unary(const struct ops *ops, int *valp, const char **cpp) · 14 unmodified lines | ||
| 700 | 702 | return (LT_IF); |
| 701 | 703 | cp = skipcomment(cp); |
| 702 | 704 | sym = findsym(cp); |
| 703 | − if (sym < 0) | |
| 704 | − return (LT_IF); | |
| 705 | − *valp = (value[sym] != NULL); | |
| 706 | 705 | cp = skipsym(cp); |
| 707 | 706 | cp = skipcomment(cp); |
| 708 | 707 | if (*cp++ != ')') |
| 709 | 708 | return (LT_IF); |
| 709 | + if (sym >= 0) | |
| 710 | + *valp = (value[sym] != NULL); | |
| 711 | + else { | |
| 712 | + *cpp = cp; | |
| 713 | + return (LT_IF); | |
| 714 | + } | |
| 710 | 715 | keepthis = false; |
| 711 | 716 | } else if (!endsym(*cp)) { |
| 712 | 717 | debug("eval%d symbol", ops - eval_ops); |
| @@ -741,11 +746,11 @@ eval_table(const struct ops *ops, int *valp, const char **cpp) · 28 unmodified lines | ||
| 741 | 746 | const struct op *op; |
| 742 | 747 | const char *cp; |
| 743 | 748 | int val; |
| 749 | + Linetype lhs, rhs; | |
| 744 | 750 | |
| 745 | 751 | debug("eval%d", ops - eval_ops); |
| 746 | 752 | cp = *cpp; |
| 747 | − if (ops->inner(ops+1, valp, &cp) == LT_IF) | |
| 748 | − return (LT_IF); | |
| 753 | + lhs = ops->inner(ops+1, valp, &cp); | |
| 749 | 754 | for (;;) { |
| 750 | 755 | cp = skipcomment(cp); |
| 751 | 756 | for (op = ops->op; op->str != NULL; op++) |
| @@ -755,14 +760,32 @@ eval_table(const struct ops *ops, int *valp, const char **cpp) · 3 unmodified lines | ||
| 755 | 760 | break; |
| 756 | 761 | cp += strlen(op->str); |
| 757 | 762 | debug("eval%d %s", ops - eval_ops, op->str); |
| 758 | − if (ops->inner(ops+1, &val, &cp) == LT_IF) | |
| 759 | − return (LT_IF); | |
| 760 | − *valp = op->fn(*valp, val); | |
| 763 | + rhs = ops->inner(ops+1, &val, &cp); | |
| 764 | + if (op->fn == op_and && (lhs == LT_FALSE || rhs == LT_FALSE)) { | |
| 765 | + debug("eval%d: and always false", ops - eval_ops); | |
| 766 | + if (lhs == LT_IF) | |
| 767 | + *valp = val; | |
| 768 | + lhs = LT_FALSE; | |
| 769 | + continue; | |
| 770 | + } | |
| 771 | + if (op->fn == op_or && (lhs == LT_TRUE || rhs == LT_TRUE)) { | |
| 772 | + debug("eval%d: or always true", ops - eval_ops); | |
| 773 | + if (lhs == LT_IF) | |
| 774 | + *valp = val; | |
| 775 | + lhs = LT_TRUE; | |
| 776 | + continue; | |
| 777 | + } | |
| 778 | + if (rhs == LT_IF) | |
| 779 | + lhs = LT_IF; | |
| 780 | + if (lhs != LT_IF) | |
| 781 | + *valp = op->fn(*valp, val); | |
| 761 | 782 | } |
| 762 | 783 | |
| 763 | 784 | *cpp = cp; |
| 764 | 785 | debug("eval%d = %d", ops - eval_ops, *valp); |
| 765 | − return (*valp ? LT_TRUE : LT_FALSE); | |
| 786 | + if (lhs != LT_IF) | |
| 787 | + lhs = (*valp ? LT_TRUE : LT_FALSE); | |
| 788 | + return lhs; | |
| 766 | 789 | } |
| 767 | 790 | |
| 768 | 791 | /* |
| @@ -773,12 +796,15 @@ eval_table(const struct ops *ops, int *valp, const char **cpp) · 4 unmodified lines | ||
| 773 | 796 | static Linetype |
| 774 | 797 | ifeval(const char **cpp) |
| 775 | 798 | { |
| 799 | + const char *cp = *cpp; | |
| 776 | 800 | int ret; |
| 777 | 801 | int val; |
| 778 | 802 | |
| 779 | 803 | debug("eval %s", *cpp); |
| 780 | 804 | keepthis = killconsts ? false : true; |
| 781 | − ret = eval_table(eval_ops, &val, cpp); | |
| 805 | + ret = eval_table(eval_ops, &val, &cp); | |
| 806 | + if (ret != LT_IF) | |
| 807 | + *cpp = cp; | |
| 782 | 808 | debug("eval = %d", val); |
| 783 | 809 | return (keepthis ? LT_IF : ret); |
| 784 | 810 | } |