tree.c revision 1.402
11.402Srillig/* $NetBSD: tree.c,v 1.402 2021/12/21 15:33:20 rillig Exp $ */ 21.2Scgd 31.1Scgd/* 41.1Scgd * Copyright (c) 1994, 1995 Jochen Pohl 51.1Scgd * All Rights Reserved. 61.1Scgd * 71.1Scgd * Redistribution and use in source and binary forms, with or without 81.1Scgd * modification, are permitted provided that the following conditions 91.1Scgd * are met: 101.1Scgd * 1. Redistributions of source code must retain the above copyright 111.1Scgd * notice, this list of conditions and the following disclaimer. 121.1Scgd * 2. Redistributions in binary form must reproduce the above copyright 131.1Scgd * notice, this list of conditions and the following disclaimer in the 141.1Scgd * documentation and/or other materials provided with the distribution. 151.1Scgd * 3. All advertising materials mentioning features or use of this software 161.1Scgd * must display the following acknowledgement: 171.1Scgd * This product includes software developed by Jochen Pohl for 181.1Scgd * The NetBSD Project. 191.1Scgd * 4. The name of the author may not be used to endorse or promote products 201.1Scgd * derived from this software without specific prior written permission. 211.1Scgd * 221.1Scgd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 231.1Scgd * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 241.1Scgd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 251.1Scgd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 261.1Scgd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 271.1Scgd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 281.1Scgd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 291.1Scgd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 301.1Scgd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 311.1Scgd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 321.1Scgd */ 331.1Scgd 341.37Sjmc#if HAVE_NBTOOL_CONFIG_H 351.37Sjmc#include "nbtool_config.h" 361.37Sjmc#endif 371.37Sjmc 381.14Schristos#include <sys/cdefs.h> 391.23Stv#if defined(__RCSID) && !defined(lint) 401.402Srillig__RCSID("$NetBSD: tree.c,v 1.402 2021/12/21 15:33:20 rillig Exp $"); 411.1Scgd#endif 421.1Scgd 431.1Scgd#include <float.h> 441.1Scgd#include <limits.h> 451.1Scgd#include <math.h> 461.49Schristos#include <signal.h> 471.92Srillig#include <stdlib.h> 481.92Srillig#include <string.h> 491.1Scgd 501.1Scgd#include "lint1.h" 511.15Stv#include "cgram.h" 521.1Scgd 531.318Srilligstatic tnode_t *build_integer_constant(tspec_t, int64_t); 541.149Srilligstatic void check_pointer_comparison(op_t, 551.149Srillig const tnode_t *, const tnode_t *); 561.154Srilligstatic bool check_assign_types_compatible(op_t, int, 571.149Srillig const tnode_t *, const tnode_t *); 581.149Srilligstatic void check_bad_enum_operation(op_t, 591.149Srillig const tnode_t *, const tnode_t *); 601.149Srilligstatic void check_enum_type_mismatch(op_t, int, 611.149Srillig const tnode_t *, const tnode_t *); 621.149Srilligstatic void check_enum_int_mismatch(op_t, int, 631.149Srillig const tnode_t *, const tnode_t *); 641.395Srilligstatic tnode_t *new_tnode(op_t, bool, type_t *, tnode_t *, tnode_t *); 651.20Slukemstatic void balance(op_t, tnode_t **, tnode_t **); 661.246Srilligstatic void warn_incompatible_types(op_t, const type_t *, tspec_t, 671.246Srillig const type_t *, tspec_t); 681.149Srilligstatic void warn_incompatible_pointers(const mod_t *, 691.149Srillig const type_t *, const type_t *); 701.149Srilligstatic bool has_constant_member(const type_t *); 711.100Srilligstatic void check_prototype_conversion(int, tspec_t, tspec_t, type_t *, 721.100Srillig tnode_t *); 731.100Srilligstatic void check_integer_conversion(op_t, int, tspec_t, tspec_t, type_t *, 741.100Srillig tnode_t *); 751.100Srilligstatic void check_pointer_integer_conversion(op_t, tspec_t, type_t *, 761.100Srillig tnode_t *); 771.273Srilligstatic void check_pointer_conversion(tnode_t *, type_t *); 781.395Srilligstatic tnode_t *build_struct_access(op_t, bool, tnode_t *, tnode_t *); 791.395Srilligstatic tnode_t *build_prepost_incdec(op_t, bool, tnode_t *); 801.395Srilligstatic tnode_t *build_real_imag(op_t, bool, tnode_t *); 811.395Srilligstatic tnode_t *build_address(bool, tnode_t *, bool); 821.395Srilligstatic tnode_t *build_plus_minus(op_t, bool, tnode_t *, tnode_t *); 831.395Srilligstatic tnode_t *build_bit_shift(op_t, bool, tnode_t *, tnode_t *); 841.395Srilligstatic tnode_t *build_colon(bool, tnode_t *, tnode_t *); 851.395Srilligstatic tnode_t *build_assignment(op_t, bool, tnode_t *, tnode_t *); 861.20Slukemstatic tnode_t *plength(type_t *); 871.20Slukemstatic tnode_t *fold(tnode_t *); 881.100Srilligstatic tnode_t *fold_test(tnode_t *); 891.100Srilligstatic tnode_t *fold_float(tnode_t *); 901.100Srilligstatic tnode_t *check_function_arguments(type_t *, tnode_t *); 911.100Srilligstatic tnode_t *check_prototype_argument(int, type_t *, tnode_t *); 921.149Srilligstatic void check_null_effect(const tnode_t *); 931.154Srilligstatic void check_array_index(tnode_t *, bool); 941.100Srilligstatic void check_integer_comparison(op_t, tnode_t *, tnode_t *); 951.100Srilligstatic void check_precedence_confusion(tnode_t *); 961.1Scgd 971.49Schristosextern sig_atomic_t fpe; 981.49Schristos 991.241Srilligstatic const char * 1001.260Srilligop_name(op_t op) 1011.241Srillig{ 1021.241Srillig return modtab[op].m_name; 1031.241Srillig} 1041.241Srillig 1051.257Srillig/* Build 'pointer to tp', 'array of tp' or 'function returning tp'. */ 1061.1Scgdtype_t * 1071.257Srilligderive_type(type_t *tp, tspec_t t) 1081.1Scgd{ 1091.1Scgd type_t *tp2; 1101.1Scgd 1111.259Srillig tp2 = getblk(sizeof(*tp2)); 1121.1Scgd tp2->t_tspec = t; 1131.1Scgd tp2->t_subt = tp; 1141.95Srillig return tp2; 1151.1Scgd} 1161.1Scgd 1171.1Scgd/* 1181.365Srillig * Derive 'pointer to tp' or 'function returning tp'. 1191.365Srillig * The memory is freed at the end of the current expression. 1201.1Scgd */ 1211.1Scgdtype_t * 1221.257Srilligexpr_derive_type(type_t *tp, tspec_t t) 1231.1Scgd{ 1241.1Scgd type_t *tp2; 1251.1Scgd 1261.259Srillig tp2 = expr_zalloc(sizeof(*tp2)); 1271.1Scgd tp2->t_tspec = t; 1281.1Scgd tp2->t_subt = tp; 1291.95Srillig return tp2; 1301.1Scgd} 1311.1Scgd 1321.1Scgd/* 1331.1Scgd * Create a node for a constant. 1341.1Scgd */ 1351.1Scgdtnode_t * 1361.318Srilligbuild_constant(type_t *tp, val_t *v) 1371.1Scgd{ 1381.1Scgd tnode_t *n; 1391.1Scgd 1401.256Srillig n = expr_zalloc_tnode(); 1411.1Scgd n->tn_op = CON; 1421.1Scgd n->tn_type = tp; 1431.259Srillig n->tn_val = expr_zalloc(sizeof(*n->tn_val)); 1441.1Scgd n->tn_val->v_tspec = tp->t_tspec; 1451.289Srillig n->tn_val->v_unsigned_since_c90 = v->v_unsigned_since_c90; 1461.1Scgd n->tn_val->v_u = v->v_u; 1471.1Scgd free(v); 1481.95Srillig return n; 1491.1Scgd} 1501.1Scgd 1511.1Scgdstatic tnode_t * 1521.318Srilligbuild_integer_constant(tspec_t t, int64_t q) 1531.1Scgd{ 1541.1Scgd tnode_t *n; 1551.1Scgd 1561.256Srillig n = expr_zalloc_tnode(); 1571.1Scgd n->tn_op = CON; 1581.1Scgd n->tn_type = gettyp(t); 1591.259Srillig n->tn_val = expr_zalloc(sizeof(*n->tn_val)); 1601.1Scgd n->tn_val->v_tspec = t; 1611.1Scgd n->tn_val->v_quad = q; 1621.95Srillig return n; 1631.1Scgd} 1641.1Scgd 1651.167Srilligstatic void 1661.167Srilligfallback_symbol(sym_t *sym) 1671.167Srillig{ 1681.167Srillig 1691.267Srillig if (fallback_symbol_strict_bool(sym)) 1701.167Srillig return; 1711.167Srillig 1721.233Srillig if (block_level > 0 && (strcmp(sym->s_name, "__FUNCTION__") == 0 || 1731.167Srillig strcmp(sym->s_name, "__PRETTY_FUNCTION__") == 0)) { 1741.167Srillig /* __FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension */ 1751.167Srillig gnuism(316); 1761.257Srillig sym->s_type = derive_type(gettyp(CHAR), PTR); 1771.167Srillig sym->s_type->t_const = true; 1781.167Srillig return; 1791.167Srillig } 1801.167Srillig 1811.233Srillig if (block_level > 0 && strcmp(sym->s_name, "__func__") == 0) { 1821.167Srillig if (!Sflag) 1831.167Srillig /* __func__ is a C9X feature */ 1841.167Srillig warning(317); 1851.257Srillig sym->s_type = derive_type(gettyp(CHAR), PTR); 1861.167Srillig sym->s_type->t_const = true; 1871.167Srillig return; 1881.167Srillig } 1891.167Srillig 1901.251Srillig /* '%s' undefined */ 1911.167Srillig error(99, sym->s_name); 1921.167Srillig} 1931.167Srillig 1941.358Srillig/* 1951.361Srillig * Functions that are predeclared by GCC or other compilers can be called 1961.361Srillig * with arbitrary arguments. Since lint usually runs after a successful 1971.361Srillig * compilation, it's the compiler's job to catch any errors. 1981.358Srillig */ 1991.358Srilligbool 2001.361Srilligis_compiler_builtin(const char *name) 2011.303Srillig{ 2021.361Srillig /* https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html */ 2031.362Srillig if (gflag) { 2041.362Srillig if (strncmp(name, "__atomic_", 9) == 0 || 2051.362Srillig strncmp(name, "__builtin_", 10) == 0 || 2061.400Srillig strcmp(name, "alloca") == 0 || 2071.362Srillig /* obsolete but still in use, as of 2021 */ 2081.362Srillig strncmp(name, "__sync_", 7) == 0) 2091.362Srillig return true; 2101.362Srillig } 2111.361Srillig 2121.361Srillig /* https://software.intel.com/sites/landingpage/IntrinsicsGuide/ */ 2131.361Srillig if (strncmp(name, "_mm_", 4) == 0) 2141.361Srillig return true; 2151.361Srillig 2161.361Srillig return false; 2171.303Srillig} 2181.303Srillig 2191.372Srilligstatic bool 2201.372Srilligstr_endswith(const char *haystack, const char *needle) 2211.372Srillig{ 2221.372Srillig size_t hlen = strlen(haystack); 2231.372Srillig size_t nlen = strlen(needle); 2241.372Srillig 2251.372Srillig return nlen <= hlen && 2261.372Srillig memcmp(haystack + hlen - nlen, needle, nlen) == 0; 2271.372Srillig} 2281.372Srillig 2291.372Srillig/* https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html */ 2301.372Srilligstatic bool 2311.372Srilligis_gcc_bool_builtin(const char *name) 2321.372Srillig{ 2331.372Srillig return strncmp(name, "__builtin_", 10) == 0 && 2341.372Srillig (str_endswith(name, "_overflow") || 2351.372Srillig str_endswith(name, "_overflow_p")); 2361.372Srillig} 2371.372Srillig 2381.371Srilligstatic void 2391.371Srilligbuild_name_call(sym_t *sym) 2401.371Srillig{ 2411.371Srillig 2421.371Srillig if (is_compiler_builtin(sym->s_name)) { 2431.371Srillig /* 2441.371Srillig * Do not warn about these, just assume that 2451.371Srillig * they are regular functions compatible with 2461.371Srillig * non-prototype calling conventions. 2471.371Srillig */ 2481.400Srillig if (gflag && is_gcc_bool_builtin(sym->s_name)) 2491.372Srillig sym->s_type = gettyp(BOOL); 2501.372Srillig 2511.371Srillig } else if (Sflag) { 2521.371Srillig /* function '%s' implicitly declared to return int */ 2531.371Srillig error(215, sym->s_name); 2541.371Srillig } else if (sflag) { 2551.371Srillig /* function '%s' implicitly declared to return int */ 2561.371Srillig warning(215, sym->s_name); 2571.371Srillig } 2581.371Srillig 2591.371Srillig /* XXX if tflag is set, the symbol should be exported to level 0 */ 2601.371Srillig sym->s_type = derive_type(sym->s_type, FUNC); 2611.371Srillig} 2621.371Srillig 2631.402Srillig/* Create a node for a name (symbol table entry). */ 2641.1Scgdtnode_t * 2651.399Srilligbuild_name(sym_t *sym, bool is_funcname) 2661.1Scgd{ 2671.1Scgd tnode_t *n; 2681.1Scgd 2691.1Scgd if (sym->s_scl == NOSCL) { 2701.1Scgd sym->s_scl = EXTERN; 2711.1Scgd sym->s_def = DECL; 2721.399Srillig if (is_funcname) 2731.371Srillig build_name_call(sym); 2741.399Srillig else 2751.167Srillig fallback_symbol(sym); 2761.1Scgd } 2771.1Scgd 2781.242Srillig lint_assert(sym->s_kind == FVFT || sym->s_kind == FMEMBER); 2791.1Scgd 2801.256Srillig n = expr_zalloc_tnode(); 2811.1Scgd n->tn_type = sym->s_type; 2821.401Srillig if (sym->s_scl == CTCONST) { 2831.401Srillig n->tn_op = CON; 2841.401Srillig n->tn_val = expr_zalloc(sizeof(*n->tn_val)); 2851.401Srillig *n->tn_val = sym->s_value; 2861.401Srillig } else { 2871.1Scgd n->tn_op = NAME; 2881.1Scgd n->tn_sym = sym; 2891.1Scgd if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) 2901.154Srillig n->tn_lvalue = true; 2911.1Scgd } 2921.1Scgd 2931.95Srillig return n; 2941.1Scgd} 2951.1Scgd 2961.1Scgdtnode_t * 2971.318Srilligbuild_string(strg_t *strg) 2981.1Scgd{ 2991.1Scgd size_t len; 3001.1Scgd tnode_t *n; 3011.365Srillig type_t *tp; 3021.1Scgd 3031.1Scgd len = strg->st_len; 3041.1Scgd 3051.256Srillig n = expr_zalloc_tnode(); 3061.1Scgd 3071.365Srillig tp = expr_zalloc(sizeof(*tp)); 3081.365Srillig tp->t_tspec = ARRAY; 3091.365Srillig tp->t_subt = gettyp(strg->st_tspec); 3101.378Srillig tp->t_dim = (int)(len + 1); 3111.365Srillig 3121.1Scgd n->tn_op = STRING; 3131.365Srillig n->tn_type = tp; 3141.154Srillig n->tn_lvalue = true; 3151.1Scgd 3161.259Srillig n->tn_string = expr_zalloc(sizeof(*n->tn_string)); 3171.104Srillig n->tn_string->st_tspec = strg->st_tspec; 3181.104Srillig n->tn_string->st_len = len; 3191.1Scgd 3201.1Scgd if (strg->st_tspec == CHAR) { 3211.257Srillig n->tn_string->st_cp = expr_zalloc(len + 1); 3221.104Srillig (void)memcpy(n->tn_string->st_cp, strg->st_cp, len + 1); 3231.1Scgd free(strg->st_cp); 3241.1Scgd } else { 3251.259Srillig size_t size = (len + 1) * sizeof(*n->tn_string->st_wcp); 3261.257Srillig n->tn_string->st_wcp = expr_zalloc(size); 3271.250Srillig (void)memcpy(n->tn_string->st_wcp, strg->st_wcp, size); 3281.1Scgd free(strg->st_wcp); 3291.1Scgd } 3301.1Scgd free(strg); 3311.1Scgd 3321.95Srillig return n; 3331.1Scgd} 3341.1Scgd 3351.1Scgd/* 3361.1Scgd * Returns a symbol which has the same name as the msym argument and is a 3371.1Scgd * member of the struct or union specified by the tn argument. 3381.1Scgd */ 3391.398Srilligstatic sym_t * 3401.98Srilligstruct_or_union_member(tnode_t *tn, op_t op, sym_t *msym) 3411.1Scgd{ 3421.208Srillig struct_or_union *str; 3431.1Scgd type_t *tp; 3441.1Scgd sym_t *sym, *csym; 3451.154Srillig bool eq; 3461.1Scgd tspec_t t; 3471.1Scgd 3481.1Scgd /* 3491.182Srillig * Remove the member if it was unknown until now, which means 3501.182Srillig * that no defined struct or union has a member with the same name. 3511.1Scgd */ 3521.1Scgd if (msym->s_scl == NOSCL) { 3531.254Srillig /* type '%s' does not have member '%s' */ 3541.300Srillig error(101, type_name(tn->tn_type), msym->s_name); 3551.1Scgd rmsym(msym); 3561.102Srillig msym->s_kind = FMEMBER; 3571.1Scgd msym->s_scl = MOS; 3581.259Srillig msym->s_styp = expr_zalloc(sizeof(*msym->s_styp)); 3591.257Srillig msym->s_styp->sou_tag = expr_zalloc( 3601.259Srillig sizeof(*msym->s_styp->sou_tag)); 3611.208Srillig msym->s_styp->sou_tag->s_name = unnamed; 3621.1Scgd msym->s_value.v_tspec = INT; 3631.95Srillig return msym; 3641.1Scgd } 3651.1Scgd 3661.1Scgd /* Set str to the tag of which msym is expected to be a member. */ 3671.1Scgd str = NULL; 3681.1Scgd t = (tp = tn->tn_type)->t_tspec; 3691.1Scgd if (op == POINT) { 3701.1Scgd if (t == STRUCT || t == UNION) 3711.1Scgd str = tp->t_str; 3721.1Scgd } else if (op == ARROW && t == PTR) { 3731.1Scgd t = (tp = tp->t_subt)->t_tspec; 3741.1Scgd if (t == STRUCT || t == UNION) 3751.1Scgd str = tp->t_str; 3761.1Scgd } 3771.1Scgd 3781.1Scgd /* 3791.182Srillig * If this struct/union has a member with the name of msym, return it. 3801.1Scgd */ 3811.1Scgd if (str != NULL) { 3821.1Scgd for (sym = msym; sym != NULL; sym = sym->s_link) { 3831.1Scgd if (sym->s_scl != MOS && sym->s_scl != MOU) 3841.1Scgd continue; 3851.1Scgd if (sym->s_styp != str) 3861.1Scgd continue; 3871.1Scgd if (strcmp(sym->s_name, msym->s_name) != 0) 3881.1Scgd continue; 3891.95Srillig return sym; 3901.1Scgd } 3911.1Scgd } 3921.1Scgd 3931.1Scgd /* 3941.185Srillig * Set eq to false if there are struct/union members with the same 3951.185Srillig * name and different types and/or offsets. 3961.1Scgd */ 3971.154Srillig eq = true; 3981.1Scgd for (csym = msym; csym != NULL; csym = csym->s_link) { 3991.1Scgd if (csym->s_scl != MOS && csym->s_scl != MOU) 4001.1Scgd continue; 4011.1Scgd if (strcmp(msym->s_name, csym->s_name) != 0) 4021.1Scgd continue; 4031.342Srillig for (sym = csym->s_link; sym != NULL; sym = sym->s_link) { 4041.154Srillig bool w; 4051.1Scgd 4061.1Scgd if (sym->s_scl != MOS && sym->s_scl != MOU) 4071.1Scgd continue; 4081.1Scgd if (strcmp(csym->s_name, sym->s_name) != 0) 4091.1Scgd continue; 4101.1Scgd if (csym->s_value.v_quad != sym->s_value.v_quad) { 4111.154Srillig eq = false; 4121.1Scgd break; 4131.1Scgd } 4141.154Srillig w = false; 4151.154Srillig eq = eqtype(csym->s_type, sym->s_type, 4161.154Srillig false, false, &w) && !w; 4171.1Scgd if (!eq) 4181.1Scgd break; 4191.105Srillig if (csym->s_bitfield != sym->s_bitfield) { 4201.154Srillig eq = false; 4211.1Scgd break; 4221.1Scgd } 4231.105Srillig if (csym->s_bitfield) { 4241.1Scgd type_t *tp1, *tp2; 4251.1Scgd 4261.1Scgd tp1 = csym->s_type; 4271.1Scgd tp2 = sym->s_type; 4281.1Scgd if (tp1->t_flen != tp2->t_flen) { 4291.154Srillig eq = false; 4301.1Scgd break; 4311.1Scgd } 4321.1Scgd if (tp1->t_foffs != tp2->t_foffs) { 4331.154Srillig eq = false; 4341.1Scgd break; 4351.1Scgd } 4361.1Scgd } 4371.1Scgd } 4381.1Scgd if (!eq) 4391.1Scgd break; 4401.1Scgd } 4411.1Scgd 4421.1Scgd /* 4431.1Scgd * Now handle the case in which the left operand refers really 4441.1Scgd * to a struct/union, but the right operand is not member of it. 4451.1Scgd */ 4461.1Scgd if (str != NULL) { 4471.1Scgd if (eq && tflag) { 4481.113Srillig /* illegal member use: %s */ 4491.1Scgd warning(102, msym->s_name); 4501.1Scgd } else { 4511.113Srillig /* illegal member use: %s */ 4521.1Scgd error(102, msym->s_name); 4531.1Scgd } 4541.95Srillig return msym; 4551.1Scgd } 4561.1Scgd 4571.1Scgd /* 4581.1Scgd * Now the left operand of ARROW does not point to a struct/union 4591.1Scgd * or the left operand of POINT is no struct/union. 4601.1Scgd */ 4611.1Scgd if (eq) { 4621.1Scgd if (op == POINT) { 4631.1Scgd if (tflag) { 4641.310Srillig /* left operand of '.' must be struct ... */ 4651.310Srillig warning(103, type_name(tn->tn_type)); 4661.1Scgd } else { 4671.310Srillig /* left operand of '.' must be struct ... */ 4681.310Srillig error(103, type_name(tn->tn_type)); 4691.1Scgd } 4701.1Scgd } else { 4711.1Scgd if (tflag && tn->tn_type->t_tspec == PTR) { 4721.113Srillig /* left operand of '->' must be pointer ... */ 4731.115Srillig warning(104, type_name(tn->tn_type)); 4741.1Scgd } else { 4751.113Srillig /* left operand of '->' must be pointer ... */ 4761.115Srillig error(104, type_name(tn->tn_type)); 4771.1Scgd } 4781.1Scgd } 4791.1Scgd } else { 4801.1Scgd if (tflag) { 4811.1Scgd /* non-unique member requires struct/union %s */ 4821.1Scgd error(105, op == POINT ? "object" : "pointer"); 4831.1Scgd } else { 4841.108Srillig /* unacceptable operand of '%s' */ 4851.260Srillig error(111, op_name(op)); 4861.1Scgd } 4871.1Scgd } 4881.1Scgd 4891.95Srillig return msym; 4901.1Scgd} 4911.1Scgd 4921.291Srilligtnode_t * 4931.291Srilligbuild_generic_selection(const tnode_t *expr, 4941.313Srillig struct generic_association *sel) 4951.291Srillig{ 4961.291Srillig tnode_t *default_result = NULL; 4971.291Srillig 4981.313Srillig for (; sel != NULL; sel = sel->ga_prev) 4991.292Srillig if (expr != NULL && 5001.313Srillig eqtype(sel->ga_arg, expr->tn_type, false, false, NULL)) 5011.313Srillig return sel->ga_result; 5021.313Srillig else if (sel->ga_arg == NULL) 5031.313Srillig default_result = sel->ga_result; 5041.291Srillig return default_result; 5051.291Srillig} 5061.291Srillig 5071.1Scgd/* 5081.395Srillig * Create a tree node for a binary operator and its two operands. Also called 5091.395Srillig * for unary operators; in that case rn is NULL. 5101.1Scgd * 5111.395Srillig * Function calls, sizeof and casts are handled elsewhere. 5121.1Scgd */ 5131.1Scgdtnode_t * 5141.395Srilligbuild_binary(tnode_t *ln, op_t op, bool sys, tnode_t *rn) 5151.1Scgd{ 5161.240Srillig const mod_t *mp; 5171.1Scgd tnode_t *ntn; 5181.219Srillig type_t *rettp; 5191.1Scgd 5201.1Scgd mp = &modtab[op]; 5211.1Scgd 5221.1Scgd /* If there was an error in one of the operands, return. */ 5231.1Scgd if (ln == NULL || (mp->m_binary && rn == NULL)) 5241.95Srillig return NULL; 5251.1Scgd 5261.1Scgd /* 5271.1Scgd * Apply class conversions to the left operand, but only if its 5281.106Srillig * value is needed or it is compared with null. 5291.1Scgd */ 5301.164Srillig if (mp->m_left_value_context || mp->m_left_test_context) 5311.1Scgd ln = cconv(ln); 5321.1Scgd /* 5331.1Scgd * The right operand is almost always in a test or value context, 5341.1Scgd * except if it is a struct or union member. 5351.1Scgd */ 5361.1Scgd if (mp->m_binary && op != ARROW && op != POINT) 5371.1Scgd rn = cconv(rn); 5381.1Scgd 5391.1Scgd /* 5401.17Smycroft * Print some warnings for comparisons of unsigned values with 5411.1Scgd * constants lower than or equal to null. This must be done 5421.1Scgd * before promote() because otherwise unsigned char and unsigned 5431.1Scgd * short would be promoted to int. Also types are tested to be 5441.1Scgd * CHAR, which would also become int. 5451.1Scgd */ 5461.164Srillig if (mp->m_comparison) 5471.100Srillig check_integer_comparison(op, ln, rn); 5481.1Scgd 5491.1Scgd /* 5501.1Scgd * Promote the left operand if it is in a test or value context 5511.1Scgd */ 5521.164Srillig if (mp->m_left_value_context || mp->m_left_test_context) 5531.172Srillig ln = promote(op, false, ln); 5541.1Scgd /* 5551.1Scgd * Promote the right operand, but only if it is no struct or 5561.1Scgd * union member, or if it is not to be assigned to the left operand 5571.1Scgd */ 5581.1Scgd if (mp->m_binary && op != ARROW && op != POINT && 5591.333Srillig op != ASSIGN && op != RETURN && op != INIT) { 5601.172Srillig rn = promote(op, false, rn); 5611.1Scgd } 5621.1Scgd 5631.1Scgd /* 5641.1Scgd * If the result of the operation is different for signed or 5651.1Scgd * unsigned operands and one of the operands is signed only in 5661.1Scgd * ANSI C, print a warning. 5671.1Scgd */ 5681.164Srillig if (mp->m_warn_if_left_unsigned_in_c90 && 5691.289Srillig ln->tn_op == CON && ln->tn_val->v_unsigned_since_c90) { 5701.1Scgd /* ANSI C treats constant as unsigned, op %s */ 5711.1Scgd warning(218, mp->m_name); 5721.289Srillig ln->tn_val->v_unsigned_since_c90 = false; 5731.1Scgd } 5741.164Srillig if (mp->m_warn_if_right_unsigned_in_c90 && 5751.289Srillig rn->tn_op == CON && rn->tn_val->v_unsigned_since_c90) { 5761.1Scgd /* ANSI C treats constant as unsigned, op %s */ 5771.1Scgd warning(218, mp->m_name); 5781.289Srillig rn->tn_val->v_unsigned_since_c90 = false; 5791.1Scgd } 5801.1Scgd 5811.1Scgd /* Make sure both operands are of the same type */ 5821.164Srillig if (mp->m_balance_operands || (tflag && (op == SHL || op == SHR))) 5831.1Scgd balance(op, &ln, &rn); 5841.1Scgd 5851.1Scgd /* 5861.1Scgd * Check types for compatibility with the operation and mutual 5871.106Srillig * compatibility. Return if there are serious problems. 5881.1Scgd */ 5891.1Scgd if (!typeok(op, 0, ln, rn)) 5901.95Srillig return NULL; 5911.1Scgd 5921.1Scgd /* And now create the node. */ 5931.1Scgd switch (op) { 5941.1Scgd case POINT: 5951.1Scgd case ARROW: 5961.395Srillig ntn = build_struct_access(op, sys, ln, rn); 5971.1Scgd break; 5981.1Scgd case INCAFT: 5991.1Scgd case DECAFT: 6001.1Scgd case INCBEF: 6011.1Scgd case DECBEF: 6021.395Srillig ntn = build_prepost_incdec(op, sys, ln); 6031.1Scgd break; 6041.169Srillig case ADDR: 6051.395Srillig ntn = build_address(sys, ln, false); 6061.1Scgd break; 6071.170Srillig case INDIR: 6081.395Srillig ntn = new_tnode(INDIR, sys, ln->tn_type->t_subt, ln, NULL); 6091.1Scgd break; 6101.1Scgd case PLUS: 6111.1Scgd case MINUS: 6121.395Srillig ntn = build_plus_minus(op, sys, ln, rn); 6131.1Scgd break; 6141.1Scgd case SHL: 6151.1Scgd case SHR: 6161.395Srillig ntn = build_bit_shift(op, sys, ln, rn); 6171.1Scgd break; 6181.1Scgd case COLON: 6191.395Srillig ntn = build_colon(sys, ln, rn); 6201.1Scgd break; 6211.1Scgd case ASSIGN: 6221.1Scgd case MULASS: 6231.1Scgd case DIVASS: 6241.1Scgd case MODASS: 6251.1Scgd case ADDASS: 6261.1Scgd case SUBASS: 6271.1Scgd case SHLASS: 6281.1Scgd case SHRASS: 6291.1Scgd case ANDASS: 6301.1Scgd case XORASS: 6311.1Scgd case ORASS: 6321.1Scgd case RETURN: 6331.333Srillig case INIT: 6341.395Srillig ntn = build_assignment(op, sys, ln, rn); 6351.1Scgd break; 6361.1Scgd case COMMA: 6371.1Scgd case QUEST: 6381.395Srillig ntn = new_tnode(op, sys, rn->tn_type, ln, rn); 6391.1Scgd break; 6401.46Schristos case REAL: 6411.46Schristos case IMAG: 6421.395Srillig ntn = build_real_imag(op, sys, ln); 6431.46Schristos break; 6441.1Scgd default: 6451.219Srillig rettp = mp->m_returns_bool 6461.151Srillig ? gettyp(Tflag ? BOOL : INT) : ln->tn_type; 6471.107Srillig lint_assert(mp->m_binary || rn == NULL); 6481.395Srillig ntn = new_tnode(op, sys, rettp, ln, rn); 6491.1Scgd break; 6501.1Scgd } 6511.1Scgd 6521.21Swiz /* Return if an error occurred. */ 6531.1Scgd if (ntn == NULL) 6541.95Srillig return NULL; 6551.1Scgd 6561.1Scgd /* Print a warning if precedence confusion is possible */ 6571.133Srillig if (mp->m_possible_precedence_confusion) 6581.100Srillig check_precedence_confusion(ntn); 6591.1Scgd 6601.1Scgd /* 6611.1Scgd * Print a warning if one of the operands is in a context where 6621.1Scgd * it is compared with null and if this operand is a constant. 6631.1Scgd */ 6641.164Srillig if (mp->m_left_test_context) { 6651.1Scgd if (ln->tn_op == CON || 6661.1Scgd ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) { 6671.227Srillig if (hflag && !constcond_flag && 6681.227Srillig !ln->tn_system_dependent) 6691.1Scgd /* constant in conditional context */ 6701.1Scgd warning(161); 6711.1Scgd } 6721.1Scgd } 6731.1Scgd 6741.1Scgd /* Fold if the operator requires it */ 6751.164Srillig if (mp->m_fold_constant_operands) { 6761.1Scgd if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { 6771.164Srillig if (mp->m_left_test_context) { 6781.100Srillig ntn = fold_test(ntn); 6791.144Srillig } else if (is_floating(ntn->tn_type->t_tspec)) { 6801.100Srillig ntn = fold_float(ntn); 6811.1Scgd } else { 6821.1Scgd ntn = fold(ntn); 6831.1Scgd } 6841.1Scgd } else if (op == QUEST && ln->tn_op == CON) { 6851.154Srillig ntn = ln->tn_val->v_quad != 0 6861.154Srillig ? rn->tn_left : rn->tn_right; 6871.1Scgd } 6881.1Scgd } 6891.1Scgd 6901.95Srillig return ntn; 6911.1Scgd} 6921.1Scgd 6931.314Srilligtnode_t * 6941.395Srilligbuild_unary(op_t op, bool sys, tnode_t *tn) 6951.317Srillig{ 6961.395Srillig return build_binary(tn, op, sys, NULL); 6971.317Srillig} 6981.317Srillig 6991.317Srilligtnode_t * 7001.395Srilligbuild_member_access(tnode_t *ln, op_t op, bool sys, sbuf_t *member) 7011.314Srillig{ 7021.314Srillig sym_t *msym; 7031.314Srillig 7041.314Srillig if (ln == NULL) 7051.314Srillig return NULL; 7061.314Srillig 7071.314Srillig if (op == ARROW) { 7081.314Srillig /* must do this before struct_or_union_member is called */ 7091.314Srillig ln = cconv(ln); 7101.314Srillig } 7111.314Srillig msym = struct_or_union_member(ln, op, getsym(member)); 7121.399Srillig return build_binary(ln, op, sys, build_name(msym, false)); 7131.314Srillig} 7141.314Srillig 7151.1Scgd/* 7161.1Scgd * Perform class conversions. 7171.1Scgd * 7181.1Scgd * Arrays of type T are converted into pointers to type T. 7191.1Scgd * Functions are converted to pointers to functions. 7201.1Scgd * Lvalues are converted to rvalues. 7211.231Srillig * 7221.231Srillig * C99 6.3 "Conversions" 7231.231Srillig * C99 6.3.2 "Other operands" 7241.231Srillig * C99 6.3.2.1 "Lvalues, arrays, and function designators" 7251.1Scgd */ 7261.1Scgdtnode_t * 7271.20Slukemcconv(tnode_t *tn) 7281.1Scgd{ 7291.1Scgd type_t *tp; 7301.1Scgd 7311.1Scgd /* 7321.1Scgd * Array-lvalue (array of type T) is converted into rvalue 7331.1Scgd * (pointer to type T) 7341.1Scgd */ 7351.1Scgd if (tn->tn_type->t_tspec == ARRAY) { 7361.1Scgd if (!tn->tn_lvalue) { 7371.118Srillig /* XXX print correct operator */ 7381.1Scgd /* %soperand of '%s' must be lvalue */ 7391.261Srillig gnuism(114, "", op_name(ADDR)); 7401.1Scgd } 7411.395Srillig tn = new_tnode(ADDR, tn->tn_sys, 7421.257Srillig expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL); 7431.1Scgd } 7441.1Scgd 7451.1Scgd /* 7461.1Scgd * Expression of type function (function with return value of type T) 7471.1Scgd * in rvalue-expression (pointer to function with return value 7481.1Scgd * of type T) 7491.1Scgd */ 7501.1Scgd if (tn->tn_type->t_tspec == FUNC) 7511.395Srillig tn = build_address(tn->tn_sys, tn, true); 7521.1Scgd 7531.1Scgd /* lvalue to rvalue */ 7541.1Scgd if (tn->tn_lvalue) { 7551.258Srillig tp = expr_dup_type(tn->tn_type); 7561.312Srillig /* C99 6.3.2.1p2 sentence 2 says to remove the qualifiers. */ 7571.154Srillig tp->t_const = tp->t_volatile = false; 7581.395Srillig tn = new_tnode(LOAD, tn->tn_sys, tp, tn, NULL); 7591.1Scgd } 7601.1Scgd 7611.95Srillig return tn; 7621.1Scgd} 7631.1Scgd 7641.266Srilligconst tnode_t * 7651.151Srilligbefore_conversion(const tnode_t *tn) 7661.151Srillig{ 7671.151Srillig while (tn->tn_op == CVT && !tn->tn_cast) 7681.151Srillig tn = tn->tn_left; 7691.151Srillig return tn; 7701.151Srillig} 7711.151Srillig 7721.190Srilligstatic bool 7731.190Srilligis_null_pointer(const tnode_t *tn) 7741.190Srillig{ 7751.190Srillig tspec_t t = tn->tn_type->t_tspec; 7761.190Srillig 7771.190Srillig return ((t == PTR && tn->tn_type->t_subt->t_tspec == VOID) || 7781.190Srillig is_integer(t)) 7791.190Srillig && (tn->tn_op == CON && tn->tn_val->v_quad == 0); 7801.190Srillig} 7811.190Srillig 7821.375Srillig/* 7831.375Srillig * Most errors required by ANSI C are reported in struct_or_union_member(). 7841.375Srillig * Here we only check for totally wrong things. 7851.375Srillig */ 7861.375Srilligstatic bool 7871.375Srilligtypeok_point(const tnode_t *ln, const type_t *ltp, tspec_t lt) 7881.375Srillig{ 7891.375Srillig if (lt == FUNC || lt == VOID || ltp->t_bitfield || 7901.375Srillig ((lt != STRUCT && lt != UNION) && !ln->tn_lvalue)) { 7911.375Srillig /* Without tflag we got already an error */ 7921.375Srillig if (tflag) 7931.375Srillig /* unacceptable operand of '%s' */ 7941.375Srillig error(111, op_name(POINT)); 7951.375Srillig return false; 7961.375Srillig } 7971.375Srillig return true; 7981.375Srillig} 7991.375Srillig 8001.375Srilligstatic bool 8011.375Srilligtypeok_arrow(tspec_t lt) 8021.375Srillig{ 8031.375Srillig if (lt == PTR || (tflag && is_integer(lt))) 8041.375Srillig return true; 8051.375Srillig 8061.375Srillig /* Without tflag we got already an error */ 8071.375Srillig if (tflag) 8081.375Srillig /* unacceptable operand of '%s' */ 8091.375Srillig error(111, op_name(ARROW)); 8101.375Srillig return false; 8111.375Srillig} 8121.375Srillig 8131.138Srilligstatic bool 8141.261Srilligtypeok_incdec(op_t op, const tnode_t *tn, const type_t *tp) 8151.138Srillig{ 8161.138Srillig /* operand has scalar type (checked in typeok) */ 8171.149Srillig if (!tn->tn_lvalue) { 8181.149Srillig if (tn->tn_op == CVT && tn->tn_cast && 8191.149Srillig tn->tn_left->tn_op == LOAD) { 8201.138Srillig /* a cast does not yield an lvalue */ 8211.138Srillig error(163); 8221.138Srillig } 8231.138Srillig /* %soperand of '%s' must be lvalue */ 8241.261Srillig error(114, "", op_name(op)); 8251.138Srillig return false; 8261.149Srillig } else if (tp->t_const) { 8271.138Srillig if (!tflag) 8281.176Srillig /* %soperand of '%s' must be modifiable lvalue */ 8291.261Srillig warning(115, "", op_name(op)); 8301.138Srillig } 8311.138Srillig return true; 8321.138Srillig} 8331.138Srillig 8341.139Srilligstatic bool 8351.180Srilligtypeok_address(const mod_t *mp, 8361.342Srillig const tnode_t *tn, const type_t *tp, tspec_t t) 8371.139Srillig{ 8381.149Srillig if (t == ARRAY || t == FUNC) { 8391.168Srillig /* ok, a warning comes later (in build_address()) */ 8401.149Srillig } else if (!tn->tn_lvalue) { 8411.149Srillig if (tn->tn_op == CVT && tn->tn_cast && 8421.149Srillig tn->tn_left->tn_op == LOAD) { 8431.139Srillig /* a cast does not yield an lvalue */ 8441.139Srillig error(163); 8451.139Srillig } 8461.139Srillig /* %soperand of '%s' must be lvalue */ 8471.139Srillig error(114, "", mp->m_name); 8481.139Srillig return false; 8491.149Srillig } else if (is_scalar(t)) { 8501.149Srillig if (tp->t_bitfield) { 8511.139Srillig /* cannot take address of bit-field */ 8521.139Srillig error(112); 8531.139Srillig return false; 8541.139Srillig } 8551.149Srillig } else if (t != STRUCT && t != UNION) { 8561.139Srillig /* unacceptable operand of '%s' */ 8571.139Srillig error(111, mp->m_name); 8581.139Srillig return false; 8591.139Srillig } 8601.149Srillig if (tn->tn_op == NAME && tn->tn_sym->s_reg) { 8611.139Srillig /* cannot take address of register %s */ 8621.149Srillig error(113, tn->tn_sym->s_name); 8631.139Srillig return false; 8641.139Srillig } 8651.139Srillig return true; 8661.139Srillig} 8671.139Srillig 8681.140Srilligstatic bool 8691.375Srilligtypeok_indir(tspec_t t) 8701.140Srillig{ 8711.140Srillig /* until now there were no type checks for this operator */ 8721.149Srillig if (t != PTR) { 8731.140Srillig /* cannot dereference non-pointer type */ 8741.140Srillig error(96); 8751.140Srillig return false; 8761.140Srillig } 8771.140Srillig return true; 8781.140Srillig} 8791.140Srillig 8801.140Srilligstatic bool 8811.246Srilligtypeok_plus(op_t op, 8821.246Srillig const type_t *ltp, tspec_t lt, 8831.246Srillig const type_t *rtp, tspec_t rt) 8841.140Srillig{ 8851.140Srillig /* operands have scalar types (checked above) */ 8861.144Srillig if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) { 8871.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 8881.140Srillig return false; 8891.140Srillig } 8901.140Srillig return true; 8911.140Srillig} 8921.140Srillig 8931.140Srilligstatic bool 8941.149Srilligtypeok_minus(op_t op, 8951.149Srillig const type_t *ltp, tspec_t lt, 8961.149Srillig const type_t *rtp, tspec_t rt) 8971.140Srillig{ 8981.140Srillig /* operands have scalar types (checked above) */ 8991.144Srillig if (lt == PTR && (!is_integer(rt) && rt != PTR)) { 9001.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 9011.140Srillig return false; 9021.140Srillig } else if (rt == PTR && lt != PTR) { 9031.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 9041.140Srillig return false; 9051.140Srillig } 9061.140Srillig if (lt == PTR && rt == PTR) { 9071.172Srillig if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { 9081.140Srillig /* illegal pointer subtraction */ 9091.140Srillig error(116); 9101.140Srillig } 9111.140Srillig } 9121.140Srillig return true; 9131.140Srillig} 9141.140Srillig 9151.140Srilligstatic void 9161.149Srilligtypeok_shr(const mod_t *mp, 9171.149Srillig const tnode_t *ln, tspec_t lt, 9181.149Srillig const tnode_t *rn, tspec_t rt) 9191.140Srillig{ 9201.143Srillig tspec_t olt, ort; 9211.143Srillig 9221.151Srillig olt = before_conversion(ln)->tn_type->t_tspec; 9231.151Srillig ort = before_conversion(rn)->tn_type->t_tspec; 9241.143Srillig 9251.140Srillig /* operands have integer types (checked above) */ 9261.335Srillig if (pflag && !is_uinteger(olt)) { 9271.140Srillig /* 9281.140Srillig * The left operand is signed. This means that 9291.140Srillig * the operation is (possibly) nonportable. 9301.140Srillig */ 9311.140Srillig if (ln->tn_op != CON) { 9321.200Srillig /* bitwise '%s' on signed value possibly nonportable */ 9331.200Srillig warning(117, mp->m_name); 9341.140Srillig } else if (ln->tn_val->v_quad < 0) { 9351.200Srillig /* bitwise '%s' on signed value nonportable */ 9361.200Srillig warning(120, mp->m_name); 9371.140Srillig } 9381.144Srillig } else if (!tflag && !sflag && !is_uinteger(olt) && is_uinteger(ort)) { 9391.140Srillig /* 9401.140Srillig * The left operand would become unsigned in 9411.140Srillig * traditional C. 9421.140Srillig */ 9431.271Srillig if (hflag && !Sflag && 9441.140Srillig (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { 9451.177Srillig /* semantics of '%s' change in ANSI C; use ... */ 9461.140Srillig warning(118, mp->m_name); 9471.140Srillig } 9481.144Srillig } else if (!tflag && !sflag && !is_uinteger(olt) && !is_uinteger(ort) && 9491.228Srillig portable_size_in_bits(lt) < portable_size_in_bits(rt)) { 9501.140Srillig /* 9511.140Srillig * In traditional C the left operand would be extended, 9521.140Srillig * possibly with 1, and then shifted. 9531.140Srillig */ 9541.271Srillig if (hflag && !Sflag && 9551.140Srillig (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { 9561.140Srillig /* semantics of '%s' change in ANSI C; use ... */ 9571.140Srillig warning(118, mp->m_name); 9581.140Srillig } 9591.140Srillig } 9601.140Srillig} 9611.140Srillig 9621.140Srilligstatic void 9631.182Srilligtypeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt) 9641.182Srillig{ 9651.140Srillig /* 9661.182Srillig * C90 does not perform balancing for shift operations, 9671.140Srillig * but traditional C does. If the width of the right operand 9681.182Srillig * is greater than the width of the left operand, then in 9691.140Srillig * traditional C the left operand would be extended to the 9701.140Srillig * width of the right operand. For SHL this may result in 9711.140Srillig * different results. 9721.140Srillig */ 9731.228Srillig if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { 9741.140Srillig /* 9751.140Srillig * XXX If both operands are constant, make sure 9761.140Srillig * that there is really a difference between 9771.140Srillig * ANSI C and traditional C. 9781.140Srillig */ 9791.271Srillig if (hflag && !Sflag) 9801.140Srillig /* semantics of '%s' change in ANSI C; use ... */ 9811.140Srillig warning(118, mp->m_name); 9821.140Srillig } 9831.140Srillig} 9841.140Srillig 9851.140Srilligstatic void 9861.149Srilligtypeok_shift(tspec_t lt, const tnode_t *rn, tspec_t rt) 9871.140Srillig{ 9881.270Srillig if (rn->tn_op != CON) 9891.270Srillig return; 9901.270Srillig 9911.270Srillig if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) { 9921.270Srillig /* negative shift */ 9931.270Srillig warning(121); 9941.270Srillig } else if ((uint64_t)rn->tn_val->v_quad == 9951.270Srillig (uint64_t)size_in_bits(lt)) { 9961.270Srillig /* shift equal to size of object */ 9971.270Srillig warning(267); 9981.270Srillig } else if ((uint64_t)rn->tn_val->v_quad > (uint64_t)size_in_bits(lt)) { 9991.270Srillig /* shift amount %llu is greater than bit-size %llu of '%s' */ 10001.270Srillig warning(122, (unsigned long long)rn->tn_val->v_quad, 10011.270Srillig (unsigned long long)size_in_bits(lt), 10021.270Srillig tspec_name(lt)); 10031.140Srillig } 10041.140Srillig} 10051.140Srillig 10061.140Srilligstatic bool 10071.187Srilligis_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt) 10081.140Srillig{ 10091.190Srillig if (lt == PTR && is_null_pointer(rn)) 10101.190Srillig return true; 10111.190Srillig if (rt == PTR && is_null_pointer(ln)) 10121.190Srillig return true; 10131.140Srillig return false; 10141.140Srillig} 10151.140Srillig 10161.140Srilligstatic bool 10171.375Srilligtypeok_compare(op_t op, 10181.375Srillig const tnode_t *ln, const type_t *ltp, tspec_t lt, 10191.375Srillig const tnode_t *rn, const type_t *rtp, tspec_t rt) 10201.140Srillig{ 10211.392Srillig const char *lx, *rx; 10221.392Srillig 10231.178Srillig if (lt == PTR && rt == PTR) { 10241.140Srillig check_pointer_comparison(op, ln, rn); 10251.178Srillig return true; 10261.140Srillig } 10271.178Srillig 10281.178Srillig if (lt != PTR && rt != PTR) 10291.178Srillig return true; 10301.178Srillig 10311.178Srillig if (!is_integer(lt) && !is_integer(rt)) { 10321.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 10331.178Srillig return false; 10341.178Srillig } 10351.178Srillig 10361.392Srillig lx = lt == PTR ? "pointer" : "integer"; 10371.392Srillig rx = rt == PTR ? "pointer" : "integer"; 10381.396Srillig /* illegal combination of %s '%s' and %s '%s', op '%s' */ 10391.260Srillig warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op)); 10401.140Srillig return true; 10411.140Srillig} 10421.140Srillig 10431.140Srilligstatic bool 10441.373Srilligtypeok_quest(tspec_t lt, const tnode_t *rn) 10451.140Srillig{ 10461.144Srillig if (!is_scalar(lt)) { 10471.140Srillig /* first operand must have scalar type, op ? : */ 10481.140Srillig error(170); 10491.140Srillig return false; 10501.140Srillig } 10511.373Srillig lint_assert(before_conversion(rn)->tn_op == COLON); 10521.140Srillig return true; 10531.140Srillig} 10541.140Srillig 10551.206Srilligstatic void 10561.212Srilligtypeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp) 10571.206Srillig{ 10581.206Srillig type_t *lstp = ltp->t_subt; 10591.206Srillig type_t *rstp = rtp->t_subt; 10601.206Srillig tspec_t lst = lstp->t_tspec; 10611.206Srillig tspec_t rst = rstp->t_tspec; 10621.206Srillig 10631.206Srillig if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) { 10641.206Srillig /* (void *)0 handled above */ 10651.206Srillig if (sflag) 10661.377Srillig /* ANSI C forbids conversion of %s to %s, op %s */ 10671.206Srillig warning(305, "function pointer", "'void *'", 10681.206Srillig mp->m_name); 10691.206Srillig return; 10701.206Srillig } 10711.206Srillig 10721.206Srillig if (eqptrtype(lstp, rstp, true)) 10731.206Srillig return; 10741.206Srillig if (!eqtype(lstp, rstp, true, false, NULL)) 10751.206Srillig warn_incompatible_pointers(mp, ltp, rtp); 10761.206Srillig} 10771.206Srillig 10781.140Srilligstatic bool 10791.149Srilligtypeok_colon(const mod_t *mp, 10801.149Srillig const tnode_t *ln, const type_t *ltp, tspec_t lt, 10811.149Srillig const tnode_t *rn, const type_t *rtp, tspec_t rt) 10821.140Srillig{ 10831.142Srillig 10841.144Srillig if (is_arithmetic(lt) && is_arithmetic(rt)) 10851.140Srillig return true; 10861.165Srillig if (lt == BOOL && rt == BOOL) 10871.165Srillig return true; 10881.140Srillig 10891.140Srillig if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) 10901.140Srillig return true; 10911.140Srillig if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) 10921.140Srillig return true; 10931.140Srillig 10941.190Srillig if (lt == PTR && is_null_pointer(rn)) 10951.190Srillig return true; 10961.190Srillig if (rt == PTR && is_null_pointer(ln)) 10971.190Srillig return true; 10981.140Srillig 10991.144Srillig if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { 11001.342Srillig const char *lx = lt == PTR ? "pointer" : "integer"; 11011.342Srillig const char *rx = rt == PTR ? "pointer" : "integer"; 11021.396Srillig /* illegal combination of %s '%s' and %s '%s', op '%s' */ 11031.140Srillig warning(123, lx, type_name(ltp), 11041.140Srillig rx, type_name(rtp), mp->m_name); 11051.140Srillig return true; 11061.140Srillig } 11071.140Srillig 11081.140Srillig if (lt == VOID || rt == VOID) { 11091.140Srillig if (lt != VOID || rt != VOID) 11101.179Srillig /* incompatible types '%s' and '%s' in conditional */ 11111.179Srillig warning(126, type_name(ltp), type_name(rtp)); 11121.140Srillig return true; 11131.140Srillig } 11141.140Srillig 11151.206Srillig if (lt == PTR && rt == PTR) { 11161.212Srillig typeok_colon_pointer(mp, ltp, rtp); 11171.140Srillig return true; 11181.140Srillig } 11191.140Srillig 11201.179Srillig /* incompatible types '%s' and '%s' in conditional */ 11211.179Srillig error(126, type_name(ltp), type_name(rtp)); 11221.140Srillig return false; 11231.140Srillig} 11241.140Srillig 11251.140Srilligstatic bool 11261.332Srilligtypeok_assign(op_t op, const tnode_t *ln, const type_t *ltp, tspec_t lt) 11271.140Srillig{ 11281.332Srillig if (op == RETURN || op == INIT || op == FARG) 11291.332Srillig return true; 11301.332Srillig 11311.140Srillig if (!ln->tn_lvalue) { 11321.140Srillig if (ln->tn_op == CVT && ln->tn_cast && 11331.140Srillig ln->tn_left->tn_op == LOAD) { 11341.140Srillig /* a cast does not yield an lvalue */ 11351.140Srillig error(163); 11361.140Srillig } 11371.140Srillig /* %soperand of '%s' must be lvalue */ 11381.332Srillig error(114, "left ", op_name(op)); 11391.140Srillig return false; 11401.140Srillig } else if (ltp->t_const || ((lt == STRUCT || lt == UNION) && 11411.140Srillig has_constant_member(ltp))) { 11421.140Srillig if (!tflag) 11431.140Srillig /* %soperand of '%s' must be modifiable lvalue */ 11441.332Srillig warning(115, "left ", op_name(op)); 11451.140Srillig } 11461.140Srillig return true; 11471.140Srillig} 11481.140Srillig 11491.150Srillig/* Check the types using the information from modtab[]. */ 11501.150Srilligstatic bool 11511.246Srilligtypeok_scalar(op_t op, const mod_t *mp, 11521.246Srillig const type_t *ltp, tspec_t lt, 11531.246Srillig const type_t *rtp, tspec_t rt) 11541.1Scgd{ 11551.165Srillig if (mp->m_takes_bool && lt == BOOL && rt == BOOL) 11561.165Srillig return true; 11571.93Srillig if (mp->m_requires_integer) { 11581.144Srillig if (!is_integer(lt) || (mp->m_binary && !is_integer(rt))) { 11591.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 11601.141Srillig return false; 11611.1Scgd } 11621.93Srillig } else if (mp->m_requires_integer_or_complex) { 11631.144Srillig if ((!is_integer(lt) && !is_complex(lt)) || 11641.144Srillig (mp->m_binary && (!is_integer(rt) && !is_complex(rt)))) { 11651.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 11661.141Srillig return false; 11671.46Schristos } 11681.93Srillig } else if (mp->m_requires_scalar) { 11691.144Srillig if (!is_scalar(lt) || (mp->m_binary && !is_scalar(rt))) { 11701.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 11711.141Srillig return false; 11721.1Scgd } 11731.93Srillig } else if (mp->m_requires_arith) { 11741.144Srillig if (!is_arithmetic(lt) || 11751.144Srillig (mp->m_binary && !is_arithmetic(rt))) { 11761.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 11771.141Srillig return false; 11781.1Scgd } 11791.1Scgd } 11801.150Srillig return true; 11811.150Srillig} 11821.1Scgd 11831.375Srillig/* 11841.375Srillig * Check the types for specific operators and type combinations. 11851.375Srillig * 11861.375Srillig * At this point, the operands already conform to the type requirements of 11871.375Srillig * the operator, such as being integer, floating or scalar. 11881.375Srillig */ 11891.150Srilligstatic bool 11901.150Srilligtypeok_op(op_t op, const mod_t *mp, int arg, 11911.150Srillig const tnode_t *ln, const type_t *ltp, tspec_t lt, 11921.150Srillig const tnode_t *rn, const type_t *rtp, tspec_t rt) 11931.150Srillig{ 11941.1Scgd switch (op) { 11951.376Srillig case ARROW: 11961.376Srillig return typeok_arrow(lt); 11971.1Scgd case POINT: 11981.375Srillig return typeok_point(ln, ltp, lt); 11991.376Srillig case INCBEF: 12001.376Srillig case DECBEF: 12011.1Scgd case INCAFT: 12021.1Scgd case DECAFT: 12031.374Srillig return typeok_incdec(op, ln, ltp); 12041.376Srillig case INDIR: 12051.376Srillig return typeok_indir(lt); 12061.169Srillig case ADDR: 12071.374Srillig return typeok_address(mp, ln, ltp, lt); 12081.1Scgd case PLUS: 12091.374Srillig return typeok_plus(op, ltp, lt, rtp, rt); 12101.1Scgd case MINUS: 12111.374Srillig return typeok_minus(op, ltp, lt, rtp, rt); 12121.376Srillig case SHL: 12131.376Srillig typeok_shl(mp, lt, rt); 12141.376Srillig goto shift; 12151.1Scgd case SHR: 12161.143Srillig typeok_shr(mp, ln, lt, rn, rt); 12171.1Scgd shift: 12181.140Srillig typeok_shift(lt, rn, rt); 12191.1Scgd break; 12201.376Srillig case LT: 12211.376Srillig case LE: 12221.376Srillig case GT: 12231.376Srillig case GE: 12241.376Srillig compare: 12251.376Srillig return typeok_compare(op, ln, ltp, lt, rn, rtp, rt); 12261.1Scgd case EQ: 12271.1Scgd case NE: 12281.187Srillig if (is_typeok_eq(ln, lt, rn, rt)) 12291.140Srillig break; 12301.376Srillig goto compare; 12311.1Scgd case QUEST: 12321.374Srillig return typeok_quest(lt, rn); 12331.1Scgd case COLON: 12341.374Srillig return typeok_colon(mp, ln, ltp, lt, rn, rtp, rt); 12351.1Scgd case ASSIGN: 12361.1Scgd case INIT: 12371.1Scgd case FARG: 12381.1Scgd case RETURN: 12391.100Srillig if (!check_assign_types_compatible(op, arg, ln, rn)) 12401.141Srillig return false; 12411.1Scgd goto assign; 12421.1Scgd case MULASS: 12431.1Scgd case DIVASS: 12441.1Scgd case MODASS: 12451.1Scgd goto assign; 12461.1Scgd case ADDASS: 12471.1Scgd case SUBASS: 12481.144Srillig if ((lt == PTR && !is_integer(rt)) || rt == PTR) { 12491.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 12501.141Srillig return false; 12511.1Scgd } 12521.1Scgd goto assign; 12531.1Scgd case SHLASS: 12541.1Scgd goto assign; 12551.1Scgd case SHRASS: 12561.144Srillig if (pflag && !is_uinteger(lt) && !(tflag && is_uinteger(rt))) { 12571.200Srillig /* bitwise '%s' on signed value possibly nonportable */ 12581.200Srillig warning(117, mp->m_name); 12591.1Scgd } 12601.1Scgd goto assign; 12611.1Scgd case ANDASS: 12621.1Scgd case XORASS: 12631.1Scgd case ORASS: 12641.1Scgd assign: 12651.374Srillig return typeok_assign(op, ln, ltp, lt); 12661.1Scgd case COMMA: 12671.164Srillig if (!modtab[ln->tn_op].m_has_side_effect) 12681.100Srillig check_null_effect(ln); 12691.1Scgd break; 12701.375Srillig default: 12711.14Schristos break; 12721.1Scgd } 12731.150Srillig return true; 12741.150Srillig} 12751.1Scgd 12761.150Srilligstatic void 12771.150Srilligtypeok_enum(op_t op, const mod_t *mp, int arg, 12781.150Srillig const tnode_t *ln, const type_t *ltp, 12791.150Srillig const tnode_t *rn, const type_t *rtp) 12801.150Srillig{ 12811.93Srillig if (mp->m_bad_on_enum && 12821.209Srillig (ltp->t_is_enum || (mp->m_binary && rtp->t_is_enum))) { 12831.100Srillig check_bad_enum_operation(op, ln, rn); 12841.93Srillig } else if (mp->m_valid_on_enum && 12851.209Srillig (ltp->t_is_enum && rtp != NULL && rtp->t_is_enum)) { 12861.100Srillig check_enum_type_mismatch(op, arg, ln, rn); 12871.93Srillig } else if (mp->m_valid_on_enum && 12881.209Srillig (ltp->t_is_enum || (rtp != NULL && rtp->t_is_enum))) { 12891.100Srillig check_enum_int_mismatch(op, arg, ln, rn); 12901.1Scgd } 12911.150Srillig} 12921.150Srillig 12931.150Srillig/* Perform most type checks. Return whether the types are ok. */ 12941.150Srilligbool 12951.150Srilligtypeok(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) 12961.150Srillig{ 12971.240Srillig const mod_t *mp; 12981.150Srillig tspec_t lt, rt; 12991.150Srillig type_t *ltp, *rtp; 13001.150Srillig 13011.150Srillig mp = &modtab[op]; 13021.150Srillig 13031.150Srillig lint_assert((ltp = ln->tn_type) != NULL); 13041.150Srillig lt = ltp->t_tspec; 13051.150Srillig 13061.150Srillig if (mp->m_binary) { 13071.150Srillig lint_assert((rtp = rn->tn_type) != NULL); 13081.150Srillig rt = rtp->t_tspec; 13091.150Srillig } else { 13101.150Srillig rtp = NULL; 13111.150Srillig rt = NOTSPEC; 13121.150Srillig } 13131.150Srillig 13141.151Srillig if (Tflag && !typeok_scalar_strict_bool(op, mp, arg, ln, rn)) 13151.151Srillig return false; 13161.246Srillig if (!typeok_scalar(op, mp, ltp, lt, rtp, rt)) 13171.150Srillig return false; 13181.150Srillig 13191.150Srillig if (!typeok_op(op, mp, arg, ln, ltp, lt, rn, rtp, rt)) 13201.150Srillig return false; 13211.1Scgd 13221.150Srillig typeok_enum(op, mp, arg, ln, ltp, rn, rtp); 13231.141Srillig return true; 13241.1Scgd} 13251.1Scgd 13261.1Scgdstatic void 13271.149Srilligcheck_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn) 13281.1Scgd{ 13291.1Scgd type_t *ltp, *rtp; 13301.187Srillig tspec_t lst, rst; 13311.188Srillig const char *lsts, *rsts; 13321.1Scgd 13331.187Srillig lst = (ltp = ln->tn_type)->t_subt->t_tspec; 13341.187Srillig rst = (rtp = rn->tn_type)->t_subt->t_tspec; 13351.1Scgd 13361.187Srillig if (lst == VOID || rst == VOID) { 13371.187Srillig if (sflag && (lst == FUNC || rst == FUNC)) { 13381.1Scgd /* (void *)0 already handled in typeok() */ 13391.188Srillig *(lst == FUNC ? &lsts : &rsts) = "function pointer"; 13401.188Srillig *(lst == VOID ? &lsts : &rsts) = "'void *'"; 13411.17Smycroft /* ANSI C forbids comparison of %s with %s */ 13421.188Srillig warning(274, lsts, rsts); 13431.1Scgd } 13441.1Scgd return; 13451.1Scgd } 13461.1Scgd 13471.172Srillig if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { 13481.98Srillig warn_incompatible_pointers(&modtab[op], ltp, rtp); 13491.1Scgd return; 13501.1Scgd } 13511.1Scgd 13521.187Srillig if (lst == FUNC && rst == FUNC) { 13531.1Scgd if (sflag && op != EQ && op != NE) 13541.108Srillig /* ANSI C forbids ordered comparisons of ... */ 13551.1Scgd warning(125); 13561.1Scgd } 13571.1Scgd} 13581.1Scgd 13591.331Srilligstatic bool 13601.336Srilligis_direct_function_call(const tnode_t *tn, const char **out_name) 13611.331Srillig{ 13621.336Srillig 13631.336Srillig if (!(tn->tn_op == CALL && 13641.336Srillig tn->tn_left->tn_op == ADDR && 13651.336Srillig tn->tn_left->tn_left->tn_op == NAME)) 13661.336Srillig return false; 13671.336Srillig 13681.336Srillig *out_name = tn->tn_left->tn_left->tn_sym->s_name; 13691.336Srillig return true; 13701.336Srillig} 13711.336Srillig 13721.336Srilligstatic bool 13731.336Srilligis_unconst_function(const char *name) 13741.336Srillig{ 13751.336Srillig 13761.336Srillig return strcmp(name, "memchr") == 0 || 13771.336Srillig strcmp(name, "strchr") == 0 || 13781.336Srillig strcmp(name, "strpbrk") == 0 || 13791.336Srillig strcmp(name, "strrchr") == 0 || 13801.336Srillig strcmp(name, "strstr") == 0; 13811.331Srillig} 13821.331Srillig 13831.331Srilligstatic bool 13841.331Srilligis_const_char_pointer(const tnode_t *tn) 13851.331Srillig{ 13861.331Srillig const type_t *tp; 13871.331Srillig 13881.331Srillig /* 13891.331Srillig * For traditional reasons, C99 6.4.5p5 defines that string literals 13901.331Srillig * have type 'char[]'. They are often implicitly converted to 13911.331Srillig * 'char *', for example when they are passed as function arguments. 13921.331Srillig * 13931.331Srillig * C99 6.4.5p6 further defines that modifying a string that is 13941.331Srillig * constructed from a string literal invokes undefined behavior. 13951.331Srillig * 13961.331Srillig * Out of these reasons, string literals are treated as 'effectively 13971.331Srillig * const' here. 13981.331Srillig */ 13991.331Srillig if (tn->tn_op == CVT && 14001.331Srillig tn->tn_left->tn_op == ADDR && 14011.331Srillig tn->tn_left->tn_left->tn_op == STRING) 14021.331Srillig return true; 14031.331Srillig 14041.331Srillig tp = before_conversion(tn)->tn_type; 14051.331Srillig return tp->t_tspec == PTR && 14061.331Srillig tp->t_subt->t_tspec == CHAR && 14071.331Srillig tp->t_subt->t_const; 14081.331Srillig} 14091.331Srillig 14101.331Srilligstatic bool 14111.384Srilligis_const_pointer(const tnode_t *tn) 14121.384Srillig{ 14131.384Srillig const type_t *tp; 14141.384Srillig 14151.384Srillig tp = before_conversion(tn)->tn_type; 14161.384Srillig return tp->t_tspec == PTR && tp->t_subt->t_const; 14171.384Srillig} 14181.384Srillig 14191.384Srilligstatic bool 14201.384Srilligis_first_arg_const_char_pointer(const tnode_t *tn) 14211.331Srillig{ 14221.336Srillig const tnode_t *an; 14231.336Srillig 14241.336Srillig an = tn->tn_right; 14251.336Srillig if (an == NULL) 14261.336Srillig return false; 14271.336Srillig 14281.336Srillig while (an->tn_right != NULL) 14291.336Srillig an = an->tn_right; 14301.336Srillig return is_const_char_pointer(an->tn_left); 14311.331Srillig} 14321.331Srillig 14331.384Srilligstatic bool 14341.384Srilligis_second_arg_const_pointer(const tnode_t *tn) 14351.384Srillig{ 14361.384Srillig const tnode_t *an; 14371.384Srillig 14381.384Srillig an = tn->tn_right; 14391.384Srillig if (an == NULL || an->tn_right == NULL) 14401.384Srillig return false; 14411.384Srillig 14421.384Srillig while (an->tn_right->tn_right != NULL) 14431.384Srillig an = an->tn_right; 14441.384Srillig return is_const_pointer(an->tn_left); 14451.384Srillig} 14461.384Srillig 14471.331Srilligstatic void 14481.378Srilligcheck_unconst_function(const type_t *lstp, const tnode_t *rn) 14491.331Srillig{ 14501.336Srillig const char *function_name; 14511.336Srillig 14521.331Srillig if (lstp->t_tspec == CHAR && !lstp->t_const && 14531.336Srillig is_direct_function_call(rn, &function_name) && 14541.336Srillig is_unconst_function(function_name) && 14551.384Srillig is_first_arg_const_char_pointer(rn)) { 14561.384Srillig /* call to '%s' effectively discards 'const' from argument */ 14571.384Srillig warning(346, function_name); 14581.384Srillig } 14591.384Srillig 14601.384Srillig if (!lstp->t_const && 14611.384Srillig is_direct_function_call(rn, &function_name) && 14621.384Srillig strcmp(function_name, "bsearch") == 0 && 14631.384Srillig is_second_arg_const_pointer(rn)) { 14641.331Srillig /* call to '%s' effectively discards 'const' from argument */ 14651.336Srillig warning(346, function_name); 14661.331Srillig } 14671.331Srillig} 14681.331Srillig 14691.369Srilligstatic void 14701.369Srilligcheck_assign_void_pointer(op_t op, int arg, 14711.369Srillig tspec_t lt, tspec_t lst, 14721.369Srillig tspec_t rt, tspec_t rst) 14731.1Scgd{ 14741.369Srillig const char *lts, *rts; 14751.1Scgd 14761.369Srillig if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID))) 14771.369Srillig return; 14781.369Srillig /* two pointers, at least one pointer to void */ 14791.1Scgd 14801.369Srillig if (!(sflag && (lst == FUNC || rst == FUNC))) 14811.369Srillig return; 14821.369Srillig /* comb. of ptr to func and ptr to void */ 14831.148Srillig 14841.369Srillig *(lst == FUNC ? <s : &rts) = "function pointer"; 14851.369Srillig *(lst == VOID ? <s : &rts) = "'void *'"; 14861.1Scgd 14871.369Srillig switch (op) { 14881.369Srillig case INIT: 14891.369Srillig case RETURN: 14901.369Srillig /* ANSI C forbids conversion of %s to %s */ 14911.369Srillig warning(303, rts, lts); 14921.369Srillig break; 14931.369Srillig case FARG: 14941.377Srillig /* ANSI C forbids conversion of %s to %s, arg #%d */ 14951.369Srillig warning(304, rts, lts, arg); 14961.369Srillig break; 14971.369Srillig default: 14981.377Srillig /* ANSI C forbids conversion of %s to %s, op %s */ 14991.369Srillig warning(305, rts, lts, op_name(op)); 15001.369Srillig break; 15011.1Scgd } 15021.369Srillig} 15031.1Scgd 15041.369Srilligstatic bool 15051.369Srilligcheck_assign_void_pointer_compat(op_t op, int arg, 15061.369Srillig const type_t *const ltp, tspec_t const lt, 15071.369Srillig const type_t *const lstp, tspec_t const lst, 15081.369Srillig const tnode_t *const rn, 15091.369Srillig const type_t *const rtp, tspec_t const rt, 15101.369Srillig const type_t *const rstp, tspec_t const rst) 15111.369Srillig{ 15121.369Srillig if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID || 15131.369Srillig eqtype(lstp, rstp, true, false, NULL)))) 15141.369Srillig return false; 15151.82Schristos 15161.369Srillig /* compatible pointer types (qualifiers ignored) */ 15171.369Srillig if (!tflag && 15181.369Srillig ((!lstp->t_const && rstp->t_const) || 15191.369Srillig (!lstp->t_volatile && rstp->t_volatile))) { 15201.369Srillig /* left side has not all qualifiers of right */ 15211.1Scgd switch (op) { 15221.1Scgd case INIT: 15231.1Scgd case RETURN: 15241.369Srillig /* incompatible pointer types (%s != %s) */ 15251.369Srillig warning(182, type_name(lstp), type_name(rstp)); 15261.1Scgd break; 15271.1Scgd case FARG: 15281.369Srillig /* converting '%s' to incompatible '%s' ... */ 15291.369Srillig warning(153, 15301.369Srillig type_name(rtp), type_name(ltp), arg); 15311.1Scgd break; 15321.1Scgd default: 15331.369Srillig /* operands have incompatible pointer type... */ 15341.369Srillig warning(128, op_name(op), 15351.369Srillig type_name(lstp), type_name(rstp)); 15361.1Scgd break; 15371.1Scgd } 15381.1Scgd } 15391.1Scgd 15401.369Srillig if (!tflag) 15411.378Srillig check_unconst_function(lstp, rn); 15421.369Srillig 15431.369Srillig return true; 15441.369Srillig} 15451.369Srillig 15461.369Srilligstatic bool 15471.369Srilligcheck_assign_pointer_integer(op_t op, int arg, 15481.369Srillig const type_t *const ltp, tspec_t const lt, 15491.369Srillig const type_t *const rtp, tspec_t const rt) 15501.369Srillig{ 15511.392Srillig const char *lx, *rx; 15521.392Srillig 15531.369Srillig if (!((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR))) 15541.369Srillig return false; 15551.369Srillig 15561.392Srillig lx = lt == PTR ? "pointer" : "integer"; 15571.392Srillig rx = rt == PTR ? "pointer" : "integer"; 15581.369Srillig 15591.369Srillig switch (op) { 15601.369Srillig case INIT: 15611.369Srillig case RETURN: 15621.369Srillig /* illegal combination of %s (%s) and %s (%s) */ 15631.369Srillig warning(183, lx, type_name(ltp), rx, type_name(rtp)); 15641.369Srillig break; 15651.369Srillig case FARG: 15661.377Srillig /* illegal combination of %s (%s) and %s (%s), arg #%d */ 15671.369Srillig warning(154, 15681.369Srillig lx, type_name(ltp), rx, type_name(rtp), arg); 15691.369Srillig break; 15701.369Srillig default: 15711.396Srillig /* illegal combination of %s '%s' and %s '%s', op '%s' */ 15721.369Srillig warning(123, 15731.369Srillig lx, type_name(ltp), rx, type_name(rtp), op_name(op)); 15741.369Srillig break; 15751.369Srillig } 15761.369Srillig return true; 15771.369Srillig} 15781.369Srillig 15791.369Srilligstatic bool 15801.369Srilligcheck_assign_pointer(op_t op, int arg, 15811.369Srillig const type_t *ltp, tspec_t lt, 15821.369Srillig const type_t *rtp, tspec_t rt) 15831.369Srillig{ 15841.369Srillig if (!(lt == PTR && rt == PTR)) 15851.369Srillig return false; 15861.369Srillig 15871.369Srillig switch (op) { 15881.369Srillig case RETURN: 15891.369Srillig warn_incompatible_pointers(NULL, ltp, rtp); 15901.369Srillig break; 15911.369Srillig case FARG: 15921.369Srillig /* converting '%s' to incompatible '%s' for ... */ 15931.369Srillig warning(153, type_name(rtp), type_name(ltp), arg); 15941.369Srillig break; 15951.369Srillig default: 15961.369Srillig warn_incompatible_pointers(&modtab[op], ltp, rtp); 15971.369Srillig break; 15981.1Scgd } 15991.369Srillig return true; 16001.369Srillig} 16011.1Scgd 16021.369Srilligstatic void 16031.369Srilligwarn_assign(op_t op, int arg, 16041.369Srillig const type_t *ltp, tspec_t lt, 16051.369Srillig const type_t *rtp, tspec_t rt) 16061.369Srillig{ 16071.1Scgd switch (op) { 16081.1Scgd case INIT: 16091.234Srillig /* cannot initialize '%s' from '%s' */ 16101.115Srillig error(185, type_name(ltp), type_name(rtp)); 16111.1Scgd break; 16121.1Scgd case RETURN: 16131.108Srillig /* return value type mismatch (%s) and (%s) */ 16141.115Srillig error(211, type_name(ltp), type_name(rtp)); 16151.1Scgd break; 16161.1Scgd case FARG: 16171.293Srillig /* passing '%s' to incompatible '%s', arg #%d */ 16181.293Srillig warning(155, type_name(rtp), type_name(ltp), arg); 16191.1Scgd break; 16201.1Scgd default: 16211.246Srillig warn_incompatible_types(op, ltp, lt, rtp, rt); 16221.1Scgd break; 16231.1Scgd } 16241.369Srillig} 16251.369Srillig 16261.369Srillig/* 16271.369Srillig * Checks type compatibility for ASSIGN, INIT, FARG and RETURN 16281.369Srillig * and prints warnings/errors if necessary. 16291.369Srillig * Returns whether the types are (almost) compatible. 16301.369Srillig */ 16311.369Srilligstatic bool 16321.369Srilligcheck_assign_types_compatible(op_t op, int arg, 16331.369Srillig const tnode_t *ln, const tnode_t *rn) 16341.369Srillig{ 16351.369Srillig tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; 16361.369Srillig type_t *ltp, *rtp, *lstp = NULL, *rstp = NULL; 16371.369Srillig 16381.369Srillig if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) 16391.369Srillig lst = (lstp = ltp->t_subt)->t_tspec; 16401.369Srillig if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) 16411.369Srillig rst = (rstp = rtp->t_subt)->t_tspec; 16421.369Srillig 16431.369Srillig if (lt == BOOL && is_scalar(rt)) /* C99 6.3.1.2 */ 16441.369Srillig return true; 16451.369Srillig 16461.369Srillig if (is_arithmetic(lt) && (is_arithmetic(rt) || rt == BOOL)) 16471.369Srillig return true; 16481.369Srillig 16491.369Srillig if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) 16501.369Srillig /* both are struct or union */ 16511.369Srillig return ltp->t_str == rtp->t_str; 16521.369Srillig 16531.369Srillig /* a null pointer may be assigned to any pointer */ 16541.369Srillig if (lt == PTR && is_null_pointer(rn)) 16551.369Srillig return true; 16561.369Srillig 16571.369Srillig check_assign_void_pointer(op, arg, lt, lst, rt, rst); 16581.369Srillig 16591.369Srillig if (check_assign_void_pointer_compat(op, arg, 16601.369Srillig ltp, lt, lstp, lst, rn, rtp, rt, rstp, rst)) 16611.369Srillig return true; 16621.369Srillig 16631.369Srillig if (check_assign_pointer_integer(op, arg, ltp, lt, rtp, rt)) 16641.369Srillig return true; 16651.369Srillig 16661.369Srillig if (check_assign_pointer(op, arg, ltp, lt, rtp, rt)) 16671.369Srillig return true; 16681.1Scgd 16691.369Srillig warn_assign(op, arg, ltp, lt, rtp, rt); 16701.154Srillig return false; 16711.1Scgd} 16721.1Scgd 16731.182Srillig/* Prints a warning if a strange operator is used on an enum type. */ 16741.1Scgdstatic void 16751.149Srilligcheck_bad_enum_operation(op_t op, const tnode_t *ln, const tnode_t *rn) 16761.1Scgd{ 16771.1Scgd 16781.1Scgd if (!eflag) 16791.1Scgd return; 16801.1Scgd 16811.1Scgd /* 16821.1Scgd * Enum as offset to a pointer is an exception (otherwise enums 16831.127Srillig * could not be used as array indices). 16841.1Scgd */ 16851.1Scgd if (op == PLUS && 16861.209Srillig ((ln->tn_type->t_is_enum && rn->tn_type->t_tspec == PTR) || 16871.209Srillig (rn->tn_type->t_is_enum && ln->tn_type->t_tspec == PTR))) { 16881.1Scgd return; 16891.1Scgd } 16901.1Scgd 16911.1Scgd /* dubious operation on enum, op %s */ 16921.260Srillig warning(241, op_name(op)); 16931.1Scgd} 16941.1Scgd 16951.1Scgd/* 16961.1Scgd * Prints a warning if an operator is applied to two different enum types. 16971.1Scgd */ 16981.1Scgdstatic void 16991.149Srilligcheck_enum_type_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) 17001.1Scgd{ 17011.240Srillig const mod_t *mp; 17021.1Scgd 17031.1Scgd mp = &modtab[op]; 17041.1Scgd 17051.1Scgd if (ln->tn_type->t_enum != rn->tn_type->t_enum) { 17061.1Scgd switch (op) { 17071.1Scgd case INIT: 17081.214Srillig /* enum type mismatch between '%s' and '%s' in ... */ 17091.214Srillig warning(210, 17101.214Srillig type_name(ln->tn_type), type_name(rn->tn_type)); 17111.1Scgd break; 17121.1Scgd case FARG: 17131.152Srillig /* enum type mismatch, arg #%d (%s != %s) */ 17141.152Srillig warning(156, arg, 17151.152Srillig type_name(ln->tn_type), type_name(rn->tn_type)); 17161.1Scgd break; 17171.1Scgd case RETURN: 17181.108Srillig /* return value type mismatch (%s) and (%s) */ 17191.115Srillig warning(211, 17201.115Srillig type_name(ln->tn_type), type_name(rn->tn_type)); 17211.1Scgd break; 17221.1Scgd default: 17231.224Srillig /* enum type mismatch: '%s' '%s' '%s' */ 17241.224Srillig warning(130, type_name(ln->tn_type), mp->m_name, 17251.224Srillig type_name(rn->tn_type)); 17261.1Scgd break; 17271.1Scgd } 17281.164Srillig } else if (Pflag && mp->m_comparison && op != EQ && op != NE) { 17291.1Scgd if (eflag) 17301.108Srillig /* dubious comparison of enums, op %s */ 17311.1Scgd warning(243, mp->m_name); 17321.1Scgd } 17331.1Scgd} 17341.1Scgd 17351.182Srillig/* Prints a warning if the operands mix between enum and integer. */ 17361.1Scgdstatic void 17371.149Srilligcheck_enum_int_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) 17381.1Scgd{ 17391.20Slukem 17401.1Scgd if (!eflag) 17411.1Scgd return; 17421.1Scgd 17431.1Scgd switch (op) { 17441.1Scgd case INIT: 17451.1Scgd /* 17461.182Srillig * Initialization with 0 is allowed. Otherwise, all implicit 17471.182Srillig * initializations would need to be warned upon as well. 17481.1Scgd */ 17491.209Srillig if (!rn->tn_type->t_is_enum && rn->tn_op == CON && 17501.144Srillig is_integer(rn->tn_type->t_tspec) && 17511.90Srillig rn->tn_val->v_quad == 0) { 17521.1Scgd return; 17531.1Scgd } 17541.218Srillig /* initialization of '%s' with '%s' */ 17551.115Srillig warning(277, type_name(ln->tn_type), type_name(rn->tn_type)); 17561.1Scgd break; 17571.1Scgd case FARG: 17581.1Scgd /* combination of '%s' and '%s', arg #%d */ 17591.115Srillig warning(278, 17601.115Srillig type_name(ln->tn_type), type_name(rn->tn_type), arg); 17611.1Scgd break; 17621.1Scgd case RETURN: 17631.1Scgd /* combination of '%s' and '%s' in return */ 17641.115Srillig warning(279, type_name(ln->tn_type), type_name(rn->tn_type)); 17651.1Scgd break; 17661.1Scgd default: 17671.108Srillig /* combination of '%s' and '%s', op %s */ 17681.115Srillig warning(242, type_name(ln->tn_type), type_name(rn->tn_type), 17691.260Srillig op_name(op)); 17701.1Scgd break; 17711.1Scgd } 17721.1Scgd} 17731.1Scgd 17741.386Srilligstatic void 17751.386Srilligcheck_enum_array_index(const tnode_t *ln, const tnode_t *rn) 17761.386Srillig{ 17771.389Srillig int max_array_index; 17781.389Srillig int64_t max_enum_value; 17791.389Srillig const struct sym *ec, *max_ec; 17801.390Schristos const type_t *lt, *rt; 17811.386Srillig 17821.390Schristos if (ln->tn_op != ADDR || ln->tn_left->tn_op != NAME) 17831.386Srillig return; 17841.390Schristos 17851.390Schristos lt = ln->tn_left->tn_type; 17861.390Schristos if (lt->t_tspec != ARRAY || lt->t_incomplete_array) 17871.386Srillig return; 17881.390Schristos 17891.391Srillig if (rn->tn_op != CVT || !rn->tn_type->t_is_enum) 17901.391Srillig return; 17911.391Srillig if (rn->tn_left->tn_op != LOAD) 17921.386Srillig return; 17931.390Schristos 17941.390Schristos rt = rn->tn_left->tn_type; 17951.390Schristos ec = rt->t_enum->en_first_enumerator; 17961.389Srillig max_ec = ec; 17971.389Srillig lint_assert(ec != NULL); 17981.389Srillig for (ec = ec->s_next; ec != NULL; ec = ec->s_next) 17991.389Srillig if (ec->s_value.v_quad > max_ec->s_value.v_quad) 18001.389Srillig max_ec = ec; 18011.389Srillig 18021.389Srillig max_enum_value = max_ec->s_value.v_quad; 18031.389Srillig lint_assert(INT_MIN <= max_enum_value && max_enum_value <= INT_MAX); 18041.386Srillig 18051.390Schristos max_array_index = lt->t_dim - 1; 18061.386Srillig if (max_enum_value == max_array_index) 18071.386Srillig return; 18081.386Srillig 18091.389Srillig /* 18101.389Srillig * If the largest enum constant is named '*_NUM_*', it is typically 18111.389Srillig * not part of the allowed enum values but a marker for the number 18121.389Srillig * of actual enum values. 18131.389Srillig */ 18141.389Srillig if (max_enum_value == max_array_index + 1 && 18151.389Srillig (strstr(max_ec->s_name, "NUM") != NULL || 18161.389Srillig strstr(max_ec->s_name, "num") != NULL)) 18171.389Srillig return; 18181.389Srillig 18191.386Srillig /* maximum value %d of '%s' does not match maximum array index %d */ 18201.390Schristos warning(348, (int)max_enum_value, type_name(rt), max_array_index); 18211.389Srillig print_previous_declaration(-1, max_ec); 18221.386Srillig} 18231.386Srillig 18241.1Scgd/* 18251.1Scgd * Build and initialize a new node. 18261.1Scgd */ 18271.1Scgdstatic tnode_t * 18281.395Srillignew_tnode(op_t op, bool sys, type_t *type, tnode_t *ln, tnode_t *rn) 18291.1Scgd{ 18301.1Scgd tnode_t *ntn; 18311.1Scgd tspec_t t; 18321.309Srillig#if 0 /* not yet */ 18331.63Schristos size_t l; 18341.63Schristos uint64_t rnum; 18351.64Schristos#endif 18361.1Scgd 18371.256Srillig ntn = expr_zalloc_tnode(); 18381.1Scgd 18391.1Scgd ntn->tn_op = op; 18401.1Scgd ntn->tn_type = type; 18411.395Srillig ntn->tn_sys = sys; 18421.1Scgd ntn->tn_left = ln; 18431.1Scgd ntn->tn_right = rn; 18441.1Scgd 18451.63Schristos switch (op) { 18461.309Srillig#if 0 /* not yet */ 18471.63Schristos case SHR: 18481.63Schristos if (rn->tn_op != CON) 18491.63Schristos break; 18501.63Schristos rnum = rn->tn_val->v_quad; 18511.236Srillig l = type_size_in_bits(ln->tn_type) / CHAR_SIZE; 18521.63Schristos t = ln->tn_type->t_tspec; 18531.63Schristos switch (l) { 18541.63Schristos case 8: 18551.63Schristos if (rnum >= 56) 18561.63Schristos t = UCHAR; 18571.63Schristos else if (rnum >= 48) 18581.63Schristos t = USHORT; 18591.63Schristos else if (rnum >= 32) 18601.63Schristos t = UINT; 18611.63Schristos break; 18621.63Schristos case 4: 18631.63Schristos if (rnum >= 24) 18641.63Schristos t = UCHAR; 18651.63Schristos else if (rnum >= 16) 18661.63Schristos t = USHORT; 18671.63Schristos break; 18681.63Schristos case 2: 18691.63Schristos if (rnum >= 8) 18701.63Schristos t = UCHAR; 18711.63Schristos break; 18721.63Schristos default: 18731.63Schristos break; 18741.63Schristos } 18751.63Schristos if (t != ln->tn_type->t_tspec) 18761.63Schristos ntn->tn_type->t_tspec = t; 18771.63Schristos break; 18781.64Schristos#endif 18791.170Srillig case INDIR: 18801.63Schristos case FSEL: 18811.107Srillig lint_assert(ln->tn_type->t_tspec == PTR); 18821.107Srillig t = ln->tn_type->t_subt->t_tspec; 18831.107Srillig if (t != FUNC && t != VOID) 18841.154Srillig ntn->tn_lvalue = true; 18851.63Schristos break; 18861.63Schristos default: 18871.63Schristos break; 18881.1Scgd } 18891.1Scgd 18901.63Schristos return ntn; 18911.1Scgd} 18921.1Scgd 18931.1Scgd/* 18941.182Srillig * Performs the "integer promotions" (C99 6.3.1.1p2), which convert small 18951.182Srillig * integer types to either int or unsigned int. 18961.1Scgd * 18971.182Srillig * If tflag is set or the operand is a function argument with no type 18981.182Srillig * information (no prototype or variable # of args), converts float to double. 18991.1Scgd */ 19001.1Scgdtnode_t * 19011.154Srilligpromote(op_t op, bool farg, tnode_t *tn) 19021.1Scgd{ 19031.1Scgd tspec_t t; 19041.1Scgd type_t *ntp; 19051.353Srillig unsigned int len; 19061.1Scgd 19071.1Scgd t = tn->tn_type->t_tspec; 19081.1Scgd 19091.144Srillig if (!is_arithmetic(t)) 19101.95Srillig return tn; 19111.1Scgd 19121.1Scgd if (!tflag) { 19131.1Scgd /* 19141.281Srillig * C99 6.3.1.1p2 requires for types with lower rank than int 19151.281Srillig * that "If an int can represent all the values of the 19161.281Srillig * original type, the value is converted to an int; otherwise 19171.281Srillig * it is converted to an unsigned int", and that "All other 19181.281Srillig * types are unchanged by the integer promotions". 19191.1Scgd */ 19201.120Srillig if (tn->tn_type->t_bitfield) { 19211.1Scgd len = tn->tn_type->t_flen; 19221.281Srillig if (len < size_in_bits(INT)) { 19231.1Scgd t = INT; 19241.281Srillig } else if (len == size_in_bits(INT)) { 19251.281Srillig t = is_uinteger(t) ? UINT : INT; 19261.1Scgd } 19271.1Scgd } else if (t == CHAR || t == UCHAR || t == SCHAR) { 19281.228Srillig t = (size_in_bits(CHAR) < size_in_bits(INT) 19291.228Srillig || t != UCHAR) ? INT : UINT; 19301.1Scgd } else if (t == SHORT || t == USHORT) { 19311.228Srillig t = (size_in_bits(SHORT) < size_in_bits(INT) 19321.228Srillig || t == SHORT) ? INT : UINT; 19331.1Scgd } else if (t == ENUM) { 19341.1Scgd t = INT; 19351.1Scgd } else if (farg && t == FLOAT) { 19361.1Scgd t = DOUBLE; 19371.1Scgd } 19381.1Scgd } else { 19391.1Scgd /* 19401.1Scgd * In traditional C, keep unsigned and promote FLOAT 19411.1Scgd * to DOUBLE. 19421.1Scgd */ 19431.1Scgd if (t == UCHAR || t == USHORT) { 19441.1Scgd t = UINT; 19451.1Scgd } else if (t == CHAR || t == SCHAR || t == SHORT) { 19461.1Scgd t = INT; 19471.1Scgd } else if (t == FLOAT) { 19481.1Scgd t = DOUBLE; 19491.1Scgd } else if (t == ENUM) { 19501.1Scgd t = INT; 19511.1Scgd } 19521.1Scgd } 19531.1Scgd 19541.1Scgd if (t != tn->tn_type->t_tspec) { 19551.258Srillig ntp = expr_dup_type(tn->tn_type); 19561.1Scgd ntp->t_tspec = t; 19571.1Scgd /* 19581.299Srillig * Keep t_is_enum even though t_tspec gets converted from 19591.299Srillig * ENUM to INT, so we are later able to check compatibility 19601.1Scgd * of enum types. 19611.1Scgd */ 19621.1Scgd tn = convert(op, 0, ntp, tn); 19631.1Scgd } 19641.1Scgd 19651.95Srillig return tn; 19661.1Scgd} 19671.1Scgd 19681.1Scgd/* 19691.182Srillig * Apply the "usual arithmetic conversions" (C99 6.3.1.8). 19701.182Srillig * 19711.182Srillig * This gives both operands the same type. 19721.182Srillig * This is done in different ways for traditional C and C90. 19731.1Scgd */ 19741.1Scgdstatic void 19751.20Slukembalance(op_t op, tnode_t **lnp, tnode_t **rnp) 19761.1Scgd{ 19771.1Scgd tspec_t lt, rt, t; 19781.154Srillig int i; 19791.154Srillig bool u; 19801.1Scgd type_t *ntp; 19811.182Srillig static const tspec_t tl[] = { 19821.323Srillig LDOUBLE, DOUBLE, FLOAT, 19831.323Srillig#ifdef INT128_SIZE 19841.323Srillig UINT128, INT128, 19851.323Srillig#endif 19861.323Srillig UQUAD, QUAD, 19871.323Srillig ULONG, LONG, 19881.323Srillig UINT, INT, 19891.1Scgd }; 19901.1Scgd 19911.1Scgd lt = (*lnp)->tn_type->t_tspec; 19921.1Scgd rt = (*rnp)->tn_type->t_tspec; 19931.1Scgd 19941.144Srillig if (!is_arithmetic(lt) || !is_arithmetic(rt)) 19951.1Scgd return; 19961.1Scgd 19971.1Scgd if (!tflag) { 19981.1Scgd if (lt == rt) { 19991.1Scgd t = lt; 20001.53Smatt } else if (lt == LCOMPLEX || rt == LCOMPLEX) { 20011.53Smatt t = LCOMPLEX; 20021.53Smatt } else if (lt == DCOMPLEX || rt == DCOMPLEX) { 20031.53Smatt t = DCOMPLEX; 20041.53Smatt } else if (lt == FCOMPLEX || rt == FCOMPLEX) { 20051.53Smatt t = FCOMPLEX; 20061.1Scgd } else if (lt == LDOUBLE || rt == LDOUBLE) { 20071.1Scgd t = LDOUBLE; 20081.1Scgd } else if (lt == DOUBLE || rt == DOUBLE) { 20091.1Scgd t = DOUBLE; 20101.1Scgd } else if (lt == FLOAT || rt == FLOAT) { 20111.1Scgd t = FLOAT; 20121.1Scgd } else { 20131.1Scgd /* 20141.1Scgd * If type A has more bits than type B it should 20151.1Scgd * be able to hold all possible values of type B. 20161.1Scgd */ 20171.228Srillig if (size_in_bits(lt) > size_in_bits(rt)) { 20181.1Scgd t = lt; 20191.228Srillig } else if (size_in_bits(lt) < size_in_bits(rt)) { 20201.1Scgd t = rt; 20211.1Scgd } else { 20221.1Scgd for (i = 3; tl[i] != INT; i++) { 20231.1Scgd if (tl[i] == lt || tl[i] == rt) 20241.1Scgd break; 20251.1Scgd } 20261.144Srillig if ((is_uinteger(lt) || is_uinteger(rt)) && 20271.144Srillig !is_uinteger(tl[i])) { 20281.1Scgd i--; 20291.1Scgd } 20301.1Scgd t = tl[i]; 20311.1Scgd } 20321.1Scgd } 20331.1Scgd } else { 20341.1Scgd /* Keep unsigned in traditional C */ 20351.144Srillig u = is_uinteger(lt) || is_uinteger(rt); 20361.1Scgd for (i = 0; tl[i] != INT; i++) { 20371.1Scgd if (lt == tl[i] || rt == tl[i]) 20381.1Scgd break; 20391.1Scgd } 20401.1Scgd t = tl[i]; 20411.144Srillig if (u && is_integer(t) && !is_uinteger(t)) 20421.114Srillig t = unsigned_type(t); 20431.1Scgd } 20441.1Scgd 20451.1Scgd if (t != lt) { 20461.258Srillig ntp = expr_dup_type((*lnp)->tn_type); 20471.1Scgd ntp->t_tspec = t; 20481.1Scgd *lnp = convert(op, 0, ntp, *lnp); 20491.1Scgd } 20501.1Scgd if (t != rt) { 20511.258Srillig ntp = expr_dup_type((*rnp)->tn_type); 20521.1Scgd ntp->t_tspec = t; 20531.1Scgd *rnp = convert(op, 0, ntp, *rnp); 20541.1Scgd } 20551.1Scgd} 20561.1Scgd 20571.1Scgd/* 20581.1Scgd * Insert a conversion operator, which converts the type of the node 20591.1Scgd * to another given type. 20601.1Scgd * If op is FARG, arg is the number of the argument (used for warnings). 20611.1Scgd */ 20621.1Scgdtnode_t * 20631.20Slukemconvert(op_t op, int arg, type_t *tp, tnode_t *tn) 20641.1Scgd{ 20651.1Scgd tnode_t *ntn; 20661.190Srillig tspec_t nt, ot; 20671.1Scgd 20681.1Scgd nt = tp->t_tspec; 20691.190Srillig ot = tn->tn_type->t_tspec; 20701.1Scgd 20711.1Scgd if (!tflag && !sflag && op == FARG) 20721.100Srillig check_prototype_conversion(arg, nt, ot, tp, tn); 20731.144Srillig if (is_integer(nt) && is_integer(ot)) { 20741.100Srillig check_integer_conversion(op, arg, nt, ot, tp, tn); 20751.190Srillig } else if (nt == PTR && is_null_pointer(tn)) { 20761.190Srillig /* a null pointer may be assigned to any pointer. */ 20771.148Srillig } else if (is_integer(nt) && nt != BOOL && ot == PTR) { 20781.100Srillig check_pointer_integer_conversion(op, nt, tp, tn); 20791.273Srillig } else if (nt == PTR && ot == PTR && op == CVT) { 20801.273Srillig check_pointer_conversion(tn, tp); 20811.1Scgd } 20821.1Scgd 20831.256Srillig ntn = expr_zalloc_tnode(); 20841.1Scgd ntn->tn_op = CVT; 20851.1Scgd ntn->tn_type = tp; 20861.1Scgd ntn->tn_cast = op == CVT; 20871.395Srillig ntn->tn_sys |= tn->tn_sys; 20881.76Schristos ntn->tn_right = NULL; 20891.1Scgd if (tn->tn_op != CON || nt == VOID) { 20901.1Scgd ntn->tn_left = tn; 20911.1Scgd } else { 20921.1Scgd ntn->tn_op = CON; 20931.259Srillig ntn->tn_val = expr_zalloc(sizeof(*ntn->tn_val)); 20941.146Srillig convert_constant(op, arg, ntn->tn_type, ntn->tn_val, 20951.146Srillig tn->tn_val); 20961.1Scgd } 20971.1Scgd 20981.95Srillig return ntn; 20991.1Scgd} 21001.1Scgd 21011.364Srilligstatic bool 21021.366Srilligshould_warn_about_prototype_conversion(tspec_t nt, 21031.366Srillig tspec_t ot, const tnode_t *ptn) 21041.344Srillig{ 21051.344Srillig 21061.367Srillig if (nt == ot) 21071.367Srillig return false; 21081.367Srillig 21091.367Srillig if (nt == ENUM && ot == INT) 21101.367Srillig return false; 21111.367Srillig 21121.364Srillig if (is_floating(nt) != is_floating(ot) || 21131.364Srillig portable_size_in_bits(nt) != portable_size_in_bits(ot)) { 21141.364Srillig /* representation and/or width change */ 21151.364Srillig if (!is_integer(ot)) 21161.364Srillig return true; 21171.383Srillig /* 21181.383Srillig * XXX: Investigate whether this rule makes sense; see 21191.383Srillig * tests/usr.bin/xlint/lint1/platform_long.c. 21201.383Srillig */ 21211.364Srillig return portable_size_in_bits(ot) > portable_size_in_bits(INT); 21221.364Srillig } 21231.364Srillig 21241.344Srillig if (!hflag) 21251.364Srillig return false; 21261.344Srillig 21271.344Srillig /* 21281.344Srillig * If the types differ only in sign and the argument has the same 21291.344Srillig * representation in both types, print no warning. 21301.344Srillig */ 21311.344Srillig if (ptn->tn_op == CON && is_integer(nt) && 21321.344Srillig signed_type(nt) == signed_type(ot) && 21331.348Srillig !msb(ptn->tn_val->v_quad, ot)) 21341.364Srillig return false; 21351.344Srillig 21361.364Srillig return true; 21371.344Srillig} 21381.344Srillig 21391.344Srillig/* 21401.367Srillig * Warn if a prototype causes a type conversion that is different from what 21411.367Srillig * would happen to the same argument in the absence of a prototype. This 21421.367Srillig * check is intended for code that needs to stay compatible with pre-C90 C. 21431.1Scgd * 21441.182Srillig * Errors/warnings about illegal type combinations are already printed 21451.100Srillig * in check_assign_types_compatible(). 21461.1Scgd */ 21471.1Scgdstatic void 21481.100Srilligcheck_prototype_conversion(int arg, tspec_t nt, tspec_t ot, type_t *tp, 21491.100Srillig tnode_t *tn) 21501.1Scgd{ 21511.1Scgd tnode_t *ptn; 21521.1Scgd 21531.144Srillig if (!is_arithmetic(nt) || !is_arithmetic(ot)) 21541.1Scgd return; 21551.1Scgd 21561.1Scgd /* 21571.1Scgd * If the type of the formal parameter is char/short, a warning 21581.1Scgd * would be useless, because functions declared the old style 21591.1Scgd * can't expect char/short arguments. 21601.1Scgd */ 21611.368Srillig if (nt == CHAR || nt == SCHAR || nt == UCHAR || 21621.368Srillig nt == SHORT || nt == USHORT) 21631.1Scgd return; 21641.1Scgd 21651.367Srillig /* apply the default promotion */ 21661.172Srillig ptn = promote(NOOP, true, tn); 21671.1Scgd ot = ptn->tn_type->t_tspec; 21681.1Scgd 21691.366Srillig if (should_warn_about_prototype_conversion(nt, ot, ptn)) { 21701.364Srillig /* argument #%d is converted from '%s' to '%s' ... */ 21711.364Srillig warning(259, arg, type_name(tn->tn_type), type_name(tp)); 21721.364Srillig } 21731.1Scgd} 21741.1Scgd 21751.1Scgd/* 21761.96Srillig * Print warnings for conversions of integer types which may cause problems. 21771.1Scgd */ 21781.1Scgdstatic void 21791.100Srilligcheck_integer_conversion(op_t op, int arg, tspec_t nt, tspec_t ot, type_t *tp, 21801.100Srillig tnode_t *tn) 21811.1Scgd{ 21821.115Srillig 21831.1Scgd if (tn->tn_op == CON) 21841.1Scgd return; 21851.1Scgd 21861.1Scgd if (op == CVT) 21871.1Scgd return; 21881.1Scgd 21891.268Srillig if (Sflag && nt == BOOL) 21901.268Srillig return; /* See C99 6.3.1.2 */ 21911.268Srillig 21921.228Srillig if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot) && 21931.144Srillig is_uinteger(nt) != is_uinteger(ot)) { 21941.154Srillig if (aflag > 0 && pflag) { 21951.1Scgd if (op == FARG) { 21961.113Srillig /* conversion to '%s' may sign-extend ... */ 21971.115Srillig warning(297, type_name(tp), arg); 21981.1Scgd } else { 21991.113Srillig /* conversion to '%s' may sign-extend ... */ 22001.115Srillig warning(131, type_name(tp)); 22011.1Scgd } 22021.1Scgd } 22031.1Scgd } 22041.51Schristos 22051.228Srillig if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot)) { 22061.51Schristos switch (tn->tn_op) { 22071.51Schristos case PLUS: 22081.51Schristos case MINUS: 22091.51Schristos case MULT: 22101.51Schristos case SHL: 22111.113Srillig /* suggest cast from '%s' to '%s' on op %s to ... */ 22121.115Srillig warning(324, type_name(gettyp(ot)), type_name(tp), 22131.290Srillig op_name(tn->tn_op)); 22141.51Schristos break; 22151.51Schristos default: 22161.51Schristos break; 22171.51Schristos } 22181.51Schristos } 22191.1Scgd 22201.228Srillig if (portable_size_in_bits(nt) < portable_size_in_bits(ot) && 22211.1Scgd (ot == LONG || ot == ULONG || ot == QUAD || ot == UQUAD || 22221.1Scgd aflag > 1)) { 22231.1Scgd /* conversion from '%s' may lose accuracy */ 22241.154Srillig if (aflag > 0) { 22251.1Scgd if (op == FARG) { 22261.377Srillig /* conversion from '%s' to '%s' may ... */ 22271.39Schristos warning(298, 22281.115Srillig type_name(tn->tn_type), type_name(tp), arg); 22291.1Scgd } else { 22301.377Srillig /* conversion from '%s' to '%s' may ... */ 22311.39Schristos warning(132, 22321.115Srillig type_name(tn->tn_type), type_name(tp)); 22331.1Scgd } 22341.20Slukem } 22351.1Scgd } 22361.1Scgd} 22371.1Scgd 22381.1Scgd/* 22391.1Scgd * Print warnings for dubious conversions of pointer to integer. 22401.1Scgd */ 22411.1Scgdstatic void 22421.100Srilligcheck_pointer_integer_conversion(op_t op, tspec_t nt, type_t *tp, tnode_t *tn) 22431.1Scgd{ 22441.20Slukem 22451.1Scgd if (tn->tn_op == CON) 22461.1Scgd return; 22471.166Srillig if (op != CVT) 22481.166Srillig return; /* We got already an error. */ 22491.228Srillig if (portable_size_in_bits(nt) >= portable_size_in_bits(PTR)) 22501.1Scgd return; 22511.1Scgd 22521.228Srillig if (pflag && size_in_bits(nt) >= size_in_bits(PTR)) { 22531.166Srillig /* conversion of pointer to '%s' may lose bits */ 22541.166Srillig warning(134, type_name(tp)); 22551.166Srillig } else { 22561.166Srillig /* conversion of pointer to '%s' loses bits */ 22571.166Srillig warning(133, type_name(tp)); 22581.1Scgd } 22591.1Scgd} 22601.1Scgd 22611.247Srilligstatic bool 22621.273Srilligshould_warn_about_pointer_cast(const type_t *nstp, tspec_t nst, 22631.273Srillig const type_t *ostp, tspec_t ost) 22641.247Srillig{ 22651.272Srillig /* 22661.272Srillig * Casting a pointer to 'struct S' to a pointer to another struct that 22671.272Srillig * has 'struct S' as its first member is ok, see msg_247.c, 'struct 22681.272Srillig * counter'. 22691.272Srillig */ 22701.272Srillig if (nst == STRUCT && ost == STRUCT && 22711.273Srillig nstp->t_str->sou_first_member != NULL && 22721.273Srillig nstp->t_str->sou_first_member->s_type == ostp) 22731.272Srillig return false; 22741.272Srillig 22751.274Srillig if (is_incomplete(nstp) || is_incomplete(ostp)) 22761.274Srillig return false; 22771.274Srillig 22781.273Srillig if ((nst == STRUCT || nst == UNION) && nstp->t_str != ostp->t_str) 22791.273Srillig return true; 22801.247Srillig 22811.249Srillig if (nst == CHAR || nst == UCHAR) 22821.249Srillig return false; /* for the sake of traditional C code */ 22831.316Srillig if (ost == CHAR || ost == UCHAR) 22841.316Srillig return false; /* for the sake of traditional C code */ 22851.249Srillig 22861.247Srillig return portable_size_in_bits(nst) != portable_size_in_bits(ost); 22871.247Srillig} 22881.247Srillig 22891.1Scgd/* 22901.248Srillig * Warn about questionable pointer conversions. 22911.1Scgd */ 22921.1Scgdstatic void 22931.273Srilligcheck_pointer_conversion(tnode_t *tn, type_t *ntp) 22941.1Scgd{ 22951.273Srillig const type_t *nstp, *otp, *ostp; 22961.248Srillig tspec_t nst, ost; 22971.248Srillig const char *nts, *ots; 22981.1Scgd 22991.273Srillig nstp = ntp->t_subt; 23001.273Srillig otp = tn->tn_type; 23011.273Srillig ostp = otp->t_subt; 23021.273Srillig nst = nstp->t_tspec; 23031.273Srillig ost = ostp->t_tspec; 23041.248Srillig 23051.248Srillig if (nst == VOID || ost == VOID) { 23061.248Srillig if (sflag && (nst == FUNC || ost == FUNC)) { 23071.248Srillig /* null pointers are already handled in convert() */ 23081.248Srillig *(nst == FUNC ? &nts : &ots) = "function pointer"; 23091.248Srillig *(nst == VOID ? &nts : &ots) = "'void *'"; 23101.1Scgd /* ANSI C forbids conversion of %s to %s */ 23111.1Scgd warning(303, ots, nts); 23121.1Scgd } 23131.1Scgd return; 23141.248Srillig } else if (nst == FUNC && ost == FUNC) { 23151.1Scgd return; 23161.248Srillig } else if (nst == FUNC || ost == FUNC) { 23171.223Srillig /* converting '%s' to '%s' is questionable */ 23181.273Srillig warning(229, type_name(otp), type_name(ntp)); 23191.1Scgd return; 23201.1Scgd } 23211.20Slukem 23221.277Srillig if (hflag && alignment_in_bits(nstp) > alignment_in_bits(ostp) && 23231.316Srillig ost != CHAR && ost != UCHAR && 23241.277Srillig !is_incomplete(ostp)) { 23251.222Srillig /* converting '%s' to '%s' may cause alignment problem */ 23261.273Srillig warning(135, type_name(otp), type_name(ntp)); 23271.1Scgd } 23281.221Srillig 23291.273Srillig if (cflag && should_warn_about_pointer_cast(nstp, nst, ostp, ost)) { 23301.247Srillig /* pointer cast from '%s' to '%s' may be troublesome */ 23311.273Srillig warning(247, type_name(otp), type_name(ntp)); 23321.1Scgd } 23331.1Scgd} 23341.1Scgd 23351.282Srilligstatic void 23361.285Srilligconvert_constant_floating(op_t op, int arg, tspec_t ot, const type_t *tp, 23371.285Srillig tspec_t nt, val_t *v, val_t *nv) 23381.282Srillig{ 23391.282Srillig ldbl_t max = 0.0, min = 0.0; 23401.282Srillig 23411.282Srillig switch (nt) { 23421.282Srillig case CHAR: 23431.282Srillig max = TARG_CHAR_MAX; min = TARG_CHAR_MIN; break; 23441.282Srillig case UCHAR: 23451.282Srillig max = TARG_UCHAR_MAX; min = 0; break; 23461.282Srillig case SCHAR: 23471.282Srillig max = TARG_SCHAR_MAX; min = TARG_SCHAR_MIN; break; 23481.282Srillig case SHORT: 23491.282Srillig max = TARG_SHRT_MAX; min = TARG_SHRT_MIN; break; 23501.282Srillig case USHORT: 23511.282Srillig max = TARG_USHRT_MAX; min = 0; break; 23521.282Srillig case ENUM: 23531.282Srillig case INT: 23541.282Srillig max = TARG_INT_MAX; min = TARG_INT_MIN; break; 23551.282Srillig case UINT: 23561.354Srillig max = TARG_UINT_MAX; min = 0; break; 23571.282Srillig case LONG: 23581.282Srillig max = TARG_LONG_MAX; min = TARG_LONG_MIN; break; 23591.282Srillig case ULONG: 23601.354Srillig max = TARG_ULONG_MAX; min = 0; break; 23611.282Srillig case QUAD: 23621.282Srillig max = QUAD_MAX; min = QUAD_MIN; break; 23631.282Srillig case UQUAD: 23641.354Srillig max = UQUAD_MAX; min = 0; break; 23651.282Srillig case FLOAT: 23661.282Srillig case FCOMPLEX: 23671.282Srillig max = FLT_MAX; min = -FLT_MAX; break; 23681.282Srillig case DOUBLE: 23691.282Srillig case DCOMPLEX: 23701.282Srillig max = DBL_MAX; min = -DBL_MAX; break; 23711.282Srillig case PTR: 23721.282Srillig /* Got already an error because of float --> ptr */ 23731.282Srillig case LDOUBLE: 23741.282Srillig case LCOMPLEX: 23751.378Srillig /* LINTED 248 */ 23761.378Srillig max = LDBL_MAX; min = -max; break; 23771.282Srillig default: 23781.282Srillig lint_assert(/*CONSTCOND*/false); 23791.282Srillig } 23801.282Srillig if (v->v_ldbl > max || v->v_ldbl < min) { 23811.282Srillig lint_assert(nt != LDOUBLE); 23821.282Srillig if (op == FARG) { 23831.377Srillig /* conversion of '%s' to '%s' is out of range, ... */ 23841.282Srillig warning(295, 23851.282Srillig type_name(gettyp(ot)), type_name(tp), arg); 23861.282Srillig } else { 23871.282Srillig /* conversion of '%s' to '%s' is out of range */ 23881.282Srillig warning(119, 23891.282Srillig type_name(gettyp(ot)), type_name(tp)); 23901.282Srillig } 23911.282Srillig v->v_ldbl = v->v_ldbl > 0 ? max : min; 23921.282Srillig } 23931.357Srillig 23941.282Srillig if (nt == FLOAT) { 23951.282Srillig nv->v_ldbl = (float)v->v_ldbl; 23961.282Srillig } else if (nt == DOUBLE) { 23971.282Srillig nv->v_ldbl = (double)v->v_ldbl; 23981.282Srillig } else if (nt == LDOUBLE) { 23991.282Srillig nv->v_ldbl = v->v_ldbl; 24001.282Srillig } else { 24011.357Srillig nv->v_quad = (int64_t)v->v_ldbl; 24021.282Srillig } 24031.282Srillig} 24041.282Srillig 24051.286Srilligstatic bool 24061.286Srilligconvert_constant_to_floating(tspec_t nt, val_t *nv, 24071.286Srillig tspec_t ot, const val_t *v) 24081.286Srillig{ 24091.286Srillig if (nt == FLOAT) { 24101.286Srillig nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? 24111.286Srillig (float)(uint64_t)v->v_quad : (float)v->v_quad; 24121.286Srillig } else if (nt == DOUBLE) { 24131.286Srillig nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? 24141.286Srillig (double)(uint64_t)v->v_quad : (double)v->v_quad; 24151.286Srillig } else if (nt == LDOUBLE) { 24161.286Srillig nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? 24171.286Srillig (ldbl_t)(uint64_t)v->v_quad : (ldbl_t)v->v_quad; 24181.286Srillig } else 24191.286Srillig return false; 24201.286Srillig return true; 24211.286Srillig} 24221.286Srillig 24231.285Srillig/* 24241.285Srillig * Print a warning if bits which were set are lost due to the conversion. 24251.285Srillig * This can happen with operator ORASS only. 24261.285Srillig */ 24271.285Srilligstatic void 24281.285Srilligconvert_constant_check_range_bitor(size_t nsz, size_t osz, const val_t *v, 24291.285Srillig uint64_t xmask, op_t op) 24301.285Srillig{ 24311.285Srillig if (nsz < osz && (v->v_quad & xmask) != 0) { 24321.377Srillig /* constant truncated by conversion, op %s */ 24331.285Srillig warning(306, op_name(op)); 24341.285Srillig } 24351.285Srillig} 24361.285Srillig 24371.285Srillig/* 24381.285Srillig * Print a warning if additional bits are not all 1 24391.285Srillig * and the most significant bit of the old value is 1, 24401.285Srillig * or if at least one (but not all) removed bit was 0. 24411.285Srillig */ 24421.285Srilligstatic void 24431.285Srilligconvert_constant_check_range_bitand(size_t nsz, size_t osz, 24441.285Srillig uint64_t xmask, const val_t *nv, 24451.285Srillig tspec_t ot, const val_t *v, 24461.285Srillig const type_t *tp, op_t op) 24471.285Srillig{ 24481.285Srillig if (nsz > osz && 24491.378Srillig (nv->v_quad & bit((unsigned int)(osz - 1))) != 0 && 24501.285Srillig (nv->v_quad & xmask) != xmask) { 24511.285Srillig /* extra bits set to 0 in conversion of '%s' to '%s', ... */ 24521.285Srillig warning(309, type_name(gettyp(ot)), 24531.285Srillig type_name(tp), op_name(op)); 24541.285Srillig } else if (nsz < osz && 24551.285Srillig (v->v_quad & xmask) != xmask && 24561.285Srillig (v->v_quad & xmask) != 0) { 24571.285Srillig /* constant truncated by conversion, op %s */ 24581.285Srillig warning(306, op_name(op)); 24591.285Srillig } 24601.285Srillig} 24611.285Srillig 24621.285Srilligstatic void 24631.285Srilligconvert_constant_check_range_signed(op_t op, int arg) 24641.285Srillig{ 24651.285Srillig if (op == ASSIGN) { 24661.285Srillig /* assignment of negative constant to unsigned type */ 24671.285Srillig warning(164); 24681.285Srillig } else if (op == INIT) { 24691.285Srillig /* initialization of unsigned with negative constant */ 24701.285Srillig warning(221); 24711.285Srillig } else if (op == FARG) { 24721.285Srillig /* conversion of negative constant to unsigned type, ... */ 24731.285Srillig warning(296, arg); 24741.285Srillig } else if (modtab[op].m_comparison) { 24751.285Srillig /* handled by check_integer_comparison() */ 24761.285Srillig } else { 24771.285Srillig /* conversion of negative constant to unsigned type */ 24781.285Srillig warning(222); 24791.285Srillig } 24801.285Srillig} 24811.285Srillig 24821.285Srillig/* 24831.285Srillig * Loss of significant bit(s). All truncated bits 24841.285Srillig * of unsigned types or all truncated bits plus the 24851.285Srillig * msb of the target for signed types are considered 24861.285Srillig * to be significant bits. Loss of significant bits 24871.295Srillig * means that at least one of the bits was set in an 24881.295Srillig * unsigned type or that at least one but not all of 24891.295Srillig * the bits was set in a signed type. 24901.285Srillig * Loss of significant bits means that it is not 24911.285Srillig * possible, also not with necessary casts, to convert 24921.285Srillig * back to the original type. A example for a 24931.285Srillig * necessary cast is: 24941.285Srillig * char c; int i; c = 128; 24951.285Srillig * i = c; ** yields -128 ** 24961.285Srillig * i = (unsigned char)c; ** yields 128 ** 24971.285Srillig */ 24981.285Srilligstatic void 24991.285Srilligconvert_constant_check_range_truncated(op_t op, int arg, const type_t *tp, 25001.285Srillig tspec_t ot) 25011.285Srillig{ 25021.285Srillig if (op == ASSIGN && tp->t_bitfield) { 25031.285Srillig /* precision lost in bit-field assignment */ 25041.285Srillig warning(166); 25051.285Srillig } else if (op == ASSIGN) { 25061.285Srillig /* constant truncated by assignment */ 25071.285Srillig warning(165); 25081.285Srillig } else if (op == INIT && tp->t_bitfield) { 25091.285Srillig /* bit-field initializer does not fit */ 25101.285Srillig warning(180); 25111.285Srillig } else if (op == INIT) { 25121.285Srillig /* initializer does not fit */ 25131.285Srillig warning(178); 25141.285Srillig } else if (op == CASE) { 25151.285Srillig /* case label affected by conversion */ 25161.285Srillig warning(196); 25171.285Srillig } else if (op == FARG) { 25181.285Srillig /* conversion of '%s' to '%s' is out of range, arg #%d */ 25191.285Srillig warning(295, 25201.285Srillig type_name(gettyp(ot)), type_name(tp), arg); 25211.285Srillig } else { 25221.285Srillig /* conversion of '%s' to '%s' is out of range */ 25231.285Srillig warning(119, 25241.285Srillig type_name(gettyp(ot)), type_name(tp)); 25251.285Srillig } 25261.285Srillig} 25271.285Srillig 25281.285Srilligstatic void 25291.285Srilligconvert_constant_check_range_loss(op_t op, int arg, const type_t *tp, 25301.285Srillig tspec_t ot) 25311.285Srillig{ 25321.285Srillig if (op == ASSIGN && tp->t_bitfield) { 25331.285Srillig /* precision lost in bit-field assignment */ 25341.285Srillig warning(166); 25351.285Srillig } else if (op == INIT && tp->t_bitfield) { 25361.285Srillig /* bit-field initializer out of range */ 25371.285Srillig warning(11); 25381.285Srillig } else if (op == CASE) { 25391.285Srillig /* case label affected by conversion */ 25401.285Srillig warning(196); 25411.285Srillig } else if (op == FARG) { 25421.285Srillig /* conversion of '%s' to '%s' is out of range, arg #%d */ 25431.285Srillig warning(295, 25441.285Srillig type_name(gettyp(ot)), type_name(tp), arg); 25451.285Srillig } else { 25461.285Srillig /* conversion of '%s' to '%s' is out of range */ 25471.285Srillig warning(119, 25481.285Srillig type_name(gettyp(ot)), type_name(tp)); 25491.285Srillig } 25501.285Srillig} 25511.285Srillig 25521.283Srilligstatic void 25531.285Srilligconvert_constant_check_range(tspec_t ot, const type_t *tp, tspec_t nt, 25541.285Srillig op_t op, int arg, const val_t *v, val_t *nv) 25551.283Srillig{ 25561.378Srillig unsigned int osz, nsz; 25571.378Srillig uint64_t xmask, xmsk1; 25581.283Srillig 25591.283Srillig osz = size_in_bits(ot); 25601.283Srillig nsz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt); 25611.287Srillig xmask = value_bits(nsz) ^ value_bits(osz); 25621.287Srillig xmsk1 = value_bits(nsz) ^ value_bits(osz - 1); 25631.283Srillig /* 25641.283Srillig * For bitwise operations we are not interested in the 25651.283Srillig * value, but in the bits itself. 25661.283Srillig */ 25671.283Srillig if (op == ORASS || op == BITOR || op == BITXOR) { 25681.285Srillig convert_constant_check_range_bitor(nsz, osz, v, xmask, op); 25691.283Srillig } else if (op == ANDASS || op == BITAND) { 25701.285Srillig convert_constant_check_range_bitand(nsz, osz, xmask, nv, ot, 25711.285Srillig v, tp, op); 25721.283Srillig } else if ((nt != PTR && is_uinteger(nt)) && 25731.283Srillig (ot != PTR && !is_uinteger(ot)) && 25741.283Srillig v->v_quad < 0) { 25751.285Srillig convert_constant_check_range_signed(op, arg); 25761.283Srillig } else if (nv->v_quad != v->v_quad && nsz <= osz && 25771.283Srillig (v->v_quad & xmask) != 0 && 25781.283Srillig (is_uinteger(ot) || (v->v_quad & xmsk1) != xmsk1)) { 25791.285Srillig convert_constant_check_range_truncated(op, arg, tp, ot); 25801.283Srillig } else if (nv->v_quad != v->v_quad) { 25811.285Srillig convert_constant_check_range_loss(op, arg, tp, ot); 25821.283Srillig } 25831.283Srillig} 25841.283Srillig 25851.1Scgd/* 25861.166Srillig * Converts a typed constant to a constant of another type. 25871.1Scgd * 25881.1Scgd * op operator which requires conversion 25891.1Scgd * arg if op is FARG, # of argument 25901.1Scgd * tp type in which to convert the constant 25911.1Scgd * nv new constant 25921.1Scgd * v old constant 25931.1Scgd */ 25941.1Scgdvoid 25951.253Srilligconvert_constant(op_t op, int arg, const type_t *tp, val_t *nv, val_t *v) 25961.1Scgd{ 25971.378Srillig tspec_t ot, nt; 25981.378Srillig unsigned int sz; 25991.378Srillig bool range_check; 26001.1Scgd 26011.276Srillig /* 26021.276Srillig * TODO: make 'v' const; the name of this function does not suggest 26031.276Srillig * that it modifies 'v'. 26041.276Srillig */ 26051.1Scgd ot = v->v_tspec; 26061.1Scgd nt = nv->v_tspec = tp->t_tspec; 26071.283Srillig range_check = false; 26081.1Scgd 26091.147Srillig if (nt == BOOL) { /* C99 6.3.1.2 */ 26101.289Srillig nv->v_unsigned_since_c90 = false; 26111.230Srillig nv->v_quad = is_nonzero_val(v) ? 1 : 0; 26121.147Srillig return; 26131.147Srillig } 26141.147Srillig 26151.1Scgd if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) { 26161.282Srillig convert_constant_floating(op, arg, ot, tp, nt, v, nv); 26171.286Srillig } else if (!convert_constant_to_floating(nt, nv, ot, v)) { 26181.286Srillig range_check = true; /* Check for lost precision. */ 26191.286Srillig nv->v_quad = v->v_quad; 26201.1Scgd } 26211.1Scgd 26221.289Srillig if ((v->v_unsigned_since_c90 && is_floating(nt)) || 26231.289Srillig (v->v_unsigned_since_c90 && (is_integer(nt) && !is_uinteger(nt) && 26241.284Srillig portable_size_in_bits(nt) > 26251.284Srillig portable_size_in_bits(ot)))) { 26261.1Scgd /* ANSI C treats constant as unsigned */ 26271.1Scgd warning(157); 26281.289Srillig v->v_unsigned_since_c90 = false; 26291.1Scgd } 26301.1Scgd 26311.297Srillig if (is_integer(nt)) { 26321.228Srillig sz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt); 26331.298Srillig nv->v_quad = convert_integer(nv->v_quad, nt, sz); 26341.1Scgd } 26351.20Slukem 26361.283Srillig if (range_check && op != CVT) 26371.283Srillig convert_constant_check_range(ot, tp, nt, op, arg, v, nv); 26381.1Scgd} 26391.1Scgd 26401.1Scgd/* 26411.1Scgd * Called if incompatible types were detected. 26421.1Scgd * Prints a appropriate warning. 26431.1Scgd */ 26441.1Scgdstatic void 26451.246Srilligwarn_incompatible_types(op_t op, 26461.246Srillig const type_t *ltp, tspec_t lt, 26471.246Srillig const type_t *rtp, tspec_t rt) 26481.1Scgd{ 26491.240Srillig const mod_t *mp; 26501.1Scgd 26511.1Scgd mp = &modtab[op]; 26521.1Scgd 26531.1Scgd if (lt == VOID || (mp->m_binary && rt == VOID)) { 26541.1Scgd /* void type illegal in expression */ 26551.110Srillig error(109); 26561.1Scgd } else if (op == ASSIGN) { 26571.1Scgd if ((lt == STRUCT || lt == UNION) && 26581.1Scgd (rt == STRUCT || rt == UNION)) { 26591.110Srillig /* assignment of different structures (%s != %s) */ 26601.111Srillig error(240, tspec_name(lt), tspec_name(rt)); 26611.1Scgd } else { 26621.246Srillig /* cannot assign to '%s' from '%s' */ 26631.246Srillig error(171, type_name(ltp), type_name(rtp)); 26641.1Scgd } 26651.1Scgd } else if (mp->m_binary) { 26661.110Srillig /* operands of '%s' have incompatible types (%s != %s) */ 26671.111Srillig error(107, mp->m_name, tspec_name(lt), tspec_name(rt)); 26681.1Scgd } else { 26691.137Srillig lint_assert(rt == NOTSPEC); 26701.137Srillig /* operand of '%s' has invalid type (%s) */ 26711.137Srillig error(108, mp->m_name, tspec_name(lt)); 26721.1Scgd } 26731.1Scgd} 26741.1Scgd 26751.1Scgd/* 26761.1Scgd * Called if incompatible pointer types are detected. 26771.1Scgd * Print an appropriate warning. 26781.1Scgd */ 26791.1Scgdstatic void 26801.149Srilligwarn_incompatible_pointers(const mod_t *mp, 26811.149Srillig const type_t *ltp, const type_t *rtp) 26821.1Scgd{ 26831.1Scgd tspec_t lt, rt; 26841.1Scgd 26851.107Srillig lint_assert(ltp->t_tspec == PTR); 26861.107Srillig lint_assert(rtp->t_tspec == PTR); 26871.1Scgd 26881.1Scgd lt = ltp->t_subt->t_tspec; 26891.1Scgd rt = rtp->t_subt->t_tspec; 26901.1Scgd 26911.1Scgd if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) { 26921.1Scgd if (mp == NULL) { 26931.1Scgd /* illegal structure pointer combination */ 26941.1Scgd warning(244); 26951.1Scgd } else { 26961.225Srillig /* incompatible structure pointers: '%s' '%s' '%s' */ 26971.225Srillig warning(245, type_name(ltp), mp->m_name, type_name(rtp)); 26981.1Scgd } 26991.1Scgd } else { 27001.1Scgd if (mp == NULL) { 27011.334Srillig /* illegal combination of '%s' and '%s' */ 27021.334Srillig warning(184, type_name(ltp), type_name(rtp)); 27031.1Scgd } else { 27041.334Srillig /* illegal combination of '%s' and '%s', op '%s' */ 27051.117Srillig warning(124, 27061.117Srillig type_name(ltp), type_name(rtp), mp->m_name); 27071.1Scgd } 27081.1Scgd } 27091.1Scgd} 27101.1Scgd 27111.263Srillig/* Return a type based on tp1, with added qualifiers from tp2. */ 27121.263Srilligstatic type_t * 27131.263Srilligmerge_qualifiers(type_t *tp1, const type_t *tp2) 27141.1Scgd{ 27151.263Srillig type_t *ntp, *nstp; 27161.392Srillig bool c1, c2, v1, v2; 27171.20Slukem 27181.107Srillig lint_assert(tp1->t_tspec == PTR); 27191.107Srillig lint_assert(tp2->t_tspec == PTR); 27201.1Scgd 27211.392Srillig c1 = tp1->t_subt->t_const; 27221.392Srillig c2 = tp2->t_subt->t_const; 27231.392Srillig v1 = tp1->t_subt->t_volatile; 27241.392Srillig v2 = tp2->t_subt->t_volatile; 27251.263Srillig 27261.264Srillig if (c1 == (c1 | c2) && v1 == (v1 | v2)) 27271.263Srillig return tp1; 27281.263Srillig 27291.263Srillig nstp = expr_dup_type(tp1->t_subt); 27301.264Srillig nstp->t_const |= c2; 27311.264Srillig nstp->t_volatile |= v2; 27321.263Srillig 27331.263Srillig ntp = expr_dup_type(tp1); 27341.263Srillig ntp->t_subt = nstp; 27351.263Srillig return ntp; 27361.1Scgd} 27371.1Scgd 27381.1Scgd/* 27391.185Srillig * Returns true if the given structure or union has a constant member 27401.1Scgd * (maybe recursively). 27411.1Scgd */ 27421.149Srilligstatic bool 27431.149Srillighas_constant_member(const type_t *tp) 27441.1Scgd{ 27451.321Srillig sym_t *m; 27461.1Scgd 27471.321Srillig lint_assert(is_struct_or_union(tp->t_tspec)); 27481.107Srillig 27491.208Srillig for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next) { 27501.321Srillig const type_t *mtp = m->s_type; 27511.321Srillig if (mtp->t_const) 27521.321Srillig return true; 27531.321Srillig if (is_struct_or_union(mtp->t_tspec) && 27541.321Srillig has_constant_member(mtp)) 27551.149Srillig return true; 27561.1Scgd } 27571.149Srillig return false; 27581.1Scgd} 27591.1Scgd 27601.1Scgd/* 27611.1Scgd * Create a new node for one of the operators POINT and ARROW. 27621.1Scgd */ 27631.1Scgdstatic tnode_t * 27641.395Srilligbuild_struct_access(op_t op, bool sys, tnode_t *ln, tnode_t *rn) 27651.1Scgd{ 27661.1Scgd tnode_t *ntn, *ctn; 27671.154Srillig bool nolval; 27681.1Scgd 27691.107Srillig lint_assert(rn->tn_op == NAME); 27701.107Srillig lint_assert(rn->tn_sym->s_value.v_tspec == INT); 27711.107Srillig lint_assert(rn->tn_sym->s_scl == MOS || rn->tn_sym->s_scl == MOU); 27721.1Scgd 27731.1Scgd /* 27741.1Scgd * Remember if the left operand is an lvalue (structure members 27751.1Scgd * are lvalues if and only if the structure itself is an lvalue). 27761.1Scgd */ 27771.1Scgd nolval = op == POINT && !ln->tn_lvalue; 27781.1Scgd 27791.1Scgd if (op == POINT) { 27801.395Srillig ln = build_address(sys, ln, true); 27811.1Scgd } else if (ln->tn_type->t_tspec != PTR) { 27821.107Srillig lint_assert(tflag); 27831.144Srillig lint_assert(is_integer(ln->tn_type->t_tspec)); 27841.257Srillig ln = convert(NOOP, 0, expr_derive_type(gettyp(VOID), PTR), ln); 27851.1Scgd } 27861.1Scgd 27871.318Srillig ctn = build_integer_constant(PTRDIFF_TSPEC, 27881.136Srillig rn->tn_sym->s_value.v_quad / CHAR_SIZE); 27891.1Scgd 27901.395Srillig ntn = new_tnode(PLUS, sys, expr_derive_type(rn->tn_type, PTR), 27911.395Srillig ln, ctn); 27921.1Scgd if (ln->tn_op == CON) 27931.1Scgd ntn = fold(ntn); 27941.1Scgd 27951.120Srillig if (rn->tn_type->t_bitfield) { 27961.395Srillig ntn = new_tnode(FSEL, sys, ntn->tn_type->t_subt, ntn, NULL); 27971.1Scgd } else { 27981.395Srillig ntn = new_tnode(INDIR, sys, ntn->tn_type->t_subt, ntn, NULL); 27991.1Scgd } 28001.1Scgd 28011.1Scgd if (nolval) 28021.154Srillig ntn->tn_lvalue = false; 28031.1Scgd 28041.95Srillig return ntn; 28051.1Scgd} 28061.1Scgd 28071.1Scgd/* 28081.1Scgd * Create a node for INCAFT, INCBEF, DECAFT and DECBEF. 28091.1Scgd */ 28101.1Scgdstatic tnode_t * 28111.395Srilligbuild_prepost_incdec(op_t op, bool sys, tnode_t *ln) 28121.1Scgd{ 28131.1Scgd tnode_t *cn, *ntn; 28141.1Scgd 28151.107Srillig lint_assert(ln != NULL); 28161.1Scgd 28171.1Scgd if (ln->tn_type->t_tspec == PTR) { 28181.1Scgd cn = plength(ln->tn_type); 28191.1Scgd } else { 28201.318Srillig cn = build_integer_constant(INT, (int64_t)1); 28211.1Scgd } 28221.395Srillig ntn = new_tnode(op, sys, ln->tn_type, ln, cn); 28231.1Scgd 28241.95Srillig return ntn; 28251.1Scgd} 28261.1Scgd 28271.1Scgd/* 28281.46Schristos * Create a node for REAL, IMAG 28291.46Schristos */ 28301.46Schristosstatic tnode_t * 28311.395Srilligbuild_real_imag(op_t op, bool sys, tnode_t *ln) 28321.46Schristos{ 28331.46Schristos tnode_t *cn, *ntn; 28341.46Schristos 28351.107Srillig lint_assert(ln != NULL); 28361.46Schristos 28371.275Srillig if (ln->tn_op == NAME) { 28381.275Srillig /* 28391.275Srillig * This may be too much, but it avoids wrong warnings. 28401.275Srillig * See d_c99_complex_split.c. 28411.275Srillig */ 28421.275Srillig mark_as_used(ln->tn_sym, false, false); 28431.275Srillig mark_as_set(ln->tn_sym); 28441.275Srillig } 28451.275Srillig 28461.46Schristos switch (ln->tn_type->t_tspec) { 28471.52Smatt case LCOMPLEX: 28481.182Srillig /* XXX: integer and LDOUBLE don't match. */ 28491.318Srillig cn = build_integer_constant(LDOUBLE, (int64_t)1); 28501.52Smatt break; 28511.46Schristos case DCOMPLEX: 28521.257Srillig /* XXX: integer and DOUBLE don't match. */ 28531.318Srillig cn = build_integer_constant(DOUBLE, (int64_t)1); 28541.46Schristos break; 28551.46Schristos case FCOMPLEX: 28561.257Srillig /* XXX: integer and FLOAT don't match. */ 28571.318Srillig cn = build_integer_constant(FLOAT, (int64_t)1); 28581.46Schristos break; 28591.46Schristos default: 28601.113Srillig /* __%s__ is illegal for type %s */ 28611.47Schristos error(276, op == REAL ? "real" : "imag", 28621.115Srillig type_name(ln->tn_type)); 28631.46Schristos return NULL; 28641.46Schristos } 28651.395Srillig ntn = new_tnode(op, sys, cn->tn_type, ln, cn); 28661.154Srillig ntn->tn_lvalue = true; 28671.46Schristos 28681.95Srillig return ntn; 28691.46Schristos} 28701.342Srillig 28711.46Schristos/* 28721.182Srillig * Create a tree node for the unary & operator 28731.1Scgd */ 28741.1Scgdstatic tnode_t * 28751.395Srilligbuild_address(bool sys, tnode_t *tn, bool noign) 28761.1Scgd{ 28771.1Scgd tspec_t t; 28781.20Slukem 28791.1Scgd if (!noign && ((t = tn->tn_type->t_tspec) == ARRAY || t == FUNC)) { 28801.1Scgd if (tflag) 28811.113Srillig /* '&' before array or function: ignored */ 28821.1Scgd warning(127); 28831.95Srillig return tn; 28841.1Scgd } 28851.1Scgd 28861.1Scgd /* eliminate &* */ 28871.170Srillig if (tn->tn_op == INDIR && 28881.1Scgd tn->tn_left->tn_type->t_tspec == PTR && 28891.1Scgd tn->tn_left->tn_type->t_subt == tn->tn_type) { 28901.95Srillig return tn->tn_left; 28911.1Scgd } 28921.20Slukem 28931.395Srillig return new_tnode(ADDR, sys, expr_derive_type(tn->tn_type, PTR), 28941.395Srillig tn, NULL); 28951.1Scgd} 28961.1Scgd 28971.1Scgd/* 28981.1Scgd * Create a node for operators PLUS and MINUS. 28991.1Scgd */ 29001.1Scgdstatic tnode_t * 29011.395Srilligbuild_plus_minus(op_t op, bool sys, tnode_t *ln, tnode_t *rn) 29021.1Scgd{ 29031.1Scgd tnode_t *ntn, *ctn; 29041.1Scgd type_t *tp; 29051.1Scgd 29061.1Scgd /* If pointer and integer, then pointer to the lhs. */ 29071.144Srillig if (rn->tn_type->t_tspec == PTR && is_integer(ln->tn_type->t_tspec)) { 29081.1Scgd ntn = ln; 29091.1Scgd ln = rn; 29101.1Scgd rn = ntn; 29111.1Scgd } 29121.1Scgd 29131.1Scgd if (ln->tn_type->t_tspec == PTR && rn->tn_type->t_tspec != PTR) { 29141.144Srillig lint_assert(is_integer(rn->tn_type->t_tspec)); 29151.1Scgd 29161.266Srillig check_ctype_macro_invocation(ln, rn); 29171.386Srillig check_enum_array_index(ln, rn); 29181.266Srillig 29191.1Scgd ctn = plength(ln->tn_type); 29201.1Scgd if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) 29211.1Scgd rn = convert(NOOP, 0, ctn->tn_type, rn); 29221.395Srillig rn = new_tnode(MULT, sys, rn->tn_type, rn, ctn); 29231.1Scgd if (rn->tn_left->tn_op == CON) 29241.1Scgd rn = fold(rn); 29251.395Srillig ntn = new_tnode(op, sys, ln->tn_type, ln, rn); 29261.1Scgd 29271.1Scgd } else if (rn->tn_type->t_tspec == PTR) { 29281.1Scgd 29291.107Srillig lint_assert(ln->tn_type->t_tspec == PTR); 29301.107Srillig lint_assert(op == MINUS); 29311.191Srillig tp = gettyp(PTRDIFF_TSPEC); 29321.395Srillig ntn = new_tnode(op, sys, tp, ln, rn); 29331.1Scgd if (ln->tn_op == CON && rn->tn_op == CON) 29341.1Scgd ntn = fold(ntn); 29351.1Scgd ctn = plength(ln->tn_type); 29361.1Scgd balance(NOOP, &ntn, &ctn); 29371.395Srillig ntn = new_tnode(DIV, sys, tp, ntn, ctn); 29381.1Scgd 29391.1Scgd } else { 29401.1Scgd 29411.395Srillig ntn = new_tnode(op, sys, ln->tn_type, ln, rn); 29421.1Scgd 29431.1Scgd } 29441.95Srillig return ntn; 29451.1Scgd} 29461.1Scgd 29471.1Scgd/* 29481.1Scgd * Create a node for operators SHL and SHR. 29491.1Scgd */ 29501.1Scgdstatic tnode_t * 29511.395Srilligbuild_bit_shift(op_t op, bool sys, tnode_t *ln, tnode_t *rn) 29521.1Scgd{ 29531.1Scgd tspec_t t; 29541.1Scgd tnode_t *ntn; 29551.1Scgd 29561.1Scgd if ((t = rn->tn_type->t_tspec) != INT && t != UINT) 29571.1Scgd rn = convert(CVT, 0, gettyp(INT), rn); 29581.395Srillig ntn = new_tnode(op, sys, ln->tn_type, ln, rn); 29591.95Srillig return ntn; 29601.1Scgd} 29611.1Scgd 29621.1Scgd/* 29631.1Scgd * Create a node for COLON. 29641.1Scgd */ 29651.1Scgdstatic tnode_t * 29661.395Srilligbuild_colon(bool sys, tnode_t *ln, tnode_t *rn) 29671.1Scgd{ 29681.1Scgd tspec_t lt, rt, pdt; 29691.262Srillig type_t *tp; 29701.1Scgd tnode_t *ntn; 29711.1Scgd 29721.1Scgd lt = ln->tn_type->t_tspec; 29731.1Scgd rt = rn->tn_type->t_tspec; 29741.191Srillig pdt = PTRDIFF_TSPEC; 29751.1Scgd 29761.1Scgd /* 29771.1Scgd * Arithmetic types are balanced, all other type combinations 29781.1Scgd * still need to be handled. 29791.1Scgd */ 29801.144Srillig if (is_arithmetic(lt) && is_arithmetic(rt)) { 29811.262Srillig tp = ln->tn_type; 29821.165Srillig } else if (lt == BOOL && rt == BOOL) { 29831.262Srillig tp = ln->tn_type; 29841.1Scgd } else if (lt == VOID || rt == VOID) { 29851.262Srillig tp = gettyp(VOID); 29861.1Scgd } else if (lt == STRUCT || lt == UNION) { 29871.1Scgd /* Both types must be identical. */ 29881.107Srillig lint_assert(rt == STRUCT || rt == UNION); 29891.107Srillig lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); 29901.194Srillig if (is_incomplete(ln->tn_type)) { 29911.1Scgd /* unknown operand size, op %s */ 29921.261Srillig error(138, op_name(COLON)); 29931.95Srillig return NULL; 29941.1Scgd } 29951.262Srillig tp = ln->tn_type; 29961.144Srillig } else if (lt == PTR && is_integer(rt)) { 29971.1Scgd if (rt != pdt) { 29981.1Scgd rn = convert(NOOP, 0, gettyp(pdt), rn); 29991.1Scgd rt = pdt; 30001.1Scgd } 30011.262Srillig tp = ln->tn_type; 30021.144Srillig } else if (rt == PTR && is_integer(lt)) { 30031.1Scgd if (lt != pdt) { 30041.1Scgd ln = convert(NOOP, 0, gettyp(pdt), ln); 30051.1Scgd lt = pdt; 30061.1Scgd } 30071.262Srillig tp = rn->tn_type; 30081.1Scgd } else if (lt == PTR && ln->tn_type->t_subt->t_tspec == VOID) { 30091.263Srillig tp = merge_qualifiers(rn->tn_type, ln->tn_type); 30101.1Scgd } else if (rt == PTR && rn->tn_type->t_subt->t_tspec == VOID) { 30111.263Srillig tp = merge_qualifiers(ln->tn_type, rn->tn_type); 30121.1Scgd } else { 30131.1Scgd /* 30141.1Scgd * XXX For now we simply take the left type. This is 30151.106Srillig * probably wrong, if one type contains a function prototype 30161.1Scgd * and the other one, at the same place, only an old style 30171.1Scgd * declaration. 30181.1Scgd */ 30191.263Srillig tp = merge_qualifiers(ln->tn_type, rn->tn_type); 30201.1Scgd } 30211.1Scgd 30221.395Srillig ntn = new_tnode(COLON, sys, tp, ln, rn); 30231.1Scgd 30241.95Srillig return ntn; 30251.1Scgd} 30261.1Scgd 30271.1Scgd/* 30281.1Scgd * Create a node for an assignment operator (both = and op= ). 30291.1Scgd */ 30301.1Scgdstatic tnode_t * 30311.395Srilligbuild_assignment(op_t op, bool sys, tnode_t *ln, tnode_t *rn) 30321.1Scgd{ 30331.1Scgd tspec_t lt, rt; 30341.1Scgd tnode_t *ntn, *ctn; 30351.1Scgd 30361.107Srillig lint_assert(ln != NULL); 30371.107Srillig lint_assert(rn != NULL); 30381.1Scgd 30391.1Scgd lt = ln->tn_type->t_tspec; 30401.1Scgd rt = rn->tn_type->t_tspec; 30411.1Scgd 30421.1Scgd if ((op == ADDASS || op == SUBASS) && lt == PTR) { 30431.144Srillig lint_assert(is_integer(rt)); 30441.1Scgd ctn = plength(ln->tn_type); 30451.1Scgd if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) 30461.1Scgd rn = convert(NOOP, 0, ctn->tn_type, rn); 30471.395Srillig rn = new_tnode(MULT, sys, rn->tn_type, rn, ctn); 30481.1Scgd if (rn->tn_left->tn_op == CON) 30491.1Scgd rn = fold(rn); 30501.1Scgd } 30511.1Scgd 30521.333Srillig if ((op == ASSIGN || op == RETURN || op == INIT) && 30531.333Srillig (lt == STRUCT || rt == STRUCT)) { 30541.107Srillig lint_assert(lt == rt); 30551.107Srillig lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); 30561.194Srillig if (is_incomplete(ln->tn_type)) { 30571.1Scgd if (op == RETURN) { 30581.1Scgd /* cannot return incomplete type */ 30591.1Scgd error(212); 30601.1Scgd } else { 30611.1Scgd /* unknown operand size, op %s */ 30621.260Srillig error(138, op_name(op)); 30631.1Scgd } 30641.95Srillig return NULL; 30651.1Scgd } 30661.1Scgd } 30671.1Scgd 30681.40Schristos if (op == SHLASS) { 30691.228Srillig if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { 30701.40Schristos if (hflag) 30711.108Srillig /* semantics of '%s' change in ANSI C; ... */ 30721.40Schristos warning(118, "<<="); 30731.1Scgd } 30741.40Schristos } else if (op != SHRASS) { 30751.1Scgd if (op == ASSIGN || lt != PTR) { 30761.1Scgd if (lt != rt || 30771.120Srillig (ln->tn_type->t_bitfield && rn->tn_op == CON)) { 30781.1Scgd rn = convert(op, 0, ln->tn_type, rn); 30791.1Scgd rt = lt; 30801.1Scgd } 30811.1Scgd } 30821.1Scgd } 30831.1Scgd 30841.395Srillig ntn = new_tnode(op, sys, ln->tn_type, ln, rn); 30851.1Scgd 30861.95Srillig return ntn; 30871.1Scgd} 30881.1Scgd 30891.1Scgd/* 30901.352Srillig * Get length of type tp->t_subt, as a constant expression of type ptrdiff_t 30911.352Srillig * as seen from the target platform. 30921.1Scgd */ 30931.1Scgdstatic tnode_t * 30941.20Slukemplength(type_t *tp) 30951.1Scgd{ 30961.352Srillig int elem, elsz_in_bits; 30971.1Scgd 30981.107Srillig lint_assert(tp->t_tspec == PTR); 30991.1Scgd tp = tp->t_subt; 31001.1Scgd 31011.1Scgd elem = 1; 31021.352Srillig elsz_in_bits = 0; 31031.1Scgd 31041.1Scgd while (tp->t_tspec == ARRAY) { 31051.1Scgd elem *= tp->t_dim; 31061.1Scgd tp = tp->t_subt; 31071.1Scgd } 31081.1Scgd 31091.1Scgd switch (tp->t_tspec) { 31101.1Scgd case FUNC: 31111.1Scgd /* pointer to function is not allowed here */ 31121.1Scgd error(110); 31131.1Scgd break; 31141.1Scgd case VOID: 31151.177Srillig /* cannot do pointer arithmetic on operand of unknown size */ 31161.118Srillig gnuism(136); 31171.1Scgd break; 31181.1Scgd case STRUCT: 31191.1Scgd case UNION: 31201.352Srillig if ((elsz_in_bits = tp->t_str->sou_size_in_bits) == 0) 31211.1Scgd /* cannot do pointer arithmetic on operand of ... */ 31221.1Scgd error(136); 31231.1Scgd break; 31241.1Scgd case ENUM: 31251.194Srillig if (is_incomplete(tp)) { 31261.1Scgd /* cannot do pointer arithmetic on operand of ... */ 31271.1Scgd warning(136); 31281.1Scgd } 31291.1Scgd /* FALLTHROUGH */ 31301.1Scgd default: 31311.352Srillig if ((elsz_in_bits = size_in_bits(tp->t_tspec)) == 0) { 31321.1Scgd /* cannot do pointer arithmetic on operand of ... */ 31331.1Scgd error(136); 31341.107Srillig } else { 31351.352Srillig lint_assert(elsz_in_bits != -1); 31361.1Scgd } 31371.1Scgd break; 31381.1Scgd } 31391.1Scgd 31401.352Srillig if (elem == 0 && elsz_in_bits != 0) { 31411.177Srillig /* cannot do pointer arithmetic on operand of unknown size */ 31421.1Scgd error(136); 31431.1Scgd } 31441.1Scgd 31451.352Srillig if (elsz_in_bits == 0) 31461.352Srillig elsz_in_bits = CHAR_SIZE; 31471.1Scgd 31481.318Srillig return build_integer_constant(PTRDIFF_TSPEC, 31491.352Srillig (int64_t)(elem * elsz_in_bits / CHAR_SIZE)); 31501.1Scgd} 31511.1Scgd 31521.1Scgd/* 31531.22Sperry * XXX 31541.22Sperry * Note: There appear to be a number of bugs in detecting overflow in 31551.22Sperry * this function. An audit and a set of proper regression tests are needed. 31561.22Sperry * --Perry Metzger, Nov. 16, 2001 31571.22Sperry */ 31581.22Sperry/* 31591.1Scgd * Do only as much as necessary to compute constant expressions. 31601.182Srillig * Called only if the operator allows folding and all operands are constants. 31611.1Scgd */ 31621.1Scgdstatic tnode_t * 31631.20Slukemfold(tnode_t *tn) 31641.1Scgd{ 31651.339Srillig val_t *v; 31661.339Srillig tspec_t t; 31671.339Srillig bool utyp, ovfl; 31681.339Srillig int64_t sl, sr = 0, q = 0, mask; 31691.25Sthorpej uint64_t ul, ur = 0; 31701.339Srillig tnode_t *cn; 31711.1Scgd 31721.259Srillig v = xcalloc(1, sizeof(*v)); 31731.345Srillig v->v_tspec = tn->tn_type->t_tspec; 31741.1Scgd 31751.345Srillig t = tn->tn_left->tn_type->t_tspec; 31761.345Srillig utyp = !is_integer(t) || is_uinteger(t); 31771.1Scgd ul = sl = tn->tn_left->tn_val->v_quad; 31781.346Srillig if (is_binary(tn)) 31791.1Scgd ur = sr = tn->tn_right->tn_val->v_quad; 31801.1Scgd 31811.287Srillig mask = value_bits(size_in_bits(t)); 31821.154Srillig ovfl = false; 31831.1Scgd 31841.1Scgd switch (tn->tn_op) { 31851.1Scgd case UPLUS: 31861.1Scgd q = sl; 31871.1Scgd break; 31881.1Scgd case UMINUS: 31891.1Scgd q = -sl; 31901.348Srillig if (sl != 0 && msb(q, t) == msb(sl, t)) 31911.154Srillig ovfl = true; 31921.1Scgd break; 31931.1Scgd case COMPL: 31941.1Scgd q = ~sl; 31951.1Scgd break; 31961.1Scgd case MULT: 31971.22Sperry if (utyp) { 31981.22Sperry q = ul * ur; 31991.22Sperry if (q != (q & mask)) 32001.154Srillig ovfl = true; 32011.22Sperry else if ((ul != 0) && ((q / ul) != ur)) 32021.154Srillig ovfl = true; 32031.22Sperry } else { 32041.22Sperry q = sl * sr; 32051.348Srillig if (msb(q, t) != (msb(sl, t) ^ msb(sr, t))) 32061.154Srillig ovfl = true; 32071.22Sperry } 32081.1Scgd break; 32091.1Scgd case DIV: 32101.1Scgd if (sr == 0) { 32111.1Scgd /* division by 0 */ 32121.1Scgd error(139); 32131.378Srillig q = utyp ? -1 : INT64_MAX; 32141.1Scgd } else { 32151.57Schristos q = utyp ? (int64_t)(ul / ur) : sl / sr; 32161.1Scgd } 32171.1Scgd break; 32181.1Scgd case MOD: 32191.1Scgd if (sr == 0) { 32201.1Scgd /* modulus by 0 */ 32211.1Scgd error(140); 32221.1Scgd q = 0; 32231.1Scgd } else { 32241.57Schristos q = utyp ? (int64_t)(ul % ur) : sl % sr; 32251.1Scgd } 32261.1Scgd break; 32271.1Scgd case PLUS: 32281.57Schristos q = utyp ? (int64_t)(ul + ur) : sl + sr; 32291.349Srillig if (msb(sl, t) && msb(sr, t) && !msb(q, t)) 32301.349Srillig ovfl = true; 32311.349Srillig if (!utyp && !msb(sl, t) && !msb(sr, t) && msb(q, t)) 32321.349Srillig ovfl = true; 32331.1Scgd break; 32341.1Scgd case MINUS: 32351.57Schristos q = utyp ? (int64_t)(ul - ur) : sl - sr; 32361.348Srillig if (!utyp && msb(sl, t) && !msb(sr, t) && !msb(q, t)) 32371.347Srillig ovfl = true; 32381.348Srillig if (!msb(sl, t) && msb(sr, t) && msb(q, t)) 32391.347Srillig ovfl = true; 32401.1Scgd break; 32411.1Scgd case SHL: 32421.57Schristos q = utyp ? (int64_t)(ul << sr) : sl << sr; 32431.1Scgd break; 32441.1Scgd case SHR: 32451.1Scgd /* 32461.22Sperry * The sign must be explicitly extended because 32471.1Scgd * shifts of signed values are implementation dependent. 32481.1Scgd */ 32491.1Scgd q = ul >> sr; 32501.298Srillig q = convert_integer(q, t, size_in_bits(t) - (int)sr); 32511.1Scgd break; 32521.1Scgd case LT: 32531.154Srillig q = (utyp ? ul < ur : sl < sr) ? 1 : 0; 32541.1Scgd break; 32551.1Scgd case LE: 32561.154Srillig q = (utyp ? ul <= ur : sl <= sr) ? 1 : 0; 32571.1Scgd break; 32581.1Scgd case GE: 32591.154Srillig q = (utyp ? ul >= ur : sl >= sr) ? 1 : 0; 32601.1Scgd break; 32611.1Scgd case GT: 32621.154Srillig q = (utyp ? ul > ur : sl > sr) ? 1 : 0; 32631.1Scgd break; 32641.1Scgd case EQ: 32651.154Srillig q = (utyp ? ul == ur : sl == sr) ? 1 : 0; 32661.1Scgd break; 32671.1Scgd case NE: 32681.154Srillig q = (utyp ? ul != ur : sl != sr) ? 1 : 0; 32691.1Scgd break; 32701.171Srillig case BITAND: 32711.57Schristos q = utyp ? (int64_t)(ul & ur) : sl & sr; 32721.1Scgd break; 32731.171Srillig case BITXOR: 32741.57Schristos q = utyp ? (int64_t)(ul ^ ur) : sl ^ sr; 32751.1Scgd break; 32761.171Srillig case BITOR: 32771.57Schristos q = utyp ? (int64_t)(ul | ur) : sl | sr; 32781.1Scgd break; 32791.1Scgd default: 32801.157Srillig lint_assert(/*CONSTCOND*/false); 32811.1Scgd } 32821.1Scgd 32831.1Scgd /* XXX does not work for quads. */ 32841.339Srillig if (ovfl || 32851.339Srillig ((uint64_t)(q | mask) != ~(uint64_t)0 && (q & ~mask) != 0)) { 32861.1Scgd if (hflag) 32871.350Srillig /* integer overflow detected, op '%s' */ 32881.261Srillig warning(141, op_name(tn->tn_op)); 32891.1Scgd } 32901.1Scgd 32911.356Srillig v->v_quad = convert_integer(q, t, 0); 32921.1Scgd 32931.318Srillig cn = build_constant(tn->tn_type, v); 32941.227Srillig if (tn->tn_left->tn_system_dependent) 32951.227Srillig cn->tn_system_dependent = true; 32961.346Srillig if (is_binary(tn) && tn->tn_right->tn_system_dependent) 32971.227Srillig cn->tn_system_dependent = true; 32981.1Scgd 32991.95Srillig return cn; 33001.1Scgd} 33011.1Scgd 33021.1Scgd/* 33031.182Srillig * Fold constant nodes, as much as is needed for comparing the value with 0 33041.182Srillig * (test context, for controlling expressions). 33051.1Scgd */ 33061.1Scgdstatic tnode_t * 33071.100Srilligfold_test(tnode_t *tn) 33081.1Scgd{ 33091.153Srillig bool l, r; 33101.1Scgd val_t *v; 33111.1Scgd 33121.259Srillig v = xcalloc(1, sizeof(*v)); 33131.1Scgd v->v_tspec = tn->tn_type->t_tspec; 33141.151Srillig lint_assert(v->v_tspec == INT || (Tflag && v->v_tspec == BOOL)); 33151.1Scgd 33161.229Srillig l = constant_is_nonzero(tn->tn_left); 33171.346Srillig r = is_binary(tn) && constant_is_nonzero(tn->tn_right); 33181.1Scgd 33191.1Scgd switch (tn->tn_op) { 33201.1Scgd case NOT: 33211.98Srillig if (hflag && !constcond_flag) 33221.265Srillig /* constant argument to '!' */ 33231.1Scgd warning(239); 33241.154Srillig v->v_quad = !l ? 1 : 0; 33251.1Scgd break; 33261.1Scgd case LOGAND: 33271.154Srillig v->v_quad = l && r ? 1 : 0; 33281.1Scgd break; 33291.1Scgd case LOGOR: 33301.154Srillig v->v_quad = l || r ? 1 : 0; 33311.1Scgd break; 33321.1Scgd default: 33331.157Srillig lint_assert(/*CONSTCOND*/false); 33341.1Scgd } 33351.1Scgd 33361.318Srillig return build_constant(tn->tn_type, v); 33371.1Scgd} 33381.1Scgd 33391.378Srilligstatic ldbl_t 33401.378Srilligfloating_error_value(tspec_t t, ldbl_t lv) 33411.378Srillig{ 33421.378Srillig if (t == FLOAT) { 33431.378Srillig return lv < 0 ? -FLT_MAX : FLT_MAX; 33441.378Srillig } else if (t == DOUBLE) { 33451.378Srillig return lv < 0 ? -DBL_MAX : DBL_MAX; 33461.378Srillig } else { 33471.378Srillig /* LINTED 248: floating-point constant out of range */ 33481.378Srillig ldbl_t max = LDBL_MAX; 33491.378Srillig return lv < 0 ? -max : max; 33501.378Srillig } 33511.378Srillig} 33521.378Srillig 33531.1Scgd/* 33541.182Srillig * Fold constant nodes having operands with floating point type. 33551.1Scgd */ 33561.1Scgdstatic tnode_t * 33571.100Srilligfold_float(tnode_t *tn) 33581.1Scgd{ 33591.1Scgd val_t *v; 33601.1Scgd tspec_t t; 33611.343Srillig ldbl_t lv, rv = 0; 33621.1Scgd 33631.157Srillig fpe = 0; 33641.259Srillig v = xcalloc(1, sizeof(*v)); 33651.1Scgd v->v_tspec = t = tn->tn_type->t_tspec; 33661.1Scgd 33671.144Srillig lint_assert(is_floating(t)); 33681.107Srillig lint_assert(t == tn->tn_left->tn_type->t_tspec); 33691.346Srillig lint_assert(!is_binary(tn) || t == tn->tn_right->tn_type->t_tspec); 33701.1Scgd 33711.343Srillig lv = tn->tn_left->tn_val->v_ldbl; 33721.346Srillig if (is_binary(tn)) 33731.343Srillig rv = tn->tn_right->tn_val->v_ldbl; 33741.1Scgd 33751.1Scgd switch (tn->tn_op) { 33761.1Scgd case UPLUS: 33771.343Srillig v->v_ldbl = lv; 33781.1Scgd break; 33791.1Scgd case UMINUS: 33801.343Srillig v->v_ldbl = -lv; 33811.1Scgd break; 33821.1Scgd case MULT: 33831.343Srillig v->v_ldbl = lv * rv; 33841.1Scgd break; 33851.1Scgd case DIV: 33861.343Srillig if (rv == 0.0) { 33871.1Scgd /* division by 0 */ 33881.1Scgd error(139); 33891.378Srillig v->v_ldbl = floating_error_value(t, lv); 33901.1Scgd } else { 33911.343Srillig v->v_ldbl = lv / rv; 33921.1Scgd } 33931.1Scgd break; 33941.1Scgd case PLUS: 33951.343Srillig v->v_ldbl = lv + rv; 33961.1Scgd break; 33971.1Scgd case MINUS: 33981.343Srillig v->v_ldbl = lv - rv; 33991.1Scgd break; 34001.1Scgd case LT: 34011.343Srillig v->v_quad = lv < rv ? 1 : 0; 34021.1Scgd break; 34031.1Scgd case LE: 34041.343Srillig v->v_quad = lv <= rv ? 1 : 0; 34051.1Scgd break; 34061.1Scgd case GE: 34071.343Srillig v->v_quad = lv >= rv ? 1 : 0; 34081.1Scgd break; 34091.1Scgd case GT: 34101.343Srillig v->v_quad = lv > rv ? 1 : 0; 34111.1Scgd break; 34121.1Scgd case EQ: 34131.343Srillig v->v_quad = lv == rv ? 1 : 0; 34141.1Scgd break; 34151.1Scgd case NE: 34161.343Srillig v->v_quad = lv != rv ? 1 : 0; 34171.1Scgd break; 34181.1Scgd default: 34191.157Srillig lint_assert(/*CONSTCOND*/false); 34201.1Scgd } 34211.1Scgd 34221.172Srillig lint_assert(fpe != 0 || isnan((double)v->v_ldbl) == 0); 34231.382Sjmcneill if (fpe != 0 || isfinite((double)v->v_ldbl) == 0 || 34241.1Scgd (t == FLOAT && 34251.1Scgd (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || 34261.1Scgd (t == DOUBLE && 34271.1Scgd (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { 34281.1Scgd /* floating point overflow detected, op %s */ 34291.261Srillig warning(142, op_name(tn->tn_op)); 34301.378Srillig v->v_ldbl = floating_error_value(t, v->v_ldbl); 34311.342Srillig fpe = 0; 34321.1Scgd } 34331.1Scgd 34341.318Srillig return build_constant(tn->tn_type, v); 34351.1Scgd} 34361.1Scgd 34371.62Schristos 34381.1Scgd/* 34391.1Scgd * Create a constant node for sizeof. 34401.1Scgd */ 34411.1Scgdtnode_t * 34421.253Srilligbuild_sizeof(const type_t *tp) 34431.1Scgd{ 34441.355Srillig unsigned int size_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; 34451.318Srillig tnode_t *tn = build_integer_constant(SIZEOF_TSPEC, size_in_bytes); 34461.227Srillig tn->tn_system_dependent = true; 34471.227Srillig return tn; 34481.62Schristos} 34491.62Schristos 34501.84Schristos/* 34511.84Schristos * Create a constant node for offsetof. 34521.84Schristos */ 34531.378Srillig/* ARGSUSED */ /* See implementation comments. */ 34541.84Schristostnode_t * 34551.253Srilligbuild_offsetof(const type_t *tp, const sym_t *sym) 34561.84Schristos{ 34571.392Srillig unsigned int offset_in_bytes; 34581.392Srillig tnode_t *tn; 34591.392Srillig 34601.392Srillig if (!is_struct_or_union(tp->t_tspec)) 34611.113Srillig /* unacceptable operand of '%s' */ 34621.84Schristos error(111, "offsetof"); 34631.89Srillig 34641.393Srillig /* XXX: wrong size, no checking for sym fixme */ 34651.392Srillig offset_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; 34661.392Srillig tn = build_integer_constant(SIZEOF_TSPEC, offset_in_bytes); 34671.227Srillig tn->tn_system_dependent = true; 34681.227Srillig return tn; 34691.84Schristos} 34701.84Schristos 34711.355Srilligunsigned int 34721.253Srilligtype_size_in_bits(const type_t *tp) 34731.62Schristos{ 34741.355Srillig unsigned int elem, elsz; 34751.154Srillig bool flex; 34761.1Scgd 34771.1Scgd elem = 1; 34781.154Srillig flex = false; 34791.1Scgd while (tp->t_tspec == ARRAY) { 34801.154Srillig flex = true; /* allow c99 flex arrays [] [0] */ 34811.1Scgd elem *= tp->t_dim; 34821.1Scgd tp = tp->t_subt; 34831.1Scgd } 34841.1Scgd if (elem == 0) { 34851.77Schristos if (!flex) { 34861.108Srillig /* cannot take size/alignment of incomplete type */ 34871.77Schristos error(143); 34881.77Schristos elem = 1; 34891.77Schristos } 34901.1Scgd } 34911.1Scgd switch (tp->t_tspec) { 34921.1Scgd case FUNC: 34931.108Srillig /* cannot take size/alignment of function */ 34941.1Scgd error(144); 34951.1Scgd elsz = 1; 34961.1Scgd break; 34971.1Scgd case STRUCT: 34981.1Scgd case UNION: 34991.194Srillig if (is_incomplete(tp)) { 35001.108Srillig /* cannot take size/alignment of incomplete type */ 35011.1Scgd error(143); 35021.1Scgd elsz = 1; 35031.1Scgd } else { 35041.237Srillig elsz = tp->t_str->sou_size_in_bits; 35051.1Scgd } 35061.1Scgd break; 35071.1Scgd case ENUM: 35081.194Srillig if (is_incomplete(tp)) { 35091.108Srillig /* cannot take size/alignment of incomplete type */ 35101.1Scgd warning(143); 35111.1Scgd } 35121.1Scgd /* FALLTHROUGH */ 35131.1Scgd default: 35141.120Srillig if (tp->t_bitfield) { 35151.108Srillig /* cannot take size/alignment of bit-field */ 35161.1Scgd error(145); 35171.1Scgd } 35181.1Scgd if (tp->t_tspec == VOID) { 35191.108Srillig /* cannot take size/alignment of void */ 35201.1Scgd error(146); 35211.1Scgd elsz = 1; 35221.1Scgd } else { 35231.228Srillig elsz = size_in_bits(tp->t_tspec); 35241.107Srillig lint_assert(elsz > 0); 35251.1Scgd } 35261.1Scgd break; 35271.1Scgd } 35281.1Scgd 35291.355Srillig return elem * elsz; 35301.1Scgd} 35311.1Scgd 35321.59Schristostnode_t * 35331.253Srilligbuild_alignof(const type_t *tp) 35341.59Schristos{ 35351.59Schristos switch (tp->t_tspec) { 35361.59Schristos case ARRAY: 35371.59Schristos break; 35381.59Schristos 35391.59Schristos case FUNC: 35401.108Srillig /* cannot take size/alignment of function */ 35411.59Schristos error(144); 35421.59Schristos return 0; 35431.59Schristos 35441.59Schristos case STRUCT: 35451.59Schristos case UNION: 35461.194Srillig if (is_incomplete(tp)) { 35471.108Srillig /* cannot take size/alignment of incomplete type */ 35481.59Schristos error(143); 35491.59Schristos return 0; 35501.59Schristos } 35511.59Schristos break; 35521.59Schristos case ENUM: 35531.59Schristos break; 35541.59Schristos default: 35551.120Srillig if (tp->t_bitfield) { 35561.108Srillig /* cannot take size/alignment of bit-field */ 35571.59Schristos error(145); 35581.59Schristos return 0; 35591.59Schristos } 35601.59Schristos if (tp->t_tspec == VOID) { 35611.108Srillig /* cannot take size/alignment of void */ 35621.59Schristos error(146); 35631.59Schristos return 0; 35641.59Schristos } 35651.59Schristos break; 35661.59Schristos } 35671.59Schristos 35681.318Srillig return build_integer_constant(SIZEOF_TSPEC, 35691.220Srillig (int64_t)alignment_in_bits(tp) / CHAR_SIZE); 35701.59Schristos} 35711.59Schristos 35721.59Schristos/* 35731.1Scgd * Type casts. 35741.1Scgd */ 35751.1Scgdtnode_t * 35761.20Slukemcast(tnode_t *tn, type_t *tp) 35771.1Scgd{ 35781.1Scgd tspec_t nt, ot; 35791.1Scgd 35801.1Scgd if (tn == NULL) 35811.95Srillig return NULL; 35821.1Scgd 35831.232Srillig /* 35841.232Srillig * XXX: checking for tp == NULL is only a quick fix for PR 22119. 35851.232Srillig * The proper fix needs to be investigated properly. 35861.232Srillig * See d_pr_22119.c for how to get here. 35871.232Srillig */ 35881.232Srillig if (tp == NULL) 35891.232Srillig return NULL; 35901.232Srillig 35911.1Scgd tn = cconv(tn); 35921.1Scgd 35931.1Scgd nt = tp->t_tspec; 35941.1Scgd ot = tn->tn_type->t_tspec; 35951.1Scgd 35961.1Scgd if (nt == VOID) { 35971.1Scgd /* 35981.106Srillig * XXX ANSI C requires scalar types or void (Plauger & Brodie). 35991.182Srillig * But this seems really questionable. 36001.1Scgd */ 36011.83Schristos } else if (nt == UNION) { 36021.83Schristos sym_t *m; 36031.208Srillig struct_or_union *str = tp->t_str; 36041.329Srillig if (!gflag) { 36051.329Srillig /* union cast is a GCC extension */ 36061.83Schristos error(328); 36071.83Schristos return NULL; 36081.83Schristos } 36091.208Srillig for (m = str->sou_first_member; m != NULL; m = m->s_next) { 36101.330Srillig if (eqtype(m->s_type, tn->tn_type, 36111.330Srillig false, false, NULL)) { 36121.256Srillig tn = expr_zalloc_tnode(); 36131.83Schristos tn->tn_op = CVT; 36141.83Schristos tn->tn_type = tp; 36151.154Srillig tn->tn_cast = true; 36161.83Schristos tn->tn_right = NULL; 36171.83Schristos return tn; 36181.83Schristos } 36191.83Schristos } 36201.113Srillig /* type '%s' is not a member of '%s' */ 36211.115Srillig error(329, type_name(tn->tn_type), type_name(tp)); 36221.83Schristos return NULL; 36231.83Schristos } else if (nt == STRUCT || nt == ARRAY || nt == FUNC) { 36241.328Srillig /* Casting to a struct is an undocumented GCC extension. */ 36251.328Srillig if (!(gflag && nt == STRUCT)) 36261.319Srillig goto invalid_cast; 36271.1Scgd } else if (ot == STRUCT || ot == UNION) { 36281.319Srillig goto invalid_cast; 36291.1Scgd } else if (ot == VOID) { 36301.1Scgd /* improper cast of void expression */ 36311.1Scgd error(148); 36321.95Srillig return NULL; 36331.144Srillig } else if (is_integer(nt) && is_scalar(ot)) { 36341.1Scgd /* ok */ 36351.144Srillig } else if (is_floating(nt) && is_arithmetic(ot)) { 36361.1Scgd /* ok */ 36371.144Srillig } else if (nt == PTR && is_integer(ot)) { 36381.1Scgd /* ok */ 36391.1Scgd } else if (nt == PTR && ot == PTR) { 36401.7Sjpo if (!tp->t_subt->t_const && tn->tn_type->t_subt->t_const) { 36411.7Sjpo if (hflag) 36421.196Srillig /* cast discards 'const' from type '%s' */ 36431.196Srillig warning(275, type_name(tn->tn_type)); 36441.7Sjpo } 36451.319Srillig } else 36461.319Srillig goto invalid_cast; 36471.1Scgd 36481.1Scgd tn = convert(CVT, 0, tp, tn); 36491.154Srillig tn->tn_cast = true; 36501.1Scgd 36511.95Srillig return tn; 36521.319Srillig 36531.319Srilliginvalid_cast: 36541.319Srillig /* invalid cast from '%s' to '%s' */ 36551.319Srillig error(147, type_name(tn->tn_type), type_name(tp)); 36561.319Srillig return NULL; 36571.1Scgd} 36581.1Scgd 36591.1Scgd/* 36601.1Scgd * Create the node for a function argument. 36611.122Srillig * All necessary conversions and type checks are done in 36621.318Srillig * build_function_call because build_function_argument has no 36631.122Srillig * information about expected argument types. 36641.1Scgd */ 36651.1Scgdtnode_t * 36661.318Srilligbuild_function_argument(tnode_t *args, tnode_t *arg) 36671.1Scgd{ 36681.1Scgd tnode_t *ntn; 36691.1Scgd 36701.1Scgd /* 36711.1Scgd * If there was a serious error in the expression for the argument, 36721.1Scgd * create a dummy argument so the positions of the remaining arguments 36731.1Scgd * will not change. 36741.1Scgd */ 36751.1Scgd if (arg == NULL) 36761.318Srillig arg = build_integer_constant(INT, 0); 36771.1Scgd 36781.395Srillig ntn = new_tnode(PUSH, arg->tn_sys, arg->tn_type, arg, args); 36791.1Scgd 36801.95Srillig return ntn; 36811.1Scgd} 36821.1Scgd 36831.1Scgd/* 36841.1Scgd * Create the node for a function call. Also check types of 36851.1Scgd * function arguments and insert conversions, if necessary. 36861.1Scgd */ 36871.1Scgdtnode_t * 36881.395Srilligbuild_function_call(tnode_t *func, bool sys, tnode_t *args) 36891.1Scgd{ 36901.1Scgd tnode_t *ntn; 36911.1Scgd op_t fcop; 36921.1Scgd 36931.1Scgd if (func == NULL) 36941.95Srillig return NULL; 36951.1Scgd 36961.1Scgd if (func->tn_op == NAME && func->tn_type->t_tspec == FUNC) { 36971.1Scgd fcop = CALL; 36981.1Scgd } else { 36991.1Scgd fcop = ICALL; 37001.1Scgd } 37011.1Scgd 37021.266Srillig check_ctype_function_call(func, args); 37031.266Srillig 37041.1Scgd /* 37051.1Scgd * after cconv() func will always be a pointer to a function 37061.1Scgd * if it is a valid function designator. 37071.1Scgd */ 37081.1Scgd func = cconv(func); 37091.1Scgd 37101.1Scgd if (func->tn_type->t_tspec != PTR || 37111.1Scgd func->tn_type->t_subt->t_tspec != FUNC) { 37121.108Srillig /* illegal function (type %s) */ 37131.115Srillig error(149, type_name(func->tn_type)); 37141.95Srillig return NULL; 37151.1Scgd } 37161.1Scgd 37171.100Srillig args = check_function_arguments(func->tn_type->t_subt, args); 37181.1Scgd 37191.395Srillig ntn = new_tnode(fcop, sys, func->tn_type->t_subt->t_subt, func, args); 37201.1Scgd 37211.95Srillig return ntn; 37221.1Scgd} 37231.1Scgd 37241.1Scgd/* 37251.1Scgd * Check types of all function arguments and insert conversions, 37261.1Scgd * if necessary. 37271.1Scgd */ 37281.1Scgdstatic tnode_t * 37291.100Srilligcheck_function_arguments(type_t *ftp, tnode_t *args) 37301.1Scgd{ 37311.1Scgd tnode_t *arg; 37321.1Scgd sym_t *asym; 37331.1Scgd tspec_t at; 37341.1Scgd int narg, npar, n, i; 37351.1Scgd 37361.1Scgd /* get # of args in the prototype */ 37371.1Scgd npar = 0; 37381.101Srillig for (asym = ftp->t_args; asym != NULL; asym = asym->s_next) 37391.1Scgd npar++; 37401.1Scgd 37411.1Scgd /* get # of args in function call */ 37421.1Scgd narg = 0; 37431.1Scgd for (arg = args; arg != NULL; arg = arg->tn_right) 37441.1Scgd narg++; 37451.1Scgd 37461.1Scgd asym = ftp->t_args; 37471.1Scgd if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) { 37481.1Scgd /* argument mismatch: %d arg%s passed, %d expected */ 37491.1Scgd error(150, narg, narg > 1 ? "s" : "", npar); 37501.1Scgd asym = NULL; 37511.1Scgd } 37521.20Slukem 37531.1Scgd for (n = 1; n <= narg; n++) { 37541.1Scgd 37551.1Scgd /* 37561.1Scgd * The rightmost argument is at the top of the argument 37571.1Scgd * subtree. 37581.1Scgd */ 37591.20Slukem for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) 37601.20Slukem continue; 37611.1Scgd 37621.106Srillig /* some things which are always not allowed */ 37631.1Scgd if ((at = arg->tn_left->tn_type->t_tspec) == VOID) { 37641.1Scgd /* void expressions may not be arguments, arg #%d */ 37651.1Scgd error(151, n); 37661.95Srillig return NULL; 37671.1Scgd } else if ((at == STRUCT || at == UNION) && 37681.194Srillig is_incomplete(arg->tn_left->tn_type)) { 37691.1Scgd /* argument cannot have unknown size, arg #%d */ 37701.1Scgd error(152, n); 37711.95Srillig return NULL; 37721.144Srillig } else if (is_integer(at) && 37731.209Srillig arg->tn_left->tn_type->t_is_enum && 37741.194Srillig is_incomplete(arg->tn_left->tn_type)) { 37751.1Scgd /* argument cannot have unknown size, arg #%d */ 37761.1Scgd warning(152, n); 37771.1Scgd } 37781.1Scgd 37791.1Scgd /* class conversions (arg in value context) */ 37801.1Scgd arg->tn_left = cconv(arg->tn_left); 37811.1Scgd 37821.1Scgd if (asym != NULL) { 37831.100Srillig arg->tn_left = check_prototype_argument( 37841.100Srillig n, asym->s_type, arg->tn_left); 37851.1Scgd } else { 37861.172Srillig arg->tn_left = promote(NOOP, true, arg->tn_left); 37871.1Scgd } 37881.1Scgd arg->tn_type = arg->tn_left->tn_type; 37891.1Scgd 37901.1Scgd if (asym != NULL) 37911.101Srillig asym = asym->s_next; 37921.1Scgd } 37931.1Scgd 37941.95Srillig return args; 37951.1Scgd} 37961.1Scgd 37971.1Scgd/* 37981.1Scgd * Compare the type of an argument with the corresponding type of a 37991.1Scgd * prototype parameter. If it is a valid combination, but both types 38001.1Scgd * are not the same, insert a conversion to convert the argument into 38011.1Scgd * the type of the parameter. 38021.1Scgd */ 38031.1Scgdstatic tnode_t * 38041.100Srilligcheck_prototype_argument( 38051.100Srillig int n, /* pos of arg */ 38061.20Slukem type_t *tp, /* expected type (from prototype) */ 38071.20Slukem tnode_t *tn) /* argument */ 38081.1Scgd{ 38091.1Scgd tnode_t *ln; 38101.154Srillig bool dowarn; 38111.1Scgd 38121.259Srillig ln = xcalloc(1, sizeof(*ln)); 38131.320Srillig ln->tn_type = expr_unqualified_type(tp); 38141.154Srillig ln->tn_lvalue = true; 38151.1Scgd if (typeok(FARG, n, ln, tn)) { 38161.154Srillig if (!eqtype(tp, tn->tn_type, 38171.154Srillig true, false, (dowarn = false, &dowarn)) || dowarn) 38181.1Scgd tn = convert(FARG, n, tp, tn); 38191.1Scgd } 38201.1Scgd free(ln); 38211.95Srillig return tn; 38221.1Scgd} 38231.1Scgd 38241.1Scgd/* 38251.1Scgd * Return the value of an integral constant expression. 38261.1Scgd * If the expression is not constant or its type is not an integer 38271.1Scgd * type, an error message is printed. 38281.1Scgd */ 38291.1Scgdval_t * 38301.154Srilligconstant(tnode_t *tn, bool required) 38311.1Scgd{ 38321.1Scgd val_t *v; 38331.1Scgd 38341.1Scgd if (tn != NULL) 38351.1Scgd tn = cconv(tn); 38361.1Scgd if (tn != NULL) 38371.172Srillig tn = promote(NOOP, false, tn); 38381.1Scgd 38391.259Srillig v = xcalloc(1, sizeof(*v)); 38401.1Scgd 38411.1Scgd if (tn == NULL) { 38421.107Srillig lint_assert(nerr != 0); 38431.325Srillig debug_step("constant node is null; returning 1 instead"); 38441.1Scgd v->v_tspec = INT; 38451.1Scgd v->v_quad = 1; 38461.95Srillig return v; 38471.1Scgd } 38481.1Scgd 38491.1Scgd v->v_tspec = tn->tn_type->t_tspec; 38501.1Scgd 38511.1Scgd if (tn->tn_op == CON) { 38521.107Srillig lint_assert(tn->tn_type->t_tspec == tn->tn_val->v_tspec); 38531.144Srillig if (is_integer(tn->tn_val->v_tspec)) { 38541.289Srillig v->v_unsigned_since_c90 = 38551.289Srillig tn->tn_val->v_unsigned_since_c90; 38561.1Scgd v->v_quad = tn->tn_val->v_quad; 38571.95Srillig return v; 38581.1Scgd } 38591.1Scgd v->v_quad = tn->tn_val->v_ldbl; 38601.1Scgd } else { 38611.1Scgd v->v_quad = 1; 38621.1Scgd } 38631.1Scgd 38641.31Schristos if (required) 38651.113Srillig /* integral constant expression expected */ 38661.31Schristos error(55); 38671.31Schristos else 38681.113Srillig /* variable array dimension is a C99/GCC extension */ 38691.45Schristos c99ism(318); 38701.1Scgd 38711.144Srillig if (!is_integer(v->v_tspec)) 38721.1Scgd v->v_tspec = INT; 38731.1Scgd 38741.95Srillig return v; 38751.1Scgd} 38761.1Scgd 38771.211Srilligstatic bool 38781.211Srilligis_constcond_false(const tnode_t *tn, tspec_t t) 38791.211Srillig{ 38801.211Srillig return (t == BOOL || t == INT) && 38811.211Srillig tn->tn_op == CON && tn->tn_val->v_quad == 0; 38821.211Srillig} 38831.211Srillig 38841.1Scgd/* 38851.317Srillig * Perform some tests on expressions which can't be done in build_binary() 38861.317Srillig * and functions called by build_binary(). These tests must be done here 38871.317Srillig * because we need some information about the context in which the operations 38881.1Scgd * are performed. 38891.217Srillig * After all tests are performed and dofreeblk is true, expr() frees the 38901.217Srillig * memory which is used for the expression. 38911.1Scgd */ 38921.1Scgdvoid 38931.280Srilligexpr(tnode_t *tn, bool vctx, bool tctx, bool dofreeblk, bool is_do_while) 38941.1Scgd{ 38951.20Slukem 38961.305Srillig if (tn == NULL) { /* in case of errors */ 38971.257Srillig expr_free_all(); 38981.1Scgd return; 38991.1Scgd } 39001.1Scgd 39011.218Srillig /* expr() is also called in global initializations */ 39021.280Srillig if (dcs->d_ctx != EXTERN && !is_do_while) 39031.98Srillig check_statement_reachable(); 39041.1Scgd 39051.172Srillig check_expr_misc(tn, vctx, tctx, !tctx, false, false, false); 39061.1Scgd if (tn->tn_op == ASSIGN) { 39071.1Scgd if (hflag && tctx) 39081.1Scgd /* assignment in conditional context */ 39091.1Scgd warning(159); 39101.1Scgd } else if (tn->tn_op == CON) { 39111.202Srillig if (hflag && tctx && !constcond_flag && 39121.227Srillig !tn->tn_system_dependent && 39131.280Srillig !(is_do_while && 39141.211Srillig is_constcond_false(tn, tn->tn_type->t_tspec))) 39151.1Scgd /* constant in conditional context */ 39161.1Scgd warning(161); 39171.1Scgd } 39181.164Srillig if (!modtab[tn->tn_op].m_has_side_effect) { 39191.1Scgd /* 39201.1Scgd * for left operands of COMMA this warning is already 39211.1Scgd * printed 39221.1Scgd */ 39231.1Scgd if (tn->tn_op != COMMA && !vctx && !tctx) 39241.100Srillig check_null_effect(tn); 39251.1Scgd } 39261.326Srillig debug_node(tn); 39271.1Scgd 39281.1Scgd /* free the tree memory */ 39291.54Sdholland if (dofreeblk) 39301.257Srillig expr_free_all(); 39311.1Scgd} 39321.1Scgd 39331.197Srilligstatic bool 39341.393Srillighas_side_effect(const tnode_t *tn) /* NOLINT(misc-no-recursion) */ 39351.1Scgd{ 39361.199Srillig op_t op = tn->tn_op; 39371.199Srillig 39381.199Srillig if (modtab[op].m_has_side_effect) 39391.199Srillig return true; 39401.199Srillig 39411.199Srillig if (op == CVT && tn->tn_type->t_tspec == VOID) 39421.199Srillig return has_side_effect(tn->tn_left); 39431.199Srillig 39441.199Srillig /* XXX: Why not has_side_effect(tn->tn_left) as well? */ 39451.199Srillig if (op == LOGAND || op == LOGOR) 39461.199Srillig return has_side_effect(tn->tn_right); 39471.199Srillig 39481.199Srillig /* XXX: Why not has_side_effect(tn->tn_left) as well? */ 39491.199Srillig if (op == QUEST) 39501.199Srillig return has_side_effect(tn->tn_right); 39511.199Srillig 39521.199Srillig if (op == COLON || op == COMMA) { 39531.199Srillig return has_side_effect(tn->tn_left) || 39541.199Srillig has_side_effect(tn->tn_right); 39551.1Scgd } 39561.197Srillig 39571.199Srillig return false; 39581.197Srillig} 39591.197Srillig 39601.341Srilligstatic bool 39611.341Srilligis_void_cast(const tnode_t *tn) 39621.341Srillig{ 39631.341Srillig 39641.341Srillig return tn->tn_op == CVT && tn->tn_cast && 39651.341Srillig tn->tn_type->t_tspec == VOID; 39661.341Srillig} 39671.341Srillig 39681.341Srilligstatic bool 39691.341Srilligis_local_symbol(const tnode_t *tn) 39701.341Srillig{ 39711.341Srillig 39721.341Srillig return tn->tn_op == LOAD && 39731.341Srillig tn->tn_left->tn_op == NAME && 39741.341Srillig tn->tn_left->tn_sym->s_scl == AUTO; 39751.341Srillig} 39761.341Srillig 39771.341Srilligstatic bool 39781.341Srilligis_int_constant_zero(const tnode_t *tn) 39791.341Srillig{ 39801.341Srillig 39811.341Srillig return tn->tn_op == CON && 39821.341Srillig tn->tn_type->t_tspec == INT && 39831.341Srillig tn->tn_val->v_quad == 0; 39841.341Srillig} 39851.341Srillig 39861.197Srilligstatic void 39871.197Srilligcheck_null_effect(const tnode_t *tn) 39881.197Srillig{ 39891.197Srillig 39901.341Srillig if (!hflag) 39911.341Srillig return; 39921.342Srillig if (has_side_effect(tn)) 39931.341Srillig return; 39941.341Srillig if (is_void_cast(tn) && is_local_symbol(tn->tn_left)) 39951.341Srillig return; 39961.341Srillig if (is_void_cast(tn) && is_int_constant_zero(tn->tn_left)) 39971.341Srillig return; 39981.341Srillig 39991.341Srillig /* expression has null effect */ 40001.341Srillig warning(129); 40011.1Scgd} 40021.1Scgd 40031.370Srilligstatic void 40041.370Srilligcheck_expr_addr(const tnode_t *ln, bool szof, bool fcall) 40051.370Srillig{ 40061.370Srillig /* XXX: Taking warn_about_unreachable into account here feels wrong. */ 40071.370Srillig if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { 40081.370Srillig if (!szof) 40091.370Srillig mark_as_set(ln->tn_sym); 40101.370Srillig mark_as_used(ln->tn_sym, fcall, szof); 40111.370Srillig } 40121.370Srillig if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) 40131.370Srillig /* check the range of array indices */ 40141.370Srillig check_array_index(ln->tn_left, true); 40151.370Srillig} 40161.370Srillig 40171.370Srilligstatic void 40181.370Srilligcheck_expr_load(const tnode_t *ln) 40191.370Srillig{ 40201.370Srillig if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) 40211.370Srillig /* check the range of array indices */ 40221.370Srillig check_array_index(ln->tn_left, false); 40231.370Srillig} 40241.370Srillig 40251.370Srilligstatic void 40261.370Srilligcheck_expr_side_effect(const tnode_t *ln, bool szof) 40271.1Scgd{ 40281.370Srillig scl_t sc; 40291.370Srillig dinfo_t *di; 40301.370Srillig 40311.370Srillig /* XXX: Taking warn_about_unreachable into account here feels wrong. */ 40321.370Srillig if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { 40331.370Srillig sc = ln->tn_sym->s_scl; 40341.370Srillig /* 40351.370Srillig * Look if there was a asm statement in one of the 40361.370Srillig * compound statements we are in. If not, we don't 40371.370Srillig * print a warning. 40381.370Srillig */ 40391.370Srillig for (di = dcs; di != NULL; di = di->d_next) { 40401.370Srillig if (di->d_asm) 40411.370Srillig break; 40421.370Srillig } 40431.370Srillig if (sc != EXTERN && sc != STATIC && 40441.370Srillig !ln->tn_sym->s_set && !szof && di == NULL) { 40451.370Srillig /* %s may be used before set */ 40461.370Srillig warning(158, ln->tn_sym->s_name); 40471.370Srillig mark_as_set(ln->tn_sym); 40481.370Srillig } 40491.370Srillig mark_as_used(ln->tn_sym, false, false); 40501.370Srillig } 40511.370Srillig} 40521.1Scgd 40531.370Srilligstatic void 40541.370Srilligcheck_expr_assign(const tnode_t *ln, bool szof) 40551.370Srillig{ 40561.370Srillig /* XXX: Taking warn_about_unreachable into account here feels wrong. */ 40571.370Srillig if (ln->tn_op == NAME && !szof && (reached || !warn_about_unreachable)) { 40581.370Srillig mark_as_set(ln->tn_sym); 40591.370Srillig if (ln->tn_sym->s_scl == EXTERN) 40601.370Srillig outusg(ln->tn_sym); 40611.370Srillig } 40621.370Srillig if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) 40631.370Srillig /* check the range of array indices */ 40641.370Srillig check_array_index(ln->tn_left, false); 40651.370Srillig} 40661.1Scgd 40671.370Srilligstatic void 40681.370Srilligcheck_expr_call(const tnode_t *tn, const tnode_t *ln, 40691.381Srillig bool szof, bool vctx, bool tctx, bool retval_discarded) 40701.370Srillig{ 40711.370Srillig lint_assert(ln->tn_op == ADDR); 40721.370Srillig lint_assert(ln->tn_left->tn_op == NAME); 40731.370Srillig if (!szof && 40741.370Srillig !is_compiler_builtin(ln->tn_left->tn_sym->s_name)) 40751.381Srillig outcall(tn, vctx || tctx, retval_discarded); 40761.370Srillig} 40771.1Scgd 40781.370Srilligstatic bool 40791.370Srilligcheck_expr_op(const tnode_t *tn, op_t op, const tnode_t *ln, 40801.381Srillig bool szof, bool fcall, bool vctx, bool tctx, 40811.381Srillig bool retval_discarded, bool eqwarn) 40821.370Srillig{ 40831.1Scgd switch (op) { 40841.169Srillig case ADDR: 40851.370Srillig check_expr_addr(ln, szof, fcall); 40861.1Scgd break; 40871.1Scgd case LOAD: 40881.370Srillig check_expr_load(ln); 40891.1Scgd /* FALLTHROUGH */ 40901.1Scgd case PUSH: 40911.1Scgd case INCBEF: 40921.1Scgd case DECBEF: 40931.1Scgd case INCAFT: 40941.1Scgd case DECAFT: 40951.1Scgd case ADDASS: 40961.1Scgd case SUBASS: 40971.1Scgd case MULASS: 40981.1Scgd case DIVASS: 40991.1Scgd case MODASS: 41001.1Scgd case ANDASS: 41011.1Scgd case ORASS: 41021.1Scgd case XORASS: 41031.1Scgd case SHLASS: 41041.1Scgd case SHRASS: 41051.46Schristos case REAL: 41061.46Schristos case IMAG: 41071.370Srillig check_expr_side_effect(ln, szof); 41081.1Scgd break; 41091.1Scgd case ASSIGN: 41101.370Srillig check_expr_assign(ln, szof); 41111.1Scgd break; 41121.1Scgd case CALL: 41131.381Srillig check_expr_call(tn, ln, szof, vctx, tctx, retval_discarded); 41141.1Scgd break; 41151.1Scgd case EQ: 41161.1Scgd if (hflag && eqwarn) 41171.113Srillig /* operator '==' found where '=' was expected */ 41181.1Scgd warning(160); 41191.1Scgd break; 41201.1Scgd case CON: 41211.1Scgd case NAME: 41221.1Scgd case STRING: 41231.370Srillig return false; 41241.73Schristos /* LINTED206: (enumeration values not handled in switch) */ 41251.171Srillig case BITOR: 41261.171Srillig case BITXOR: 41271.14Schristos case NE: 41281.14Schristos case GE: 41291.14Schristos case GT: 41301.14Schristos case LE: 41311.14Schristos case LT: 41321.14Schristos case SHR: 41331.14Schristos case SHL: 41341.14Schristos case MINUS: 41351.14Schristos case PLUS: 41361.14Schristos case MOD: 41371.14Schristos case DIV: 41381.14Schristos case MULT: 41391.170Srillig case INDIR: 41401.14Schristos case UMINUS: 41411.14Schristos case UPLUS: 41421.14Schristos case DEC: 41431.14Schristos case INC: 41441.14Schristos case COMPL: 41451.14Schristos case NOT: 41461.14Schristos case POINT: 41471.14Schristos case ARROW: 41481.14Schristos case NOOP: 41491.171Srillig case BITAND: 41501.14Schristos case FARG: 41511.14Schristos case CASE: 41521.14Schristos case INIT: 41531.14Schristos case RETURN: 41541.14Schristos case ICALL: 41551.14Schristos case CVT: 41561.14Schristos case COMMA: 41571.14Schristos case FSEL: 41581.14Schristos case COLON: 41591.14Schristos case QUEST: 41601.14Schristos case LOGOR: 41611.14Schristos case LOGAND: 41621.14Schristos break; 41631.1Scgd } 41641.370Srillig return true; 41651.370Srillig} 41661.370Srillig 41671.370Srillig/* ARGSUSED */ 41681.370Srilligvoid 41691.370Srilligcheck_expr_misc(const tnode_t *tn, bool vctx, bool tctx, 41701.381Srillig bool eqwarn, bool fcall, bool retval_discarded, bool szof) 41711.370Srillig{ 41721.392Srillig tnode_t *ln, *rn; 41731.370Srillig const mod_t *mp; 41741.392Srillig op_t op; 41751.392Srillig bool cvctx, ctctx, eq, discard; 41761.370Srillig 41771.370Srillig if (tn == NULL) 41781.370Srillig return; 41791.370Srillig 41801.370Srillig ln = tn->tn_left; 41811.370Srillig rn = tn->tn_right; 41821.370Srillig mp = &modtab[op = tn->tn_op]; 41831.370Srillig 41841.370Srillig if (!check_expr_op(tn, op, ln, 41851.381Srillig szof, fcall, vctx, tctx, retval_discarded, eqwarn)) 41861.370Srillig return; 41871.1Scgd 41881.392Srillig cvctx = mp->m_left_value_context; 41891.392Srillig ctctx = mp->m_left_test_context; 41901.392Srillig eq = mp->m_warn_if_operand_eq && 41911.392Srillig !ln->tn_parenthesized && 41921.392Srillig rn != NULL && !rn->tn_parenthesized; 41931.173Srillig 41941.1Scgd /* 41951.1Scgd * values of operands of ':' are not used if the type of at least 41961.1Scgd * one of the operands (for gcc compatibility) is void 41971.1Scgd * XXX test/value context of QUEST should probably be used as 41981.1Scgd * context for both operands of COLON 41991.1Scgd */ 42001.1Scgd if (op == COLON && tn->tn_type->t_tspec == VOID) 42011.154Srillig cvctx = ctctx = false; 42021.392Srillig discard = op == CVT && tn->tn_type->t_tspec == VOID; 42031.173Srillig check_expr_misc(ln, cvctx, ctctx, eq, op == CALL, discard, szof); 42041.1Scgd 42051.1Scgd switch (op) { 42061.1Scgd case PUSH: 42071.1Scgd if (rn != NULL) 42081.173Srillig check_expr_misc(rn, false, false, eq, false, false, 42091.173Srillig szof); 42101.1Scgd break; 42111.1Scgd case LOGAND: 42121.1Scgd case LOGOR: 42131.173Srillig check_expr_misc(rn, false, true, eq, false, false, szof); 42141.1Scgd break; 42151.1Scgd case COLON: 42161.173Srillig check_expr_misc(rn, cvctx, ctctx, eq, false, false, szof); 42171.19Smycroft break; 42181.19Smycroft case COMMA: 42191.173Srillig check_expr_misc(rn, vctx, tctx, eq, false, false, szof); 42201.1Scgd break; 42211.1Scgd default: 42221.1Scgd if (mp->m_binary) 42231.173Srillig check_expr_misc(rn, true, false, eq, false, false, 42241.173Srillig szof); 42251.1Scgd break; 42261.1Scgd } 42271.1Scgd} 42281.1Scgd 42291.1Scgd/* 42301.1Scgd * Checks the range of array indices, if possible. 42311.1Scgd * amper is set if only the address of the element is used. This 42321.106Srillig * means that the index is allowed to refer to the first element 42331.1Scgd * after the array. 42341.1Scgd */ 42351.1Scgdstatic void 42361.154Srilligcheck_array_index(tnode_t *tn, bool amper) 42371.1Scgd{ 42381.1Scgd int dim; 42391.1Scgd tnode_t *ln, *rn; 42401.1Scgd int elsz; 42411.25Sthorpej int64_t con; 42421.1Scgd 42431.1Scgd ln = tn->tn_left; 42441.1Scgd rn = tn->tn_right; 42451.1Scgd 42461.1Scgd /* We can only check constant indices. */ 42471.1Scgd if (rn->tn_op != CON) 42481.1Scgd return; 42491.1Scgd 42501.1Scgd /* Return if the left node does not stem from an array. */ 42511.169Srillig if (ln->tn_op != ADDR) 42521.1Scgd return; 42531.1Scgd if (ln->tn_left->tn_op != STRING && ln->tn_left->tn_op != NAME) 42541.1Scgd return; 42551.1Scgd if (ln->tn_left->tn_type->t_tspec != ARRAY) 42561.1Scgd return; 42571.20Slukem 42581.1Scgd /* 42591.1Scgd * For incomplete array types, we can print a warning only if 42601.1Scgd * the index is negative. 42611.1Scgd */ 42621.194Srillig if (is_incomplete(ln->tn_left->tn_type) && rn->tn_val->v_quad >= 0) 42631.1Scgd return; 42641.1Scgd 42651.1Scgd /* Get the size of one array element */ 42661.1Scgd if ((elsz = length(ln->tn_type->t_subt, NULL)) == 0) 42671.1Scgd return; 42681.136Srillig elsz /= CHAR_SIZE; 42691.1Scgd 42701.1Scgd /* Change the unit of the index from bytes to element size. */ 42711.144Srillig if (is_uinteger(rn->tn_type->t_tspec)) { 42721.25Sthorpej con = (uint64_t)rn->tn_val->v_quad / elsz; 42731.1Scgd } else { 42741.1Scgd con = rn->tn_val->v_quad / elsz; 42751.1Scgd } 42761.1Scgd 42771.1Scgd dim = ln->tn_left->tn_type->t_dim + (amper ? 1 : 0); 42781.1Scgd 42791.144Srillig if (!is_uinteger(rn->tn_type->t_tspec) && con < 0) { 42801.1Scgd /* array subscript cannot be negative: %ld */ 42811.1Scgd warning(167, (long)con); 42821.57Schristos } else if (dim > 0 && (uint64_t)con >= (uint64_t)dim) { 42831.1Scgd /* array subscript cannot be > %d: %ld */ 42841.1Scgd warning(168, dim - 1, (long)con); 42851.1Scgd } 42861.1Scgd} 42871.1Scgd 42881.359Srilligstatic bool 42891.359Srilligis_out_of_char_range(const tnode_t *tn) 42901.359Srillig{ 42911.359Srillig return tn->tn_op == CON && 42921.360Srillig !(0 <= tn->tn_val->v_quad && 42931.360Srillig tn->tn_val->v_quad < 1 << (CHAR_SIZE - 1)); 42941.359Srillig} 42951.359Srillig 42961.1Scgd/* 42971.17Smycroft * Check for ordered comparisons of unsigned values with 0. 42981.1Scgd */ 42991.1Scgdstatic void 43001.100Srilligcheck_integer_comparison(op_t op, tnode_t *ln, tnode_t *rn) 43011.1Scgd{ 43021.1Scgd tspec_t lt, rt; 43031.1Scgd 43041.1Scgd lt = ln->tn_type->t_tspec; 43051.1Scgd rt = rn->tn_type->t_tspec; 43061.1Scgd 43071.1Scgd if (ln->tn_op != CON && rn->tn_op != CON) 43081.1Scgd return; 43091.1Scgd 43101.144Srillig if (!is_integer(lt) || !is_integer(rt)) 43111.1Scgd return; 43121.1Scgd 43131.385Srillig if (hflag || pflag) { 43141.385Srillig if (lt == CHAR && is_out_of_char_range(rn)) { 43151.385Srillig /* nonportable character comparison '%s %d' */ 43161.385Srillig warning(230, op_name(op), (int)rn->tn_val->v_quad); 43171.385Srillig return; 43181.385Srillig } 43191.385Srillig if (rt == CHAR && is_out_of_char_range(ln)) { 43201.385Srillig /* nonportable character comparison '%s %d' */ 43211.385Srillig warning(230, op_name(op), (int)ln->tn_val->v_quad); 43221.385Srillig return; 43231.385Srillig } 43241.1Scgd } 43251.385Srillig 43261.144Srillig if (is_uinteger(lt) && !is_uinteger(rt) && 43271.1Scgd rn->tn_op == CON && rn->tn_val->v_quad <= 0) { 43281.1Scgd if (rn->tn_val->v_quad < 0) { 43291.17Smycroft /* comparison of %s with %s, op %s */ 43301.115Srillig warning(162, type_name(ln->tn_type), 43311.261Srillig "negative constant", op_name(op)); 43321.379Srillig } else if (op == LT || op == GE) { 43331.17Smycroft /* comparison of %s with %s, op %s */ 43341.261Srillig warning(162, type_name(ln->tn_type), "0", op_name(op)); 43351.1Scgd } 43361.1Scgd return; 43371.1Scgd } 43381.144Srillig if (is_uinteger(rt) && !is_uinteger(lt) && 43391.1Scgd ln->tn_op == CON && ln->tn_val->v_quad <= 0) { 43401.1Scgd if (ln->tn_val->v_quad < 0) { 43411.17Smycroft /* comparison of %s with %s, op %s */ 43421.26Schristos warning(162, "negative constant", 43431.261Srillig type_name(rn->tn_type), op_name(op)); 43441.379Srillig } else if (op == GT || op == LE) { 43451.17Smycroft /* comparison of %s with %s, op %s */ 43461.261Srillig warning(162, "0", type_name(rn->tn_type), op_name(op)); 43471.1Scgd } 43481.1Scgd return; 43491.1Scgd } 43501.1Scgd} 43511.1Scgd 43521.1Scgd/* 43531.218Srillig * Return whether the expression can be used for static initialization. 43541.1Scgd * 43551.218Srillig * Constant initialization expressions must be constant or an address 43561.1Scgd * of a static object with an optional offset. In the first case, 43571.1Scgd * the result is returned in *offsp. In the second case, the static 43581.1Scgd * object is returned in *symp and the offset in *offsp. 43591.1Scgd * 43601.169Srillig * The expression can consist of PLUS, MINUS, ADDR, NAME, STRING and 43611.1Scgd * CON. Type conversions are allowed if they do not change binary 43621.1Scgd * representation (including width). 43631.278Srillig * 43641.278Srillig * C99 6.6 "Constant expressions" 43651.278Srillig * C99 6.7.8p4 restricts initializers for static storage duration 43661.1Scgd */ 43671.174Srilligbool 43681.253Srilligconstant_addr(const tnode_t *tn, const sym_t **symp, ptrdiff_t *offsp) 43691.1Scgd{ 43701.253Srillig const sym_t *sym; 43711.1Scgd ptrdiff_t offs1, offs2; 43721.1Scgd tspec_t t, ot; 43731.1Scgd 43741.1Scgd switch (tn->tn_op) { 43751.1Scgd case MINUS: 43761.28Schristos if (tn->tn_right->tn_op == CVT) 43771.174Srillig return constant_addr(tn->tn_right, symp, offsp); 43781.28Schristos else if (tn->tn_right->tn_op != CON) 43791.174Srillig return false; 43801.1Scgd /* FALLTHROUGH */ 43811.1Scgd case PLUS: 43821.1Scgd offs1 = offs2 = 0; 43831.1Scgd if (tn->tn_left->tn_op == CON) { 43841.1Scgd offs1 = (ptrdiff_t)tn->tn_left->tn_val->v_quad; 43851.174Srillig if (!constant_addr(tn->tn_right, &sym, &offs2)) 43861.174Srillig return false; 43871.1Scgd } else if (tn->tn_right->tn_op == CON) { 43881.1Scgd offs2 = (ptrdiff_t)tn->tn_right->tn_val->v_quad; 43891.1Scgd if (tn->tn_op == MINUS) 43901.1Scgd offs2 = -offs2; 43911.174Srillig if (!constant_addr(tn->tn_left, &sym, &offs1)) 43921.174Srillig return false; 43931.1Scgd } else { 43941.174Srillig return false; 43951.1Scgd } 43961.1Scgd *symp = sym; 43971.1Scgd *offsp = offs1 + offs2; 43981.215Srillig return true; 43991.169Srillig case ADDR: 44001.1Scgd if (tn->tn_left->tn_op == NAME) { 44011.1Scgd *symp = tn->tn_left->tn_sym; 44021.1Scgd *offsp = 0; 44031.215Srillig return true; 44041.215Srillig } else { 44051.1Scgd /* 44061.1Scgd * If this would be the front end of a compiler we 44071.215Srillig * would return a label instead of 0, at least if 44081.215Srillig * 'tn->tn_left->tn_op == STRING'. 44091.1Scgd */ 44101.215Srillig *symp = NULL; 44111.1Scgd *offsp = 0; 44121.215Srillig return true; 44131.1Scgd } 44141.1Scgd case CVT: 44151.1Scgd t = tn->tn_type->t_tspec; 44161.1Scgd ot = tn->tn_left->tn_type->t_tspec; 44171.144Srillig if ((!is_integer(t) && t != PTR) || 44181.144Srillig (!is_integer(ot) && ot != PTR)) { 44191.174Srillig return false; 44201.90Srillig } 44211.380Srillig#if 0 44221.89Srillig /* 44231.27Schristos * consider: 44241.97Srillig * struct foo { 44251.97Srillig * unsigned char a; 44261.97Srillig * } f = { 44271.353Srillig * (unsigned char)(unsigned long) 44281.353Srillig * (&(((struct foo *)0)->a)) 44291.27Schristos * }; 44301.353Srillig * since psize(unsigned long) != psize(unsigned char), 44311.353Srillig * this fails. 44321.27Schristos */ 44331.27Schristos else if (psize(t) != psize(ot)) 44341.95Srillig return -1; 44351.27Schristos#endif 44361.215Srillig return constant_addr(tn->tn_left, symp, offsp); 44371.1Scgd default: 44381.174Srillig return false; 44391.1Scgd } 44401.1Scgd} 44411.1Scgd 44421.351Srillig/* Append s2 to s1, then free s2. */ 44431.1Scgdstrg_t * 44441.351Srilligcat_strings(strg_t *s1, strg_t *s2) 44451.1Scgd{ 44461.351Srillig size_t len1, len2, sz; 44471.1Scgd 44481.351Srillig if (s1->st_tspec != s2->st_tspec) { 44491.1Scgd /* cannot concatenate wide and regular string literals */ 44501.1Scgd error(292); 44511.351Srillig return s1; 44521.1Scgd } 44531.1Scgd 44541.351Srillig len1 = s1->st_len; 44551.351Srillig len2 = s2->st_len; 44561.66Schristos 44571.351Srillig if (s1->st_tspec == CHAR) { 44581.351Srillig sz = sizeof(*s1->st_cp); 44591.351Srillig s1->st_cp = xrealloc(s1->st_cp, (len1 + len2 + 1) * sz); 44601.351Srillig memcpy(s1->st_cp + len1, s2->st_cp, (len2 + 1) * sz); 44611.351Srillig free(s2->st_cp); 44621.351Srillig } else { 44631.351Srillig sz = sizeof(*s1->st_wcp); 44641.351Srillig s1->st_wcp = xrealloc(s1->st_wcp, (len1 + len2 + 1) * sz); 44651.351Srillig memcpy(s1->st_wcp + len1, s2->st_wcp, (len2 + 1) * sz); 44661.351Srillig free(s2->st_wcp); 44671.351Srillig } 44681.66Schristos 44691.351Srillig s1->st_len = len1 + len2; 44701.351Srillig free(s2); 44711.1Scgd 44721.351Srillig return s1; 44731.1Scgd} 44741.1Scgd 44751.134Srilligstatic bool 44761.134Srilligis_confusing_precedence(op_t op, op_t lop, bool lparen, op_t rop, bool rparen) 44771.134Srillig{ 44781.134Srillig 44791.134Srillig if (op == SHL || op == SHR) { 44801.145Srillig if (!lparen && (lop == PLUS || lop == MINUS)) 44811.134Srillig return true; 44821.145Srillig if (!rparen && (rop == PLUS || rop == MINUS)) 44831.134Srillig return true; 44841.134Srillig return false; 44851.134Srillig } 44861.134Srillig 44871.134Srillig if (op == LOGOR) { 44881.145Srillig if (!lparen && lop == LOGAND) 44891.134Srillig return true; 44901.145Srillig if (!rparen && rop == LOGAND) 44911.134Srillig return true; 44921.134Srillig return false; 44931.134Srillig } 44941.134Srillig 44951.171Srillig lint_assert(op == BITAND || op == BITXOR || op == BITOR); 44961.134Srillig if (!lparen && lop != op) { 44971.145Srillig if (lop == PLUS || lop == MINUS) 44981.134Srillig return true; 44991.171Srillig if (lop == BITAND || lop == BITXOR) 45001.134Srillig return true; 45011.134Srillig } 45021.134Srillig if (!rparen && rop != op) { 45031.145Srillig if (rop == PLUS || rop == MINUS) 45041.134Srillig return true; 45051.171Srillig if (rop == BITAND || rop == BITXOR) 45061.134Srillig return true; 45071.134Srillig } 45081.134Srillig return false; 45091.134Srillig} 45101.134Srillig 45111.1Scgd/* 45121.1Scgd * Print a warning if the given node has operands which should be 45131.1Scgd * parenthesized. 45141.1Scgd * 45151.1Scgd * XXX Does not work if an operand is a constant expression. Constant 45161.1Scgd * expressions are already folded. 45171.1Scgd */ 45181.1Scgdstatic void 45191.100Srilligcheck_precedence_confusion(tnode_t *tn) 45201.1Scgd{ 45211.135Srillig tnode_t *ln, *rn; 45221.1Scgd 45231.1Scgd if (!hflag) 45241.1Scgd return; 45251.1Scgd 45261.326Srillig debug_node(tn); 45271.1Scgd 45281.346Srillig lint_assert(is_binary(tn)); 45291.1Scgd for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) 45301.135Srillig continue; 45311.133Srillig for (rn = tn->tn_right; rn->tn_op == CVT; rn = rn->tn_left) 45321.135Srillig continue; 45331.1Scgd 45341.135Srillig if (is_confusing_precedence(tn->tn_op, 45351.135Srillig ln->tn_op, ln->tn_parenthesized, 45361.135Srillig rn->tn_op, rn->tn_parenthesized)) { 45371.1Scgd /* precedence confusion possible: parenthesize! */ 45381.1Scgd warning(169); 45391.1Scgd } 45401.1Scgd} 4541