I1090801%DBSTU1.BITNET@CUNYVM.CUNY.EDU (11/25/87)
I am a student of computer science and I have to write a C-compiler.
The problem I came across is: does a C-compiler have to generate code
to check if a function really delivers a result in all cases?
Example: In the following (nonsense) function
int f()
{
int a;
a = 1; /* only to set a to a non-garbage value */
if (...)
return a;
else
... /* statements without any return */
}
a value is delivered in the then part but in the else part nothing
happens and the program just runs out of the end of the function.
So, in this case, some garbage is delivered. In this example you can
easily see this, but things get worse if the function is more
complicated. I think it isn't easy for a compiler to see all this
at compile-time, so things should be checked during runtime of a
program. My idea is to generate code that sets an internal flag
to FALSE at the start of the function. Each return(expression) should
set this flag to TRUE and then jump to the end of the function where
the return is handled. Here the flag should be checked and an error-
message be generated if it is still FALSE. This way it can be deteced
if the way through the function passed a return(expression).
I wonder if all this is really necessary, but I can't find anything
about this problem in K&R. Do other compilers check this? I think,
some strange errors can be detected by this method.
Maybe someone on the net can help me.
Ulf Gruene
I1090801@DBSTU1.BITNET
Technische Universitaet Braunschweig
West Germany
firth@sei.cmu.edu.UUCP (11/25/87)
In article <10530@brl-adm.ARPA> I1090801%DBSTU1.BITNET@CUNYVM.CUNY.EDU writes: I am a student of computer science and I have to write a C-compiler. The problem I came across is: does a C-compiler have to generate code to check if a function really delivers a result in all cases? Example: In the following (nonsense) function int f() { int a; a = 1; /* only to set a to a non-garbage value */ if (...) return a; else ... /* statements without any return */ } a value is delivered in the then part but in the else part nothing happens and the program just runs out of the end of the function. So, in this case, some garbage is delivered. In this example you can easily see this, but things get worse if the function is more complicated. I think it isn't easy for a compiler to see all this at compile-time, so things should be checked during runtime of a program. My idea is to generate code that sets an internal flag to FALSE at the start of the function. Each return(expression) should set this flag to TRUE and then jump to the end of the function where the return is handled. Here the flag should be checked and an error- message be generated if it is still FALSE. This way it can be deteced if the way through the function passed a return(expression). I wonder if all this is really necessary, but I can't find anything about this problem in K&R. Do other compilers check this? I think, some strange errors can be detected by this method. Well, a C compiler probably doesn't have to check ANYTHING! In addition, this check is not necessarily a good one to put in: it is legal to call a C function and throw away the result, so, who knows, maybe every call that bypasses a return statement is one that doesn't want the result. However, if you do put the check in, there is a much simpler mechanism: have the return statements all execute a proper return, and plug the end of the function body with your error code. That is essentially free: you execute no extra code to do the check. A typical implementation might look like this: f: ; procedure entry sequence ... ; return a move a into R0 jump to exitlabel ... ; end of function goto NO_RETURN_VALUE_ERROR exitlabel: ; normal return sequence goes here I assume you know enough to hoist that code at exitlabel if there is only one return statement in the function. (To do that is one pass: generate the exit code at the point of the first return statement, and if necessary jump back to it.)
gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/26/87)
In article <10530@brl-adm.ARPA> I1090801%DBSTU1.BITNET@CUNYVM.CUNY.EDU writes: >... I think it isn't easy for a compiler to see all this >at compile-time, ... No, whether or not a function execution ends with an explicit "return <expression>;" statement is not difficult to determine at compile time, and all such statically-determinable usage errors should be detected by the compiler/linker, not at run time. Producing a correct implementation of C from scratch is a difficult project; it is much better for most purposes to port some version of AT&T's Portable C Compiler than to have to rediscover all the details of how to compile the language. If the goal is an ANSI/ISO conformant implementation of C, I would say it's too big a project for one person.
dag@chinet.UUCP (Daniel A. Glasser) (11/26/87)
In article <10530@brl-adm.ARPA> I1090801%DBSTU1.BITNET@CUNYVM.CUNY.EDU writes: >I am a student of computer science and I have to write a C-compiler. >The problem I came across is: does a C-compiler have to generate code >to check if a function really delivers a result in all cases? [Lots of stuff deleted] >I wonder if all this is really necessary, but I can't find anything >about this problem in K&R. Do other compilers check this? I think, >some strange errors can be detected by this method. > >Maybe someone on the net can help me. > > Ulf Gruene Well, Ulf, maybe I can help you -- K&R explicitly covers this in chapter 4. In section 1 (Basics) (in my book, it's page 68) there is the following: (Reproduced without permission) "The return statement is the mechanism for returning a value from the called function to its caller. Any expression can follow return: return ( expression ) The calling function is free to ignore the returned value if it wishes. Furthermore, there need be no expression after return; in that case, no value is returned to the caller. Control also returns to the caller with no value when execution "falls off the end" of the function by reaching the closing right brace. It is not illegal, but probably a sign of trouble, if a function returns a value from one place and no value from another. In any case, the "value" of a function which does not return one is certain to be garbage. The C verifier lint checks for such errors. The scheme that you propose introduces a large amount of overhead. The compiler knows when it is transfering control to the function epilogue (return) code, and knows how it gets there. You could make the compiler generate a warning (if the function is not declared void) if you like. The ANSI draft standard covers the return statement in section 3.6.6.4. The text of that portion is (also quoted without permission): 3.6.6.4 The return statement Constraints A return statement with an expression shall not appear in a function whose return type is void. Semantics A return statement terminates execution of the current function and returns control to its caller. A function may have any number of return statements, with and without expressions. If a return statement with an expression is executed, the value of the expression is returned to the caller. If the expression has a type different from that of the function in which it appears, it is converted as if it were assigned to an object of that type. If a return statement without an expression is executed, and the value of the function call is used by the caller, the behavior is undefined. Reaching the } that terminates a function is equivalent to execution a return statement without an expression. I hope that this information helps. Remember structure passing, returns and assignment, enumerated types and pointers to void. Otherwise, only 90% of the C code in the world will work with your compiler. Daniel A. Glasser Disclaimer: The contents of this posting are subject to change without notice. void where prohibited by law. int everywhere else. The above is not the truth. I don't know the truth. -- Daniel A. Glasser ...!ihnp4!chinet!dag ...!ihnp4!mwc!dag ...!ihnp4!mwc!gorgon!dag One of those things that goes "BUMP!!! (ouch!)" in the night.
eao@anumb.UUCP (e.a.olson) (12/03/87)
In article <10530@brl-adm.ARPA> I1090801%DBSTU1.BITNET@CUNYVM.CUNY.EDU writes: >I am a student of computer science and I have to write a C-compiler. >The problem I came across is: does a C-compiler have to generate code >to check if a function really delivers a result in all cases? >Example: In the following (nonsense) function I seem to remember bing told in school, that in the absence of an explicit return, the return value would be the last expression evaluated in the function. But I've never heard anything otherwise on the subject and it seems awfully implementation-dependent.