Bug 78503 - -Wint-in-bool-context false positive on unsigned multiplication
Summary: -Wint-in-bool-context false positive on unsigned multiplication
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2016-11-24 00:35 UTC by Martin Sebor
Modified: 2017-05-20 05:59 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2017-05-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Sebor 2016-11-24 00:35:21 UTC
GCC issues a -Wint-in-bool-context warning on the following test case and suggests using the AND expression instead.  The code is valid (it tries to avoid calling malloc with a zero argument) and the warning is a false positive.  The suggestion to use the AND expression also isn't very helpful here (it's confusing).  There is no obvious way the AND expression could be used while preserving the effects of the code.  Changing expression to (n * sizeof (int) != 0) does avoid the warning.

$ cat c.c && gcc -S -Wall c.c
void f (void*);

void g (unsigned n)
{
  void *p = (n * sizeof (int)) ? __builtin_malloc (n * sizeof (n)) : 0;
  f (p);
}
c.c: In function ‘g’:
c.c:5:16: warning: ‘*’ in boolean context, suggest ‘&&’ instead [-Wint-in-bool-context]
   void *p = (n * sizeof (int)) ? __builtin_malloc (n * sizeof (n)) : 0;
             ~~~^~~~~~~~~~~~~~~


Note that the test case has been distilled from a modified definition of the XALLOCAVEC macro in libiberty:

  #define XALLOCAVEC(T, N)   ((N) ? (T *) alloca (sizeof (T) * (N)) : (T *)0)

The modified definition which tries to prevent zero-size allocation then causes GCC to fail to bootstrap with errors like the following:

/src/gcc/svn/gcc/fold-const.c:1499:33: error: ‘*’ in boolean context, suggest ‘&&’ instead [-Werror=int-in-bool-context]
  elts = XALLOCAVEC (tree, nelts * 4);
/src/gcc/svn/gcc/../include/libiberty.h:356:28: note: in definition of macro ‘XALLOCAVEC’
 #define XALLOCAVEC(T, N) ((N) ? (T *) alloca (sizeof (T) * (N)) : (T *)0)
                            ^
Comment 1 jbeulich 2017-05-19 09:04:28 UTC
We have something similar in the Xen hypervisor sources:

#define __compat_access_ok(d, addr, size) \
    __compat_addr_ok(d, (unsigned long)(addr) + ((size) ? (size) - 1 : 0))

#define compat_access_ok(addr, size) \
    __compat_access_ok(current->domain, addr, size)

#define compat_array_access_ok(addr,count,size) \
    (likely((count) < (~0U / (size))) && \
     compat_access_ok(addr, (count) * (size)))

Instead of != 0 (which seems rather strange to not have the same effect of producing a warning) for now we're adding in zero, but the example shows clearly that replacing * by && is not an option here just like in the original example.

Assuming that there's no intention to eliminate such false positives, could we at least get a workaround allowing to suppress the warning which is going to be usable also on future compiler versions (just like I'd expect the presence/absence of != 0 to make not difference, I could imagine the + 0 to get eliminated before inspecting the expression for whether to emit the warning).

Disabling the warning altogether does not seem to be desirable.
Comment 2 Martin Sebor 2017-05-19 15:38:18 UTC
Confirming based on comment #1.  I CC the author of the warning for his input.
Comment 3 Bernd Edlinger 2017-05-20 05:59:07 UTC
It is on purpose that the warning gets suppressed
when "(N) != 0" or "(N) + 0" is used, so that won't
go away.

But may I suggest the following for the XALLOCAVEC macro:

#define XALLOCAVEC(T, N) ((N) > 0 ? (T *) alloca (sizeof (T) * (N)) : (T *)0)

this would also avoid possible warnings about alloca with negative N.