Module Name: src Committed By: rillig Date: Sat Jan 28 00:24:05 UTC 2023
Modified Files: src/usr.bin/xlint/lint1: tree.c Log Message: lint: split integer promotions into separate functions No functional change. To generate a diff of this commit: cvs rdiff -u -r1.495 -r1.496 src/usr.bin/xlint/lint1/tree.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/xlint/lint1/tree.c diff -u src/usr.bin/xlint/lint1/tree.c:1.495 src/usr.bin/xlint/lint1/tree.c:1.496 --- src/usr.bin/xlint/lint1/tree.c:1.495 Sat Jan 28 00:12:00 2023 +++ src/usr.bin/xlint/lint1/tree.c Sat Jan 28 00:24:05 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.495 2023/01/28 00:12:00 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.496 2023/01/28 00:24:05 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: tree.c,v 1.495 2023/01/28 00:12:00 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.496 2023/01/28 00:24:05 rillig Exp $"); #endif #include <float.h> @@ -2092,6 +2092,53 @@ new_tnode(op_t op, bool sys, type_t *typ return ntn; } +/* In traditional C, keep unsigned and promote FLOAT to DOUBLE. */ +static tspec_t +promote_trad(tspec_t t) +{ + + if (t == UCHAR || t == USHORT) + return UINT; + if (t == CHAR || t == SCHAR || t == SHORT) + return INT; + if (t == FLOAT) + return DOUBLE; + if (t == ENUM) + return INT; + return t; +} + +/* + * C99 6.3.1.1p2 requires for types with lower rank than int that "If an int + * can represent all the values of the original type, the value is converted + * to an int; otherwise it is converted to an unsigned int", and that "All + * other types are unchanged by the integer promotions". + */ +static tspec_t +promote_c90(const tnode_t *tn, tspec_t t, bool farg) +{ + if (tn->tn_type->t_bitfield) { + unsigned int len = tn->tn_type->t_flen; + if (len < size_in_bits(INT)) + return INT; + if (len == size_in_bits(INT)) + return is_uinteger(t) ? UINT : INT; + return t; + } + + if (t == CHAR || t == UCHAR || t == SCHAR) + return size_in_bits(CHAR) < size_in_bits(INT) || t != UCHAR + ? INT : UINT; + if (t == SHORT || t == USHORT) + return size_in_bits(SHORT) < size_in_bits(INT) || t == SHORT + ? INT : UINT; + if (t == ENUM) + return INT; + if (farg && t == FLOAT) + return DOUBLE; + return t; +} + /* * Performs the "integer promotions" (C99 6.3.1.1p2), which convert small * integer types to either int or unsigned int. @@ -2102,69 +2149,23 @@ new_tnode(op_t op, bool sys, type_t *typ tnode_t * promote(op_t op, bool farg, tnode_t *tn) { - tspec_t t; - type_t *ntp; - unsigned int len; - t = tn->tn_type->t_tspec; - - if (!is_arithmetic(t)) + tspec_t ot = tn->tn_type->t_tspec; + if (!is_arithmetic(ot)) return tn; - if (allow_c90) { - /* - * C99 6.3.1.1p2 requires for types with lower rank than int - * that "If an int can represent all the values of the - * original type, the value is converted to an int; otherwise - * it is converted to an unsigned int", and that "All other - * types are unchanged by the integer promotions". - */ - if (tn->tn_type->t_bitfield) { - len = tn->tn_type->t_flen; - if (len < size_in_bits(INT)) { - t = INT; - } else if (len == size_in_bits(INT)) { - t = is_uinteger(t) ? UINT : INT; - } - } else if (t == CHAR || t == UCHAR || t == SCHAR) { - t = (size_in_bits(CHAR) < size_in_bits(INT) - || t != UCHAR) ? INT : UINT; - } else if (t == SHORT || t == USHORT) { - t = (size_in_bits(SHORT) < size_in_bits(INT) - || t == SHORT) ? INT : UINT; - } else if (t == ENUM) { - t = INT; - } else if (farg && t == FLOAT) { - t = DOUBLE; - } - } else { - /* - * In traditional C, keep unsigned and promote FLOAT - * to DOUBLE. - */ - if (t == UCHAR || t == USHORT) { - t = UINT; - } else if (t == CHAR || t == SCHAR || t == SHORT) { - t = INT; - } else if (t == FLOAT) { - t = DOUBLE; - } else if (t == ENUM) { - t = INT; - } - } - - if (t != tn->tn_type->t_tspec) { - ntp = expr_dup_type(tn->tn_type); - ntp->t_tspec = t; - /* - * Keep t_is_enum even though t_tspec gets converted from - * ENUM to INT, so we are later able to check compatibility - * of enum types. - */ - tn = convert(op, 0, ntp, tn); - } + tspec_t nt = allow_c90 ? promote_c90(tn, ot, farg) : promote_trad(ot); + if (nt == ot) + return tn; - return tn; + type_t *ntp = expr_dup_type(tn->tn_type); + ntp->t_tspec = nt; + /* + * Keep t_is_enum even though t_tspec gets converted from + * ENUM to INT, so we are later able to check compatibility + * of enum types. + */ + return convert(op, 0, ntp, tn); } static tnode_t *