@@ -1421,11 +1421,21 @@ instrument_object_size (gimple_stmt_iter
switch (TREE_CODE (t))
{
- case ARRAY_REF:
case COMPONENT_REF:
+ if (TREE_CODE (t) == COMPONENT_REF
+ && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE)
+ {
+ tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1));
+ t = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (t, 0),
+ repr, NULL_TREE);
+ }
+ break;
+ case ARRAY_REF:
case INDIRECT_REF:
case MEM_REF:
case VAR_DECL:
+ case PARM_DECL:
+ case RESULT_DECL:
break;
default:
return;
@@ -1446,8 +1456,7 @@ instrument_object_size (gimple_stmt_iter
|| bitsize != size_in_bytes * BITS_PER_UNIT)
return;
- bool decl_p = VAR_P (inner) || TREE_CODE (inner) == PARM_DECL
- || TREE_CODE (inner) == RESULT_DECL;
+ bool decl_p = DECL_P (inner);
tree base = decl_p ? inner : TREE_OPERAND (inner, 0);
tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
@@ -1464,14 +1473,15 @@ instrument_object_size (gimple_stmt_iter
break;
}
- if (!POINTER_TYPE_P (TREE_TYPE (base)) && !VAR_P (base))
+ if (!POINTER_TYPE_P (TREE_TYPE (base)) && !DECL_P (base))
return;
tree sizet;
- tree base_addr = build1 (ADDR_EXPR,
- build_pointer_type (TREE_TYPE (base)), base);
- unsigned HOST_WIDE_INT size = compute_builtin_object_size (decl_p ? base_addr
- : base, 0);
+ tree base_addr = base;
+ if (decl_p)
+ base_addr = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (base)), base);
+ unsigned HOST_WIDE_INT size = compute_builtin_object_size (base_addr, 0);
if (size != (unsigned HOST_WIDE_INT) -1)
sizet = build_int_cst (sizetype, size);
else if (optimize)
@@ -1479,7 +1489,7 @@ instrument_object_size (gimple_stmt_iter
/* Generate __builtin_object_size call. */
sizet = builtin_decl_explicit (BUILT_IN_OBJECT_SIZE);
- sizet = build_call_expr_loc (loc, sizet, 2, decl_p ? base_addr : base,
+ sizet = build_call_expr_loc (loc, sizet, 2, base_addr,
integer_zero_node);
sizet = force_gimple_operand_gsi (gsi, sizet, false, NULL_TREE, true,
GSI_SAME_STMT);
@@ -1492,8 +1502,7 @@ instrument_object_size (gimple_stmt_iter
/* ptr + sizeof (*ptr) - base */
t = fold_build2 (MINUS_EXPR, sizetype,
fold_convert (pointer_sized_int_node, ptr),
- fold_convert (pointer_sized_int_node,
- decl_p ? base_addr : base));
+ fold_convert (pointer_sized_int_node, base_addr));
t = fold_build2 (PLUS_EXPR, sizetype, t, TYPE_SIZE_UNIT (type));
/* Perhaps we can omit the check. */
On Thu, Sep 11, 2014 at 07:47:51PM +0200, Marek Polacek wrote: > So, how does this look now? Looks much better. There are some nits I'd change, like: 1) no need not to handle bitfields 2) IMHO it should handle PARM_DECL and RESULT_DECL alongside of VAR_DECL 3) decl_p IMHO should use just DECL_P 4) it doesn't make sense to build ADDR_EXPR if you are never going to use it Attaching some (incomplete) testcase I've used to look at the implementation, e.g. f1 is for testing how it plays together with -fsanitize=bounds (perhaps, maybe as a follow-up, we could optimize by looking for UBSAN_BOUNDS call with expected arguments in a few statements before array access (e.g. remember last UBSAN_BOUNDS seen in the same basic block) if inner is DECL_P), f2 to show a case which -fsanitize=bounds doesn't instrument, but -fsanitize=object-size should, f3/f4 the same with PARM_DECL, f5/f6 unsuccessful attempt for RESULT_DECL, f7/f8 bitfield tests, f9 something where __bos is folded very early (already before objsz1 pass), f10 where __bos is folded during objsz1 pass. If you want to turn parts of that testcase into real /ubsan/ tests, go ahead. Other than that, if you are fine with following changes, can you incorporate them into the patch and retest? Thanks. Jakub struct T { char d[8]; int e; }; struct T t = { "abcdefg", 1 }; #ifdef __cplusplus struct C { C () : d("abcdefg"), e(1) {} C (const C &x) { __builtin_memcpy (d, x.d, 8); e = x.e; } ~C () {} char d[8]; int e; }; #endif struct U { int a : 5; int b : 19; int c : 8; }; struct S { struct U d[10]; }; struct S s; int f1 (int i) { return t.d[i]; } int f2 (int i) { char *p = t.d; p += i; return *p; } int f3 (struct T x, int i) { return x.d[i]; } int f4 (struct T x, int i) { char *p = x.d; p += i; return *p; } #ifdef __cplusplus struct C f5 (int i) { struct C x; x.d[i] = 'z'; return x; } struct C f6 (int i) { struct C x; char *p = x.d; p += i; *p = 'z'; return x; } #endif int f7 (int i) { return s.d[i].b; } int f8 (int i) { struct U *u = s.d; u += i; return u->b; } int f9 (void) { char *p = t.d; p += 4; return *p; } int f10 (int x) { char *p = t.d + (x ? 6 : 3); return *p; }