There was a recent post on Ask Ubuntu, where OP was trying to compile a program which included term.h
. When the code had #include <term.h>
, the errors were:
In file included from clear_screen_UNIX.c:5:0:
clear_screen_UNIX.c:9:6: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘->’ token
void clear_screen(void) {
^
clear_screen_UNIX.c: In function ‘main’:
clear_screen_UNIX.c:23:14: error: called object is not a function or function pointer
clear_screen();
^
clear_screen_UNIX.c:26:14: error: called object is not a function or function pointer
clear_screen();
The OP then included the full path to term.h
(#include "/usr/include/term.h"
), which led to the much more useful message:
In file included from clear_screen_UNIX.c:7:0:
/usr/include/term.h:125:21: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘->’ token
#define CUR cur_term->type.
^
/usr/include/term.h:202:40: note: in expansion of macro ‘CUR’
#define clear_screen CUR Strings[5]
^
clear_screen_UNIX.c:9:6: note: in expansion of macro ‘clear_screen’
void clear_screen(void) {
^
clear_screen_UNIX.c: In function ‘main’:
clear_screen_UNIX.c:23:14: error: called object is not a function or function pointer
clear_screen();
^
clear_screen_UNIX.c:26:14: error: called object is not a function or function pointer
clear_screen();
These messages clearly indicate the problem is due to a macro expansion.
I verified the results myself, too. I wonder why GCC produced much better errors when the full path was given. Can I make it produce similar messages with the system include syntax as well?
I am using GCC 4.9.2, and I suspect OP was using GCC 4.8.2 (given the version of Ubuntu).
The reason GCC gives different/better messages if the full path of the header is given is that the GCC preprocessor gives information to GCC's cc1
compiler that the included header is a system header file or local header file by some digits at the end of the comment line of the preprocessor-generated .i
file.
Then the cc1
compiler will generate more helpful messages if the header file is an local header file, and will suppress some error message if the header file is a system header, according to the GCC documentation.
To make the normal version of the code output error messages just like the code which specified the full path of the header file, as you asked for, GCC needs to stop including all system directories by specifying option -nostdinc
, and then explicitly tell GCC the directories it could search for header files while not treat the directory as system directory using -I
flag.
For your code, the command line could be like below (GCC_INCLUDE_DIR
is your default GCC include directory, for the system default GCC, it could be /usr/lib/gcc/x86_64-unknown-linux-gnu/4.9.2/include/
) :
gcc -c t.c -nostdinc -I/usr/include/ -IGCC_INCLUDE_DIR
Moved the source code here from this original post to make this answer more helpful.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <term.h>
//#include "/usr/include/term.h"
void clear_screen(void) {
if (!cur_term) {
int result;
setupterm( NULL, STDOUT_FILENO, &result );
if (result <= 0)
return;
}
putp( tigetstr( "clear" ) );
}
int main(void) {
puts("I am going to clear the screen");
sleep(1);
clear_screen();
puts("Screen Cleared");
sleep(1);
clear_screen();
return 0;
}
You could use the following command line to ask GCC to output the preproceser generated code. This code will be fed into the actual compiler of GCC, cc1
. If the preprocessor generated files are exactly the same, the cc1
compiler's behavior should be exactly the same. (Assuming the code is put into file t.c
)
gcc -E t.c -o t.i
Following is the difference between the two gcc preprocessor generated .i
files. The t.fullpath.i
is the file generated with the full path header file, while t.i
is the code without full path (Some of the diff
output have been removed, since they are only filename differences.)
$ diff t.i t.fullpath.i
2920,2922c2920,2924
< # 1 "/usr/include/term.h" 1 3 4
< # 47 "/usr/include/term.h" 3 4
---
> # 1 "/usr/include/term.h" 1
> # 47 "/usr/include/term.h"
2924,2925c2926,2927
< # 48 "/usr/include/term.h" 2 3 4
< # 80 "/usr/include/term.h" 3 4
---
> # 48 "/usr/include/term.h" 2
> # 80 "/usr/include/term.h"
3007,3008c3009,3010
< # 81 "/usr/include/term.h" 2 3 4
< # 673 "/usr/include/term.h" 3 4
---
> # 81 "/usr/include/term.h" 2
> # 673 "/usr/include/term.h"
3041c3043
< # 729 "/usr/include/term.h" 3 4
---
> # 729 "/usr/include/term.h"
The different flag in the preprocessor generated code's comments makes the difference
GCC's cc1
compiler will take advantage of the preprocessor genrated information to generate the source code location of the error message, and also the debug information which will be used for gdb in the future.
For the following format:
# line-number "source-file" [flags]
The digits 3
and 4
of the flags mean:
#include <>
vs #include ""
)4: Following text should be treated as being wrapped in an implicit extern "C"
block.
For more information about different kind of these flags, please refer to this link.
Therefore, for the code without fully specified path, cc1
compiler will treat it as a system header file, and assume that system code is mostly correct, and then just output error message of the user's code. That is why the error message is shorter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With