diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile | 4 | ||||
| -rwxr-xr-x | cgcc | 2 | ||||
| -rw-r--r-- | evaluate.c | 34 | ||||
| -rw-r--r-- | expand.c | 28 | ||||
| -rw-r--r-- | gcc-attr-list.h | 1 | ||||
| -rw-r--r-- | linearize.c | 8 | ||||
| -rw-r--r-- | parse.c | 20 | ||||
| -rw-r--r-- | sparse.1 | 15 | ||||
| -rw-r--r-- | symbol.h | 4 | ||||
| -rw-r--r-- | validation/Waddress-space-all-attr.c | 14 | ||||
| -rw-r--r-- | validation/Waddress-space-from.c | 63 | ||||
| -rw-r--r-- | validation/Waddress-space-strict.c | 1 | ||||
| -rw-r--r-- | validation/Wcast-to-as.c | 36 | ||||
| -rw-r--r-- | validation/constexpr-constcond.c | 10 | ||||
| -rw-r--r-- | validation/constexpr-shift.c | 12 | ||||
| -rw-r--r-- | validation/enum-sign-extend.c | 12 | ||||
| -rw-r--r-- | validation/eval-bad-assign1.c | 14 | ||||
| -rw-r--r-- | validation/eval-bad-assign2.c | 22 | ||||
| -rw-r--r-- | validation/expand/bad-shift.c | 64 | ||||
| -rw-r--r-- | validation/ioc-typecheck.c | 4 |
21 files changed, 321 insertions, 48 deletions
@@ -5,6 +5,7 @@ *.so .*.swp *.pyc +*~ # generated version.h @@ -1,4 +1,4 @@ -VERSION=0.6.0 +VERSION=0.6.1-rc1 ######################################################################## # The following variables can be overwritten from the command line @@ -165,7 +165,7 @@ ifeq ($(shell expr "$(LLVM_VERSION)" : '[3-9]\.'),2) LLVM_PROGS := sparse-llvm $(LLVM_PROGS): LD := g++ LLVM_LDFLAGS := $(shell $(LLVM_CONFIG) --ldflags) -LLVM_CFLAGS := -I$(shell $(LLVM_CONFIG) --includedir) +LLVM_CFLAGS := $(shell $(LLVM_CONFIG) --cppflags) LLVM_LIBS := $(shell $(LLVM_CONFIG) --libs) LLVM_LIBS += $(shell $(LLVM_CONFIG) --system-libs 2>/dev/null) LLVM_LIBS += $(shell $(LLVM_CONFIG) --cxxflags | grep -F -q -e '-stdlib=libc++' && echo -lc++) @@ -52,7 +52,7 @@ while (@ARGV) { $m32 = 1 if /^-m32$/; $m64 = 1 if /^-m64$/; - $gendeps = 1 if /^-(M|MM|MD|MMD)$/; + $gendeps = 1 if /^-(M|MM)$/; if (/^-target=(.*)$/) { $check .= &add_specs ($1); @@ -1178,20 +1178,22 @@ static struct symbol *evaluate_conditional_expression(struct expression *expr) expr->flags = (expr->conditional->flags & (*cond)->flags & expr->cond_false->flags & ~CEF_CONST_MASK); /* - * A conditional operator yields a particular constant - * expression type only if all of its three subexpressions are - * of that type [6.6(6), 6.6(8)]. - * As an extension, relax this restriction by allowing any - * constant expression type for the condition expression. - * - * A conditional operator never yields an address constant - * [6.6(9)]. - * However, as an extension, if the condition is any constant - * expression, and the true and false expressions are both - * address constants, mark the result as an address constant. + * In the standard, it is defined that an integer constant expression + * shall only have operands that are themselves constant [6.6(6)]. + * While this definition is very clear for expressions that need all + * their operands to be evaluated, for conditional expressions with a + * constant condition things are much less obvious. + * So, as an extension, do the same as GCC seems to do: + * Consider a conditional expression with a constant condition + * as having the same constantness as the argument corresponding + * to the truth value (including in the case of address constants + * which are defined more stricly [6.6(9)]). */ - if (expr->conditional->flags & (CEF_ACE | CEF_ADDR)) - expr->flags = (*cond)->flags & expr->cond_false->flags & ~CEF_CONST_MASK; + if (expr->conditional->flags & (CEF_ACE | CEF_ADDR)) { + int is_true = expr_truth_value(expr->conditional); + struct expression *arg = is_true ? *cond : expr->cond_false; + expr->flags = arg->flags & ~CEF_CONST_MASK; + } lclass = classify_type(ltype, <ype); rclass = classify_type(rtype, &rtype); @@ -3016,14 +3018,14 @@ static struct symbol *evaluate_cast(struct expression *expr) } } - if (ttype == &ulong_ctype && !Wcast_from_as) + if ((ttype == &ulong_ctype || ttype == uintptr_ctype) && !Wcast_from_as) tas = &bad_address_space; else if (tclass == TYPE_PTR) { examine_pointer_target(ttype); tas = ttype->ctype.as; } - if (stype == &ulong_ctype && !Wcast_from_as) + if ((stype == &ulong_ctype || stype == uintptr_ctype)) sas = &bad_address_space; else if (sclass == TYPE_PTR) { examine_pointer_target(stype); @@ -3385,7 +3387,7 @@ void check_duplicates(struct symbol *sym) } if (!declared) { unsigned long mod = sym->ctype.modifiers; - if (mod & (MOD_STATIC | MOD_REGISTER)) + if (mod & (MOD_STATIC | MOD_REGISTER | MOD_EXT_VISIBLE)) return; if (!(mod & MOD_TOPLEVEL)) return; @@ -47,6 +47,11 @@ static int expand_expression(struct expression *); static int expand_statement(struct statement *); + +// If set, don't issue a warning on divide-by-0, invalid shift, ... +// and don't mark the expression as erroneous but leave it as-is. +// This allows testing some characteristics of the expression +// without creating any side-effects (e.g.: is_zero_constant()). static int conservative; static int expand_symbol_expression(struct expression *expr) @@ -166,19 +171,14 @@ Float: expr->type = EXPR_FVALUE; } -static void check_shift_count(struct expression *expr, struct expression *right) +static void warn_shift_count(struct expression *expr, struct symbol *ctype, long long count) { - struct symbol *ctype = expr->ctype; - long long count = get_longlong(right); - if (count < 0) { if (!Wshift_count_negative) return; warning(expr->pos, "shift count is negative (%lld)", count); return; } - if (count < ctype->bit_size) - return; if (ctype->type == SYM_NODE) ctype = ctype->ctype.base_type; @@ -187,6 +187,19 @@ static void check_shift_count(struct expression *expr, struct expression *right) warning(expr->pos, "shift too big (%llu) for type %s", count, show_typename(ctype)); } +/* Return true if constant shift size is valid */ +static bool check_shift_count(struct expression *expr, struct expression *right) +{ + struct symbol *ctype = expr->ctype; + long long count = get_longlong(right); + + if (count >= 0 && count < ctype->bit_size) + return true; + if (!conservative) + warn_shift_count(expr, ctype, count); + return false; +} + /* * CAREFUL! We need to get the size and sign of the * result right! @@ -205,9 +218,8 @@ static int simplify_int_binop(struct expression *expr, struct symbol *ctype) return 0; r = right->value; if (expr->op == SPECIAL_LEFTSHIFT || expr->op == SPECIAL_RIGHTSHIFT) { - if (conservative) + if (!check_shift_count(expr, right)) return 0; - check_shift_count(expr, right); } if (left->type != EXPR_VALUE) return 0; diff --git a/gcc-attr-list.h b/gcc-attr-list.h index 8da31435..c7800175 100644 --- a/gcc-attr-list.h +++ b/gcc-attr-list.h @@ -42,7 +42,6 @@ GCC_ATTR(either) GCC_ATTR(error) GCC_ATTR(exception) GCC_ATTR(exception_handler) -GCC_ATTR(externally_visible) GCC_ATTR(far) GCC_ATTR(fast_interrupt) GCC_ATTR(fastcall) diff --git a/linearize.c b/linearize.c index 09b1c7ee..30ed2a30 100644 --- a/linearize.c +++ b/linearize.c @@ -1764,7 +1764,7 @@ static pseudo_t linearize_cond_branch(struct entrypoint *ep, struct expression * { pseudo_t cond; - if (!expr || !bb_reachable(ep->active)) + if (!expr || !valid_type(expr->ctype) || !bb_reachable(ep->active)) return VOID; switch (expr->type) { @@ -1864,7 +1864,7 @@ static void linearize_argument(struct entrypoint *ep, struct symbol *arg, int nr static pseudo_t linearize_expression(struct entrypoint *ep, struct expression *expr) { - if (!expr) + if (!expr || !valid_type(expr->ctype)) return VOID; current_pos = expr->pos; @@ -2419,6 +2419,10 @@ static pseudo_t linearize_statement(struct entrypoint *ep, struct statement *stm bb_true = alloc_basic_block(ep, stmt->pos); bb_false = endif = alloc_basic_block(ep, stmt->pos); + // If the condition is invalid, the following + // statement(s) are not evaluated. + if (!cond || !valid_type(cond->ctype)) + return VOID; linearize_cond_branch(ep, cond, bb_true, bb_false); set_activeblock(ep, bb_true); @@ -82,6 +82,7 @@ typedef struct token *attr_t(struct token *, struct symbol *, static attr_t attribute_packed, attribute_aligned, attribute_modifier, + attribute_ext_visible, attribute_bitwise, attribute_address_space, attribute_context, attribute_designated_init, @@ -373,6 +374,10 @@ static struct symbol_op attr_mod_op = { .attribute = attribute_modifier, }; +static struct symbol_op ext_visible_op = { + .attribute = attribute_ext_visible, +}; + static struct symbol_op attr_bitwise_op = { .attribute = attribute_bitwise, }; @@ -562,6 +567,8 @@ static struct init_keyword { {"const", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__const", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__const__", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, + {"externally_visible", NS_KEYWORD, .op = &ext_visible_op }, + {"__externally_visible__", NS_KEYWORD, .op = &ext_visible_op }, { "mode", NS_KEYWORD, .op = &mode_op }, { "__mode__", NS_KEYWORD, .op = &mode_op }, @@ -890,10 +897,8 @@ static void cast_enum_list(struct symbol_list *list, struct symbol *base_type) expr->ctype = &int_ctype; continue; } - expr->ctype = base_type; - if (ctype->bit_size == base_type->bit_size) - continue; cast_value(expr, base_type, expr, ctype); + expr->ctype = base_type; } END_FOR_EACH_PTR(sym); } @@ -1106,6 +1111,12 @@ static struct token *attribute_modifier(struct token *token, struct symbol *attr return token; } +static struct token *attribute_ext_visible(struct token *token, struct symbol *attr, struct decl_state *ctx) +{ + ctx->is_ext_visible = 1; + return token; +} + static struct token *attribute_bitwise(struct token *token, struct symbol *attr, struct decl_state *ctx) { if (Wbitwise) @@ -1343,7 +1354,8 @@ static unsigned long storage_modifiers(struct decl_state *ctx) [SRegister] = MOD_REGISTER }; return mod[ctx->storage_class] | (ctx->is_inline ? MOD_INLINE : 0) - | (ctx->is_tls ? MOD_TLS : 0); + | (ctx->is_tls ? MOD_TLS : 0) + | (ctx->is_ext_visible ? MOD_EXT_VISIBLE : 0); } static void set_storage_class(struct position *pos, struct decl_state *ctx, int class) @@ -41,9 +41,16 @@ Sparse allows an extended attribute on pointers, which designates a pointer target in address space \fIid\fR (an identifier or a constant integer). With \fB\-Waddress\-space\fR, Sparse treats pointers with -identical target types but different address spaces as distinct types. To -override this warning, such as for functions which convert pointers between -address spaces, use a type that includes \fB__attribute__((force))\fR. +identical target types but different address spaces as distinct types and +will warn accordingly. + +Sparse will also warn on casts which remove the address space (casts to an +integer type or to a plain pointer type). An exception to this is when the +destination type is \fBuintptr_t\fR (or \fBunsigned long\fR) since such casts +are often used to "get a pointer value representation in an integer type" and +such values are independent of the address space. + +To override these warnings, use a type that includes \fB__attribute__((force))\fR. Sparse issues these warnings by default. To turn them off, use \fB\-Wno\-address\-space\fR. @@ -97,6 +104,8 @@ Sparse does not issues these warnings by default. Warn about casts which add an address space to a pointer type. A cast that includes \fB__attribute__((force))\fR will suppress this warning. +No warning is generated if the original type is \fBuintptr_t\fR +(or \fBunsigned long\fR). Sparse does not issue these warnings by default. . @@ -110,6 +110,7 @@ struct decl_state { struct ident **ident; struct symbol_op *mode; unsigned char prefer_abstract, is_inline, storage_class, is_tls; + unsigned char is_ext_visible; }; struct symbol_op { @@ -237,6 +238,7 @@ struct symbol { #define MOD_NOCAST 0x04000000 #define MOD_NODEREF 0x08000000 #define MOD_NORETURN 0x10000000 +#define MOD_EXT_VISIBLE 0x20000000 #define MOD_ACCESS (MOD_ASSIGNED | MOD_ADDRESSABLE) @@ -246,7 +248,7 @@ struct symbol { #define MOD_LONG_ALL (MOD_LONG | MOD_LONGLONG | MOD_LONGLONGLONG) #define MOD_SPECIFIER (MOD_CHAR | MOD_SHORT | MOD_LONG_ALL | MOD_SIGNEDNESS) #define MOD_SIZE (MOD_CHAR | MOD_SHORT | MOD_LONG_ALL) -#define MOD_IGNORE (MOD_STORAGE | MOD_ACCESS | MOD_USERTYPE | MOD_EXPLICITLY_SIGNED) +#define MOD_IGNORE (MOD_STORAGE | MOD_ACCESS | MOD_USERTYPE | MOD_EXPLICITLY_SIGNED | MOD_EXT_VISIBLE) #define MOD_QUALIFIER (MOD_CONST | MOD_VOLATILE | MOD_RESTRICT | MOD_ATOMIC) #define MOD_PTRINHERIT (MOD_QUALIFIER | MOD_NODEREF | MOD_NORETURN | MOD_NOCAST) /* modifiers preserved by typeof() operator */ diff --git a/validation/Waddress-space-all-attr.c b/validation/Waddress-space-all-attr.c index 5b2d0f92..b0c17693 100644 --- a/validation/Waddress-space-all-attr.c +++ b/validation/Waddress-space-all-attr.c @@ -13,27 +13,27 @@ static void expl(obj_t __kernel *k, obj_t __iomem *o, obj_t __user *p, obj_t __percpu *pc, obj_t __rcu *r) { - (ulong)(k); + (ulong)(k); (__UINTPTR_TYPE__)(k); (void *)(k); (obj_t*)(k); (obj_t __kernel*)(k); - (ulong)(o); + (ulong)(o); (__UINTPTR_TYPE__)(o); (void *)(o); (obj_t*)(o); (obj_t __iomem*)(o); - (ulong)(p); + (ulong)(p); (__UINTPTR_TYPE__)(p); (void *)(p); (obj_t*)(p); (obj_t __user*)(p); - (ulong)(pc); + (ulong)(pc); (__UINTPTR_TYPE__)(pc); (void *)(pc); (obj_t*)(pc); (obj_t __percpu*)(pc); - (ulong)(r); + (ulong)(r); (__UINTPTR_TYPE__)(r); (void *)(r); (obj_t*)(r); (obj_t __rcu*)(r); @@ -45,15 +45,19 @@ static void expl(obj_t __kernel *k, obj_t __iomem *o, * * check-error-start Waddress-space-all-attr.c:21:10: warning: cast removes address space '<asn:2>' of expression +Waddress-space-all-attr.c:21:22: warning: cast removes address space '<asn:2>' of expression Waddress-space-all-attr.c:22:10: warning: cast removes address space '<asn:2>' of expression Waddress-space-all-attr.c:23:10: warning: cast removes address space '<asn:2>' of expression Waddress-space-all-attr.c:26:10: warning: cast removes address space '<asn:1>' of expression +Waddress-space-all-attr.c:26:22: warning: cast removes address space '<asn:1>' of expression Waddress-space-all-attr.c:27:10: warning: cast removes address space '<asn:1>' of expression Waddress-space-all-attr.c:28:10: warning: cast removes address space '<asn:1>' of expression Waddress-space-all-attr.c:31:10: warning: cast removes address space '<asn:3>' of expression +Waddress-space-all-attr.c:31:23: warning: cast removes address space '<asn:3>' of expression Waddress-space-all-attr.c:32:10: warning: cast removes address space '<asn:3>' of expression Waddress-space-all-attr.c:33:10: warning: cast removes address space '<asn:3>' of expression Waddress-space-all-attr.c:36:10: warning: cast removes address space '<asn:4>' of expression +Waddress-space-all-attr.c:36:22: warning: cast removes address space '<asn:4>' of expression Waddress-space-all-attr.c:37:10: warning: cast removes address space '<asn:4>' of expression Waddress-space-all-attr.c:38:10: warning: cast removes address space '<asn:4>' of expression * check-error-end diff --git a/validation/Waddress-space-from.c b/validation/Waddress-space-from.c new file mode 100644 index 00000000..317a205b --- /dev/null +++ b/validation/Waddress-space-from.c @@ -0,0 +1,63 @@ + +#define __kernel __attribute__((address_space(0))) +#define __user __attribute__((address_space(__user))) +#define __iomem __attribute__((address_space(__iomem))) +#define __percpu __attribute__((address_space(__percpu))) +#define __rcu __attribute__((address_space(__rcu))) + + +typedef struct s obj_t; + +static void expl(obj_t __kernel *k, obj_t __iomem *o, + obj_t __user *p, obj_t __percpu *pc, + obj_t __rcu *r) +{ + (__UINTPTR_TYPE__)(k); // OK + (unsigned long)(k); // OK + (void *)(k); // OK + (obj_t*)(k); // OK + (obj_t __kernel*)(k); // OK + + (__UINTPTR_TYPE__)(o); // OK + (unsigned long)(o); // OK + (void *)(o); + (obj_t*)(o); + (obj_t __iomem*)(o); // OK + + (__UINTPTR_TYPE__)(p); // OK + (unsigned long)(p); // OK + (void *)(p); + (obj_t*)(p); + (obj_t __user*)(p); // OK + + (__UINTPTR_TYPE__)(pc); // OK + (unsigned long)(pc); // OK + (void *)(pc); + (obj_t*)(pc); + (obj_t __percpu*)(pc); // OK + + (__UINTPTR_TYPE__)(r); // OK + (unsigned long)(r); // OK + (void *)(r); + (obj_t*)(r); + (obj_t __rcu*)(r); // OK +} + +/* + * check-name: Waddress-space-from + * check-command: sparse -Wno-cast-from-as $file + * check-description: Test the removal of AS from a pointer but only + * in the non-strict variant where casts to ulong (or uintptr_t) + * are allowed. + * + * check-error-start +Waddress-space-from.c:23:10: warning: cast removes address space '__iomem' of expression +Waddress-space-from.c:24:10: warning: cast removes address space '__iomem' of expression +Waddress-space-from.c:29:10: warning: cast removes address space '__user' of expression +Waddress-space-from.c:30:10: warning: cast removes address space '__user' of expression +Waddress-space-from.c:35:10: warning: cast removes address space '__percpu' of expression +Waddress-space-from.c:36:10: warning: cast removes address space '__percpu' of expression +Waddress-space-from.c:41:10: warning: cast removes address space '__rcu' of expression +Waddress-space-from.c:42:10: warning: cast removes address space '__rcu' of expression + * check-error-end + */ diff --git a/validation/Waddress-space-strict.c b/validation/Waddress-space-strict.c index 7987eb1d..a1c5b277 100644 --- a/validation/Waddress-space-strict.c +++ b/validation/Waddress-space-strict.c @@ -27,7 +27,6 @@ static void expl(ulong u, void *v, obj_t *o, obj_t __user *p) * check-command: sparse -Wcast-from-as -Wcast-to-as $file * * check-error-start -Waddress-space-strict.c:9:10: warning: cast adds address space '<asn:1>' to expression Waddress-space-strict.c:12:10: warning: cast adds address space '<asn:1>' to expression Waddress-space-strict.c:17:10: warning: cast adds address space '<asn:1>' to expression Waddress-space-strict.c:19:10: warning: cast removes address space '<asn:1>' of expression diff --git a/validation/Wcast-to-as.c b/validation/Wcast-to-as.c new file mode 100644 index 00000000..8c512091 --- /dev/null +++ b/validation/Wcast-to-as.c @@ -0,0 +1,36 @@ +#define __user __attribute__((address_space(1))) + +typedef __UINTPTR_TYPE__ uintptr_t; +typedef unsigned long ulong; +typedef struct s obj_t; + +static void expl(ulong u, uintptr_t uip, void *v, obj_t *o, obj_t __user *p) +{ + (obj_t*)(u); + (obj_t __user*)(u); + + (obj_t*)(uip); + (obj_t __user*)(uip); + + (obj_t*)(v); + (obj_t __user*)(v); + + (ulong)(o); + (void *)(o); + (obj_t*)(o); + (obj_t __user*)(o); + + (ulong)(p); + (obj_t __user*)(p); + +} + +/* + * check-name: cast-to-as + * check-command: sparse -Wcast-to-as $file + * + * check-error-start +Wcast-to-as.c:16:10: warning: cast adds address space '<asn:1>' to expression +Wcast-to-as.c:21:10: warning: cast adds address space '<asn:1>' to expression + * check-error-end + */ diff --git a/validation/constexpr-constcond.c b/validation/constexpr-constcond.c new file mode 100644 index 00000000..d98da3dc --- /dev/null +++ b/validation/constexpr-constcond.c @@ -0,0 +1,10 @@ +extern int var; + +static int a[] = { + [0 ? var : 1] = 0, + [1 ? 2 : var] = 0, +}; + +/* + * check-name: constexprness in constant conditionals + */ diff --git a/validation/constexpr-shift.c b/validation/constexpr-shift.c new file mode 100644 index 00000000..df01b74e --- /dev/null +++ b/validation/constexpr-shift.c @@ -0,0 +1,12 @@ +#define __is_constexpr(x) \ + (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8))) + +static void test(int x) { + static int b[] = { + [__builtin_choose_expr(__is_constexpr(1 << 1), 1, x)] = 0, + }; +} + +/* + * check-name: constexpr-shift + */ diff --git a/validation/enum-sign-extend.c b/validation/enum-sign-extend.c new file mode 100644 index 00000000..d852c934 --- /dev/null +++ b/validation/enum-sign-extend.c @@ -0,0 +1,12 @@ +enum num { + a = 0x80000000, + b = -1, +}; + +_Static_assert([typeof(b)] == [long], "type"); +_Static_assert(b == -1L, "value"); + +/* + * check-name: enum-sign-extend + * check-command: sparse -m64 $file + */ diff --git a/validation/eval-bad-assign1.c b/validation/eval-bad-assign1.c new file mode 100644 index 00000000..57138c7a --- /dev/null +++ b/validation/eval-bad-assign1.c @@ -0,0 +1,14 @@ +static void kos(int *r, int a) +{ + r = ({ __builtin_types_compatible_p(int, int); }); +} + +/* + * check-name: eval-bad-assign1 + * + * check-error-start +eval-bad-assign1.c:3:11: warning: incorrect type in assignment (different base types) +eval-bad-assign1.c:3:11: expected int *r +eval-bad-assign1.c:3:11: got int + * check-error-end + */ diff --git a/validation/eval-bad-assign2.c b/validation/eval-bad-assign2.c new file mode 100644 index 00000000..4d08cb90 --- /dev/null +++ b/validation/eval-bad-assign2.c @@ -0,0 +1,22 @@ +struct s { + char c[1]; +}; + +struct s fun(void); + + +static void foo(void) +{ + char c[1]; + c = fun().c; +} + +/* + * check-name: eval-bad-assign2 + * + * check-error-start +eval-bad-assign2.c:11:11: warning: incorrect type in assignment (invalid types) +eval-bad-assign2.c:11:11: expected char c[1] +eval-bad-assign2.c:11:11: got char * + * check-error-end + */ diff --git a/validation/expand/bad-shift.c b/validation/expand/bad-shift.c new file mode 100644 index 00000000..22c4341f --- /dev/null +++ b/validation/expand/bad-shift.c @@ -0,0 +1,64 @@ +#define MAX (sizeof(int) * __CHAR_BIT__) + +static int lmax(int a) +{ + return 1 << MAX; +} + +static int lneg(int a) +{ + return 1 << -1; +} + +static int rmax(int a) +{ + return 1 >> MAX; +} + +static int rneg(int a) +{ + return 1 >> -1; +} + +/* + * check-name: bad-shift + * check-command: test-linearize -Wno-decl $file + * + * check-output-start +lmax: +.L0: + <entry-point> + shl.32 %r1 <- $1, $32 + ret.32 %r1 + + +lneg: +.L2: + <entry-point> + shl.32 %r3 <- $1, $0xffffffff + ret.32 %r3 + + +rmax: +.L4: + <entry-point> + asr.32 %r5 <- $1, $32 + ret.32 %r5 + + +rneg: +.L6: + <entry-point> + asr.32 %r7 <- $1, $0xffffffff + ret.32 %r7 + + + * check-output-end + * + * check-error-start +expand/bad-shift.c:5:18: warning: shift too big (32) for type int +expand/bad-shift.c:10:18: warning: shift count is negative (-1) +expand/bad-shift.c:15:18: warning: shift too big (32) for type int +expand/bad-shift.c:20:18: warning: shift count is negative (-1) + * check-error-end + */ diff --git a/validation/ioc-typecheck.c b/validation/ioc-typecheck.c index 34b37d31..7780773b 100644 --- a/validation/ioc-typecheck.c +++ b/validation/ioc-typecheck.c @@ -4,8 +4,4 @@ static unsigned iocnrs[] = { }; /* * check-name: integer constant & conditional expression - * check-known-to-fail - * - * check-error-start - * check-error-end */ |
