https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66963

            Bug ID: 66963
           Summary: __builtin_constant_p and __builtin_choose_expr do not
                    agree on what is a constexpr with -O2
           Product: gcc
           Version: 5.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nicstange at gmail dot com
  Target Milestone: ---

The first argument to __builtin_choose_expr() must be a constant expression.

However, at -O2, the following does not work:

  int foo (void)
  {
    const int a = 0;
    return __builtin_choose_expr(__builtin_choose_expr(__builtin_constant_p(a +
1), a + 1, 0),
                                 0, 0);
  }

test.c: In function ‘foo’:
test.c:4:10: error: first argument to ‘__builtin_choose_expr’ not a constant
   return __builtin_choose_expr(__builtin_choose_expr(__builtin_constant_p(a +
1), a + 1, 0),
          ^

Obviously, __builtin_constant_p() recognizes 'a+1' as being constant-foldable
and returns nonzero. This makes the inner __builtin_choose_expr() select its
second argument, i.e. 'a+1'. The outer __builtin_choose_expr() in turn refuses
to accept that 'a+1' as a constant expression for its condition argument
because it does not recognize it as a constexpr.


As a workaround, you can wrap the 'a+1' in a __builtin_expect() which seems to
apply constant-folding in the same way the __builtin_constant_p() does:
  __builtin_choose_expr(__builtin_choose_expr(__builtin_constant_p(a + 1),
                                              __builtin_expect(a + 1, 1), 0),
                        0, 0);

Thus, it looks like constant folding is not applied to
__builtin_choose_expr()'s first argument.

Reply via email to