Discussion:
What is the point of restrict in fopen?
(too old to reply)
Kaz Kylheku
2023-05-24 23:41:30 UTC
Permalink
I've noticed that both arguments of fopen are restrict-qualified.

What does this achieve?

If I have:

const char *path = "foobar";
const char *mode = path + 6;

FILE *f = fopen(path, mode);

is the behavior undefined, since the mode pointer accesses
something which is also accessed through path?

What if the code is this:

FILE *f = fopen("foobar", "r");

and the compiler itself merges the two string literals so
that they share storage?

The arguments are treated as immutable by fopen, so what is
the purpose of restrict?

The benefit of restrict is that when an object is being modified through
a restrict-qualified pointer, the implementation is not required to care
whether the object is aliased through another object. Access through the
other pointer can be cached as if that modification didn't happen.
If aliasing is occurring, the behavior is undefined, allowing the
implementor not to care about that situation.

But the arguments to fopen must not be modified.

How can fopen be made faster based on the assurance that the inputs do
not overlap, (and is that really worth breaking programs?)
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Tim Rentsch
2023-07-20 17:17:37 UTC
Permalink
Post by Kaz Kylheku
I've noticed that both arguments of fopen are restrict-qualified.
What I think you mean is that the arguments given in the prototype
declaration in the C standard are qualified with the 'restrict'
keyword.

Note that this form of declaration has no effect on the semantics of
the function. The function declaration, and its semantics, are just
the same as if the uses of 'restrict' were removed.
Jakob Bohm
2023-07-21 06:55:48 UTC
Permalink
Post by Tim Rentsch
Post by Kaz Kylheku
I've noticed that both arguments of fopen are restrict-qualified.
What I think you mean is that the arguments given in the prototype
declaration in the C standard are qualified with the 'restrict'
keyword.
Note that this form of declaration has no effect on the semantics of
the function. The function declaration, and its semantics, are just
the same as if the uses of 'restrict' were removed.
Note that Tim's critique or restrict in May 2023 is very similar to the
critique of the similar noalias proposal in messageid <***@alice.UUCP>
by someone highly respected in this group. That was posted 35 years
ago.

Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded
Kaz Kylheku
2023-07-22 05:37:15 UTC
Permalink
Post by Jakob Bohm
Post by Tim Rentsch
Post by Kaz Kylheku
I've noticed that both arguments of fopen are restrict-qualified.
What I think you mean is that the arguments given in the prototype
declaration in the C standard are qualified with the 'restrict'
keyword.
Note that this form of declaration has no effect on the semantics of
the function. The function declaration, and its semantics, are just
the same as if the uses of 'restrict' were removed.
Note that Tim's critique or restrict in May 2023 is very similar to the
by someone highly respected in this group. That was posted 35 years
ago.
That someone was even opposed to const, for some good reasons.

The present issue reveals a design flaw in the C type system:
that qualifiers on function parameters don't matter.

They should, though.

void f(const int);
void f(int);

should be incomaptible and diagnosed! Someone thought, at some point, that
those qualifiers which existed then (const, volatile) only affect the
function definition locally, and not its interface semantics.

So, it probably seemed like a marvellous idea. I know! Let's make
qualifiers on parameters not matter, as if they were not there.
Then you can make a parameter const, if that makes sense in
the function definition, without disturbing the declaration.

But restrict is not like this. When a pointer parameter is restrict, it
changes the semantics in a way that is very much relevant to the caller.

Here is how it should work:

The rule should be that only const and volatile qualifiers do not matter
on a function parameter, as far as type compatibility and composite type
is concerned. The restrict qualifier should matter, and future
qualifiers that may be introduced have to be considered on a
case-by-casde basis.

If a function definition is changed to include a restrict parameter,
that should render it incompatible with the declaration.

The declaration is then updated, and makes a semantic difference to the
calls; the calls become undefined behavior if they pass overlapping
objects. This can be detected at translation time and diagnosed, with
the translation unit then being rejected, even if all that is known bout
the function is its declaration with restrict parameters.

Alternative rules:

// All declarations must be identical in restrict qualification:

int f(const char * restrict);
int f(const char *); // error: incompatible redeclaration

// Definition is allowed to change restrict qualification

int f(const char *p) // OK
{
// type of f here is without the restrict.
// Only the parameter itself lacks the qualifier.
// If f recurses, restrict does not apply to call.
}

// type of f in this scope is *with* the restrict from decl.

In other words, the type doesn't compose with regard to restrict
qualification. Only a definition can change the restrict-qualification
of a parameter, and then in taht definition's own scope, its own
restrict qualifiers (or lack thereof) apply, and determine the type of
the function, not only the local parameters.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @***@mstdn.ca
Tim Rentsch
2023-07-25 12:35:30 UTC
Permalink
Post by Kaz Kylheku
Post by Jakob Bohm
Post by Tim Rentsch
Post by Kaz Kylheku
I've noticed that both arguments of fopen are restrict-qualified.
What I think you mean is that the arguments given in the prototype
declaration in the C standard are qualified with the 'restrict'
keyword.
Note that this form of declaration has no effect on the semantics
of the function. The function declaration, and its semantics, are
just the same as if the uses of 'restrict' were removed.
Note that Tim's critique or restrict in May 2023 is very similar
to the critique of the similar noalias proposal in messageid
That was posted 35 years ago.
That someone was even opposed to const, for some good reasons.
that qualifiers on function parameters don't matter.
They should, though.
void f(const int);
void f(int);
should be incomaptible and diagnosed!
A foolish consistency is the hobgoblin of little minds.
Kaz Kylheku
2023-07-25 19:33:46 UTC
Permalink
Post by Tim Rentsch
Post by Kaz Kylheku
Post by Jakob Bohm
Post by Tim Rentsch
Post by Kaz Kylheku
I've noticed that both arguments of fopen are restrict-qualified.
What I think you mean is that the arguments given in the prototype
declaration in the C standard are qualified with the 'restrict'
keyword.
Note that this form of declaration has no effect on the semantics
of the function. The function declaration, and its semantics, are
just the same as if the uses of 'restrict' were removed.
Note that Tim's critique or restrict in May 2023 is very similar
to the critique of the similar noalias proposal in messageid
That was posted 35 years ago.
That someone was even opposed to const, for some good reasons.
that qualifiers on function parameters don't matter.
They should, though.
void f(const int);
void f(int);
should be incomaptible and diagnosed!
A foolish consistency is the hobgoblin of little minds.
I deserve that for starting with that silly bait,
but I later acknowledged that the flexibility is necessary
to be able to const-qualify a parameter in the definition
without touching the declaration.

Here is a realistic plan.

Phase 1:

Qualifiers except restrict are ignored in function
declarators, are not part of the function type and do not
participate in composition. The restrict qualifier is now
part of the type. If a declaration restrict-qualifies a parameter, a
redeclaration (or definition) need not. The composite type of the
parameter will be restrict-qualified.

Tolerance for the presence of const and volatile qualifiers on
paramaters in prototype declarations is marked obsolescent.

Phase 2:

The obsolescence period introduced in Phasae 1 ends. Const and volatile
qualifiers are no longer allowed on parameters in declarations; it is a
diagnosable constraint violation. They are allowed in definitions only,
and don't contribute to the function type declared.

A new obsolescence period begins: situations in which multiple
declarations of a function differ in the restrict-qualification of a
parameter are considered obsolescent.

Phase 3:

Obsolescence period from Phase 2 ends: it is a constraint violation
whenever a declaration or definition of a function differs
from a previous declaration in the restrict qualification of
a parameter.

// Phase 1 Phase 2 Phase 3
void f(const int); // obsol. error error
//
void f(char *restrict p); //
void g(char *); //
//
void f(char *p) { } // obsol. error
void g(char *restrict p) // obsol. error

i.e. the language becomes sane. Bullshit code smells like qualifiers
that do nothing become errors. If restrict is used to optimize a
function in a way that affects the interface contract, that must be
reflected in the declaration; it is not possible to use restrict
in a definition, but omit that in a declaration.
Tim Rentsch
2023-08-05 03:15:45 UTC
Permalink
Post by Kaz Kylheku
Post by Tim Rentsch
Post by Kaz Kylheku
I've noticed that both arguments of fopen are
restrict-qualified.
What I think you mean is that the arguments given in the
prototype declaration in the C standard are qualified with
the 'restrict' keyword.
Note that this form of declaration has no effect on the
semantics of the function. The function declaration, and its
semantics, are just the same as if the uses of 'restrict'
were removed.
[...]
Post by Kaz Kylheku
Here is a realistic plan.
[...]
[...]
[...]
Here is a simpler and better idea.

Add a Recommended Practice that compilers provide an
option to produce a diagnostic when a function
parameter is restrict-qualified in the function
definition but is not restrict-qualified in any other
declaration of the function in the same compilation
unit.

And nothing more than that.

Tim Rentsch
2023-07-25 12:37:22 UTC
Permalink
Post by Jakob Bohm
Post by Tim Rentsch
Post by Kaz Kylheku
I've noticed that both arguments of fopen are restrict-qualified.
What I think you mean is that the arguments given in the prototype
declaration in the C standard are qualified with the 'restrict'
keyword.
Note that this form of declaration has no effect on the semantics
of the function. The function declaration, and its semantics, are
just the same as if the uses of 'restrict' were removed.
Note that Tim's critique or restrict in May 2023 is very similar
to the critique of the similar noalias proposal in messageid
My comment wasn't a critique, just an observation.
Loading...