Date: Tue, 11 Aug 2020 17:01:52 -0700
On Tue, 11 Aug 2020, 16:07 Uecker, Martin, <
Martin.Uecker_at_[hidden]> wrote:
> Am Dienstag, den 11.08.2020, 15:35 -0700 schrieb Richard Smith:
> > On Tue, 11 Aug 2020, 14:36 Uecker, Martin, <
> > Martin.Uecker_at_[hidden]> wrote:
> >
> > > Am Dienstag, den 11.08.2020, 14:10 -0700 schrieb Richard Smith:
> > > > On Tue, Aug 11, 2020 at 2:05 PM Uecker, Martin via Liaison <
> > > > liaison_at_[hidden]> wrote:
> > > >
> > > > > Am Dienstag, den 11.08.2020, 17:01 -0400 schrieb Aaron Ballman:
> > > > > > On Tue, Aug 11, 2020 at 4:45 PM Uecker, Martin
> > > > > > <Martin.Uecker_at_[hidden]> wrote:
> > > > > > >
> > > > > > > Am Dienstag, den 11.08.2020, 16:41 -0400 schrieb Aaron Ballman:
> > > > > > > > On Tue, Aug 11, 2020 at 4:38 PM Uecker, Martin via Liaison
> > > > > > > > <liaison_at_[hidden]> wrote:
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > BTW: Is
> > > > > > > > >
> > > > > > > > > if (x)
> > > > > > > > > int y;
> > > > > > > > >
> > > > > > > > > intentionally allowed in C++? Is there a sensible use
> > > > > > > > > case?
> > > > > > > >
> > > > > > > > Yes, that's well-formed C++ code. A possible use case would
> be
> > >
> > > for an
> > > > > > > > RAII object which performs work in its constructor or
> destructor
> > >
> > > (so
> > > > > > > > the declaration itself causes code to be executed).
> > > > > > >
> > > > > > > I understand this. I was thinking more about a
> > > > > > > high-level example where it would make sense to use
> > > > > > > it in this way.
> > > > > > >
> > > > > > > A file which is opened and immediately close again
> > > > > > > also does not make too much sense.
> > > > > > >
> > > > > > > But maybe there are better examples?
> > > > > >
> > > > > > My line of thinking may be contrived, but because constructors
> can
> > > > > > accept arguments to them (including references or pointers to
> other
> > > > > > objects), the RAII object could be performing some modification.
> > >
> > > e.g.,
> > > > > >
> > > > > > if (enable_special_magic)
> > > > > > RAIIObject Special(Magic);
> > > > > >
> > > > > > where the constructor for RAIIObject takes an argument by
> reference
> > > > > > and does something special to it (calls a function on it,
> modifies a
> > > > > > value somewhere, etc). However, I wouldn't say this is a
> construct
> > > > > > I've run across myself in the wild. As an example, perhaps the
> RAII
> > > > > > object is logging to a file in the constructor (and perhaps
> flushing
> > > > > > the file in the destructor).
> > > > > >
> > > > > > ~Aaron
> > > > >
> > > > > Thanks Aaron!
> > > > >
> > > > > I can see that it could potentially be used in some cases,
> > > > > but it seems this was not added to the C++ language on purpose.
> > >
> > > (And you can create an object and run the constructor without
> > > declaration, so naming a variable here really makes no sense.)
> > >
> > > > I think it depends on what you mean by "on purpose". The example here
> > >
> > > seems
> > > > to suggest that it was fully intentional:
> > > > http://eel.is/c++draft/stmt.select#2 .
> > >
> > > Yes, but to me it seems more that paragraph 2 needed to be added
> > > to fix scoping for this particular corner case of the language
> > > and this is probably the sole reason the example is given.
> > >
> > > > However, it seems likely that it's
> > > > allowed for consistency (declarations are statements, 'if' allows any
> > > > statement, therefore 'if' allows a declaration) rather than to
> enable a
> > > > specific anticipated usage.
> > >
> > > This makes sense. Someone made the decision that declarations
> > > are statements. I assume the purpose was to allow labels to be
> > > placed in front of declarations.
> > >
> >
> > I don't know (maybe Bjarne can tell us) but I doubt that was the reason.
> > Rather, I suspect that when C++ started to allow declarations to appear
> > anywhere in a compound-statement, modelling declarations as a kind of
> > statement was the simplest way to get that effect. And it makes sense and
> > simplifies the model to only have one kind of thing that can appear in a
> > compound-statement.
>
> I can't see this. You just have the alternative declaration
> vs. statement somewhere else in the parser/grammar. This
> should have the same implementation complexity.
>
It's a question of the user-facing complexity, not the implementation
complexity. It's simpler to say that an expression-statement, a
declaration-statement, and an if-statement are siblings than to introduce
hierarchy between them that makes no difference in practice.
> But this left open two corner cases:
> > >
> > > - The 'if (1) int i;' example, because declarations were now
> > > also allowed where only statements make sense.
> > >
> >
> > This seems like a natural consequence of uniform rules to me rather than
> a
> > corner case.
> > I suppose it depends whether you're more used to the C or C++
> > rules, but I find the C behaviour for this example to be the corner case.
> > *shrug*
>
> If you bought into the idea that declarations and statements
> should be treated identically, I can see how you could come
> to this conclusion.
>
> But to me this makes no sense and the corner case is just
> one example.
>
> Here is another one: Should this be allowed?
>
> for (if (1) j = 3; j < n; j++)
>
In an expression-oriented language, yes. But the block structure of C and
C++ isn't well-suited to such constructs. So we restrict to only some of
the forms of statement.
> - Placement of labels at the end of compound statements is
> > > still not allowed. (which requires teaching people to add
> > > pointless null statements)
> > >
> >
> > This is indeed a consequence of only having one kind of thing that can
> > appear in a compound-statement.
>
> I fail to see why this is important or desirable.
>
> > I wonder, do you have implementation experience for your new rule? For a
>
> I am never proposing anything I can not implement.
>
> I implemented it in the compiler I am in the progress of writing.
> It is still far from finished but
> has a fairly complete C
> frontend and compiles many interesting examples. This was
> very easy to
> implement and caused no problems.
>
I would expect the problems to emerge when retrofitting this into an
existing implementation based around the old rules :)
> recursive descent parser, I'd expect it to be quite awkward to recursively
> > parse an unbounded sequence of labels as part of statement parsing only
> to
> > find that you hit a close brace and aren't actually parsing a labelled
> > statement at all.
>
> The proposed grammar prevents this:
>
> block-item = label | declaration | unlabeled-statement
> labeled-statement = label unlabeled-statement
>
>
> So inside a compound statement you do not recurse into
> labels when parsing statements.
>
And presumably you allow the substatement of an if/while/... to be either
an unlabeled-statement or a labeled-statement?
(Minor: that does not appear to allow two labels on the same statement
except in a block. But maybe that's handled in part of the grammar you
didn't show.)
That's quite a departure from the classical rules, and the different
treatment in blocks versus other contexts is a surprise. But OK.
> In contrast, the new rule in C has neither problem and
> > > is more logical: Labels are about control flow and make
> > > sense everywhere where statements make sense.
> > >
> >
> > Hm, would you allow a label after `if (` or `for (`? At least in C++,
> > that's somewhere where (a restricted set of) statements can appear.
>
> Similar to my example above ;-)
>
> I did not know that C++ allowed statement other than
> and declarations there.
>
Only declaration-statements, expression-statements, and empty statements.
I would not allow statements or labels.
>
> Best,
> Martin
>
>
> > (In contrast, declarations are about introducing names
> > > and should interact well with scoping rules, so really
> > > should follow different rules.)
> > >
> > > Best,
> > > Martin
> > >
> > >
Martin.Uecker_at_[hidden]> wrote:
> Am Dienstag, den 11.08.2020, 15:35 -0700 schrieb Richard Smith:
> > On Tue, 11 Aug 2020, 14:36 Uecker, Martin, <
> > Martin.Uecker_at_[hidden]> wrote:
> >
> > > Am Dienstag, den 11.08.2020, 14:10 -0700 schrieb Richard Smith:
> > > > On Tue, Aug 11, 2020 at 2:05 PM Uecker, Martin via Liaison <
> > > > liaison_at_[hidden]> wrote:
> > > >
> > > > > Am Dienstag, den 11.08.2020, 17:01 -0400 schrieb Aaron Ballman:
> > > > > > On Tue, Aug 11, 2020 at 4:45 PM Uecker, Martin
> > > > > > <Martin.Uecker_at_[hidden]> wrote:
> > > > > > >
> > > > > > > Am Dienstag, den 11.08.2020, 16:41 -0400 schrieb Aaron Ballman:
> > > > > > > > On Tue, Aug 11, 2020 at 4:38 PM Uecker, Martin via Liaison
> > > > > > > > <liaison_at_[hidden]> wrote:
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > BTW: Is
> > > > > > > > >
> > > > > > > > > if (x)
> > > > > > > > > int y;
> > > > > > > > >
> > > > > > > > > intentionally allowed in C++? Is there a sensible use
> > > > > > > > > case?
> > > > > > > >
> > > > > > > > Yes, that's well-formed C++ code. A possible use case would
> be
> > >
> > > for an
> > > > > > > > RAII object which performs work in its constructor or
> destructor
> > >
> > > (so
> > > > > > > > the declaration itself causes code to be executed).
> > > > > > >
> > > > > > > I understand this. I was thinking more about a
> > > > > > > high-level example where it would make sense to use
> > > > > > > it in this way.
> > > > > > >
> > > > > > > A file which is opened and immediately close again
> > > > > > > also does not make too much sense.
> > > > > > >
> > > > > > > But maybe there are better examples?
> > > > > >
> > > > > > My line of thinking may be contrived, but because constructors
> can
> > > > > > accept arguments to them (including references or pointers to
> other
> > > > > > objects), the RAII object could be performing some modification.
> > >
> > > e.g.,
> > > > > >
> > > > > > if (enable_special_magic)
> > > > > > RAIIObject Special(Magic);
> > > > > >
> > > > > > where the constructor for RAIIObject takes an argument by
> reference
> > > > > > and does something special to it (calls a function on it,
> modifies a
> > > > > > value somewhere, etc). However, I wouldn't say this is a
> construct
> > > > > > I've run across myself in the wild. As an example, perhaps the
> RAII
> > > > > > object is logging to a file in the constructor (and perhaps
> flushing
> > > > > > the file in the destructor).
> > > > > >
> > > > > > ~Aaron
> > > > >
> > > > > Thanks Aaron!
> > > > >
> > > > > I can see that it could potentially be used in some cases,
> > > > > but it seems this was not added to the C++ language on purpose.
> > >
> > > (And you can create an object and run the constructor without
> > > declaration, so naming a variable here really makes no sense.)
> > >
> > > > I think it depends on what you mean by "on purpose". The example here
> > >
> > > seems
> > > > to suggest that it was fully intentional:
> > > > http://eel.is/c++draft/stmt.select#2 .
> > >
> > > Yes, but to me it seems more that paragraph 2 needed to be added
> > > to fix scoping for this particular corner case of the language
> > > and this is probably the sole reason the example is given.
> > >
> > > > However, it seems likely that it's
> > > > allowed for consistency (declarations are statements, 'if' allows any
> > > > statement, therefore 'if' allows a declaration) rather than to
> enable a
> > > > specific anticipated usage.
> > >
> > > This makes sense. Someone made the decision that declarations
> > > are statements. I assume the purpose was to allow labels to be
> > > placed in front of declarations.
> > >
> >
> > I don't know (maybe Bjarne can tell us) but I doubt that was the reason.
> > Rather, I suspect that when C++ started to allow declarations to appear
> > anywhere in a compound-statement, modelling declarations as a kind of
> > statement was the simplest way to get that effect. And it makes sense and
> > simplifies the model to only have one kind of thing that can appear in a
> > compound-statement.
>
> I can't see this. You just have the alternative declaration
> vs. statement somewhere else in the parser/grammar. This
> should have the same implementation complexity.
>
It's a question of the user-facing complexity, not the implementation
complexity. It's simpler to say that an expression-statement, a
declaration-statement, and an if-statement are siblings than to introduce
hierarchy between them that makes no difference in practice.
> But this left open two corner cases:
> > >
> > > - The 'if (1) int i;' example, because declarations were now
> > > also allowed where only statements make sense.
> > >
> >
> > This seems like a natural consequence of uniform rules to me rather than
> a
> > corner case.
> > I suppose it depends whether you're more used to the C or C++
> > rules, but I find the C behaviour for this example to be the corner case.
> > *shrug*
>
> If you bought into the idea that declarations and statements
> should be treated identically, I can see how you could come
> to this conclusion.
>
> But to me this makes no sense and the corner case is just
> one example.
>
> Here is another one: Should this be allowed?
>
> for (if (1) j = 3; j < n; j++)
>
In an expression-oriented language, yes. But the block structure of C and
C++ isn't well-suited to such constructs. So we restrict to only some of
the forms of statement.
> - Placement of labels at the end of compound statements is
> > > still not allowed. (which requires teaching people to add
> > > pointless null statements)
> > >
> >
> > This is indeed a consequence of only having one kind of thing that can
> > appear in a compound-statement.
>
> I fail to see why this is important or desirable.
>
> > I wonder, do you have implementation experience for your new rule? For a
>
> I am never proposing anything I can not implement.
>
> I implemented it in the compiler I am in the progress of writing.
> It is still far from finished but
> has a fairly complete C
> frontend and compiles many interesting examples. This was
> very easy to
> implement and caused no problems.
>
I would expect the problems to emerge when retrofitting this into an
existing implementation based around the old rules :)
> recursive descent parser, I'd expect it to be quite awkward to recursively
> > parse an unbounded sequence of labels as part of statement parsing only
> to
> > find that you hit a close brace and aren't actually parsing a labelled
> > statement at all.
>
> The proposed grammar prevents this:
>
> block-item = label | declaration | unlabeled-statement
> labeled-statement = label unlabeled-statement
>
>
> So inside a compound statement you do not recurse into
> labels when parsing statements.
>
And presumably you allow the substatement of an if/while/... to be either
an unlabeled-statement or a labeled-statement?
(Minor: that does not appear to allow two labels on the same statement
except in a block. But maybe that's handled in part of the grammar you
didn't show.)
That's quite a departure from the classical rules, and the different
treatment in blocks versus other contexts is a surprise. But OK.
> In contrast, the new rule in C has neither problem and
> > > is more logical: Labels are about control flow and make
> > > sense everywhere where statements make sense.
> > >
> >
> > Hm, would you allow a label after `if (` or `for (`? At least in C++,
> > that's somewhere where (a restricted set of) statements can appear.
>
> Similar to my example above ;-)
>
> I did not know that C++ allowed statement other than
> and declarations there.
>
Only declaration-statements, expression-statements, and empty statements.
I would not allow statements or labels.
>
> Best,
> Martin
>
>
> > (In contrast, declarations are about introducing names
> > > and should interact well with scoping rules, so really
> > > should follow different rules.)
> > >
> > > Best,
> > > Martin
> > >
> > >
Received on 2020-08-11 19:05:30