Statement with no effect warning with GCC and Flex/Bison - c

When compiling my project with gcc and the -Wall option, I get a warning about a statement with no effect in the non-existant last line of my flex file:
Warning:
gcc -Wall -O0 -ggdb3 -DNOSUDO -DJOBC -DDEBUG -c lex.yy.c
tokenizer.l: In function ‘yylex’:
tokenizer.l:179: warning: statement with no effect
Shell Command:
$ wc -l tokenizer.l
178 tokenizer.l
Last part of lex file:
; {
return SEMI;
}
Anyone know why I might be getting this warning?
If I suppress all #line Directives, the error is:
lex.yy.c: In function ‘yylex’:
lex.yy.c:1021: warning: statement with no effect
Which refers to the ECHO line in:
case 30:
YY_RULE_SETUP
ECHO;
YY_BREAK
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(inQuote):
case YY_STATE_EOF(inWord):
yyterminate();

In general, you'll get that error from any lex rule that has an unconditional 'return' in it, because flex ends up generating code that looks like (after macro expansion):
case xxx:
return SEMI;
break;
The problem being that the 'break' is unreachable. It needs to be there in case your rule does not return (so the code won't fall through to the code for the next token, but will instead go on to recognize the next token.) Flex isn't smart enough to actually parse your rule code and do flow analysis to determine when the break is unneeded, so it just always puts it there. In general, using -Wall on the output of flex (or bison) will give you lots of warnings like this...

I guess it feels that ; is a statement with no effect. Try quoting it:
";" {
return SEMI;
}

I ran into the same problem and looked a bit into it. It turned out that one of my "#includes" in the flex source file (the .l file) somehow indirectly included the standard library termios.h file, which defines a macro named "ECHO" (as "0000010").
The source file generated by flex on the other hand also wants to create a macro named "ECHO", there is an "#ifndef ECHO" before that. But of course, with termios.h included, that "ifndef" evaluates to false and ECHO wasn't defined as intended. That led to the error.
Long explanation, short solution: I put
#ifdef ECHO
#undef ECHO
#endif
below all my includes in my .l file, and that did the trick.
I know this discussion thread is already a bit old, but it turned up first when I googled the warning, so my contribution might still be useful for folks.

As the other answers said, the trouble is that a 'break' after a 'return' can't be reached.
It used to be possible to satisfy a compiler that there was a way to get to the 'break' by faking a conditional return:
if (1) return SEMI;
I have a suspicion that some modern compilers are clever enough to see through this - which is actually counter-productive of them. "Yes, you're right, Mr Compiler, but I can't avoid it so STFU".

Related

Linker error while using lex to compile simple print file. have newest version of macOS 13.1 and xcode installed

I'm trying to run a simple progam in flex that reads the string "hello world" and prints "Goodbye"
here is the file:
%%
"hello world" printf("Goodbye\n");
. ;
%%
the commands are
% flex ex1.l
% gcc lex.yy.c -ll
Error message:
ld: warning: object file (/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/libl.a(libmain.o)) was built for newer macOS version (13.1) than being linked (13.0)
I have redownloaded the newest version of Xcode and have the updated macOS. I'm not sure what I can try to get this error code to go away.
I have also ran
% CMAKE_OSX_DEPLOYMENT_TARGET 13.0
to try and force the link to V13.0 without success.
The lex library, which the linker will use if given the -ll command-line flag, is supposed to be a convenience to make it easier to write quick and dirty (f)lex programs. If your compiler toolchain installation is OK, then it is a small convenience, but it seems like it's pretty easy to get the installation wrong, and since no-one seems to bother documenting the details of toolchain installation, it's hard to debug configuration issues unless you have lots of experience. That makes it a lot less convenient.
You could use this is as a learning experience in configuring your compilation environment, a skill which you will certainly find useful. But if you just want to get on with flex, it's really easy to avoid the need to use of the lex library.
The lex library consists of exactly two things, neither of which are necessary.
First, it contains a definition of yywrap(). The generated lexer calls yywrap() when it encounters the end of an input file. If yywrap returns 0, the lexer assumes that you have done something which will allow the lexer to continue reading input. That's actually not a very common use case, because most parsers just read one input file from beginning to end, and then finish. So a good default is to write a version of yywrap() which always returns 1, in which case the lexer will return an end-of-file token (0), and that should cause the lexer's caller to stop calling the lexer. The lex library includes the definition of precisely that simple default implementation:
int yywrap() { return 1; }
So you could include that code in your flex file, but a better solution is to tell flex to omit the yywrap() call and just assume that end-of-file means that there is no more input. Which you do by inserting the following declaration in your Flex prologue (not in the %{...%} code section):
%option noyywrap
I always recommend using a few more options:
%option noinput nounput noyywrap nodefault
The first two of those suppress the generation of the input() and unput() functions, so that you don't get "Unused function" warnings when you compile. Or better said, so that you wouldn't get warnings if you requested warnings when you compiled. But you should always request warnings. (And you should read them and act on them.) See the sample build instructions at the end of this answer.
The last option, nodefault, causes flex to produce a warning if there is any input which could trigger the automatic default action. The automatic default is to write the unmatched input to stdout and do nothing else, which is practically never what you want to do with unmatched input. Even if you wanted to ignore all unmatched input, which is a good way of ignoring programming errors, you'd very rarely want to print unmatched input to the output.
As it happens, your code will trigger this warning if you add the nodefault option, because you used . as your fallback pattern. . in (f)lex matches anything other than a newline character, and nothing in your program matches a newline, so the newline will go unmatched. Which means it will be echoed to standard output. Instead, you should use .|\n so that your default pattern also matches a newline. (Alternatively, with flex, you can use the s pattern flag, which causes . to really match anything: (?s:.).)
The other thing that the lex library contains is a default definition of main(). It's somewhat interesting that this is even possible. It works because the linker only includes functions from a library if the functions are not defined in the object files being linked. And, in C, main() really acts like an ordinary function. So if you link with a library which defines main(), that main program will be used whenever you don't define main() in your source code. That can be handy for debugging, but it's not really recommended in production code.
The particular main() function which is included in -ll just calls yylex() repeatedly until it returns an end-of-file token (0):
int main() {
while (yylex() != 0) { }
return 0;
}
So instead of relying on the lex library, just add those four lines at the end of your lexer definition, after the second %%.
If you apply both of these suggestions, you will end up with:
%option noinput nounput noyywrap nodefault
%{
/* So that `printf` is declared */
#include <stdio.h>
%}
%%
"hello world" printf("Goodbye\n");
.|\n ;
%%
int main() {
while (yylex() != 0) { }
return 0;
}
You can then build it without the -ll flag. But you should always build with compiler warnings enabled, and personally I think that using the default executable name a.out is bad style:
% flex ex1.l
% gcc -Wall -o ex1 lex.yy.c

Issue on adding werror flag

I am trying to add warning as error flag in my makefiles. But I am getting the following problem.
When I am compiling without adding the flag it is successful. But when I am adding Werror flag in some ".mk" files, compilation is failing with some error. But in the successful build log warning was not there for that source file(".c") which is throwing error now(Werror).
I am adding he following flags.
UN_CDEFS := -Wno-error=%
CDEFS := -Wall -Werror -Wextra
SUB_CDEFS := -Wall -Werror -Wextra
So please suggest what might be the problem.
Caveat: This isn't a complete answer because we need more information, but it would become [too] lengthy for more top comments like the ones I've already posted.
As you refine the problem and/or post more data, I can edit this answer accordingly. At a minimum, posting your actual makefiles might help, as well as, the actual final cc commands and the compiler warning/error output for the failing .c file [There may be multiple ones, but the single/first one should be sufficient].
Below are some detailed instructions on how to debug this, based on my own experience with such issues.
But, before I get to that, I'll hazard a guess. I notice that you're doing:
CDEFS := -Wall -Werror
[leaving off the -Wextra as you mentioned in a comment].
If this is done as [nearly] the first thing in the makefile, it's fine. However, if it occurs in the middle, you are replacing CDEFS with your own value. If a prior line in the makefile did (e.g.):
CDEFS = -Dwont_build_cleanly_without_this_option
then, when you add your line, that could be the issue, because this gets [effectively] removed. You might try this instead:
CDEFS += -Wall -Werror
This just appends to the existing symbol, so any prior value will be retained.
Also, the base makefile might have something like:
ifndef CDEFS
CDEFS := -Dwont_build_cleanly_without_this_option
endif
Normally, make will output the full text of commands it executes to create targets. For compilation, this is (e.g.) cc -c foo.c.
Some fancier builds wrap the command in (e.g.) #doit cc -c foo.c where doit prints a message like compiling foo.c ... and only outputs the full command if there is an error. (e.g. the linux kernel build does this, IIRC). I'm assuming you don't have this, but if you do, there is usually a command line override such as make VERBOSE=1
So, there is some .c file somewhere that builds cleanly with the normal options but generates an error when extra compile options are added. Let's call this file badnews.c
What we want to see is the compilation command that make printed for badnews.c and the warning/error output for two cases:
without the extra options
with the extra options in various combinations
In particular, examining the case (1) command against the case (2) commands might show that options other than the -W are different. This indicates a makefile issue, similar to my "guess" above. You've said that [your equivalent of] case (1) is clean with no warnings, but, given the trouble you're having, it wouldn't hurt to double check.
You can cut and paste the case (1) cc command into a shell script and manually add the -W options. Watch out for things with spaces, such as -DSTRING="foo bar" in the makefile that may need extra quotes in a shell script.
To alleviate conflicts similar to yours, in my own makefiles I separate the symbols.
DFLAGS for all -DFOO=1
COPTS for -g, -O2, -Wall, -fno-inline-functions, etc.
Then, I either do:
CFLAGS := $(COPTS) $(DFLAGS)
Or:
%.o: %.c:
cc -c $(COPTS) $(DFLAGS) $<
There are other ways to do this as well.
UPDATE:
I am using following command to build: emq PRODUCT=ASG >build_log_0508.log
I'm unfamiliar with emq. I can't find a reference to it, except as "enterprise mail queue for JIRA", which [AFAICT] may be part of cPanel?
Getting the following error on compilation: prod/libs/app/app.c:720:5: error: incompatible implicit declaration of built-in function 'free' [-Werror] free(tmp_dn);
This is the smoking gun ...
I don't know what compiler you're using, or what OS/environment, but it appears to not flag this as a warning/error by default.
However, it is a bug in the source app.c that needs to be fixed. It was correctly flagged as a warning/error by the addition of -Wall and -Werror
Note: As I mentioned in my original answer, it would be helpful to have the final cc command line that produced this error [as well as the cc command when this file is not flagged].
I created a simple test case:
void
myfree(void *ptr)
{
free(ptr);
}
Here, under gcc, I did gcc -c test.c and I get:
test.c: In function 'myfree':
test.c:5:2: warning: implicit declaration of function 'free' [-Wimplicit-function-declaration]
free(ptr);
^
test.c:5:2: warning: incompatible implicit declaration of built-in function 'free'
test.c:5:2: note: include '<stdlib.h>' or provide a declaration of 'free'
So, gcc flags this by default [even without -Wall or -Werror]. But, your compiler does not unless it is given -Wall. This could occur if your compiler were clang and you also specified -std=c89
As I implied earlier, if you just specify -Wall but not -Werror, you should get the same warnings but they just won't stop the build. In a large build, they can be easily overlooked in the log [by a human (e.g.) me :-)].
Referring to the suggestions in my original answer, assuming that the cc commands between case (1) ["good"] and case (2) ["bad"] only differed by the addition of -Wall, the correct way to fix this is to edit app.c and add #include <stdlib.h> as part of the includes.
Is there any problem with "SUB_CDEFS := -Wall -Werror"?
It will have similar problems/benefits as with CDEFS.
I am adding at the end of the makefiles
This is all the more reason to use += instead of :=. You might be "killing off" the -std=c89 if that were specified somewhere.
UPDATE #2:
It worked after doing += instead of :=.
As I mentioned, using := removed some critical compile options, that were specified elsewhere in the makefile(s).
But, once again, the source code has a bug and is broken. It was broken before you ever touched it. By adding -Wall -Werror using :=, you uncovered this bug, that previously was masked incorrectly. This is a good thing.
Using += just sweeps the bug under the rug [again], by restoring some build options that were lost with :=. But, these "lost" build options were wrong. They allowed a genuine flaw in the C code to escape detection.
This is not about getting the build to work [with a workaround], but to fix the root cause of the build problems, which is to modify the C source code. There are probably other such C source code bugs and some may be more severe.
With the workaround to "fix" the build, you've now got a piece of built software that can not be trusted to run correctly. It could fail in intermittent ways on your system(s). Or, produce incorrect results. Or, allow your system to be hacked [and potentially expose you to legal liability] if you're putting this on a publicly facing site.
If you're not comfortable doing the source modification yourself, file a bug report with the original author of the software. The source code should have a README file, or BUGS file, or whatever that should outline a procedure for doing so.
Just need one more clarification for what is the difference between SUB_CDEFS, UN_CDEFS, and CDEFS
It's completely arbitrary.
Software projects built with make, can often build multiple programs or libraries. These often are placed in subdirectories. Each such subdirectory often has its own Makefile.
To avoid needless duplication [and potential error], the parts that would be common to these makefiles are placed in a single makefile, often called a rules file [but it's just a makefile]. The individual makefiles then have a line like: include ../common/rules.mk
The rules file expects that certain symbols are defined that help guide it to build the targets for the given subdirectory.
CDEFS et. al. are an example of such symbols. Names that are descriptive of function are [should be] chosen. That is, CDEFS [probably] means "C definitions". The actual symbol names and their function depends upon the rules file. We could use the symbol SHRONK instead of CDEFS. That doesn't help much with understanding things, but if all makefiles were edited to change CDEFS to SHRONK, it would work.
For example, in other software, instead of CDEFS, a similar symbol might be named CFLAGS or COPTS. This is fairly common.
Side note: It's a bit moot at this point, but things would have gone much more smoothly and quickly if you had edited your question and posted the output cc commands and [some of] your makefiles as I had requested. You would have gotten specific answers in a matter of hours instead of general guidelines [that took several days].
So, without the rules file, it's not possible to tell. Only make a guess, based upon the names:
CDEFS -- global cc options for a subdirectories
SUB_CDEF -- cc options for this particular subdirectory
UN_CDEFS -- specify -Ufoo options
The particular software you are building may have documentation for this in a documentation file or in comments in one or more of the makefiles.
To understand this generally, there are many online guides to make. Under Linux, there are "info" files. So, try info make. Other systems have detailed manpages, so do man make

Scratchbox2 returns "Implicit declaration of function getline", among other weird behaviour

I'm trying to cross compile my application for the maemo environment (GNU).
When compiling the application normally, everything works fine, however when it's compiled through sb2 the following warning comes up:
$ sb2 gcc -D_GNU_SORCE -o app -Wall -g -I.......//don't think this is relevant
In file included from wifi_collector_menu.c:50:
wifi_collector_list.c: In function `show_net_apns':
wifi_collector_list.c:777: warning: implicit declaration of function `getline'
I am completely confused as to why this happens, there are other getlines that do work in the program, i have tried to define the variable _GNU_SOURCE both inside the code and in the compiler command (not at the same time)
This is the line of code which causes the warning apparently:
size_t bytesnum = MAX_ESSID;
size_t bytes_read;
char *netname = NULL;
printf("Enter name of selected network:");
bytes_read=getline(&netname,&bytesnum,stdin);//This line
Any help would be appreciated, thanks in advance.
Problem solved, all I had to do was add:
#define _GNU_SOURCE
In each header file, before stdio.h was included, very simple really.
I guess this info is assumed known between programmers as i was unable to find it anywhere online, and had to ask my C programming professor personally, and even then we had some trouble tracing the source.
Thanks anyway.
Change your compiler line to include the -E option and redirect the output. The compiler will only pre-proccess your file when this option is used. Do this for both versions, with and without sb2. getline() is normally found in stdio.h. By viewing the preprocessed output from both versions, you should be able to see where getline() is being included from.

problems with memset in Metal C

I’m trying to initialize the Metal C environment with the following code, but get the following errors on the memset line.
ERROR CCN3275 IMIJWS0.METAL.SAMPLIB(MEM):6 Unexpected text ')' encountered.
ERROR CCN3045 IMIJWS0.METAL.SAMPLIB(MEM):6 Undeclared identifier ___MEMSET.
ERROR CCN3277 IMIJWS0.METAL.SAMPLIB(MEM):6 Syntax error: possible missing ')' or ','?
CCN0793(I) Compilation failed for file //'IMIJWS0.METAL.SAMPLIB(MEM)'. Object file not created.
Below is my code
#include &lt string.h&gt
#include &lt stdlib.h&gt
#include &lt metal.h&gt
void mymtlfcn(void) {
struct __csysenv_s mysysenv;
memset ( &mysysenv, 0, sizeof ( mysysenv ) );
mysysenv.__cseversion = __CSE_VERSION_1;
mysysenv.__csesubpool = 129;
mysysenv.__cseheap31initsize = 131072;
mysysenv.__cseheap31incrsize = 8192;
mysysenv.__cseheap64initsize = 20;
mysysenv.__cseheap64incrsize = 1;
The issue was with the search order. Although I did search(/usr/metal/include) from with in my JCL I didn't proceed it with a nosearch option, so string.h was getting picked up from the standard system librarys instead of the version included with Metal C. I've pasted my optfile dataset I passed to the CPARM below for refference.
//OPTIONS DD *
SO
LIST
LONG
NOXREF
CSECT
METAL
LP64
NOSEARCH
search(/usr/include/metal/)
So, I have no idea. But some suggestions:
You might try copying/pasting this code here from this example just to make sure it works 'as expected'
Maybe try defining some of the macros here? (when I did C programming on zOS, I had to do include some weird macros in order to get stuff to work. I have no reasonable technical explanation for this.)
You could try searching for memset() using "=3.14" (from ispf.) See if any other modules use that function, and then check the headers that they include (or macros that they define - either in the C files or H files) to make it work.
Another thought: before the memset(), try doing putting a printf() in. If you get a syntax error on the same line (only for printf, rather than memset) then you can see if the problem is before line 6 - like a misplaced parenthesis.
Finally, if i recall correctly, I had to compile my individual modules, and then link them manually (unless I wrote a JCL to do this for me.) So you might have to link once to link with your other modules, and then link again against the C library. Not to be pedantic, but: you're fairly certain that you're doing all of the link passes?
I realize that's a lot of hoops to try and you've probably already read the manuals, but maybe there is something useful to try?
Also, and you probably already know this, but this site (for looking up error codes) is infinitely useful. (along with the above links for full-text-searching the manual)
Edit: this page also talks about "built-in functions" - you could try (as stated at the bottom of the page) "#undef memcpy" to use the non-built-in version?
Can you show us your compiler arguments? You need to make sure that you're not pulling in the standard C header files in addition to the metal C ones. Here's an example:
xlc -c -Wc,metal,longname,nosearch,'list(./)' -I. -I /usr/include/metal -I "//'SYS1.SIEAHDRV'" -S -qlanglvl=extended foo.c
as -mrent -mgoff -a=foo.list -o foo.o foo.s
ld -bac=1 -brent -S "//'SYS1.CSSLIB'" -o foo foo.o
Are you missing the closing brace '}' for the function? How about any missing semi-colon line terminators? When missing braces/semi-colons the z/OS C compiler throws some strange/misleading messages sometimes. I don't have it to try out, but I'm assuming Metal does as well.

Errors while compiling Neko VM OS X

I'm trying to compile the Neko VM on Mac OS X (10.5.7) using GCC 4.01 and I'm completely stuck, because it stops while compiling saying:
vm/threads.c:202: error: conflicting types for 'neko_thread_register'
vm/neko_vm.h:37: error: previous declaration of 'neko_thread_register' was here
I've tried googling this and some say it's because of lack of a "prototype" and some say it's because of a header include being done several times, and I can't really find any of those.
The affected line in threads.c:202 looks like this:
EXTERN bool neko_thread_register( bool t ) {
And the affected line in neko_vm.h:37 looks like this:
EXTERN bool neko_thread_register( bool t );
I can't see any difference in them, besides one of them being the implementation of the other.
The compiler command I'm using is:
cc -Wall -O3 -v -fPIC -fomit-frame-pointer -I vm -D_GNU_SOURCE -arch i386 -L/usr/local/lib -L/opt/local/lib -I/opt/local/include -o vm/threads.o -c vm/threads.c
I'd appreciate some ideas on what i might be able to do here, I don't really know where to go from here.
A mirror of the code for Neko which I'm trying to compile can be found here.
Thanks!
Have you tried compiling that file alone and outputting the preprocessed version? It could be that the scope or linkage macros are being modified somewhere in between the header file and the implementation file-- the same could be true of the 'bool' type, which is usually a macro defined by a system header.
According to the GCC 4.2 docs here, you should need to add the -E flag to the compilation line above, and you ought to change -o vm/threads.o to -o vm/threads.i so a file with the correct extension is created (.i means 'preprocessed file', essentially).
First, make sure you compile this as C, not C++.
Second, without seeing the code, it's pretty much impossible to say what the problem is.
But reading the error messages is often helpful (even before you google them):
Apparently neko_thread_register is declared twice, once in threads.c:202 and once in neko_vm.h:37, and the two declarations have different (conflicting) types. So look at the two declarations. If you can't see a problem with them, show us some code.
At the very least, seeing those two lines of code would be necessary. Most likely, the types are typedefs or macros or something similar, and then we'd need to see where they are defined as well.
Without seeing the code, all we can do is repeat the compiler error. "neko_thread_register has two conflicting definitions, at the lines specified."
Did you uncomment this line:
# For OSX
#
# MACOSX = 1 <-- this one
In the makefile?

Resources