• Re: __func__ is not a keyword

    From Kaz Kylheku@21:1/5 to Keith Thompson on Sun Mar 16 07:18:38 2025
    On 2025-03-15, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    I'm mildly curious how gcc and clang treat "__func__" internally
    that leads to this odd behavior. The obvious way to implement it
    would be to internally create a declaration of __func__ on entry
    to each function definition, which shouldn't cause the symptom
    you're seeing. But it's not a conformance issue

    The main reason is this:

    "As an extension, at file (or, in C++, namespace scope), __func__
    evaluates to the empty string."

    You might think that this is due to history: GCC had function
    name access as the __FUNCTION__ and __PRETTY__FUNCTION__ extensions
    before __func__ was standardized. __func__ is still documented
    as an alternate name for __FUNCTION__.

    However, it is not the case that __FUNCTION__ was always documented
    as expanding at file scope!

    The documentation for GCC 2.95 does not mention any such thing. It
    specifies that __FUNCTION__ is a variable, and that it gives the name of
    the current function, not specifying anything about when there is no
    current functiona:

    These names are not macros: they are predefined string variables. For
    example, `#ifdef __FUNCTION__' does not have any special meaning
    inside a function, since the preprocessor does not do anything special
    with the identifier __FUNCTION__.

    It turns out that the documentation for 2.95 lied. The GCC 3.6.4
    documentation (GCC 3 end-of-life release) contradicts the above,
    revealing that only in C++ had those identifiers been variables:

    These identifiers are not preprocessor macros. In GCC 3.3 and earlier,
    in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as string
    literals; they could be used to initialize char arrays, and they could
    be concatenated with other string literals. GCC 3.4 and later treat
    them as variables, like __func__. In C++, __FUNCTION__ and
    __PRETTY_FUNCTION__ have always been variables.

    However, the 3.4.6 documentation still does not say anything
    about file scope, even though it does describe the C99 __func__
    already. I don't have a build of 3.4.6 to test the actual behavior.

    So it doesn't look as if recognition of __func__ at file scope
    is simply due to it being an alias for an existing GCC feature
    which had that behavior historically. It looks like an extension
    they bestowed upon __func__, and in so doing also upon the
    __FUNCTION__.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Keith Thompson on Sun Mar 16 15:51:30 2025
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Thiago Adams <thiago.adams@gmail.com> writes:
    This program does not compile..in gcc and clang

    int __func__ i =1;



    I'm mildly curious how gcc and clang treat "__func__" internally
    that leads to this odd behavior.

    From the gcc info page:

    GCC provides three magic variables that hold the name of the current
    function, as a string. The first of these is '__func__', which is part
    of the C99 standard:

    The identifier '__func__' is implicitly declared by the translator as
    if, immediately following the opening brace of each function definition,
    the declaration

    static const char __func__[] = "function-name";

    appeared, where function-name is the name of the lexically-enclosing
    function. This name is the unadorned name of the function.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Keith Thompson on Sun Mar 16 19:05:05 2025
    On 2025-03-16, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    source code and its behavior indicate that gcc treats __func__ as
    a keyword, which is inconsistent with the info page. For example,
    one would expect this:

    int main(void) {
    {
    int __func__;
    }
    }

    to be accepted, with the inner definition of __func__ hiding the
    implicit static declaration, but gcc reports a syntax error.

    It's not a conformance issue, since __func__ is a reserved identifier
    and any code that can tell whether it's a keyword has undefined
    behavior.

    But __func__ is not a reserved identifier! Inside a function, it's a
    documented identifier with specified properties, and those properties do
    not support an interpretation that it may be a keyword.

    We have to distinguish between specific, defined, standard identifiers allocated from a reserved namespace, and the reserved namespace itself.

    If gcc (in c99 mode or later) *allowed* int _Bool = 42; would you
    call that conforming, because _B* is in the reserved namespace, so
    any behavior is okay?

    Since __func__ is not described as existing outside of a function,
    there, it is just an identifier landing in the reserved namespace.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Kaz Kylheku on Sun Mar 16 16:35:36 2025
    On 3/16/25 15:05, Kaz Kylheku wrote:
    On 2025-03-16, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    ...
    It's not a conformance issue, since __func__ is a reserved identifier
    and any code that can tell whether it's a keyword has undefined
    behavior.

    But __func__ is not a reserved identifier!

    Footnote 79 disagrees: "79) Since the name __func__ is reserved for any
    use by the implementation (7.1.3), if any other identifier is explicitly declared using the name __func__, the behavior is undefined."

    Actually, I don't see how 7.1.3 applies. I think the conclusion is
    correct, but the relevant citation should be 6.2.4.1p7: "All identifiers
    that begin with a double underscore (__) ... are reserved for any use.
    ...". That wording used to be in 7.1.3. That wording was moved from
    7.3.1 in n2573.pdf (2020-10-01) to 6.2.4.1 in n2596.pdf (2020-12-11).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Keith Thompson on Mon Mar 17 17:03:19 2025
    On 2025-03-16, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Are you suggesting that a conforming compiler must accept the above
    code (defining __func__ in an inner scope)? If so, I disagree.

    I was initially divided on this one.

    On the one hand, inside a function, __func__ is not reserved (for future
    use); it is described as being bound as a variable name, and that makes
    it compatible with lexical shadowing.

    On the other hand, macros coming from standard headers could
    have expansions that refer to __func__. (Macros not intended to be
    used at file scope.)

    If you redefine __func__, and use any macro or function that could be implemented as a macro, then all bets are off.

    The remaining doubt is this: could the implementation have code
    generation features that rely on __func__, so that even if the
    program doesn't use any macros or functions in that scope where
    __func__ is redefined, there is a problem?

    Say that the implementation supports a debug trace mode where for every
    line executed it prints the function name and line number, and this
    depends on generated code which expects __func__ to be undisturbed.
    That seems like something in the space of "useful and good".

    Of course, from a portable programming point of view, we must regard
    __func__ as off-limits. In light of the above possibilities, though, it
    seems that it would be best to formally interpret it that way, too.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Keith Thompson on Mon Mar 17 20:31:27 2025
    On 2025-03-17, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Kaz Kylheku <643-408-1753@kylheku.com> writes:
    On 2025-03-16, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
    Are you suggesting that a conforming compiler must accept the above
    code (defining __func__ in an inner scope)? If so, I disagree.

    I was initially divided on this one.

    On the one hand, inside a function, __func__ is not reserved (for future
    use); it is described as being bound as a variable name, and that makes
    it compatible with lexical shadowing.

    That's where I disagree, though I'm not 100% certain.

    Identifiers starting with __ are not conditionally reserved, and
    they're not reserved "for future use". They're simply "reserved
    for any use".

    I completely agree now.

    Part of the cocept of an identifier being "reserved" is that the
    implementation itself can refer to the identifier, blindly assuming that
    the identifier is defined as documented, and has not been shadowed or
    tampered with.

    OK, that being said, since __func__ is described in a certain way,
    namely *as-if* this declaration followed the opening brace
    of the function::

    static const char __func__[] = "function-name";

    I think that legitimizes the program using expressions like:

    sizeof __func__

    with the expectation that this yields the number of characters
    oin the function name, plus one.

    That will obviously not work if the implementation takes some
    license, and makes the implicit declaration as if it were:

    static const char *func = "function-name";

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Tue Mar 18 10:00:31 2025
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    On 2025-03-15, Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    I'm mildly curious how gcc and clang treat "__func__" internally
    that leads to this odd behavior. The obvious way to implement it
    would be to internally create a declaration of __func__ on entry
    to each function definition, which shouldn't cause the symptom
    you're seeing. But it's not a conformance issue

    The main reason is this:

    "As an extension, at file (or, in C++, namespace scope), __func__
    evaluates to the empty string."

    But it produces a diagnostic

    warning: ?__func__? is not defined outside of function scope

    And in a very quick look through the documentation, I don't see
    a way to disable that warning (other than "-w", which disables
    all warnings). Looks like they don't really want you using this
    extension.

    It seems more likely that they just don't care. I expect there
    has been very little demand for an option specifically to cover
    this situation.

    By the way, clang has -Wpredefined-identifier-outside-function,
    along with the corresponding no- version to turn off the warning.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)