&& CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS;
}
+/* Return true iff t is COND_EXPR with arg 2 == VOID_CST. */
+
+bool
+ubsan_compound_instrumented_expr_p (const_tree t)
+{
+ if (TREE_CODE (t) != COND_EXPR)
+ return false;
+
+ return TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 2)) == VOID_CST;
+}
+
/* Instrument an ARRAY_REF, if it hasn't already been instrumented.
IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
extern tree ubsan_instrument_return (location_t);
extern tree ubsan_instrument_bounds (location_t, tree, tree *, bool);
extern bool ubsan_array_ref_instrumented_p (const_tree);
+extern bool ubsan_compound_instrumented_expr_p (const_tree);
extern void ubsan_maybe_instrument_array_ref (tree *, bool);
extern void ubsan_maybe_instrument_reference (tree);
extern void ubsan_maybe_instrument_member_call (tree, bool);
if (instrument_expr != NULL)
{
- if (flag_sanitize & SANITIZE_UI_OVERFLOW)
+ if ((flag_sanitize & SANITIZE_UI_OVERFLOW)
+ && !ubsan_compound_instrumented_expr_p (instrument_expr))
{
/* Inherit side effects. TODO: what another attributes should be
inherited? */
if (instrument_expr != NULL)
{
- if (flag_sanitize & SANITIZE_UI_OVERFLOW)
+ if ((flag_sanitize & SANITIZE_UI_OVERFLOW)
+ && !ubsan_compound_instrumented_expr_p (instrument_expr))
{
/* Inherit side effects. TODO: what another attributes should be
inherited? */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fsyntax-only -fsanitize=shift,unsigned-integer-overflow" } */
+
+#define CHECK_UI(type) \
+type foo_##type (type n) \
+ { \
+ type x = n; \
+ x <<= n; \
+ return x << n; \
+}
+
+typedef unsigned int uint ;
+typedef unsigned int ulong ;
+
+/* Both singed and unsigned were affected. */
+CHECK_UI(int);
+CHECK_UI(uint);
+CHECK_UI(long);
+CHECK_UI(ulong);