次の (単純化された) コードを複数のプラットフォーム用にコンパイルしようとすると、IBM の xlC_r. さらに調査したところ、comeau と clang でも失敗することがわかりました。g++ および Solaris の CC で正常にコンパイルされます。
コードは次のとおりです。
int main()
{
int a1[1];
bool a2[1];
for (int *it = a1, *end = a1+1; it != end; ++it) {
//...
bool *jt = a2, *end = a2+1;
//...
}
}
xlC_r エラー:
"main.cpp", line 8.25: 1540-0400 (S) "end" has a conflicting declaration.
"main.cpp", line 6.25: 1540-0425 (I) "end" is defined on line 6 of "main.cpp".
クランエラー:
main.cpp:8:25: error: redefinition of 'end' with a different type
bool *jt = a2, *end = a2+1;
^
main.cpp:6:25: note: previous definition is here
for (int *it = a1, *end = a1+1; it != end; ++it) {
^
コモーエラー:
"ComeauTest.c", line 8: error: "end", declared in for-loop initialization, may not
be redeclared in this scope
bool *jt = a2, *end = a2+1;
^
問題は、なぜこれがエラーになるのかということです。
2003年の標準に目を通すと、次のように書かれています(6.5.3):
The for statement
for ( for-init-statement; condition; expression ) statement
is equivalent to
{
for-init-statement;
while ( condition ) {
statement;
expression;
}
}
except that names declared in the for-init-statement are in the same
declarative-region as those declared in condition
ここでは、条件で宣言された名前はありません。
さらに、それは言います(6.5.1):
When the condition of a while statement is a declaration, the scope
of the variable that is declared extends from its point of declaration
(3.3.1) to the end of the while statement. A while statement of the form
while (T t = x) statement
is equivalent to
label:
{
T t = x;
if (t) {
statement;
goto label;
}
}
繰り返しますが、条件に宣言がないため、これが関連しているかどうかはわかりません。したがって、6.5.3 から同等の書き直しを行うと、私のコードは次のようになります。
int main()
{
int a1[1];
bool a2[1];
{
int *it = a1, *end = a1+1;
while (it != end) {
//...
bool *jt = a2, *end = a2+1;
//...
++it;
}
}
}
これにより、明らかに end を再宣言できます。