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.
90 lines
2.4 KiB
C
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;
|
|
}
|