Bug
A name declared twice in one scope gets no diagnostic. The transpiler exits 0 and emits both declarations, and gcc rejects the C. Two shapes:
- Two locals of one name in the same block.
- A local in a function's outermost block with the name of one of the function's parameters. C gives the parameters and the function's outermost block one scope, so this is a redeclaration too.
ADR-057 allows shadowing "matching C behavior". C forbids a second declaration of a name in the same scope, so neither shape is shadowing.
Found while reviewing PR #1993. That PR changes how the second shape fails (below).
Reproduction (--target host)
u32 total <- 7;
u32 dup() {
u32 a <- 1;
u32 a <- 2;
return a;
}
u32 plain(u32 a) {
u32 a <- 2;
return a;
}
u32 shadowing(u32 total) {
u32 total <- 3;
return total;
}
On main @ 7d7f27158, exit 0:
uint32_t dup(void) {
uint32_t a = 1U;
uint32_t a = 2U; // gcc: redefinition of 'a'
...
uint32_t plain(uint32_t a) {
uint32_t a = 2U; // gcc: 'a' redeclared as different kind of symbol
...
uint32_t shadowing(uint32_t total) {
uint32_t shadowing__total = 3U; // compiles: only the local moved (ADR-057)
return shadowing__total;
}
On PR #1993 @ 14d9241c9, exit 0. dup and plain are unchanged. shadowing now fails too, because the parameter moves as well (#1290) and the two declarations share one C name:
uint32_t shadowing(uint32_t shadowing__total) {
uint32_t shadowing__total = 3U; // gcc: 'shadowing__total' redeclared as different kind of symbol
Control: the same local one block deeper (if (total > 0) { u32 total <- 3; … }) is shadowing. It transpiles on the PR to an inner uint32_t shadowing__total = 3U;, compiles under -Wall -Wextra -Werror, and global.total still reads the global.
Cause
1.4 frames every function-body declaration. Since #1290 that includes the parameters, in the function's frame. Nothing checks a new declaration against the declarations already in its scope, so LexicalFrames.emittedName names both and render emits both.
Definition of done
Bug
A name declared twice in one scope gets no diagnostic. The transpiler exits 0 and emits both declarations, and gcc rejects the C. Two shapes:
ADR-057 allows shadowing "matching C behavior". C forbids a second declaration of a name in the same scope, so neither shape is shadowing.
Found while reviewing PR #1993. That PR changes how the second shape fails (below).
Reproduction (
--target host)On
main@7d7f27158, exit 0:On PR #1993 @
14d9241c9, exit 0.dupandplainare unchanged.shadowingnow fails too, because the parameter moves as well (#1290) and the two declarations share one C name:Control: the same local one block deeper (
if (total > 0) { u32 total <- 3; … }) is shadowing. It transpiles on the PR to an inneruint32_t shadowing__total = 3U;, compiles under-Wall -Wextra -Werror, andglobal.totalstill reads the global.Cause
1.4 frames every function-body declaration. Since #1290 that includes the parameters, in the function's frame. Nothing checks a new declaration against the declarations already in its scope, so
LexicalFrames.emittedNamenames both and render emits both.Definition of done
test-errorfixtures for both shapes, including the shadowing-a-global variant of the parameter shape. Beside them goes a control that must stay silent: the same local one block deeper. Each is mutation-checked.