fix: 남은 중복 진단 두 건을 정리한다

format 검사는 인자가 떨어진 자리에서 개수 불일치를 말하고 문자열을 다 훑은
뒤 같은 말을 또 했다. aggregate storage 검사는 M7 쪽이 optional 뒤의 참조를
보려고 도는 김에 평범한 &T 필드까지 잡아서, 뒤이어 도는 M6 검사와 겹쳤다.

fixture 전수 검사 결과 --check 경로에 중복 진단이 남아 있지 않다.
This commit is contained in:
2026-08-17 04:51:19 +09:00
parent f5bffec7dd
commit c7d0a900bd
+14 -3
View File
@@ -659,6 +659,7 @@ static void check_format_call(FeCheckerState *s, FeNode *n)
unsigned offset=0; unsigned offset=0;
int verb; int verb;
int bad=0; int bad=0;
int counted=0;
if (strcmp(n->text,"@fprint")==0) offset=1; if (strcmp(n->text,"@fprint")==0) offset=1;
fmt_node=n->children; fmt_node=n->children;
if (offset) { if (offset) {
@@ -693,7 +694,10 @@ static void check_format_call(FeCheckerState *s, FeNode *n)
if (verb!=' ' && verb!='x' && verb!='c' && verb!='s' && verb!='b') { if (verb!=' ' && verb!='x' && verb!='c' && verb!='s' && verb!='b') {
err(s->c,n->loc,"unsupported format verb"); bad=1; err(s->c,n->loc,"unsupported format verb"); bad=1;
} }
if (!arg) { err(s->c,n->loc,"format argument count mismatch"); bad=1; } if (!arg) {
err(s->c,n->loc,"format argument count mismatch");
bad=1; counted=1;
}
else { else {
t=arg->sem_type; t=arg->sem_type;
if (verb==' ' && t && t->kind==FE_TYPE_ENUM && t->is_error) verb='s'; if (verb==' ' && t && t->kind==FE_TYPE_ENUM && t->is_error) verb='s';
@@ -705,7 +709,9 @@ static void check_format_call(FeCheckerState *s, FeNode *n)
if (fmt[i]=='}') { err(s->c,n->loc,"unmatched '}' in format"); bad=1; } if (fmt[i]=='}') { err(s->c,n->loc,"unmatched '}' in format"); bad=1; }
++i; ++i;
} }
if (count!=argc) { err(s->c,n->loc,"format argument count mismatch"); bad=1; } /* Running out of arguments mid-string already said this. Saying it again
once the whole string has been walked adds nothing. */
if (count!=argc && !counted) { err(s->c,n->loc,"format argument count mismatch"); bad=1; }
(void)bad; (void)bad;
} }
@@ -2730,8 +2736,13 @@ static void m7_check_storage(FeCheck *c, FeNode *decl)
FeNode *m; FeNode *m;
if (!decl) return; if (!decl) return;
if (decl->kind==FE_N_STRUCT || decl->kind==FE_N_ENUM) { if (decl->kind==FE_N_STRUCT || decl->kind==FE_N_ENUM) {
/* This pass exists for the shapes the other one cannot see, such as a
reference behind an optional. A plain `&T` field is seen by both, so
leave that one to check_reference_storage below. */
for (m=decl->children;m;m=m->next) for (m=decl->children;m;m=m->next)
if (m->kind==FE_N_FIELD && m7_ast_reference_storage(m->a)) if (m->kind==FE_N_FIELD && m7_ast_reference_storage(m->a) &&
!own_ast_reference_type(m->a) &&
!own_ast_pointer_to_reference(m->a))
err(c,m->loc,"reference type is not allowed in aggregate storage"); err(c,m->loc,"reference type is not allowed in aggregate storage");
} }
check_reference_storage(c,decl); check_reference_storage(c,decl);