The following code emits "non constant" but conceptually should emit "constant". The type of __func__
is "static const char *" so either fold_builtin_constant_p needs to be relaxed a bit or fname_decl should
be building STRING_CST.
int main(int argc, char **argv)
puts (__builtin_constant_p(__func__) ? "constant" : "non constant");
Confirmed on the mainline and on the tree-ssa.
Well note that it cannot be a STRING_CST as the C99 standard defines __func__ as a variable.
The documented purpose of the __builtin_constant_p intrinsic is "to determine if a value is known to be constant at compile time." C11 specifies the identifier as "static const char __func__ = "..." defined at function scope. While __func__ does qualify as an /address constant/ its value, or the address of any other object with static storage duration, isn't known to GCC at compile time.
Since no further update to this request has been made in over 10 years, and since implementing it would result in an inconsistency with other static const arrays (which are not treated as a constant expression by GCC), I'm going to close it as WONTFIX.
If you have a compelling reason for this enhancement that would outweigh or render moot the concerns above please feel free to reopen the request and provide your rationale.
In the new world where C++ constexpr can do this kind of thing, I wonder if this definition for __builtin_constant_p() is still desirable.
(This bug hasn't been updated in a decade because I was busy working on LLVM instead.)
Since Clang tries for reasonable compatibility with GCC language extensions like this, having a more rational definition of __builtin_constant_p() going forward would be desirable for both compilers.
Thank you for the feedback.
Having __builtin_constant_p(__func__) return 1 in C++ constexpr contexts makes sense since it's accepted there (starting with r234530) and treated as a constant expression. That it doesn't in 6.0 is likely an oversight. However, as evident from a recent discussion on firstname.lastname@example.org, whether or not __func__ was or is intended be allowed in constexpr functions to begin with is a subject of ongoing discussion.
On the other hand, it wouldn't be right to do the same thing outside constexpr constexts or in GCC (i.e., in C mode, as in the example in comment #0) unless __func__ (or similar objects) really were treated as a compile-time constant.
Of course, if the GCC definition for __builtin_constant_p() were to change, the value it returned for a given expression would be subject to this new definition. If that's the direction you would like to go I suggest to start by coming up with and proposing the new definition to see what implementation changes it might require and whether there is consensus to adopt it.
(I've reset the status from Assigned back to New since you didn't assign the bug to anyone when reopening it.)
Returning 1 for addresses of objects is highly undesirable. Not only it isn't really constant on many targets or with many options (e.g. in shared libraries,
or PIE executables), but even in position dependent code you don't know the address at compile time, only at link time. And, as we don't return 1 for any object addresses, so why should __func__ be an exception?
static int a;
static const int b = 3;
static const char c = "ab";
static const char *d = "cd";
static const char *const e = "ef";
return 1 * __builtin_constant_p (&a)
+ 2 * __builtin_constant_p (&b)
+ 4 *__builtin_constant_p (c)
+ 8 * __builtin_constant_p (c)
+ 16 *__builtin_constant_p (d)
+ 32 * __builtin_constant_p (d)
+ 64 *__builtin_constant_p (e)
+ 128 * __builtin_constant_p (e);
The returned value is 8 + 32 + 128, which is IMHO right, what is really constant are the individual characters of the string literals.
So, if you want to test whether __func__ is constant, you should test whether e.g. __func__ is __builtin_constant_p, the address of that can be anything and is not known at compile time.
Talking about clang, it gets it wrong, returns 0.