cplusplus / draft

C++ standards drafts
http://www.open-std.org/jtc1/sc22/wg21/
5.7k stars 751 forks source link

[basic.scope.block] p1 The note should be as a normative rule #4841

Open xmh0511 opened 3 years ago

xmh0511 commented 3 years ago

Each

  • selection or iteration statement ([stmt.select], [stmt.iter]),
  • substatement of such a statement,
  • handler ([except.pre]), or
  • compound statement ([stmt.block]) that is not the compound-statement of a handler

introduces a block scope that includes that statement or handler.

[Note 1: A substatement that is also a block has only one scope. — end note]

Isn't that note should be phrased as a normative rule? My proposal is that

Each

  • [...]
  • substatement of such a statement that is not a compound-statement,
  • [...]
  • compound statement ([stmt.block]) that is not the compound-statement of a handler

introduces a block scope that includes that statement or handler.

[Note 1: A substatement that is also a block has only one scope. — end note].

if(true) {
}

The substatement is a compound-statement, hence the second bullet does not apply but the last bullet does, which means the substatement only introduced one block scope.

jensmaurer commented 3 years ago

I disagree there is a need to clarify this normatively; I think the note is good enough for directing the reading here.

@opensdh, any thoughts on this?

xmh0511 commented 3 years ago

If there is no normative rule, we could say the compound-statement of the selection statement can introduce two blocks, please note the wording Each, a compound-statement of the selection statement is both the substatement and the compound-statement itself, which satisfies the second bullet and the last bullet.

xmh0511 commented 3 years ago

To stress the opinion, please consider this example

if(int a = 1)
  if(int a = 0){}

The declaration of a in the second line will not violate [basic.scope.block] p2, since the substatement of the first selection statement is both a substatement itself and is a selection statement, hence according to the first and second bullet of [basic.scope.block] p1, it will introduce two block scopes.

opensdh commented 3 years ago

I agree with @jensmaurer. A statement that matches two bullets doesn't produce two scopes; it just produces one scope for two different reasons. (It might be more reasonable to read it as two scopes if "and" separated the bullets, but even then there's only one object to have this property.) It's true that the if(…) if(…) example is another way that a statement can deserve a scope in two different ways; we could extend the note to cover that too if that would help.

xmh0511 commented 3 years ago

@opensdh

It's true that the if(…) if(…) example is another way that a statement can deserve a scope in two different ways;

If the second if(...) only introduces one scope, then the declaration in it would violate [basic.scope.block#2]. Since the parent scope of the the target scope of the second declaration of a is the scope introduced by the first if, which contains another declaration of a, they are potential conflict. However, the example is accepted by all compilers https://godbolt.org/z/rWac8j8vW

jensmaurer commented 3 years ago

@opensdh: The concern is the treatment of these two examples:

void f()
{
  if (int a = 1)
    if (int a = 0) ;     // #1 OK

  if (int b = 1) {
    int b = 0;            // #2 error
  }
}

1 combines the "selection statement" and "substatement" bullets of [basic.scope.block] p1 and is ok (according to gcc and clang). #2 combines the "substatement" and "compound-statement" bullets of [basic.scope.block] p1 and is ill-formed.

I can't reconcile the different treatment of #1 and #2 by the compilers with the normative wording we're looking at. To make that work, the model for #1 needs to be if (int x = 1) ... is rewritten to { int x = 1; if (x) ... }, but we lack normative words to say that.

jensmaurer commented 3 years ago

http://lists.isocpp.org/core/2021/08/11372.php

xmh0511 commented 3 years ago

@jensmaurer After the above fix. I think we could add "or, if not that" into the end of each item in [basic.scope.block] p1, which will make that "just produces one scope for two different reasons." more clear.

xmh0511 commented 2 years ago

For this issue. We might say

Each distinct statement of the following:

  • [...]

introduces a block scope that includes that statement or handler.

This might clarify this issue. Since the compound statement itself as the substatement of a selection statement is the same statement, it introduces only one scope.

opensdh commented 2 years ago

I still don't see the need to do anything here: a list of "every Fibonacci number or cube less than 100" doesn't include 8 twice and 1 three times.

xmh0511 commented 2 years ago

"every Fibonacci number or cube less than 100" doesn't include 8 twice and 1 three times

Because, either Fibonacci number or cube, it has a clear mathematical definition and formulation from which each value arises. Back to natural language, consider this case

Each person in the group X

  • has an apple, or
  • has a banana

The group X gets one score.

Assume a person has an apple and a banana, the group should get two scores because the person satisfies two. It wouldn't happen that the group X could only get one score due to the person has dedicated one score due to his apple so the one score for the banana would be discarded.

IMO, the application of the bullet is equivalent to


for(auto i : list){  // list is we defined
   if(statement.has(i) == true){  
      statement.introduces_block++;
  }
}