inline + va_list

L

Laurent Deniau

When I compile the code below with gcc -std=c99 -W -Wall -pedantic -O3
-Winline, it reports the following:

variadic.c: In function ‘fv’:
variadic.c:12: warning: function ‘fv’ can never be inlined because it
uses variable argument lists
variadic.c: In function ‘vf’:
variadic.c:12: warning: inlining failed in call to ‘fv’: function not
inlinable
variadic.c:27: warning: called from here

but the function does not use a variable argument lists, it uses a
variable of type va_list. Did I miss something or gcc emits an invalid
warning?

ld.

#include <stdarg.h>
#include <stdio.h>

static inline int f(int a, va_list va) {
return a + va_arg(va,int);
}

static inline int fv(int a, va_list va) {
int res;
va_list vac;
va_copy(vac, va);
res = f(a, vac);
va_end(vac);
return res;
}

static int vf(int a, ...) {
int ret;
va_list va;
va_start(va, a);
ret = fv(a, va);
va_end(va);
return ret;
}

int main(void) {
printf("%d\n", vf(1,2));
}
 
L

Laurent Deniau

There is no such thing as an invalid warning, a compiler is allowed to
emit any diagnostics it wants so long as it compiles a correct
program.

What are the criteria to affirm that a program is correct?
Also, the C99 inline keyword is merely a hint to the compiler that you
would like it to expand a function inline rather than call a
separately located instance.  The compiler is under no obligation to
comply with your request.  In fact, a compiler that never generates in
line code for a function regardless of whether you use the inline
keyword or not can be perfectly conforming to C99.  When and whether
it actually generates function code in line is a QOI issue.

I known this point and it is not my question
Nor is a compiler required to tell you whether or not it generates
functions in line, whether you used the keyword or not.

I known this point and it is not my question
It appears that the maintainers of this particular version of your
compiler have decided two things:

1.  Not to inline functions whose parameters include a va_list,
regardless of whether or not the function actually uses any of the
variadic macros/functions on the va_list, although both of your
functions do.

2.  To issue a diagnostic when it decides to ignore the inline
keyword, at least for this particular reason.

Both of these decisions are perfectly valid in a conforming C99
compiler.  Nor is it unreasonable to term any function accepting a
va_list parameter a "variadic" function.

That's the point. The norm says that a variadic functions is a
function waiting for a variable arguments list, namely ..., and this
is not the case of the function fv. So what I am querying about is if
the wording of the warning is correct. If it's not, I could report
something positive to the compiler developers and maintainers.
If you disagree with the compiler maintainers' decisions, or do not
like the wording of the diagnostic they decided to issue, take it up
with them.

This is the goal after checking here that a function accepting a
va_list is not qualified as accepting a variable arguments list, which
has a very different meaning in the norm.
 There is nothing "invalid" about it, according to the C
standard.

So you claim that a function accepting an argument of type va_list is
defined in the norm as being a function accepting a variable arguments
list?

Sure a warning cannot be invalid and could say that the compiler
authors love ice cream during each compilation, but it's not very
constructive.

The issue behind this question is about portability. The same compiler
with the same compilation options on the same machine and operating
system emit the warning with target arch x86_64 and not with target
arch x86_32, probably because the type of va_list changed. Since all
my programs compile with all warning enabled and -Werror, my program
stops to compile in this special case. Sure, I could remove the inline
keyword or the -Winline warning or the -Werror warnings as errors or
write pure C89 code, but this is not the question.

Thanks for your help.

a+, ld.
 
S

Stephen Sprunk

Laurent said:
That's the point. The norm says that a variadic functions is a
function waiting for a variable arguments list, namely ..., and this
is not the case of the function fv. So what I am querying about is if
the wording of the warning is correct. If it's not, I could report
something positive to the compiler developers and maintainers. ....
The issue behind this question is about portability. The same compiler
with the same compilation options on the same machine and operating
system emit the warning with target arch x86_64 and not with target
arch x86_32, probably because the type of va_list changed. Since all
my programs compile with all warning enabled and -Werror, my program
stops to compile in this special case. Sure, I could remove the inline
keyword or the -Winline warning or the -Werror warnings as errors or
write pure C89 code, but this is not the question.

It appears the authors of your compiler have decided to call any
function that has a va_list a "variadic" function. This seems strictly
incorrect use of the term, but it's understandable.

Your comment that this happens on x86_64 targets but not i386 targets
leads me to believe that the reason is that their va_list code is tied
into the calling convention used. i386 passes all function arguments on
the stack, so any function called by a variadic function can retrieve
the original variable arguments with just a pointer to the fixed
argument. However, x86_64 passes the first few arguments in registers,
which means the compiler would have to do a lot of additional magic to
make them available in called functions. They apparently haven't gotten
around to doing that, or they forgot to mark that magic compatible with
inline functions.

I'd submit a bug report for each of the above problems and quit using
-Werror until it was fixed. You may also want to check first to make
sure you're using the latest version; every time I've found a bug in
GCC, it turns out someone had already fixed it in a later version.

S
 
L

Laurent Deniau

It appears the authors of your compiler have decided to call any
function that has a va_list a "variadic" function. This seems strictly
incorrect use of the term, but it's understandable.
yes.

Your comment that this happens on x86_64 targets but not i386 targets
leads me to believe that the reason is that their va_list code is tied
into the calling convention used. i386 passes all function arguments on
the stack, so any function called by a variadic function can retrieve
the original variable arguments with just a pointer to the fixed
argument. However, x86_64 passes the first few arguments in registers,
which means the compiler would have to do a lot of additional magic to
make them available in called functions.

that was my guess.
They apparently haven't gotten
around to doing that, or they forgot to mark that magic compatible with
inline functions.

this is exaltly the object of my question.
I'd submit a bug report for each of the above problems and quit using
-Werror until it was fixed. You may also want to check first to make
sure you're using the latest version; every time I've found a bug in
GCC, it turns out someone had already fixed it in a later version.

right. Thanks for the advices.

a+, ld.
 
L

Laurent Deniau

I didn't know that you knew this, and I suppose I assumed that perhaps
you did not. We get a lot of posts here from relatively inexperienced
newbies, with questions about particular diagnostic messages, such as
what they mean or are the messages correct.

So if I assumed you had less knowledge and experience than you
actually possess, I assure you that it was not intentional and no
slight was intended.

Don't worry, I am posting here around for 10+ years, but not very
often these past years (missing time). So I often see this kind of
assumption ;-)
What do you mean by "the norm"?

ISO/IEC 9899:1999(E)
The term "variadic" is not defined by, or mentioned in, the C language
standard.

Right the term is borrowed from the Harbison (shorter and widely
used).
The va_list type and the corresponding va_* macros and/or
functions are all defined by the C99 standard in the section named
"7.15 Variable arguments <stdarg.h>".

I think the point here is that the compiler might go through some
extra parameter passing gymnastics when passing a va_list, regardless
of whether it is followed by an ellipsis.

This is my guess.
One point to ponder, and perhaps take up with the developers, is how
difficult it might be to treat a function with a va_list as its final
argument, without the following ellipsis, differently so as to allow
it to be inlined. And whether the utility would justify the effort.

I do not ask for inlining, I ask for deterministic diagnostic (even
for warning) for better portability. It's not a major concern, but I
like to see "no warning" when I compile my code. The -Werror, which I
finally removed for this particular case, was there to ensure that I
do not miss a warning during long compilation.
As to the wording of the diagnostic, I suppose you could suggest that
they change the phrase "because it uses variable argument lists" to
something like "because it uses a va_list", but I really think it
unlikely that the current wording would confuse anyone.

It did confuse me and I still do not see motivation for this warning.
I understand that va_list could be a pointer, a structure or a builtin
object depending on the arch. I think I will check for bug reports and
emit one if it doesn't exists yet.

Thanks for your time.

a+, ld.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top