Files
ww/test/wcc/948_selfimport.c
Hojun-Cho 9f8df525c2 wcc/check: reject self-import, both stages (#16 ENFORCE-checker)
check-(c): a package importing itself (any spelling) is a hard error,
mirroring Go. Predicate is leaf==owner at the N_USE/installdecl seam —
sound only after the PREP commits (dotted-test renames, package-less
boundary directive). Identical wording both stages; diagnostics-only,
byte-id-neutral. 948 pins the reject in both compilers; 708's
pos_selfimp (which pinned the abolished self-import skip) converts to
neg_selfimp + new pos_crossmod preserving the param-shadow tolerance
the case existed for. Checks (a) unused and (b)/(d) name-membership
stay deferred to the multi-package arc: imports are filename-keyed
pulls, so those need import->file provenance this compiler lacks.
2026-06-10 15:18:58 +09:00

90 lines
2.4 KiB
C

/*
* 948_selfimport — #16 check-(c): a package may not import itself.
*
* Both compiler stages (w6c, w6c_ww) must loud-reject `package foo;
* import foo;` — nonzero exit AND a "self-import" diagnostic on stderr.
* Compile-only (`-o /dev/null`): w6c/w6c_ww do not expand imports (the
* driver does), so a lone fixture triggers check-(c) directly. This is
* NOT a ww_ww DRIVER test — it never invokes the driver — so it is
* Phase-1-safe and does not race the 990-997 byte-id gates (rule 14).
*
* check-(a) unused + (b)/(d) membership are DEFERRED to task #8 (ww's
* filename-keyed file-inclusion imports lack import->file->symbol
* provenance); only self-import is package-model-independent.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static const char *
absbin(void)
{
const char *b = getenv("BIN");
if (!b) b = "out/bin";
if (b[0] == '/') return b;
static char buf[2048];
char cwd[1024];
if (getcwd(cwd, sizeof cwd) == NULL) return NULL;
snprintf(buf, sizeof buf, "%s/%s", cwd, b);
return buf;
}
/* reject — `<comp> <fixture> -o /dev/null` must exit nonzero and print
* <substr> on stderr. */
static int
reject(const char *bin, const char *comp, const char *fixture,
const char *substr)
{
int pid = getpid();
char errf[256], cmd[4096], line[4096];
snprintf(errf, sizeof errf, "/tmp/si948_%s_%d.err", comp, pid);
snprintf(cmd, sizeof cmd, "%s/%s %s -o /dev/null 2>%s",
bin, comp, fixture, errf);
int rc = system(cmd);
if (rc == 0) {
fprintf(stderr, "948 FAIL: %s accepted %s (expected reject)\n",
comp, fixture);
return 1;
}
int found = 0;
FILE *f = fopen(errf, "r");
if (f) {
while (fgets(line, sizeof line, f))
if (strstr(line, substr)) { found = 1; break; }
fclose(f);
}
unlink(errf);
if (!found) {
fprintf(stderr, "948 FAIL: %s rejected %s but no '%s' on stderr\n",
comp, fixture, substr);
return 1;
}
return 0;
}
static const struct {
const char *comp;
const char *fixture;
const char *substr;
} rows[] = {
{ "w6c", "test/wcc/data/selfimport.ww", "self-import" },
{ "w6c_ww", "test/wcc/data/selfimport.ww", "self-import" },
};
int
main(void)
{
const char *bin = absbin();
if (!bin) { fprintf(stderr, "948 FAIL: getcwd\n"); return 1; }
for (size_t i = 0; i < sizeof rows / sizeof rows[0]; i++)
if (reject(bin, rows[i].comp, rows[i].fixture, rows[i].substr) != 0)
return 1;
printf("self-import rejected by w6c and w6c_ww\n");
return 0;
}