From c7d0a900bda5fbc9368d668142a6f53ebed0b8ea Mon Sep 17 00:00:00 2001 From: Sebastian Jeong Date: Mon, 17 Aug 2026 04:51:19 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EB=82=A8=EC=9D=80=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=20=EC=A7=84=EB=8B=A8=20=EB=91=90=20=EA=B1=B4=EC=9D=84=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit format 검사는 인자가 떨어진 자리에서 개수 불일치를 말하고 문자열을 다 훑은 뒤 같은 말을 또 했다. aggregate storage 검사는 M7 쪽이 optional 뒤의 참조를 보려고 도는 김에 평범한 &T 필드까지 잡아서, 뒤이어 도는 M6 검사와 겹쳤다. fixture 전수 검사 결과 --check 경로에 중복 진단이 남아 있지 않다. --- fec/src/check.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/fec/src/check.c b/fec/src/check.c index 031a415..3983a75 100644 --- a/fec/src/check.c +++ b/fec/src/check.c @@ -659,6 +659,7 @@ static void check_format_call(FeCheckerState *s, FeNode *n) unsigned offset=0; int verb; int bad=0; + int counted=0; if (strcmp(n->text,"@fprint")==0) offset=1; fmt_node=n->children; 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') { 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 { t=arg->sem_type; 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; } ++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; } @@ -2730,8 +2736,13 @@ static void m7_check_storage(FeCheck *c, FeNode *decl) FeNode *m; if (!decl) return; 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) - 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"); } check_reference_storage(c,decl);