Skip to content

CWG2476 [dcl.spec.auto.general] p3 "function declarator" in the rule has a ambiguous meaning #85

Description

@xmh0511

Full name of submitter (unless configured in github; will be published with the issue): Jim X

A stackoverflow question: Is a pointer to function (sometimes/always?) a function declarator?

[dcl.spec.auto.general] p3 says

If the function declarator includes a trailing-return-type ([dcl.fct]), that trailing-return-type specifies the declared return type of the function. Otherwise, the function declarator shall declare a function.

Does the function declarator refer to the declarator in a declaration that first matches the form defined in [dcl.fct](namely, fun in T fun();, or to the declarator that is comprised by a declaration that declares a function(namely, T *fun();)? In the latter declaration, the declarator first matches the form defined in [dcl.ptr].

Presumably, the wording "function declarator" intends to refer to both.

Suggested resolution

Change [dcl.spec.auto.general] p3 to

A placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where such a declarator is valid. If the function declarator includes a trailing-return-type ([dcl.fct]), that trailing-return-type specifies the declared return type of the function. If the declared return type of the function contains a placeholder type, either the minimum constituent declaration in which the function declarator appears shall be one of the following:

  • is a paramter-declaration, or
  • is a initializing declaration of a variable, or
  • declares a function.

or the function declarator shall appear in the type-id of a new-expression.

The proposed resolution tries to make the intent of the "function declarator" clear and fix the remaining issue in CWG2476.

Activity

  1. jensmaurer commented on Jul 7, 2022

    @jensmaurer
    Member

    This seems to be squarely what CWG2476 is about, including being precise about "function declarator".

  2. changed the title [-][dcl.spec.auto.general] p3 "function declarator" in the rule has a ambiguous meaning[/-] [+]CWG2476 [dcl.spec.auto.general] p3 "function declarator" in the rule has a ambiguous meaning[/+] on Jul 7, 2022
  3. xmh0511 commented on Jul 8, 2022

    @xmh0511
    Author

    This seems to be squarely what CWG2476 is about, including being precise about "function declarator".

    The additional notes in CWG2476 says

    It was observed that the proposed resolution above does not address the example in the issue

    I have updated the proposed wording. We could also add these complex examples for the wording

    using type = void(*)(int);
    void fun(int){}
    type show(int){
       return &fun;
    }
    void foo(auto (*ptr)(int)->auto(*)(int)){}
    
    auto (*ptr)(int)->auto(*)(int)  = &show;  
    
    foo(&show);  // Clang accepts it but GCC rejects

    For the last example, I think this is #84.

    The proposed wording can be well to explain these complex examples(including the examples mentioned in Additional notes in CWG2476). Could you please merge the proposed wording and the complex examples to CWG2476 or as a new CWG issue that cross-references to CWG2476?

  4. jensmaurer commented on Sep 10, 2022

    @jensmaurer
    Member

    What's the "minimum constituent declaration"? The last three examples in CWG2476 do not seem to be addressed by your suggested changes.

  5. xmh0511 commented on Sep 11, 2022

    @xmh0511
    Author

    What's the "minimum constituent declaration"?

    The smallest declaration the declarator is subsumed to. For example

    void fun(int(*ptr)()){}

    In this case, the minimal constituent declaration of the declarator (*ptr)() is the parameter-declaration rather than the function-definition.

    The last three examples in CWG2476 do not seem to be addressed by your suggested changes.

    For C<auto(*)()->int> c2; // OK, since trailing-return-type specifies the declared return type, which is int, hence there is no more restriction in this case. For the other two cases( C<auto(*)()> c1; // Not OK and C<auto(*)()->auto> c3; // Not OK ), they basially has the same reason, the declared return types of these two cases contain placeholder types, hence the proposed bullets apply to these cases. I thought [dcl.name] p1 could be enough to clarify what the minimal declarations for the two cases

    This can be done with a type-id, which is syntactically a declaration for a variable or function of that type that omits the name of the entity.

    This is based on we have a similar rule, [dcl.decl.general] p3(i.e. the declarators would be analized with the seprated declarations)

    Each init-declarator or member-declarator in a declaration is analyzed separately as if it were in a declaration by itself.

    By this logical, the minimal declarations of the two case are auto(*)() and auto(*)()->auto, which are not

    1. paramter-declaration
    2. initializing declarations of variables
    3. or, do no declare functions

    and the function declarators do not appear in the type-id of a new-expression.

    It could arguably say we would consider the minimal declarations are C<auto(*)()> c1 and C<auto(*)()->auto> c3 if we don't think [dcl.name] p1 is helpful here. What do you think about?

    Change the second bullet would be a option

    is a initializing declaration of a variable unless the declarator appears in a type-id in a template-argument, or

  6. jensmaurer commented on Sep 11, 2022

    @jensmaurer
    Member

    At the very least, "minimum constituent declaration" isn't the right words, and I do think we need to special-case the template-argument case (because a template argument is not a declaration). The text about type-id is just explanatory and addressing any parsing concerns.

    We also need a few examples in the standard text.

    In any case, this is squarely in the scope of resolving CWG2476.

  7. xmh0511 commented on Sep 11, 2022

    @xmh0511
    Author

    In any case, this is squarely in the scope of resolving CWG2476.

    Agree that this issue concerns the same things as that of CW2476. Merely, this issue wants to clean two more points

    1. Clarify the meaning of function declarator
    2. Try to find wording that can clarify all cases mentioned in CWG2476.

    I do think we need to special-case the template-argument case (because a template argument is not a declaration).

    From the current situation, I think it is necessary. There seems to not have a concise way to reword and is good enough to clarify these cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions