Empty arguments/empty argument lists [Was: Re: [splint-discuss] Parse Error on Macro, help]

James Dennett jdennett at acm.org
Thu Sep 7 10:15:47 EDT 2006


Richard A. O'Keefe wrote:
> James Dennett <jdennett at acm.org> wrote:
> 	This is the question at hand: was it a change, or was it not?
>
> The WG154 archive definitely SAYS it was.
> Terry Colligan <terry-splint at tenberry.com>
> also says it was.
>
> 	>     #define foobar(dummy) (1+1)
> 	>     ...
> 	> 	dummy()
> 	>
> 	> would have been legal.
> 	>   
> 	Was that the example you meant to use?
>
> OK so there is a silly thinko:  dummy() should have been foobar().
>   
Fair enough. As I said, that would fall foul of a different rule, the rule
that the number of macro arguments must match the number of macro
parameters.  So I don't think it illustrates your point -- except that you
appear to claim that this use of the macro foobar has a single (empty)
argument.

That seems to be the key of this issue.

Those who believe (based on a reading and understanding of the
standard(s)) that there are no arguments, and those who believe
(based on their reading and understanding of the standard(s)) that
there is a single, empty argument.
> 	Did you mean to attempt to use the macro foobar with no
> 	arguments (which is illegal, as the number of arguments is
> 	required to match the number of parameters)?
>
> With the correct call, foobar(), you are mistaken.
> The number of actual parameters is *ONE*; that parameter happens
> to be empty. 
As I say -- that is key to this. 

I can't find text in C++98 that says this, but some compilers I have here
appear to agree with you.  (I have one C++ compiler here from Sun
that considers this an issue "Warning: Too few arguments in macro
foo".)

To be clear: I'm testing the compilers/preprocessors with
#define foobar(a)
int main() { foobar(); return 0; }
>  This is in no way different from
>
>     #define foo(bar, ugh) bar ugh
>
>     foo(,);		/* two empty arguments */
>     foo(,zip());	/* one empty argument */
>     foo(zap(),);	/* one empty argument */
>
>   
It is different in one crucial way: the complete absence of an argument 
list.
Unfortunately I do not find in any of the documents I have here a formal
specification for handling of this case.

In the analagous case of a function call, fn() has no arguments.
Of course it's true that argument by analogy is weak.
> 	No.  In C90, it was legal to have an empty list of arguments,
> 	but in C99 it is also legal to have a non-empty list of
> 	arguments, one or more of which is itself empty.  (C90 does not
> 	permit an argument to be empty.)
>
> Yes, that's what *I* said.
> It's PRECISELY what I said.
>   
Except for one crucial point, which is that you were not clear that
you considered that foobar() does not have an empty list of arguments,
but rather a list of one argument which is itself empty.
> 	> (A) is a statement that "the latter" (that is, an INVOCATION of a macro
> 	> with an empty argument) conformed.
> 	> (B) is a statement that it didn't (it used to be a "common extension",
> 	> like three-argument main(), not "part of the standard").
> 	>   
> 	No; B refers to something else, which is the new feature in C99 of allowing
> 	#define binary(a,b)
> 	binary(2,)
> 	i.e., where there are two arguments but the second argument is empty.
>
> Yes, that's what I *SAID* it was.
> Please read more carefully.
>   
I can't find that in your previous words; your new wording is clearer,
thank you.
> 	There are probably other lists for language wars.  I use both C
> 	and C++ as appropriate, and don't find either standard
> 	particularly more or less readable than the other.
>
> That wasn't a "language war" remark.  It was a remark about the
> readability of the *standard*.  Some parts of the C++ standard are good.
> But having sweated over the scope rules section for hour after hour,
> there is no way that you can persuade me that it is readable.
>   
The name lookup rules themselves are amazingly complicated, sad to say.
> 	Possibly you have misread B to be a contradiction to A, instead of 
> 	realizing that it must have been referring to empty arguments and not to 
> 	an empty argument _list_.
>
> You are making me very cross indeed.
>   
Unfortunate; I'm attempting to engage in a civil discussion.  Please note
that I only said that it was _possible_. 

(Also note the point I've made -- probably too often -- elsewhere in this
post, that distinguishing the two cases #args=0 and arg[n]="" is vital.)
> I understood PERFECTLY WELL what (B) was referring to.
>   
I hope that with my clarifications you will feel that "shouting" is
no longer required.
> Please do not assume that someone who disagrees with you is an idiot.
>
>   
Trust me, I don't.  In turn, please don't assume ill will where
none is meant; discussions will go better that way.
> One more time:
> 	> 	> unless you mean to invoke it as
> 	> 	>     ... FOO() ...
> 	> 	
> 	> 	  Yes! Exactly.
> 	> 	
> 	> 	> and the latter really was undefined behaviour caught by at least one
> 	> 	> compiler.
> 	> 	
> 	> (A)	  Then that compiler was not conforming to the 1989 standard.
>
> Got that?
>   
If I re-add the context, he was saying that a compiler that refused to
translate a use FOO() of a function-like macro with no parameters was
non-conforming with the C89 standard.

Do you agree with this description?
> At that point in the mesage, I was talking about *EMPTY ACTUAL ARGUMENTS*
> for macros.  Look again and you will see that FOO() is not a macro definition!
>   
I did read it that way all along, and was also discussing that case.
> I said that passing empty actual arguments ("the latter") was undefined
> behaviour caught by a compiler, and (A) is a claim that a compiler that
> rejected *EMPTY ACTUAL ARGUMENTS* did not conform to the 1989 standard.
>
>   
A is a claim that a compiler that rejected a use (with no arguments)
of a function-like macro (with no parameters) did not conform.
> 	> (B)	  What C99 upgraded from a common extension to part of the standard was
> 	> 	  the possiblility of empty actual arguments.
>
> (B) is an explicit statement that EMPTY ACTUAL ARGUMENTS were something
> "upgraded" in C99, that they previously were only a "common extension",
> not "part of the standard".
>
> That is, (A) and (B) *are* contradictory because they are *BOTH*
> about EMPTY ACTUAL ARGUMENTS; *neither* of them is about macro definitions.
>
>   
I believe (A) was intended to be about an empty argument list,
while (B) is about a non-empty argument list including one or
more empty arguments.  Maybe the OP would like to step in,
as his interpretation of the statement must surely have some
authority.
> 	No.  In C90, it was legal to have an empty list of arguments,
>
> which is completely irrelevant to (A) and (B), neither of which is
> concerned with macro definitions or their formal parameters.
>   
It's entirely relevant: "arguments" applies in the context of a use of
a macro, and it is in this context I was using it.  To expand: it was a
claim that, in C90, it was legal to invoke a function-like macro (that
has been defined with no parameters) with no (actual) arguments.

(An unqualified use of the term "arguments" is most commonly --
in my experience -- taken to mean "actual arguments", whereas the
terse way to say "formal arguments" is "parameters".)
> 	I'm very confident that it was not confirmed, and reasonably confident 
> 	that it is not true.
> 	
> "It" here was "C99 allows EMPTY ACTUAL ARGUMENTS in a macro call and C89
> did not".  That _is_ true, and Terry Colligan did confirm it.
>   
Your use of the term "empty actual arguments" is unfortunate
in failing to distinguish between the two key cases here.

However: I'm leaning towards thinking that your interpretation is
more probably correct than not for C99 and C++0x.  (That said,
I've not yet found wording there which makes it clear that foo()
has one (actual) argument.  If C90 doesn't specify, then the use
foo() would still be undefined simply because of the lack of such
a definition.)

Given that we both assume someone disagreeing with us can still
be intelligent, it's fair to assume that Terry probably did *not* intend
to say anything self-contradictory, so it would be great if he would
step in and clarify his meaning.  This subject matter is non-trivial,
and the terminology less than optimal; there's room for intelligent
people to disagree, and even to make mistakes.

Given that this discussion is interesting (in particular: I've seen
behaviour from compilers that doesn't match my expectations,
which is none too common), I hope we can iron out the remaining
details (though at this point I might take it to comp.std.c and/or
comp.std.c++ in any case).

-- James



More information about the splint-discuss mailing list