Bug 14505 - __builtin_constant_p(__func__) is not true
Summary: __builtin_constant_p(__func__) is not true
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 3.3
: P3 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2004-03-09 18:21 UTC by Alex Rosenberg
Modified: 2016-04-05 06:34 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-02-18 18:12:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alex Rosenberg 2004-03-09 18:21:34 UTC
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");
}
Comment 1 Andrew Pinski 2004-03-09 19:49:02 UTC
Confirmed on the mainline and on the tree-ssa.
Comment 2 Andrew Pinski 2004-06-08 03:31:36 UTC
Well note that it cannot be a STRING_CST as the C99 standard defines __func__ as a variable.
Comment 3 Martin Sebor 2016-04-04 20:47:48 UTC
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.
Comment 4 Alex Rosenberg 2016-04-04 23:06:57 UTC
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.
Comment 5 Martin Sebor 2016-04-05 00:24:05 UTC
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 core@lists.isocpp.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.)
Comment 6 Jakub Jelinek 2016-04-05 06:33:07 UTC
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?
Try:
int
foo ()
{
  static int a;
  static const int b = 3;
  static const char c[3] = "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[0])
         + 16 *__builtin_constant_p (d)
         + 32 * __builtin_constant_p (d[0])
         + 64 *__builtin_constant_p (e)
         + 128 * __builtin_constant_p (e[0]);
}
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__[0] is __builtin_constant_p, the address of that can be anything and is not known at compile time.
Comment 7 Jakub Jelinek 2016-04-05 06:34:14 UTC
Talking about clang, it gets it wrong, returns 0.