https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119933
Jiahao Xu <xujiahao at loongson dot cn> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |xujiahao at loongson dot cn
--- Comment #3 from Jiahao Xu <xujiahao at loongson dot cn> ---
All 120 unexpected failures appear to be caused by the warning:
warning: 'SECTION segment' requires '-dialect ibm' [-Wsegment]
This warning is emitted on LoongArch64, but not on x86_64 or AArch64.
Tracing the warning shows that it originates from the following code in the
generated parse.cc:
if ((yyvsp[0].string)
&& dialect_ok((yylsp[0]), IbmSectionSegmentW, "SECTION segment"))
{
...
}
On x86_64 and AArch64, yyvsp[0].string is NULL, so dialect_ok is not called. On
LoongArch64, however, yyvsp[0].string becomes a non-NULL invalid pointer,
causing the condition to evaluate as true and the warning to be emitted.
yyvsp[0] comes from yylval, which is a union whose first members are:
union YYSTYPE
{
bool boolean;
int number;
char *string;
...
};
Before the check above, the lexer executes:
if (token == SECTION)
yylval.number = 0;
On x86_64, the previous pointer value stored in the union typically has its
upper 32 bits equal to zero. After writing 0 to the number member, the same
storage is later observed as a null pointer when accessed through the string
member.
On LoongArch64, the previous pointer value often has non-zero upper 32 bits.
Writing 0 to the number member clears only the lower 32 bits, leaving the upper
32 bits unchanged. When the union storage is later interpreted as a char *, it
becomes a non-NULL invalid pointer (for example, 0x100000000), causing the
condition above to evaluate as true and the warning to be emitted.
As an experiment, I changed:
if (token == SECTION)
yylval.number = 0;
to:
if (token == SECTION)
yylval.string = NULL;
After this change, the warning disappears and all COBOL tests pass on both
x86_64 and LoongArch64.
I am not familiar enough with this part of the COBOL frontend to determine
whether this is the correct fix, but it appears that the current behavior
depends on reading a different union member from the one that was written, and
LoongArch64 exposes the issue because pointer values commonly have non-zero
upper 32 bits.