Topic: Name lookup for parameter-declaration-clause


Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Sat, 9 Nov 2002 01:28:08 +0000 (UTC)
Raw View
Troels Nordfalk wrote:
 >"James Kuyper Jr." wrote:
 >
....

 >However, my primary concern was not these types. My example was
 >flawed with regards to my intent. Here is a better one:
 >
 >struct A2 {
 > void g(int x=d) {int y=x;} // 1
 > void h(int x=d);           // 2
 > static const int d;
 >};
 >
 >The problem still is the conflict between 3.4.1-7 and 3.4.1-8, and the
 >exclusion of member function DECLARATIONs in 3.4.1-8.
 >
 >(1) is covered by both 3.4.1-7 and 3.4.1-8, whereas (2) is only
 >covered by 3.4.1-7 and is therefore ill-formed. To me, this does not

OK, that makes your point clear, and it seems reasonable to me. However,
there's two different ways to resolve it. The other one would be to
restrict 3.4.1-8 to function bodies. That would obviously be the less
convenient resolution for developers, but there might be a reason by
implementors would prefer it - I haven't thought through all the
consequences.

 >It seems to me that a lot of other places in the standard uses
 >definition, where they mean both definition and declaration. Is there
 >an explanation for this ?

Sorry; I don't know the answers to the "why" questions.

 >>The only way to make that typedef work as desired is to make sure that
 >>all uses of it occur in "the declarative region following the name's
 >>declarator". As it stands, the use of 'X' in the parameter lists of g()
 >>and h() must refer to a different 'X' than the one declared in the
 >>typedef. If there is no other declaration of X, which is in scope in
 >>those two places, then there's a syntax error.
 >>
 >>
 >
 >Sorry for not being specific; Unless otherwise mentioned, my examples
 >consists of entire translation-units.

Ordinarily, that's what I'd assume. However, because of the
misunderstanding about scope, the failure mode of your code was one you
probably hadn't been thinking of, so I just wanted to make it clear
precisely how it would fail.

 >>3.4.1p7 applies to names used outside a member function body. 3.4.1p8
 >>applies to names used inside the definition of a member function. The
 >>domains where they apply overlap in that part of a function definition
 >>which lies outside the function body: the decl-specifier-seq, the
 >>declarator itself, and the ctor-initializer (8.4p1). However, that
 >>
 >>
 >
 >Didn't you overlook the default arguments ?

Those are part of the declarator. See 8.4p1, and 8.3.5.

....
 >Exactly one of my gripes with issue 192.
 >
 >By the way, is there anyone from the committee, which can elaborate on
 >this ? Has issue 192 been discussed ?

On the web site there's no evidence that it's been discussed. I don't
know any more than that.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: tnordfalk@get2net.dk (Troels Nordfalk)
Date: Thu, 7 Nov 2002 13:14:50 +0000 (UTC)
Raw View
Hi,

I'm reading the standard as part of my thesis on parsing C++, and
amongst other things I stumbled on this:

Is using a member in a parameter-declaration well-formed, if the
member has not been declared yet ?

struct A {
 void g(X x) {X y=x;} // 1
 void h(X x);         // 2
 typedef int X;
};

void A::h(X x) {}

As issue 192 points out there is a contradiction between 3.4.1-7 and
3.4.1-8. The issue states that it "was not the intent of the
Committee". However, if this is so, does it mean that 3.4.1-8 should
only concern members defined outside the body of the class ?

Back to the example: According to 3.4.1-8 (seen isolated) g (1) is
well-formed, but h (2) is not described since it is not a
definition. This does not make much sense to me. Maybe "definition"
should be replaced by "definition or declaration".

FYI: Comeau 4.3.0.1 accepts neither g nor h.


Thanks,

Troels

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Thu, 7 Nov 2002 21:13:46 +0000 (UTC)
Raw View
Troels Nordfalk wrote:
> Hi,
>
> I'm reading the standard as part of my thesis on parsing C++, and
> amongst other things I stumbled on this:
>
> Is using a member in a parameter-declaration well-formed, if the
> member has not been declared yet ?
>
> struct A {
>  void g(X x) {X y=x;} // 1
>  void h(X x);         // 2
>  typedef int X;
> };

The relevant section is 3.3.6p1, which says that "The potential scope of
a name declared in a class consists not only of the declarative region
following the name's declarator, but also of all function bodies,
default arguments, and constructor _ctor-initializers in that class ..."

The only way to make that typedef work as desired is to make sure that
all uses of it occur in "the declarative region following the name's
declarator". As it stands, the use of 'X' in the parameter lists of g()
and h() must refer to a different 'X' than the one declared in the
typedef. If there is no other declaration of X, which is in scope in
those two places, then there's a syntax error.


> void A::h(X x) {}
>
> As issue 192 points out there is a contradiction between 3.4.1-7 and
> 3.4.1-8.  ...


3.4.1p7 applies to names used outside a member function body. 3.4.1p8
applies to names used inside the definition of a member function. The
domains where they apply overlap in that part of a function definition
which lies outside the function body: the decl-specifier-seq, the
declarator itself, and the ctor-initializer (8.4p1). However, that
doesn't make a contradiction. Each of those two paragraphs contains a
list of ways the name could be declared, at least one of which much
apply to every name used in the specified locations. In those locations
to which both sections apply, every name used must satisfy one option
from 3.4.1p7 AND one option from 3.4.1p8. No matter how different those
two lists are, that doesn't constitute a contradiction.

In fact, the two lists are very similar; the relevant difference in this
case is only that 3.4.1p8 allows use of any member of the class, while
3.4.1p7 allows use only of names of members that were declared before
the function definition.

If the 'X' typedef were in scope in those two places, it's use would
violate the stricter requirements of 3.4.1p7, and would therefore be an
error. Since that typedef isn't in scope, then if the code does not
contain a syntax error, the declaration of 'X' that is in scope at those
two places must be provided somewhere else. Depending upon where that
other declaration of 'X' is located; the code might meet the
requirements of both 3.4.1p7 and p8.

 > ... The issue states that it "was not the intent of the
> Committee".  ...

"... to allow the following code:

     struct S {
         void f(I i) { }
         typedef int I;
     };
"

I'm not a member of the committee, so I can't address "the intent of the
Committee". However, the use of I in the declaration of f() is outside
the scope of the typedef declaration of I. Unless there's another
declaration of I which is in scope at that point, this is a syntax error.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: tnordfalk@get2net.dk (Troels Nordfalk)
Date: Fri, 8 Nov 2002 15:26:33 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Troels Nordfalk wrote:
> >
> > Is using a member in a parameter-declaration well-formed, if the
> > member has not been declared yet ?
> >
> > struct A {
> >  void g(X x) {X y=x;}
> >  void h(X x);
> >  typedef int X;
> > };
>
> The relevant section is 3.3.6p1, which says that "The potential scope of
> a name declared in a class consists not only of the declarative region
> following the name's declarator, but also of all function bodies,
> default arguments, and constructor _ctor-initializers in that class ..."

Ahh... thanks for pointing it out. I was confused by the fact that
in name look-up the turning point is after the function declarator-id
("g" and "h"). Also 3.3.6-2 ties the USE of names to scope.

Side note: I only wish it was formulated without the "not only":
"The potential scope of a name declared in a class consists of the
declarative region following the name's declarator AND all function
bodies, default arguments, and constructor _ctor-initializers in that
class ..."

So the type of parameters are not in the scope of members declared
earlier in the class. excellent point.

However, my primary concern was not these types. My example was
flawed with regards to my intent. Here is a better one:

struct A2 {
 void g(int x=d) {int y=x;} // 1
 void h(int x=d);           // 2
 static const int d;
};

The problem still is the conflict between 3.4.1-7 and 3.4.1-8, and the
exclusion of member function DECLARATIONs in 3.4.1-8.

(1) is covered by both 3.4.1-7 and 3.4.1-8, whereas (2) is only
covered by 3.4.1-7 and is therefore ill-formed. To me, this does not
make sense. Apparently GCC and Comeau agrees with me, since they
compile A2. This basically translates into that GCC, Comeau and I
would like 3.4.1-8 changed from ...

"A name used in the definition of a function that is a member
function (9.3)29) of class X shall be declared in one of the following
ways:..."

... into ...

"A name used in the DECLARATION of a function that is a member
function (9.3)29) of class X shall be declared in one of the following
ways:..."

It seems to me that a lot of other places in the standard uses
definition, where they mean both definition and declaration. Is there
an explanation for this ?

> The only way to make that typedef work as desired is to make sure that
> all uses of it occur in "the declarative region following the name's
> declarator". As it stands, the use of 'X' in the parameter lists of g()
> and h() must refer to a different 'X' than the one declared in the
> typedef. If there is no other declaration of X, which is in scope in
> those two places, then there's a syntax error.

Sorry for not being specific; Unless otherwise mentioned, my examples
consists of entire translation-units.

> > void A::h(X x) {}
> >
> > As issue 192 points out there is a contradiction between 3.4.1-7 and
> > 3.4.1-8.  ...
>
>
> 3.4.1p7 applies to names used outside a member function body. 3.4.1p8
> applies to names used inside the definition of a member function. The
> domains where they apply overlap in that part of a function definition
> which lies outside the function body: the decl-specifier-seq, the
> declarator itself, and the ctor-initializer (8.4p1). However, that

Didn't you overlook the default arguments ?

> doesn't make a contradiction. Each of those two paragraphs contains a
> list of ways the name could be declared, at least one of which much
> apply to every name used in the specified locations. In those locations
> to which both sections apply, every name used must satisfy one option
> from 3.4.1p7 AND one option from 3.4.1p8. No matter how different those
> two lists are, that doesn't constitute a contradiction.

Your interpretation of two (consecutive) statements as conjuctive clauses
makes sense, but I am not sure the standard as a whole will stand up to
it. If the committee accepts your interpretation issue 192 is NAD.

However I would like to point out that since GCC and Comeau actually
accepts the above example, they assume not AND but OR or maybe prefers
one over the other in some cases. your interpretation implies that
nothing but the function body needs to be postponed during parsing of
a class definition. Since this should be easier to parse than what GCC
and Comeau does, I can only conclude that these compiler-writers
whole-heartedly disagree with you.

> In fact, the two lists are very similar; the relevant difference in this
> case is only that 3.4.1p8 allows use of any member of the class, while
> 3.4.1p7 allows use only of names of members that were declared before
> the function definition.
>
> If the 'X' typedef were in scope in those two places, it's use would
> violate the stricter requirements of 3.4.1p7, and would therefore be an
> error. Since that typedef isn't in scope, then if the code does not
> contain a syntax error, the declaration of 'X' that is in scope at those
> two places must be provided somewhere else. Depending upon where that
> other declaration of 'X' is located; the code might meet the
> requirements of both 3.4.1p7 and p8.
>
>  > ... The issue states that it "was not the intent of the
> > Committee".  ...
>
> "... to allow the following code:
>
>      struct S {
>          void f(I i) { }
>          typedef int I;
>      };
> "
>
> I'm not a member of the committee, so I can't address "the intent of the
> Committee". ...

Exactly one of my gripes with issue 192.

By the way, is there anyone from the committee, which can elaborate on
this ? Has issue 192 been discussed ?



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]