warning: return makes integer from pointer without a cast

T

Ton 't Lam

Please, consider the following minimal example code:

# more f.l
%option noyywrap

%{
#include <string.h>
%}

%%

[0-9]+ return( strdup (yytext));

%%

# more main.c
#include <stdio.h>

main()
{
printf( "%s\n", yylex());
}

# flex f.l
# cc -o prog main.c lex.yy.c
f.l: In function ‘yylex’:
f.l:9: warning: return makes integer from pointer without a cast

The program 'main' works correctly.

gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)
flex 2.5.33

If I cast with (char *) on several places, I see no improvement.
Googling didn't lead me to a solution either.

How can I corect the code, so I don't have this warning?

Many thanks,
Ton
 
N

Nate Eldredge

Ton 't Lam said:
Please, consider the following minimal example code:

# more f.l
%option noyywrap

%{
#include <string.h>
%}

%%

[0-9]+ return( strdup (yytext));

%%

# more main.c
#include <stdio.h>

main()
{
printf( "%s\n", yylex());
}

# flex f.l
# cc -o prog main.c lex.yy.c
f.l: In function ‘yylex’:
f.l:9: warning: return makes integer from pointer without a cast

The program 'main' works correctly.

gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)
flex 2.5.33

If I cast with (char *) on several places, I see no improvement.
Googling didn't lead me to a solution either.

How can I corect the code, so I don't have this warning?

This is not a question about C, but about flex. The yylex function it
generates is declared by default as returning int, but your return
statement (which gets inserted into yylex) returns a char *. Read
Chaper 9 of the flex manual ("The Generated Scanner") which explains how
change the return type. Further questions should go to a forum that
deals with flex specifically.
 
T

Ton 't Lam

You're right. This is not a question about C, but about flex.

Anyway, the solution is to have:

%option noyywrap

%{
#include <string.h>
#define YY_PROTO(proto) proto
#define YY_DECL char *yylex YY_PROTO(( void ))
%}

%%

[0-9]+ return( (char *) strdup (yytext));

%%
 
K

Keith Thompson

Ton 't Lam said:
You're right. This is not a question about C, but about flex.

Anyway, the solution is to have:

%option noyywrap

%{
#include <string.h>
#define YY_PROTO(proto) proto
#define YY_DECL char *yylex YY_PROTO(( void ))
%}

%%

[0-9]+ return( (char *) strdup (yytext));

%%

Since you didn't post any context from previous articles, it's
difficult to tell what you changed. Lookup upthread, you originally had:
[0-9]+ return( strdup (yytext));
which you've now changed to
[0-9]+ return( (char *) strdup (yytext));

That silences the warning, but the warning wasn't the problem. Adding
a cast to silence a warning is almost never a good idea. Without
seeing the full C code that's generated from your flex input, it's
difficult to tell, but here's what I think is happening:

strdup returns a result of type char*. Your compiler isn't seeing a
declaration for strdup, so it assumes that it returns int. This alone
invokes undefined behavior. You were lucky enough to get a warning
because you tried to use the result in a context that requires a char*
value (the return statement).

After you added the cast, the compiler is *still* assuming,
incorrectly, that strdup returns a result of type int. When the call
is executed at run time, likely results are that the actual char*
value returned by the function is treated as an int, or an int value
is grabbed from some arbitrary location, giving you a garbage int
value. The cast does two things: it converts this garbage int value
to char*, and it silences the warning because you've told the compiler
that you know what you're doing (sorry, but you don't).

strdup is not a standard function. (It's very commonly provided, but
the ANSI committee chose not to standardize it back in 1989.) Even if
your implementation provides strdup, it probably doesn't provide a
declaration of it in <string.h> unless you do something special to
enable it.

The quick solution would be to find out how to enable the declaration
of strdup in your C implementation. A more portable solution would be
to write your own strdup implementation (it's not difficult) and give
it a different name, such as dupstr.

Either way, lose the cast.
 
K

Keith Thompson

Eric Sosman said:
Keith Thompson wrote: [...]
Since you didn't post any context from previous articles, it's
difficult to tell what you changed. Lookup upthread, you originally had:
[0-9]+ return( strdup (yytext));
which you've now changed to
[0-9]+ return( (char *) strdup (yytext));
That silences the warning, but the warning wasn't the problem.
Adding
a cast to silence a warning is almost never a good idea. Without
seeing the full C code that's generated from your flex input, it's
difficult to tell, but here's what I think is happening:
strdup returns a result of type char*. Your compiler isn't seeing a
declaration for strdup, so it assumes that it returns int. This alone
invokes undefined behavior. You were lucky enough to get a warning
because you tried to use the result in a context that requires a char*
value (the return statement).

If so, the diagnostic was extremely misleading. Note the sense
of the conversion it complained about: not integer to pointer, but
pointer to integer. If the diagnostic is to be believed, then the
compiler knew [1] that strdup() returns a pointer, and [2] that the
pointer was being converted to an integer in `return'.

D'oh! You're right.
As you say, adding a cast to silence a warning is seldom a good
idea, and in this case I suspect it had nothing to do with the cure.
The cure was probably the introduction of the YY_PROTO and YY_DECL
macros, which most likely changed the return type of the generated
C function from `int' to `char*'. If I'm right, then the cast in
the `return' statement is harmless, but useless.

Agreed.
 
T

Ton 't Lam

Keith said:
Eric Sosman said:
Keith Thompson wrote: [...]
Since you didn't post any context from previous articles, it's
difficult to tell what you changed. Lookup upthread, you originally had:
[0-9]+ return( strdup (yytext));
which you've now changed to
[0-9]+ return( (char *) strdup (yytext));
That silences the warning, but the warning wasn't the problem.
Adding
a cast to silence a warning is almost never a good idea. Without
seeing the full C code that's generated from your flex input, it's
difficult to tell, but here's what I think is happening:
strdup returns a result of type char*. Your compiler isn't seeing a
declaration for strdup, so it assumes that it returns int. This alone
invokes undefined behavior. You were lucky enough to get a warning
because you tried to use the result in a context that requires a char*
value (the return statement).
If so, the diagnostic was extremely misleading. Note the sense
of the conversion it complained about: not integer to pointer, but
pointer to integer. If the diagnostic is to be believed, then the
compiler knew [1] that strdup() returns a pointer, and [2] that the
pointer was being converted to an integer in `return'.

D'oh! You're right.
As you say, adding a cast to silence a warning is seldom a good
idea, and in this case I suspect it had nothing to do with the cure.
The cure was probably the introduction of the YY_PROTO and YY_DECL
macros, which most likely changed the return type of the generated
C function from `int' to `char*'. If I'm right, then the cast in
the `return' statement is harmless, but useless.

Agreed.


Yes, this seems to misleading indeed. It took me quite some re-reading
to comprehend this error, which is correct anyway.

It is the return() in flex that returns an integer by default, however
in this case it ought to be a pointer to character. So you have to declare

#define YY_PROTO(proto) proto
#define YY_DECL char *yylex YY_PROTO(( void ))

From here the return() in flex will return a pointer to a character.

At first I thought it was the strdup as well, but this is another story.
I've seen that if you don't strdup the yytext, then on a next invokation
of yylex() you may get weird results, because yytext (a pointer)
changes! You simply have to run of a copy, and always save.

The #include <string.h> contains the declaration of strdup().

My code now compiles warning free.

Many thanks for all replies.

Ton 't Lam
 

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

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top