Bug 54021 - [c++0x] __builtin_constant_p should be constexpr
Summary: [c++0x] __builtin_constant_p should be constexpr
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: unknown
: P3 enhancement
Target Milestone: 4.8.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2012-07-18 19:52 UTC by Andy Lutomirski
Modified: 2017-02-28 18:38 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andy Lutomirski 2012-07-18 19:52:07 UTC
It's hard to tell how __builtin_constant_p works right now, due to PR54020.

// Preliminaries.
extern int nonconst_func(int);
constexpr int identity(int x) { return x; }
constexpr int zero() { return identity(0); }
constexpr int one() { return identity(1); }

// These are the same.  Only the latter is accepted, though.
// I suspect that the acceptance of the latter is due to the bug above.
constexpr int rejected_const_4(int x) { return __builtin_constant_p(x) ? 4 : nonconst_func(x); }
constexpr int accepted_const_4(int x) { return identity(__builtin_constant_p(x)) ? 4 : nonconst_func(x); }

// This is rejected.  I would like it to work.
constexpr int four = accepted_const_4(1);

The ability to use the construction __builtin_constant_p(x) ? const_func(x) : nonconst_func(x) in constexpr context would be quite powerful.
Comment 1 Jakub Jelinek 2012-07-19 06:53:11 UTC
This is rejected only at -O0 and quite matches how __builtin_constant_p normally behaves at -O0 - you really need a constant right in the __builtin_constant_p argument, everything else results in 0.  With -O1 and above you get BUILTIN_CONSTANT_P not folded right away to 0 if not constant and whether it in the end folds to 0 or 1 depends on optimization, whether a constant is propagated to it or not.
Comment 2 Jakub Jelinek 2012-07-19 07:12:18 UTC
Perhaps the C++ FE could when parsing a constexpr function during finish_call_expr of __builtin_constant_p just temporarily force optimize = 1
if it is zero to prevent folding it to 0 (or alternatively, if it folds to 0, build it non-folded), it would be an extension over how this builtin behaves right now, on the other side as constexpr is "optimized" even at -O0 it would match the intent of the builtin.  The question is if/when it will be actually folded to 0 afterwards if not in constexpr context.
Comment 3 Jason Merrill 2012-07-19 20:02:13 UTC
Author: jason
Date: Thu Jul 19 20:02:08 2012
New Revision: 189677

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=189677
Log:
	PR c++/54021
	* call.c (build_cxx_call): Set optimize when folding
	__builtin_constant_p in a constexpr function.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin2.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/testsuite/ChangeLog
Comment 4 Jason Merrill 2012-07-19 20:57:21 UTC
I'm not sure when exactly it gets folded later, but it does seem to happen appropriately.
Comment 5 David Stone 2012-09-08 21:36:10 UTC
I'm running into some issues with this bug, and it's much broader than the test cases suggest. On gcc 4.7.0, this is what happens:

int main() {
    int x = 0;
    // This assigns false to a:
    bool const a = __builtin_constant_p(x);
    // This assigns true to b:
    bool const b = __builtin_constant_p(__builtin_constant_p(x));
    // This causes "error: the value of 'x' is not usable in a constant expression"
    constexpr bool c = __builtin_constant_p(x);
}
Comment 6 Andy Lutomirski 2012-09-08 22:29:17 UTC
I think that's correct.  x isn't a standards-mandated constant expression, so __builtin_constant_p depends on optimization level and probably shouldn't be allowed as a constexpr.
Comment 7 David Stone 2012-09-09 06:00:37 UTC
That seems to me like saying that `constexpr bool d = sizeof(x);` should be disallowed because it uses a non-constexpr. You're not using the value of x, just a property about it. Whether a value is constexpr is guaranteed to be known at compile time, and so should be usable as a constexpr.
Comment 8 Andy Lutomirski 2012-09-09 06:05:34 UTC
Did you mean "constexpr bool a" instead of "book const a"?  If so, I agree.  But consider:

bool const a = something complicated

Is a a constant?
Comment 9 Jason Merrill 2012-09-09 16:48:46 UTC
(In reply to comment #5)
>     // This causes "error: the value of 'x' is not usable in a constant expression"
>     constexpr bool c = __builtin_constant_p(x);
> }

This is also fixed by my patch.