diff options
| -rw-r--r-- | bits.h | 61 | ||||
| -rw-r--r-- | lib.h | 1 | ||||
| -rw-r--r-- | linearize.c | 20 | ||||
| -rw-r--r-- | show-parse.c | 2 | ||||
| -rw-r--r-- | simplify.c | 105 | ||||
| -rw-r--r-- | symbol.h | 8 | ||||
| -rw-r--r-- | validation/check_access-store.c | 21 | ||||
| -rw-r--r-- | validation/eval-typeof-vla.c | 26 | ||||
| -rw-r--r-- | validation/fp-ops.c | 2 | ||||
| -rw-r--r-- | validation/linear/cast-constant-to-float.c | 6 | ||||
| -rw-r--r-- | validation/linear/cast-constants.c | 20 | ||||
| -rw-r--r-- | validation/optim/bool-context-fp.c | 16 | ||||
| -rw-r--r-- | validation/optim/lsr-asr.c | 42 | ||||
| -rw-r--r-- | validation/optim/shift-big.c | 62 | ||||
| -rw-r--r-- | validation/optim/shift-shift.c | 149 | ||||
| -rw-r--r-- | validation/optim/zext-asr.c | 13 | ||||
| -rw-r--r-- | validation/shift-negative.c | 17 | ||||
| -rw-r--r-- | validation/shift-undef.c | 24 |
18 files changed, 529 insertions, 66 deletions
@@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Helper functions for manipulation & testing of integer values + * like zero or sign-extensions. + * + * Copyright (C) 2017 Luc Van Oostenryck + * + */ + +#ifndef BITS_H +#define BITS_H + +static inline unsigned long long sign_bit(unsigned size) +{ + return 1ULL << (size - 1); +} + +static inline unsigned long long sign_mask(unsigned size) +{ + unsigned long long sbit = sign_bit(size); + return sbit - 1; +} + +static inline unsigned long long bits_mask(unsigned size) +{ + unsigned long long sbit = sign_bit(size); + return sbit | (sbit - 1); +} + + +static inline long long zero_extend(long long val, unsigned size) +{ + return val & bits_mask(size); +} + +static inline long long sign_extend(long long val, unsigned size) +{ + if (val & sign_bit(size)) + val |= ~sign_mask(size); + return val; +} + +/// +// sign extend @val but only if exactly representable +static inline long long sign_extend_safe(long long val, unsigned size) +{ + unsigned long long mask = bits_mask(size); + if (!(val & ~mask)) + val = sign_extend(val, size); + return val; +} + +static inline long long bits_extend(long long val, unsigned size, int is_signed) +{ + val = zero_extend(val, size); + if (is_signed) + val = sign_extend(val, size); + return val; +} + +#endif @@ -34,6 +34,7 @@ #include "compat.h" #include "ptrlist.h" #include "utils.h" +#include "bits.h" #define DO_STRINGIFY(x) #x #define STRINGIFY(x) DO_STRINGIFY(x) diff --git a/linearize.c b/linearize.c index c1e4498e..016b853b 100644 --- a/linearize.c +++ b/linearize.c @@ -368,7 +368,7 @@ const char *show_instruction(struct instruction *insn) buf += sprintf(buf, "%lld", expr->value); break; case EXPR_FVALUE: - buf += sprintf(buf, "%Lf", expr->fvalue); + buf += sprintf(buf, "%Le", expr->fvalue); break; case EXPR_STRING: buf += sprintf(buf, "%.40s", show_string(expr->string)); @@ -386,7 +386,7 @@ const char *show_instruction(struct instruction *insn) } case OP_SETFVAL: buf += sprintf(buf, "%s <- ", show_pseudo(insn->target)); - buf += sprintf(buf, "%Lf", insn->fvalue); + buf += sprintf(buf, "%Le", insn->fvalue); break; case OP_SWITCH: { @@ -776,7 +776,6 @@ static void add_branch(struct entrypoint *ep, struct expression *expr, pseudo_t } } -/* Dummy pseudo allocator */ pseudo_t alloc_pseudo(struct instruction *def) { static int nr = 0; @@ -881,13 +880,8 @@ struct access_data { struct symbol *type; // ctype pseudo_t address; // pseudo containing address .. unsigned int offset; // byte offset - struct position pos; }; -static void finish_address_gen(struct entrypoint *ep, struct access_data *ad) -{ -} - static int linearize_simple_address(struct entrypoint *ep, struct expression *addr, struct access_data *ad) @@ -930,7 +924,6 @@ static int linearize_address_gen(struct entrypoint *ep, if (!ctype) return 0; - ad->pos = expr->pos; ad->type = ctype; if (expr->type == EXPR_PREOP && expr->op == '*') return linearize_simple_address(ep, expr->unop, ad); @@ -1105,7 +1098,6 @@ static pseudo_t linearize_access(struct entrypoint *ep, struct expression *expr) if (!linearize_address_gen(ep, expr, &ad)) return VOID; value = linearize_load_gen(ep, &ad); - finish_address_gen(ep, &ad); return value; } @@ -1126,7 +1118,6 @@ static pseudo_t linearize_inc_dec(struct entrypoint *ep, struct expression *expr one = value_pseudo(expr->op_value); new = add_binary_op(ep, expr->ctype, op, old, one); linearize_store_gen(ep, new, &ad); - finish_address_gen(ep, &ad); return postop ? old : new; } @@ -1444,7 +1435,6 @@ static pseudo_t linearize_assignment(struct entrypoint *ep, struct expression *e value = cast_pseudo(ep, dst, ctype, expr->ctype); } value = linearize_store_gen(ep, value, &ad); - finish_address_gen(ep, &ad); return value; } @@ -1755,7 +1745,6 @@ static pseudo_t linearize_position(struct entrypoint *ep, struct expression *pos struct expression *init_expr = pos->init_expr; ad->offset = pos->init_offset; - ad->type = init_expr->ctype; return linearize_initializer(ep, init_expr, ad); } @@ -1790,7 +1779,6 @@ static void linearize_argument(struct entrypoint *ep, struct symbol *arg, int nr ad.type = arg; ad.address = symbol_pseudo(ep, arg); linearize_store_gen(ep, argument_pseudo(ep, nr), &ad); - finish_address_gen(ep, &ad); } static pseudo_t linearize_expression(struct entrypoint *ep, struct expression *expr) @@ -1894,15 +1882,12 @@ static pseudo_t linearize_one_symbol(struct entrypoint *ep, struct symbol *sym) // only the existing fields need to be initialized. // FIXME: this init the whole aggregate even if // all fields arelater explicitely initialized. - struct expression *expr = sym->initializer; - ad.pos = expr->pos; ad.type = sym; ad.address = symbol_pseudo(ep, sym); linearize_store_gen(ep, value_pseudo(0), &ad); } value = linearize_initializer(ep, sym->initializer, &ad); - finish_address_gen(ep, &ad); return value; } @@ -2002,7 +1987,6 @@ static void add_asm_output(struct entrypoint *ep, struct instruction *insn, stru if (!expr || !linearize_address_gen(ep, expr, &ad)) return; linearize_store_gen(ep, pseudo, &ad); - finish_address_gen(ep, &ad); rule = __alloc_asm_constraint(0); rule->ident = ident; rule->constraint = constraint; diff --git a/show-parse.c b/show-parse.c index 72d3f385..6328439c 100644 --- a/show-parse.c +++ b/show-parse.c @@ -987,7 +987,7 @@ static int show_fvalue(struct expression *expr) int new = new_pseudo(); long double value = expr->fvalue; - printf("\tmovf.%d\t\tv%d,$%Lf\n", expr->ctype->bit_size, new, value); + printf("\tmovf.%d\t\tv%d,$%Le\n", expr->ctype->bit_size, new, value); return new; } @@ -546,31 +546,117 @@ undef: return NULL; } +static long long check_shift_count(struct instruction *insn, unsigned long long uval) +{ + unsigned int size = insn->size; + long long sval = uval; + + if (uval < size) + return uval; + + sval = sign_extend_safe(sval, size); + sval = sign_extend_safe(sval, bits_in_int); + if (sval < 0) + insn->src2 = value_pseudo(sval); + if (insn->tainted) + return sval; + + if (sval < 0 && Wshift_count_negative) + warning(insn->pos, "shift count is negative (%lld)", sval); + if (sval > 0 && Wshift_count_overflow) { + struct symbol *ctype = insn->type; + const char *tname; + if (ctype->type == SYM_NODE) + ctype = ctype->ctype.base_type; + tname = show_typename(ctype); + warning(insn->pos, "shift too big (%llu) for type %s", sval, tname); + } + insn->tainted = 1; + return sval; +} static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long value) { + struct instruction *def; + unsigned long long nval; unsigned int size; + pseudo_t src2; if (!value) return replace_with_pseudo(insn, pseudo); + value = check_shift_count(insn, value); + if (value < 0) + return 0; size = insn->size; - if (value >= size && !insn->tainted) { - if (Wshift_count_overflow) - warning(insn->pos, "shift by bigger than operand's width"); - insn->tainted = 1; - } switch (insn->opcode) { case OP_ASR: + if (value >= size) + return 0; + if (pseudo->type != PSEUDO_REG) + break; + def = pseudo->def; + switch (def->opcode) { + case OP_LSR: + case OP_ASR: + if (def == insn) // cyclic DAG! + break; + src2 = def->src2; + if (src2->type != PSEUDO_VAL) + break; + nval = src2->value; + if (nval > insn->size || nval == 0) + break; + value += nval; + if (def->opcode == OP_LSR) + insn->opcode = OP_LSR; + else if (value >= size) + value = size - 1; + goto new_value; + + case OP_ZEXT: + // transform: + // zext.N %t <- (O) %a + // asr.N %r <- %t, C + // into + // zext.N %t <- (O) %a + // lsr.N %r <- %t, C + insn->opcode = OP_LSR; + return REPEAT_CSE; + } break; case OP_LSR: size = operand_size(insn, pseudo); /* fall through */ case OP_SHL: if (value >= size) - return replace_with_pseudo(insn, value_pseudo(0)); + goto zero; + if (pseudo->type != PSEUDO_REG) + break; + def = pseudo->def; + if (def->opcode == insn->opcode) { + if (def == insn) // cyclic DAG! + break; + src2 = def->src2; + if (src2->type != PSEUDO_VAL) + break; + nval = src2->value; + if (nval > insn->size) + break; + value += nval; + goto new_value; + } + break; } return 0; + +new_value: + if (value < size) { + insn->src2 = value_pseudo(value); + return replace_pseudo(insn, &insn->src1, pseudo->def->src1); + } +zero: + return replace_with_pseudo(insn, value_pseudo(0)); } static int simplify_mul_div(struct instruction *insn, long long value) @@ -1363,6 +1449,13 @@ int simplify_instruction(struct instruction *insn) return simplify_switch(insn); case OP_RANGE: return simplify_range(insn); + case OP_FADD: + case OP_FSUB: + case OP_FMUL: + case OP_FDIV: + if (dead_insn(insn, &insn->src1, &insn->src2, NULL)) + return REPEAT_CSE; + break; } return 0; } @@ -453,6 +453,14 @@ static inline int get_sym_type(struct symbol *type) return type->type; } +static inline long long extend_value(long long val, struct symbol *ctype) +{ + int is_signed = !(ctype->ctype.modifiers & MOD_UNSIGNED); + unsigned size = ctype->bit_size; + + return bits_extend(val, size, is_signed); +} + static inline struct symbol *lookup_keyword(struct ident *ident, enum namespace ns) { if (!ident->keyword) diff --git a/validation/check_access-store.c b/validation/check_access-store.c new file mode 100644 index 00000000..489507fd --- /dev/null +++ b/validation/check_access-store.c @@ -0,0 +1,21 @@ +extern int a[1]; + +static int r(void) +{ + return a[1]; +} + +static void w(void) +{ + a[1] = 2; +} + +/* + * check-name: check_access-store + * check-known-to-fail + * + * check-error-start +check_access-store.c:5:17: warning: invalid access past the end of 'a' (4 4) +check_access-store.c:10:17: warning: invalid access past the end of 'a' (4 4) + * check-error-end + */ diff --git a/validation/eval-typeof-vla.c b/validation/eval-typeof-vla.c new file mode 100644 index 00000000..56a9ec20 --- /dev/null +++ b/validation/eval-typeof-vla.c @@ -0,0 +1,26 @@ +extern int a[1]; + +static int foo(int n) +{ + int i = 0; + int (*p)[1] = (typeof(++i, (int (*)[n])a)) &a; + + (void) p; + + return i; +} + +/* + * check-name: eval-typeof-vla + * check-command: test-linearize -Wno-vla $file + * check-known-to-fail + * + * check-output-start +foo: +.L0: + <entry-point> + ret.32 $1 + + + * check-output-end + */ diff --git a/validation/fp-ops.c b/validation/fp-ops.c index 81f73384..96c246f8 100644 --- a/validation/fp-ops.c +++ b/validation/fp-ops.c @@ -48,7 +48,7 @@ fneg: ftst: .L10: <entry-point> - setfval.64 %r21 <- 0.000000 + setfval.64 %r21 <- 0.000000e+00 fcmpoeq.1 %r23 <- %arg1, %r21 ret.1 %r23 diff --git a/validation/linear/cast-constant-to-float.c b/validation/linear/cast-constant-to-float.c index ef7892f1..ac4eff0f 100644 --- a/validation/linear/cast-constant-to-float.c +++ b/validation/linear/cast-constant-to-float.c @@ -13,21 +13,21 @@ double f3(void) { return -1.0; } f1: .L0: <entry-point> - setfval.64 %r1 <- -1.000000 + setfval.64 %r1 <- -1.000000e+00 ret.64 %r1 f2: .L2: <entry-point> - setfval.64 %r3 <- -1.000000 + setfval.64 %r3 <- -1.000000e+00 ret.64 %r3 f3: .L4: <entry-point> - setfval.64 %r5 <- -1.000000 + setfval.64 %r5 <- -1.000000e+00 ret.64 %r5 diff --git a/validation/linear/cast-constants.c b/validation/linear/cast-constants.c index 9e200672..c1fdab41 100644 --- a/validation/linear/cast-constants.c +++ b/validation/linear/cast-constants.c @@ -286,70 +286,70 @@ vptr_2_iptr: int_2_float: .L76: <entry-point> - setfval.32 %r39 <- 123.000000 + setfval.32 %r39 <- 1.230000e+02 ret.32 %r39 uint_2_float: .L78: <entry-point> - setfval.32 %r41 <- 123.000000 + setfval.32 %r41 <- 1.230000e+02 ret.32 %r41 long_2_float: .L80: <entry-point> - setfval.32 %r43 <- 123.000000 + setfval.32 %r43 <- 1.230000e+02 ret.32 %r43 ulong_2_float: .L82: <entry-point> - setfval.32 %r45 <- 123.000000 + setfval.32 %r45 <- 1.230000e+02 ret.32 %r45 double_2_float: .L84: <entry-point> - setfval.32 %r47 <- 1.123000 + setfval.32 %r47 <- 1.123000e+00 ret.32 %r47 int_2_double: .L86: <entry-point> - setfval.64 %r49 <- 123.000000 + setfval.64 %r49 <- 1.230000e+02 ret.64 %r49 uint_2_double: .L88: <entry-point> - setfval.64 %r51 <- 123.000000 + setfval.64 %r51 <- 1.230000e+02 ret.64 %r51 long_2_double: .L90: <entry-point> - setfval.64 %r53 <- 123.000000 + setfval.64 %r53 <- 1.230000e+02 ret.64 %r53 ulong_2_double: .L92: <entry-point> - setfval.64 %r55 <- 123.000000 + setfval.64 %r55 <- 1.230000e+02 ret.64 %r55 float_2_double: .L94: <entry-point> - setfval.64 %r57 <- 1.123000 + setfval.64 %r57 <- 1.123000e+00 ret.64 %r57 diff --git a/validation/optim/bool-context-fp.c b/validation/optim/bool-context-fp.c index 50e96825..3bfc3343 100644 --- a/validation/optim/bool-context-fp.c +++ b/validation/optim/bool-context-fp.c @@ -18,7 +18,7 @@ int ifand(float a, float b) { return a && b; } bfimp: .L0: <entry-point> - setfval.32 %r2 <- 0.000000 + setfval.32 %r2 <- 0.000000e+00 fcmpune.1 %r3 <- %arg1, %r2 ret.1 %r3 @@ -26,7 +26,7 @@ bfimp: bfexp: .L2: <entry-point> - setfval.32 %r6 <- 0.000000 + setfval.32 %r6 <- 0.000000e+00 fcmpune.1 %r7 <- %arg1, %r6 ret.1 %r7 @@ -34,7 +34,7 @@ bfexp: bfnot: .L4: <entry-point> - setfval.32 %r10 <- 0.000000 + setfval.32 %r10 <- 0.000000e+00 fcmpoeq.1 %r12 <- %arg1, %r10 ret.1 %r12 @@ -42,7 +42,7 @@ bfnot: ifnot: .L6: <entry-point> - setfval.32 %r15 <- 0.000000 + setfval.32 %r15 <- 0.000000e+00 fcmpoeq.32 %r16 <- %arg1, %r15 ret.32 %r16 @@ -50,7 +50,7 @@ ifnot: bfior: .L8: <entry-point> - setfval.32 %r19 <- 0.000000 + setfval.32 %r19 <- 0.000000e+00 fcmpune.1 %r20 <- %arg1, %r19 fcmpune.1 %r23 <- %arg2, %r19 or.1 %r24 <- %r20, %r23 @@ -61,7 +61,7 @@ bfior: ifior: .L10: <entry-point> - setfval.32 %r29 <- 0.000000 + setfval.32 %r29 <- 0.000000e+00 fcmpune.1 %r30 <- %arg1, %r29 fcmpune.1 %r33 <- %arg2, %r29 or.1 %r34 <- %r30, %r33 @@ -72,7 +72,7 @@ ifior: bfand: .L12: <entry-point> - setfval.32 %r38 <- 0.000000 + setfval.32 %r38 <- 0.000000e+00 fcmpune.1 %r39 <- %arg1, %r38 fcmpune.1 %r42 <- %arg2, %r38 and.1 %r43 <- %r39, %r42 @@ -83,7 +83,7 @@ bfand: ifand: .L14: <entry-point> - setfval.32 %r48 <- 0.000000 + setfval.32 %r48 <- 0.000000e+00 fcmpune.1 %r49 <- %arg1, %r48 fcmpune.1 %r52 <- %arg2, %r48 and.1 %r53 <- %r49, %r52 diff --git a/validation/optim/lsr-asr.c b/validation/optim/lsr-asr.c new file mode 100644 index 00000000..aee46940 --- /dev/null +++ b/validation/optim/lsr-asr.c @@ -0,0 +1,42 @@ +int lsrasr0(unsigned int x) +{ + return ((int) (x >> 15)) >> 15; +} + +int lsrasr1(unsigned int x) +{ + return ((int) (x >> 16)) >> 15; +} + +int lsrasr2(unsigned int x) +{ + return ((int) (x >> 16)) >> 16; +} + +/* + * check-name: lsr-asr + * check-command: test-linearize -Wno-decl $file + * + * check-output-start +lsrasr0: +.L0: + <entry-point> + lsr.32 %r3 <- %arg1, $30 + ret.32 %r3 + + +lsrasr1: +.L2: + <entry-point> + lsr.32 %r7 <- %arg1, $31 + ret.32 %r7 + + +lsrasr2: +.L4: + <entry-point> + ret.32 $0 + + + * check-output-end + */ diff --git a/validation/optim/shift-big.c b/validation/optim/shift-big.c index da65c5cd..84bcd2ce 100644 --- a/validation/optim/shift-big.c +++ b/validation/optim/shift-big.c @@ -1,20 +1,29 @@ typedef unsigned int u32; typedef int s32; -static u32 lsr32(u32 a) { return a >> 32; } -static s32 asr32(s32 a) { return a >> 32; } -static u32 shl32(u32 a) { return a << 32; } +s32 asr31(s32 a) { return a >> 31; } +s32 asr32(s32 a) { return a >> 32; } +s32 asr33(s32 a) { return a >> 33; } + +u32 lsr31(u32 a) { return a >> 31; } +u32 lsr32(u32 a) { return a >> 32; } +u32 lsr33(u32 a) { return a >> 33; } + +u32 shl31(u32 a) { return a << 31; } +u32 shl32(u32 a) { return a << 32; } +u32 shl33(u32 a) { return a << 33; } /* * check-name: optim/shift-big.c - * check-command: test-linearize -fnormalize-pseudos $file + * check-command: test-linearize -Wno-decl -m64 $file * * check-error-ignore * check-output-start -lsr32: +asr31: .L0: <entry-point> - ret.32 $0 + asr.32 %r2 <- %arg1, $31 + ret.32 %r2 asr32: @@ -24,9 +33,48 @@ asr32: ret.32 %r5 -shl32: +asr33: .L4: <entry-point> + asr.32 %r8 <- %arg1, $33 + ret.32 %r8 + + +lsr31: +.L6: + <entry-point> + lsr.32 %r11 <- %arg1, $31 + ret.32 %r11 + + +lsr32: +.L8: + <entry-point> + ret.32 $0 + + +lsr33: +.L10: + <entry-point> + ret.32 $0 + + +shl31: +.L12: + <entry-point> + shl.32 %r20 <- %arg1, $31 + ret.32 %r20 + + +shl32: +.L14: + <entry-point> + ret.32 $0 + + +shl33: +.L16: + <entry-point> ret.32 $0 diff --git a/validation/optim/shift-shift.c b/validation/optim/shift-shift.c new file mode 100644 index 00000000..12a4b7d4 --- /dev/null +++ b/validation/optim/shift-shift.c @@ -0,0 +1,149 @@ +unsigned int shl0(unsigned int x) +{ + return x << 15 << 15; +} + +unsigned int shl1(unsigned int x) +{ + return x << 16 << 15; +} + +unsigned int shl2(unsigned int x) +{ + return x << 16 << 16; +} + +unsigned int shl3(unsigned int x) +{ + return x << 12 << 10 << 10; +} + + +unsigned int lsr0(unsigned int x) +{ + return x >> 15 >> 15; +} + +unsigned int lsr1(unsigned int x) +{ + return x >> 16 >> 15; +} + +unsigned int lsr2(unsigned int x) +{ + return x >> 16 >> 16; +} + +unsigned int lsr3(unsigned int x) +{ + return x >> 12 >> 10 >> 10; +} + + +int asr0(int x) +{ + return x >> 15 >> 15; +} + +int asr1(int x) +{ + return x >> 16 >> 15; +} + +int asr2(int x) +{ + return x >> 16 >> 16; +} + +int asr3(int x) +{ + return x >> 12 >> 10 >> 10; +} + +/* + * check-name: shift-shift + * check-command: test-linearize -Wno-decl $file + * + * check-output-start +shl0: +.L0: + <entry-point> + shl.32 %r3 <- %arg1, $30 + ret.32 %r3 + + +shl1: +.L2: + <entry-point> + shl.32 %r7 <- %arg1, $31 + ret.32 %r7 + + +shl2: +.L4: + <entry-point> + ret.32 $0 + + +shl3: +.L6: + <entry-point> + ret.32 $0 + + +lsr0: +.L8: + <entry-point> + lsr.32 %r20 <- %arg1, $30 + ret.32 %r20 + + +lsr1: +.L10: + <entry-point> + lsr.32 %r24 <- %arg1, $31 + ret.32 %r24 + + +lsr2: +.L12: + <entry-point> + ret.32 $0 + + +lsr3: +.L14: + <entry-point> + ret.32 $0 + + +asr0: +.L16: + <entry-point> + asr.32 %r37 <- %arg1, $30 + ret.32 %r37 + + +asr1: +.L18: + <entry-point> + asr.32 %r41 <- %arg1, $31 + ret.32 %r41 + + +asr2: +.L20: + <entry-point> + asr.32 %r45 <- %arg1, $31 + ret.32 %r45 + + +asr3: +.L22: + <entry-point> + asr.32 %r50 <- %arg1, $31 + ret.32 %r50 + + + * check-output-end + */ diff --git a/validation/optim/zext-asr.c b/validation/optim/zext-asr.c new file mode 100644 index 00000000..5f235ad8 --- /dev/null +++ b/validation/optim/zext-asr.c @@ -0,0 +1,13 @@ +unsigned short foo(unsigned short a) +{ + return a >> 16; +} + +/* + * check-name: zext-asr + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-contains: ret\\..*\\$0 + * check-output-excludes: asr\\. + */ diff --git a/validation/shift-negative.c b/validation/shift-negative.c new file mode 100644 index 00000000..fff5cf12 --- /dev/null +++ b/validation/shift-negative.c @@ -0,0 +1,17 @@ +unsigned int fn1(unsigned int a) { return a >> -1; } +unsigned int fn2(unsigned int a) { return a >> ~0; } + +unsigned int fo1(unsigned int a) { return a >> ((a & 0) | -1); } +unsigned int fo2(unsigned int a) { return a >> ((a & 0) ^ ~0); } + +/* + * check-name: shift-negative + * check-command: sparse -Wno-decl $file + * + * check-error-start +shift-negative.c:1:45: warning: shift count is negative (-1) +shift-negative.c:2:45: warning: shift count is negative (-1) +shift-negative.c:4:59: warning: shift count is negative (-1) +shift-negative.c:5:59: warning: shift count is negative (-1) + * check-error-end + */ diff --git a/validation/shift-undef.c b/validation/shift-undef.c index 54c8359b..4e94fa23 100644 --- a/validation/shift-undef.c +++ b/validation/shift-undef.c @@ -130,12 +130,12 @@ shift-undef.c:17:30: warning: shift too big (108) for type unsigned int shift-undef.c:18:30: warning: shift count is negative (-7) shift-undef.c:19:30: warning: shift count is negative (-8) shift-undef.c:20:30: warning: shift count is negative (-9) -shift-undef.c:21:29: warning: shift by bigger than operand's width -shift-undef.c:22:29: warning: shift by bigger than operand's width -shift-undef.c:23:29: warning: shift by bigger than operand's width -shift-undef.c:24:29: warning: shift by bigger than operand's width -shift-undef.c:25:29: warning: shift by bigger than operand's width -shift-undef.c:26:29: warning: shift by bigger than operand's width +shift-undef.c:21:29: warning: shift too big (109) for type int +shift-undef.c:22:29: warning: shift too big (110) for type unsigned int +shift-undef.c:23:29: warning: shift too big (111) for type unsigned int +shift-undef.c:24:29: warning: shift count is negative (-10) +shift-undef.c:25:29: warning: shift count is negative (-11) +shift-undef.c:26:29: warning: shift count is negative (-12) shift-undef.c:32:11: warning: shift too big (100) for type int shift-undef.c:33:11: warning: shift too big (101) for type unsigned int shift-undef.c:34:11: warning: shift too big (102) for type unsigned int @@ -154,11 +154,11 @@ shift-undef.c:46:30: warning: shift too big (108) for type unsigned int shift-undef.c:47:30: warning: shift count is negative (-7) shift-undef.c:48:30: warning: shift count is negative (-8) shift-undef.c:49:30: warning: shift count is negative (-9) -shift-undef.c:50:26: warning: shift by bigger than operand's width -shift-undef.c:51:26: warning: shift by bigger than operand's width -shift-undef.c:52:26: warning: shift by bigger than operand's width -shift-undef.c:53:26: warning: shift by bigger than operand's width -shift-undef.c:54:26: warning: shift by bigger than operand's width -shift-undef.c:55:26: warning: shift by bigger than operand's width +shift-undef.c:50:26: warning: shift too big (109) for type int +shift-undef.c:51:26: warning: shift too big (110) for type int +shift-undef.c:52:26: warning: shift too big (111) for type int +shift-undef.c:53:26: warning: shift count is negative (-10) +shift-undef.c:54:26: warning: shift count is negative (-11) +shift-undef.c:55:26: warning: shift count is negative (-12) * check-error-end */ |
