Question about FunctionDecl::isVariadic()

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 2 14:32:20 PDT 2015


On Fri, Oct 2, 2015 at 5:22 PM, mats petersson <mats at planetcatfish.com> wrote:
>
>
> On 2 October 2015 at 22:07, Aaron Ballman <aaron at aaronballman.com> wrote:
>>
>> On Fri, Oct 2, 2015 at 4:01 PM, mats petersson <mats at planetcatfish.com>
>> wrote:
>> > Since "varargs" often involve some kind of special passing mechanisms
>> > [I've
>> > seen implementations that build data block and pass a pointer to that,
>> > rather than passing on the stack, for example], or additional code in
>> > the
>> > recipient function, I would say that `f2()` does not mean `f2(...)`.
>>
>> I kind of wondered if that was the case. If that's reality, perhaps we
>> may want to consider naming it FunctionDecl::hasVarArgs() or something
>> that specifies the difference is in whether we need to care about
>> packaging up the argument list so it can be used with va_start() and
>> friends?
>
>
> My understanding of the meaning of `isVariadic` is indeed "needs to use va_*
> to get arguments".
>
> I believe it's technically valid to do something like:
>
> void f2();
>
> ....
>     f2(42);
> ....
>
> voif f2(int x)
> {
>     ... use x ...
> }
>
> and no special code should be required. Of course, the results of changing
> `f2(42);` int `f2(4.2);` or `f2("foo");` and retaining the `int x` parameter
> will lead to undefined behaviour, and compiler can do anything it likes with
> that... :)

That is correct, and why I was originally surprised that isVaridic()
was returning false for such a declaration. However, what you can't do
with an empty parameter declaration list, but can do with a trailing
varargs, is get a va_list out of the final parameter. AFAIK, you
cannot do this:

void f2();

void f2(int x, ...) {
  va_list va;
  va_start(va, x);
  va_end(va);
}

int main(void) {
  f2(12, 1.2, "this is one reason why I hate C");
}

~Aaron

>
> --
> Mats
>>
>>
>> ~Aaron
>>
>> >
>> > --
>> > Mats
>> >
>> > On 2 October 2015 at 20:16, Aaron Ballman via cfe-commits
>> > <cfe-commits at lists.llvm.org> wrote:
>> >>
>> >> Given the following two function declarations:
>> >>
>> >> void f1(...);
>> >> void f2();
>> >>
>> >> It makes sense to me that isVariadic() returns true for f1 in both C
>> >> and C++. It makes sense to me that isVariadic() returns false for f2
>> >> in C++. I am confused as to why it returns false instead of true for
>> >> C, however.
>> >>
>> >> In C11, 6.7.6.3p9 states: If the list terminates with an ellipsis (,
>> >> ...), no information about the number or types of the parameters after
>> >> the comma is supplied.
>> >>
>> >> p14 states, in part: "The empty list in a function declarator that is
>> >> not part of a definition of that function specifies that no
>> >> information about the number or types of the parameters is supplied."
>> >>
>> >> It seems to me that for function *declarations* (not definitions),
>> >> isVariadic() should return true for f2 in C. Is there a reason it
>> >> doesn't currently behave that way, or is this a bug?
>> >>
>> >> I ask because I was writing an AST matcher for isVariadic() for an
>> >> in-progress checker, but the checker was failing to catch that f2 was
>> >> a variadic function. I am not certain whether
>> >> FunctionDecl::isVariadic() should be changed, whether the AST matcher
>> >> isVariadic() should be smarter about C code, or whether the checker
>> >> itself needs to be smarter about this particular behavior in C code.
>> >> My gut reaction is that FunctionDecl::isVariadic() has a bug, but from
>> >> looking at code elsewhere, everything seems to assume isVariadic()
>> >> implies the ellipsis, which makes me think I just need to make my
>> >> checker smarter.
>> >>
>> >> Thanks!
>> >>
>> >> ~Aaron
>> >> _______________________________________________
>> >> cfe-commits mailing list
>> >> cfe-commits at lists.llvm.org
>> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>> >
>> >
>
>


More information about the cfe-commits mailing list