[cfe-dev] K&R style argument lists and the type system

Chris Lattner clattner at apple.com
Mon Aug 25 22:43:07 PDT 2008


On Aug 25, 2008, at 4:08 PM, Eli Friedman wrote:

> Consider the following testcase:
> int a() {return 0;}
> int b() {return a(1);}
>
> Calling b has undefined behavior per C99, but no diagnostics are  
> required.

Right.  I think that we should type functions with no arguments or  
with an identifier list as FunctionTypeNoProto *always*.  To issue the  
(not required but prefered) diagnostic in this case, we should do two  
checks:

1) is the callee compatible with the argument list (yes)
2) if the callee has a FunctionTypeNoProto type, and if it's body is  
available, look at the body to see how many arguments it really had,  
does it match up with the call site (no)

> Consider the following testcase:
> int a(int);
> int a() {return 0;}
> This is a constraint violation per C99.

Right, the sequence of events should be:
1) parse the declaration, "a" gets type "int(int)"
2) parse the definition which has type "int()"
3) merge the two types, giving "int(int)"
4) since it is a definition, verify that the actual argument list  
matches the merged type.

> We currently map a() to FunctionTypeNoProto, and this has roughly the
> right behavior when we don't merge types.  However, by adding merge
> types, we conclude that a() has type a(int), which is clearly wrong,
> and leads to crashes trying to access non-existent parameter
> declarations.  But if we instead map a() to a FunctionTypeProto with
> no parameters, we incorrectly error out on the first example.

I think that the problem basically boils down to the fact that we  
handle these:

int a() {}
int b(x) int x; {}

as FunctionTypeProto instead of FunctionTypeNoProto.  Even though we  
can "see" that 'a' takes no arguments, C doesn't let us take this into  
consideration for its type.  These should both really be  
FunctionTypeNoProto.

>
> And actually, we already have this problem for cases like the
> following, which are less common:
> int a(x,y) int x,y; {return x+y;}
> int b() {return a(1,2,3);}
>
> Any ideas for how to solve this?  We could always map definitions
> identifier-lists to FunctionTypeNoProto,

Yep, I agree with Steve that this is the best approach.

> but that means a good chunk
> of additional code to check type-merging doesn't do bad stuff to a
> definition and allow CodeGen to synthesize the type of such a function
> definition properly.

I'm not sure what you mean by this?

>  Another possibility would be to  add a flag to
> FunctionTypeProto which signifies whether the type comes from an
> identifier list; however, I have no idea where to add such a flag.

I think it would be better to make the compatibility check handle  
FunctionTypeNoProto to see if it has a definition.  As "value add", it  
could look at the body to see if the body has arguments that are  
incompatible with a call.

-Chris



More information about the cfe-dev mailing list