[comp.lang.c] #pragma does only half the job

bill@proxftl.UUCP (T. William Wells) (07/05/88)

In article <8176@brl-smoke.ARPA>, gwyn@brl-smoke.ARPA (Doug Gwyn ) writes:
> In article <381@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes:
> >My reasoning is this: in a correct program, where the #pragma
> >would be used, the variables referred to are IN FACT not
> >aliased. This means that the #pragma has NO effect on the
> >results of the program.
>
> Nice try, but no cigar.  "Correct program" is logically prior to
> consideration of the effect of #pragma.  The intention, I believe,
> was to specify that an arbitrary #pragma-free correct program could
> have an arbitrary #pragma inserted at an arbitrary (line boundary)
> point and would still be a correct program.  This doesn't fit what
> you're trying to do.
>
> I have finally been convinced that whether or not #pragma is really
> allowed to affect the semantics of a correct program has not been
> clearly specified.  Unless this is remedied, the only safe thing to
> do with #pragma will be to not use it.

I just spent 20 seconds reading what the (second draft) standard
had to say about #pragma. In two words: NOT ENOUGH. All the
standard says is that adding one causes the implementation to
behave in an implementation defined manner. AND THAT IS ALL.
That does prohibit a #pragma from giving additional information
about the program. Let me repeat that:

	A PRAGMA CAN NOT GIVE INFORMATION ABOUT THE PROGRAM THAT
	THE COMPILER CAN'T FIGURE OUT FOR ITSELF.

Let me add: DAMN.

About the only kinds of things that I can see the current
#pragma being used for is to do things like

	#pragma fortran-callable        (arrange that fortran pgms can call)
	#pragma int*4                   (integers are 4 bytes)
	#pragma wchar_t short           (wide characters are shorts)
	#pragma base_reg a4             (specifies addressing off register a4)

and other things which have to do with the implementation.  This
is useful but is only half of what we need.

The standard should have, either as an extension to #pragma or
as another preprocessing statement, something like:

"If the #pragma asserts that X is a property of the program and
X is in fact a property of the program, a correct program shall
still be correct when the #pragma is added."

This would mean that writing strcpy as:

	char *
	strcpy(p1, p2)
	char    *p1;
	char    *p2;
	#pragma noalias p1[],p2[];
	{
		...
	}

is ok, because, given that the assertion (that p1 and p2 are not
aliased) is true, should the compiler make that assumption, the
program will be still correct.

An additional benefit is that the compiler could add run time
checks to verify the condition; this would not be an improper use
of the construct, for as long as the condition were true, there
would be no effect on the program.

barmar@think.COM (Barry Margolin) (07/08/88)

In article <423@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes:
>All the
>standard says is that adding one causes the implementation to
>behave in an implementation defined manner. AND THAT IS ALL.
>That does prohibit a #pragma from giving additional information
>about the program. Let me repeat that:
>	A PRAGMA CAN NOT GIVE INFORMATION ABOUT THE PROGRAM THAT
>	THE COMPILER CAN'T FIGURE OUT FOR ITSELF.

How does this restriction follow from what the standard says?  As you
said, adding a pragma causes the implementation to behave in an
implementation-defined manner, i.e. it can do WHATEVER the compiler
designer wants it to do.  For example, it can make assumptions about
the aliasing of variables that are mentioned in the pragma.  How is
that different from "behaving in an implementation-defined manner"?

Barry Margolin
Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar

nevin1@ihlpf.ATT.COM (00704a-Liber) (07/08/88)

In article <423@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes:

>This would mean that writing strcpy as:
>
>	char *
>	strcpy(p1, p2)
>	char    *p1;
>	char    *p2;
>	#pragma noalias p1[],p2[];
>	{
>		...
>	}
>
>is ok, because, given that the assertion (that p1 and p2 are not
>aliased) is true, should the compiler make that assumption, the
>program will be still correct.

But, as Dennis Ritchie pointed out in his 'noalias must go' declaration (BTW,
I kept a copy of it and I have been emailing it to all those who have
requested it):

|	     A substantial fraction of the library cannot be
|	expressed in the proposed language.
|	
|	     One of the simplest routines,
|	
|	        char *strchr(const noalias char *s, int c);
|	
|	can return its first parameter.  This first parameter must
|	be declared with `const noalias;' otherwise, it would be
|	illegal (by the constraints on assignment, 3.3.16.1) to pass
|	the address of a const or noalias object.  That is, the type
|	qualifiers in the prototype are not merely an optional
|	pleasantry of the interface; they are required, if one is to
|	pass some kinds of data to this or most other library routines.

Specfically, in your example, strcpy() returns an ALIAS to p1, which by
the definition of noalias is not allowed.
-- 
 _ __			NEVIN J. LIBER	..!ihnp4!ihlpf!nevin1	(312) 510-6194
' )  )				You are in a little twisting maze of
 /  / _ , __o  ____		 email paths, all different.
/  (_</_\/ <__/ / <_	These are solely MY opinions, not AT&T's, blah blah blah

bill@proxftl.UUCP (T. William Wells) (07/08/88)

In article <23349@think.UUCP>, barmar@think.COM (Barry Margolin) writes:
> In article <423@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes:
> >     A PRAGMA CAN NOT GIVE INFORMATION ABOUT THE PROGRAM THAT
> >     THE COMPILER CAN'T FIGURE OUT FOR ITSELF.
>
> How does this restriction follow from what the standard says?

Because implementation defined means that you can change only a
very limited subset of things, i.e., those things labeled as
implementation defined in the standard.  For example, the effect
of right shifting a signed number is implementation defined.
This means that you could write #pragmas like:

#pragma right_shift zero_fill
#pragma right_shift sign_fill
#pragma right_shift generate_abort

which would cause the interpretation of the right shift to
change.  (By the way, since the standard says only that the
effect is implementation defined, any behaviour is allowable.
Thus my final example, where the compiler is being instructed to
create an abort instruction.  This is a defect in the standard; I
sent in a nitpick about it, we'll see if it gets fixed.)

[B.T.W., another, possibly loose, interpretation of what the
standard says is that the existence of #pragma widens the range
of implementation-defined to include whatever you might want to
dream up.  This ambiguity is the cause of the debate about what
can be done with #pragma.]

henry@utzoo.uucp (Henry Spencer) (07/11/88)

>... implementation defined means that you can change only a
>very limited subset of things, i.e., those things labeled as
>implementation defined in the standard...

Please justify this with specific citations from X3J11.  I spent quite a
while examining the precise semantics of #pragma when I was arguing with
Doug about this; I recall nothing that would support this interpretation.
The words (2ndP.C. draft) are "causes the implementation to behave in an
implementation-defined manner".  The definition of "implementation-defined"
just says that it depends on the implementation and must be documented.
Even the original GNU CC semantics -- in which recognition of a #pragma
causes the compiler to try to start one of the usual Unix interactive game
programs -- is technically legitimate, albeit unfriendly.

The fact is that the whole effect of a #pragma is implementation-defined,
and the draft does not specify whether it is allowed to alter the language
semantics.  Either interpretation is self-consistent.
-- 
Anyone who buys Wisconsin cheese is  |  Henry Spencer @ U of Toronto Zoology
a traitor to mankind.  --Pournelle   | {ihnp4,decvax,uunet!mnetor}!utzoo!henry

bill@proxftl.UUCP (T. William Wells) (07/11/88)

In article <5240@ihlpf.ATT.COM>, nevin1@ihlpf.ATT.COM (00704a-Liber) writes:
> In article <423@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes:
>
> >This would mean that writing strcpy as:
> >
> >     char *
> >     strcpy(p1, p2)
> >     char    *p1;
> >     char    *p2;
> >     #pragma noalias p1[],p2[];
> >     {
> >             ...
> >     }
> >
> >is ok, because, given that the assertion (that p1 and p2 are not
> >aliased) is true, should the compiler make that assumption, the
> >program will be still correct.
>
> But, as Dennis Ritchie pointed out in his 'noalias must go' declaration (BTW,
> I kept a copy of it and I have been emailing it to all those who have
> requested it):

> [something from dmr, omitted]

> Specfically, in your example, strcpy() returns an ALIAS to p1, which by
> the definition of noalias is not allowed.

Upon reading your response my first idea was to flame you for
not having read my posting carefully. Instead, I get to flame
myself. (snap, crackle, whoosh: OK, you idiot, why didn't you
say that your #pragma was different from the proposed noalias
keyword? :-)

Anyway, here is what I should have inserted into my posting:

"I might define a

	#pragma noalias declarator_list;

which asserts that, should an expression of a form equivalent to
one of these declarators be used to modify an object, that
object will not be referencable by means of an expression of a
form equivalent to any of the other declarators."

In the given example, the only thing that the compiler may
assume is that, since p1[] is going to be modified, p2[] will not
be.

I am aware that my example #pragma is a little rough around the
edges, but since I only needed it as an example, I am not going
to elaborate on how it might be fixed up.

bill@proxftl.UUCP (T. William Wells) (07/20/88)

In article <1988Jul10.201104.27556@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
> >... implementation defined means that you can change only a
> >very limited subset of things, i.e., those things labeled as
> >implementation defined in the standard...
>
> Please justify this with specific citations from X3J11.

3.8.6 says:

"[a pragma] causes the implementation to behave in an
implementation-defined manner...."

My reading of this says that a pragma changes the implementation,
not (directly) the interpretation of the program.  However, the
changed implementation must also be conforming.  This means that
it can only change those aspects of the standard which are
subject to choice, i.e., those things which are implementation
defined (or one of the other indeterminate characteristics).

Anyway, given that reasonable people can disagree on the
interpretation of this, it should be changed.

faustus@ic.Berkeley.EDU (Wayne A. Christopher) (07/21/88)

In article <502@proxftl.UUCP>, bill@proxftl.UUCP (T. William Wells) writes:
> "[a pragma] causes the implementation to behave in an
> implementation-defined manner...."
> 
> My reading of this says that a pragma changes the implementation,
> not (directly) the interpretation of the program.  However, the
> changed implementation must also be conforming.

You're right, this statement is sort of confusing, but when you think
about it, it has to mean that #pragma can cause a compiler to become
non-conforming.  Otherwise, #pragma noalias wouldn't be possible.
Telling the compiler that a set of parameters is noalias changes the
semantics of the function.

	Wayne

bill@proxftl.UUCP (T. William Wells) (07/22/88)

In article <4580@pasteur.Berkeley.Edu> faustus@ic.Berkeley.EDU (Wayne A. Christopher) writes:
> In article <502@proxftl.UUCP>, bill@proxftl.UUCP (T. William Wells) writes:
> > "[a pragma] causes the implementation to behave in an
> > implementation-defined manner...."
> >
> > My reading of this says that a pragma changes the implementation,
> > not (directly) the interpretation of the program.  However, the
> > changed implementation must also be conforming.
>
> You're right, this statement is sort of confusing, but when you think
> about it, it has to mean that #pragma can cause a compiler to become
> non-conforming.  Otherwise, #pragma noalias wouldn't be possible.
> Telling the compiler that a set of parameters is noalias changes the
> semantics of the function.

Perhaps you came in late on this debate?  The whole point of it
is whether the standard DOES allow the use of #pragma to specify
noalias (and friends).  The reading I give to it prohibits this;
other readings permit it.

Reading 1: #pragma modifies the implementation.  #pragma noalias
    is not permitted.

Reading 2: #pragma modifies the program.  Anything goes,
    including #pragma noalias.

And, as I said, this ought to be clarified for the next draft
standard.

henry@utzoo.uucp (Henry Spencer) (07/23/88)

In article <502@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes:
>"[a pragma] causes the implementation to behave in an
>implementation-defined manner...."
>
>My reading of this says that a pragma changes the implementation,
>not (directly) the interpretation of the program.  However, the
>changed implementation must also be conforming.  This means that
>it can only change those aspects of the standard which are
>subject to choice, i.e., those things which are implementation
>defined (or one of the other indeterminate characteristics).

Sorry, no.  One of the things that is subject to choice is how the
implementation behaves when it sees #pragma!  "Conforming" means that
it conforms to a standard which includes section 3.8.6 (#pragma) --
which only says that #pragma does something implementation-defined.
The only restraint this imposes is that the behavior must be documented.

You cannot excise 3.8.6 from the document and then claim that #pragma
must conform to the resulting subset; standards must be taken as a whole.
Your argument works only if you already believe that #pragma is not
allowed to alter the meaning of other parts of the language.  This is
circular reasoning.  There isn't any way out of it; the (draft) standard
simply does not tell you whether #pragma is allowed to change the rest of
the language or not.
-- 
Anyone who buys Wisconsin cheese is|  Henry Spencer at U of Toronto Zoology
a traitor to mankind.  --Pournelle |uunet!mnetor!utzoo! henry @zoo.toronto.edu

bill@proxftl.UUCP (T. William Wells) (07/25/88)

In article <1988Jul22.172848.6344@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
: In article <502@proxftl.UUCP> bill@proxftl.UUCP (T. William Wells) writes:
: > [I defend my interpretation of the #pragma]
:
: [He says that my interpretation is based on circular logic and context
: dropping].
:
:                      There isn't any way out of it; the (draft) standard
: simply does not tell you whether #pragma is allowed to change the rest of
: the language or not.

I have come to the conclusion that the language used is sufficiently
ambiguous to permit either my or your interpretation, I have to agree
with your final statement.  This means that there is no further point
in discussion as the difference is one of preference rather than one
which can be decided by reference to the standard.

As a final note, I much prefer an interpretation of pragma that says
that it a) may change the behavior of the implementation in any way
that leaves it still conforming, or b) makes assertions about the
program which the implementation may assume to be true.

This is weaker (read: permits more) than the my interpretation of the
standard but stronger than yours.  In any case, the language ought to
be clarified for the next edition.