Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Several issues about function parameter scope #4710

Open
xmh0511 opened this issue Jun 21, 2021 · 3 comments
Open

Several issues about function parameter scope #4710

xmh0511 opened this issue Jun 21, 2021 · 3 comments

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented Jun 21, 2021

A parameter-declaration-clause P introduces a function parameter scope that includes P.

  • If P is associated with a declarator and is preceded by a (possibly-parenthesized) noptr-declarator of the form declarator-id attribute-specifier-seq opt, its scope extends to the end of the nearest enclosing init-declarator, member-declarator, declarator of a parameter-declaration or a nodeclspec-function-declaration, or function-definition, but does not include the locus of the associated declarator.
  • If P is associated with a lambda-declarator, its scope extends to the end of the compound-statement in the lambda-expression.
  • If P is associated with a requirement-parameter-list, its scope extends to the end of the requirement-body of the requires-expression.
  • If P is associated with a deduction-guide, its scope extends to the end of the deduction-guide.

Please see this example:

using rt = auto(*)(int a)->decltype(a);

It's obviously P is not associated with any declarator instead with abstract-declarator, let alone whether it is preceded by noptr-declarator of the form declarator-id attribute-specifier-seq opt. In this example, the name of the parameter is used in the place that has exceeded the scope of the function parameter scope introduced by P. However, the case is valid in any major implementation other than MSVC. The other bullets are irrelevant with this case. So, it seems the function parameter scope is underspecified for this case.


Issue 2:

auto(* ptr(double a))(int b)->decltype(a);
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                  (       int b      )
         init-declarator-> declarator-> noptr-declarator parameters-and-qualifiers  trailing-return-type
                                         ^^^^^^^^^^^^^^^ 
                                         ( ptr-declarator )  
                                                  ↓
                                    (  ptr-operator ptr-declarator )
                                                      ↓
                                    (      *      noptr-declarator)   
                                                      ↓
                                                                   (  double a     )
                                    (      *     noptr-declarator parameters-and-qualifiers)
                                                      ↓
                                                                   (  double a     )
                                    (      *     declarator-id    parameters-and-qualifiers)
                                                  ^^^^^^^^^
                                                   ptr

First of all, this case is rejected by all major implementations. Assume the parameter-declaration-clause that comprises the parameter declaration double a is called P1, the other(comprises int b) is called P2. As shown in the Figure, P1 is associated with the declarator of the complete declaration and is preceded by noptr-declarator of the form declarator-id attribute-specifier-seq opt that is ptr. In terms of the first bullet in the above, the scope should be extended to the nearest enclosing init-declarator (* ptr(double a))(int b)->decltype(a) since the other cases(member-declarator...) are all not suitable here. Hence, the use of the identifier a within decltype should be valid. But this conclusion is denied by implementations.

@xmh0511 xmh0511 changed the title Function parameter scope of abtract-declarator Function parameter scope of the abtract-declarator Jun 21, 2021
@xmh0511 xmh0511 changed the title Function parameter scope of the abtract-declarator Function parameter scope of the abstract-declarator Jun 21, 2021
@xmh0511 xmh0511 changed the title Function parameter scope of the abstract-declarator Several issues about function parameter scope Jun 21, 2021
@xmh0511
Copy link
Contributor Author

xmh0511 commented Jun 21, 2021

The first issue might be interpreted by the following rule:

In all contexts, a declarator is interpreted as given below. Where an abstract-declarator can be used (or omitted) in place of a declarator ([dcl.fct], [except.pre]), it is as if a unique identifier were included in the appropriate place ([dcl.name]).

That means MSVC has a wrong implementation. The second issue still remains no explanation.

@opensdh
Copy link
Contributor

opensdh commented Jun 21, 2021

First, this is not the place to file core issues, even if Jens is often kind enough to relay them.

Considering that

auto f(int) -> int;
auto (*p)(int a) -> decltype(a) = f;

is accepted by all of the usual suspects but that

template<class T> int g(std::remove_pointer_t<T>);
int (*q)(int a) = g<decltype(a)>;

is just as universally rejected, we evidently need a new rule for non-function declarations that doesn't use init-declarator as the extent. You're right about the case of a function returning a function pointer, but we need to figure out what the rule should be for non-function declarations before we try to fix the "function but not the outermost function declarator" case.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Jun 22, 2021

First, this is not the place to file core issues, even if Jens is often kind enough to relay them.

Considering that

auto f(int) -> int;
auto (*p)(int a) -> decltype(a) = f;

is accepted by all of the usual suspects but that

template<class T> int g(std::remove_pointer_t<T>);
int (*q)(int a) = g<decltype(a)>;

is just as universally rejected, we evidently need a new rule for non-function declarations that doesn't use init-declarator as the extent. You're right about the case of a function returning a function pointer, but we need to figure out what the rule should be for non-function declarations before we try to fix the "function but not the outermost function declarator" case.

@jensmaurer Thanks. @opensdh I just don't find an high efficiently channel to discuss these issues except here. Back to the issue itself, if the behavior of these implementations is correct, we might need to define the rule for concept what is P associated with a declarator(which declarator is it?), it might be:

P is associated with a declarator of which a parameters-and-qualifiers is a direct component and the parameters-and-qualifiers directly enclose the P, and the declarator has the form noptr-declarator parameters-and-qualifiers trailing-return-type or noptr-declarator parameters-and-qualifiers.
P is associated with a component if P is firstly introduced by the component (i.e, P is the direct component of that component on grammar).

If P is associated with a declarator, its scope extends to the end of the declarator, or function-definition of which the declarator declares a function.

Example:

auto(* ptr(double a))(int b)->decltype(b); //ok  auto D(int b)-> decltype(b), b extends to the end of the declarator

auto(* fun(double a))(int b)->int{
    a = 1;   //ok  fun(double a) declares a function, a can be named here
    b = 0; //error auto (* D)(int b)->int, since `(* D)(int b)->int` does not declare a function
    return nullptr;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants