CW71, ColdFire: Missing prototype results in wrong code?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

CW71, ColdFire: Missing prototype results in wrong code?

2,958 Views
jbezem
Contributor III

In my project, moving from CW6.3 to 7.1 (Target CodFire), an error occurred. It appears that 7.1 uses different registers for returning values like 'int' (in D0) and pointers (in A0).

Now, if a call to 'malloc' is used without a prototype in view, the compiler assumes a return value typed 'int', and looks for the return value in D0.

However, 'malloc' really returns a pointer, so the return value is passed in A0.

 

According to my understanding of C, this is a real error, not reconcileable with the Standard: Implicit conversions will be applicable in such a case, converting an int to a pointer, however, it seems not permissible to lose the return value altogether, even when no prototype is used.

 

Can anyone confirm my observation? Is this a known error for Freescale already, and if not, where do I report this as an error? Is there a fix available?

 

Thanks,

 

Johan

Labels (1)
0 Kudos
8 Replies

711 Views
bkatt
Contributor IV

jbezem wrote:

In my project, moving from CW6.3 to 7.1 (Target CodFire), an error occurred. It appears that 7.1 uses different registers for returning values like 'int' (in D0) and pointers (in A0).



I'm not using 7.1, but my prefix file says #pragma pointers_in_D0
and there is a matching setting in one of the project preference panels. If this is still available it would solve your immediate problem.

 

However coding without function prototypes is a bad thing...

Message Edited by bkatt on 2009-02-23 05:01 PM
0 Kudos

711 Views
jbezem
Contributor III

This is most helpful. I would have hoped this to be the default setting, but other than that this may invalidate my remark about a non-compliant compiler. I will look into this pragma.

And yes, you're right, prototypes are to be mandatory, but if you newly inherit a project, you cannot always oversee the full scope and change everything immediately and at once.

 

Thanks!

 

Johan

0 Kudos

711 Views
CrasyCat
Specialist III

Hello

 

The compiler is fully compliant with ANSI C standard.

 

If there is no prototype available for a function, a compliant ANSI C compiler will assume all parameters and return value are from type int.

 

This is not a bug in the compiler but a definition of the ANSI C language.

 

So here the solution is pretty simple.

Just include the appropriate .h file to have a prototype for the function before you attempt to call it.

 

CrasyCat

0 Kudos

711 Views
jbezem
Contributor III
CrasyCat wrote:

If there is no prototype available for a function, a compliant ANSI C compiler will assume all parameters and return value are from type int.

 

Sure, but this is too easy. If I have legacy code without prototypes, even ANSI-C will allow this. AFAIK there is neither an absolute requirement for prototypes to be used, nor a remark that the compiler is free to do anything its wants (including producing invalid code) in such cases (a.k.a. implementation dependent).

 

This is not a bug in the compiler but a definition of the ANSI C language.

As I said, prototypes are not required, as in C++. Otherwise, the compiler shall report an error, not a suppressible warning.

 

So here the solution is pretty simple.

Just include the appropriate .h file to have a prototype for the function before you attempt to call it.

Again: Granted, but it's too simple.

[And of course, some team member stumbled upon such an error, because warnings were suppressed...]

 

IMHO CW71 in this respect is not ANSI-compliant...

 

CrasyCat

 

BR,

 

Johan

0 Kudos

711 Views
CompilerGuru
NXP Employee
NXP Employee

Sure, but this is too easy. If I have legacy code without prototypes, even ANSI-C will allow this. AFAIK there is neither an absolute requirement for prototypes to be used, nor a remark that the compiler is free to do anything its wants (including producing invalid code) in such cases (a.k.a. Implementation dependent).

Function prototypes in ANSI C are not a requirement, if a function is not declared there is an implicit "int function()" declaration. However if this implicit declaration does not match the function called, then it is "undefined behavior" which means "the compiler is free to do anything its wants (including producing invalid code)" (this is not the same as implementation dependent though). I did not see any maintained C code in the last 10 years which was using implicitly parameter declarations intentionally (and not just because of an unintentionally not included header).

If you have legacy code using malloc implicitly I would suggest to adapt that code. If not possible, you can include the required header in a prefix file without "changing" the original code.

This is not a bug in the compiler but a definition of the ANSI C language.

As I said, prototypes are not required, as in C++. Otherwise, the compiler shall report an error, not a suppressible warning.

 

:smileyhappy:

 

C is not a safe language. It's very easy to generate undefined behavior. In C (and to a lesser extend in C++) correct coding is difficult and there are many little traps waiting. In many cases, compilers will just compile incorrect code and not even issue a warning as in this case. If you want to get an error for dangerous things, I'm tempted to say use java :smileyhappy:.

 

If you really think that it is a compiler bug, I would suggest to lookup the ANSI C standard (or at least the openly available draft for C89) and refer to the paragraph which the compiler does not implement properly. The feeling how the standard should be can be easily misleading.

 

So here the solution is pretty simple.

Just include the appropriate .h file to have a prototype for the function before you attempt to call it.

Again: Granted, but it's too simple.

[And of course, some team member stumbled upon such an error, because warnings were suppressed...]

 

Suppressing the implicit parameter declaration warning is a dangerous idea. I would recommend to go in the other direction and make implicit parameter declaration an error instead.

 

 

Daniel

0 Kudos

711 Views
jbezem
Contributor III

OK, I looked in the C99 spec (I don't have the C90 spec available), but that should be comparable, except for the reference itself.

Look at section 6.8.6.4 "The return statement" paragraph 3 (given that an implicit prototype "int malloc()" is assumed, the return statement tries to return a value of a type dfifferent than specified):

<quote>

If a return statement with an expression is executed, the value of the expression is returned to the caller as the value of the function call expression. If the expression has a type different from the return type of the function in which it appears, the value is converted as if by assignment to an object having the return type of the function.

</quote>

This is valid independent of the way the physical decomposition is done (i.e. precompiled libraries), so in my understanding this means the malloc-pointer is to be converted to 'int', in which case it would again be converted to a pointer when the return value of the malloc call is assigned to the variable.

If an 'int' cannot contain the full range of a pointer (say, 16-bit 'int's with 4 byte pointers), the value may be different than intended, but for a ColdFire both 'int's and pointers are 4 bytes, so by the best-effort conversion required, the double conversion should still work properly, as it did in CW6.3.

 

I agree (and we now have implemented) that such warnings need to be active in any project, at best converted to errors, but this doesn't mean that the compiler's action to return an arbitrary value is acceptable IMHO.

 

Comments welcome.

 

BR,

 

Johan

0 Kudos

711 Views
CompilerGuru
NXP Employee
NXP Employee

C99 does no longer implicitely declare functions, so you wont find there the relevant parts.

The issue is that the implicitely declared prototype does not match the actual type used to define the function.

The reference to the return statement is a bit misleading, it talks about the semantics of a return statement, but the issue here is the samenatics of a malloc call expression. In which context the malloc call expression is used is pointless if the malloc call expression on its own is undefined.

 

Out of the C90 draft (http://flash-gordon.me.uk/ansi.c.txt),

chapter "3.5.4.3 Function declarators (including prototypes)"

 

>For two function types to be compatible, both shall specify

>compatible return types.

 

Therefore the "void*malloc(size_t)" malloc definition and the "int malloc()" implicitely defined declaration are not compatible.

 

And according to 3.1.2.6 Compatible type and composite type:

 
>All declarations that refer to the same object or function shall

> have compatible type; otherwise the behavior is undefined.

 

Obviously the implcit declaration of malloc and the function definition (which is a declaration too) violate this, hence the behavior is undefined.

 

Daniel

 

 

Message Edited by CompilerGuru on 2009-02-24 11:28 AM
0 Kudos

711 Views
jbezem
Contributor III

OK, you convinced me. And the pragma reference pointed me in the right direction.

Above all that, the warnings have been reviewed and switched-on for most cases in my project, so we shouldn't have any problems here anymore. I had no idea how many warnings were switched-off in the first place... :smileysad:

 

Thanks,

 

Johan

0 Kudos