Versions: PAL a9ebbed · F*/Pulse nightly 2026-08-27 · Clang 20.1.8
Summary
A function declared inside a function body — the K&R-era idiom of declaring a library function locally instead of including its header — is dropped, and the call then has no definition to resolve to.
PAL does report unsupported variable declaration Function, but translation continues and emits a module that cannot verify.
Minimal repro
#include "pal.h"
/* 1. FAILS -- callee declared inside the body. */
double local_decl(_array double *v, unsigned n)
_preserves(v._length == n)
_requires(n > 0)
{
double floor();
double d = floor(2.0);
return v[0] + d;
}
/* 2. control -- identical, callee declared at FILE scope. VERIFIES */
double floor_at_file_scope();
double control_file_scope(_array double *v, unsigned n)
_preserves(v._length == n)
_requires(n > 0)
{
double d = floor_at_file_scope();
return v[0] + d;
}
/* 3. control -- no call at all. VERIFIES */
double control_no_call(_array double *v, unsigned n)
_preserves(v._length == n)
_requires(n > 0)
{
return v[0];
}
$ pal --outdir out repro.c
error: unsupported variable declaration Function
error: (internal, after merge) unknown function floor
error: (internal, after normalize_casts) unknown function floor
error: (internal, after elim_cis) unknown function floor
error: (internal, after elim_cis) cannot infer type of floor(N): floor is not a function
$ run-fstar.sh --include out out/Func_local_decl.fst
Error 72: Identifier not found: func_floor
$ run-fstar.sh --include out out/Func_control_file_scope.fst # Verified
$ run-fstar.sh --include out out/Func_control_no_call.fst # Verified
All three functions carry the same trivially provable array index (v[0]), so the only variable is where the callee is declared.
Impact
We are using PAL to prove spatial memory safety on the Olden and Ptrdist benchmark suites, holding the C source fixed and adding only annotations. Older C in these suites declares floor, sqrt, atoi and similar locally rather than including a header, so the construct shows up in real code.
The impact is modest on its own — in olden/bh it accounts for 2 of 73 obligations — but the diagnostic is misleading: the reported error is about a variable declaration, and the eventual failure is an unresolved identifier in generated code, so the connection back to the local declaration is not obvious.
Suggested behaviour
Either treat a function declared in block scope the same as one declared at file scope (C's scoping rules make this equivalent for the callee's type), or make the translation error fatal so it is not silently followed by an unverifiable module.
Related: #92 (Provide specifications for C library functions), #73 (Support separate function declarations, closed).
Versions: PAL
a9ebbed· F*/Pulse nightly2026-08-27· Clang 20.1.8Summary
A function declared inside a function body — the K&R-era idiom of declaring a library function locally instead of including its header — is dropped, and the call then has no definition to resolve to.
PAL does report
unsupported variable declaration Function, but translation continues and emits a module that cannot verify.Minimal repro
All three functions carry the same trivially provable array index (
v[0]), so the only variable is where the callee is declared.Impact
We are using PAL to prove spatial memory safety on the Olden and Ptrdist benchmark suites, holding the C source fixed and adding only annotations. Older C in these suites declares
floor,sqrt,atoiand similar locally rather than including a header, so the construct shows up in real code.The impact is modest on its own — in
olden/bhit accounts for 2 of 73 obligations — but the diagnostic is misleading: the reported error is about a variable declaration, and the eventual failure is an unresolved identifier in generated code, so the connection back to the local declaration is not obvious.Suggested behaviour
Either treat a function declared in block scope the same as one declared at file scope (C's scoping rules make this equivalent for the callee's type), or make the translation error fatal so it is not silently followed by an unverifiable module.
Related: #92 (Provide specifications for C library functions), #73 (Support separate function declarations, closed).