I'm trying to get some code from elsewhere (specifically, here), to compile without any warnings when gcc is given the -pedantic flag. The only problem is this bit of code:
struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
struct nlmsghdr nl_hdr;
/* Unnamed struct start. */
struct __attribute__ ((__packed__)) {
struct cn_msg cn_msg;
struct proc_event proc_ev;
};
/* Unnamed struct end. */
} nlcn_msg;
No matter where I try to put in a name for the structure, it results in a compilation error. Is there some way to modify the given code to satisfy -pedantic? Or is there some way to tell gcc to not issues a warning just for that piece of code?
Which standard are you compiling to?
Given this code:
#define NLMSG_ALIGNTO 4
struct nlmsghdr { int x; };
struct cn_msg { int x; };
struct proc_event { int x; };
struct __attribute__ ((aligned(NLMSG_ALIGNTO))) {
struct nlmsghdr nl_hdr;
/* Unnamed struct start. */
struct __attribute__ ((__packed__)) {
struct cn_msg cn_msg;
struct proc_event proc_ev;
};
/* Unnamed struct end. */
} nlcn_msg;
Compiling with C99 mode, I get errors:
$ gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Werror -pedantic -c x2.c
x2.c:13:6: error: ISO C99 doesn’t support unnamed structs/unions [-Werror=pedantic]
};
^
cc1: all warnings being treated as errors
$
Compiling with C11 mode, I get no errors:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition -Werror -pedantic -c x2.c
$
Related
I ran into some really weird problem with the compilation of a very simple code
typedef volatile struct _underflow_test
{
unsigned int OPERATION_MODE;
unsigned int UNDERFLOW;
} underflow_test;
This code fails to compile in MSYS2 using gcc12.2. Using the -E option I have checked that the code about is converted to this:
typedef volatile struct _underflow_test
{
unsigned int OPERATION_MODE;
unsigned int
# 4137 "C:/Users/work/eec_control/TC367_project/Libraries/Infra/Sfr/TC36A/_Reg/IfxGeth_regdef.h" 3
4
# 4137 "C:/Users/work/eec_control/TC367_project/Libraries/Infra/Sfr/TC36A/_Reg/IfxGeth_regdef.h"
;
} underflow_test;
So preprocessor converted UNDERFLOW into just 4. Then this conversion fails to compile.
Using the gcc11 doesn't do this - it doesn't convert UNDERFLOW field into 4.
The command line is the same in both cases:
cd C:/Users/work/build-eec-gnu/core_files/bsp && C:/msys64/mingw64/bin/gcc.exe
-DROOT_INSTALL_DIR="\"C:/Program Files (x86)/eec-control\""
#CMakeFiles/bsp-core-tc367-a1.dir/includes_C.rsp
-Wall -Wextra -Wno-unknown-pragmas -Wfloat-equal -Wconversion -Wparentheses -Wunused-parameter -Wunused-variable -Wstrict-prototypes
-DMAJOR_RELEASE_NUMBER=1 -DMINOR_RELEASE_NUMBER=0 -DPATCH_RELEASE_NUMBER=42 -E -O0 -DNDEBUG -g
-fdiagnostics-color=always -std=gnu99 -MD -MT core_files/bsp/CMakeFiles/bsp-core-tc367-a1.dir/hal.c.obj
-MF CMakeFiles/bsp-core-tc367-a1.dir/hal.c.obj.d -o CMakeFiles/bsp-core-tc367-a1.dir/hal.c.obj
-c C:/Users/work/eec_control/core_files/bsp/hal.c
Anyone know what could be causing this and how to solve this strange effect? Perhaps I'm missing something.
I am trying to compile an old C program on Centos8 Linux and it is failing, i'd appreciate any help.
I have broken below into the Makefile used, the error and code.
Any help would be much appreciated.
Thank you.
Makefile:
CC = gcc
C_FLAGS = -Wall -O0 -ggdb -march=i686 -m32 -DDEBUG=1
C_FLAGS2 = -Wall -O4 -march=i686 -s
LIBS = -lcrypt -lmysqlclient
Error
gcc -c -Wall -O0 -ggdb -march=i686 -m32 -DDEBUG=1 chat.c
In file included from chat.c:12:
command.h:152:30: error: array type has incomplete element type ‘struct cmd_type’
extern const struct cmd_type cmd_table[];
^~~~~~~~~
command.h
#ifndef _COMMAND_H
#define _COMMAND_H
/* returns 0 if not a command, or if the command is handled "on the fly".
otherwise, it handles it and returns 1 */
int execute_command(request_rec *r);
/* does that "print everything you've got" thing */
void archive_command(request_rec *r, user_rec **user_list,
message_rec **message_list, char *title, char *topic,
int chat_open);
#define DECLARE_CHAT_CMD( cmd ) CHAT_CMD cmd
typedef int CHAT_CMD (request_rec *r, char *message_text);
extern const struct cmd_type cmd_table[];
struct cmd_type
{
char *name;
CHAT_CMD *cmd;
int rank;
int room;
};
DECLARE_CHAT_CMD(do_admin);
DECLARE_CHAT_CMD(do_alink);
DECLARE_CHAT_CMD(do_archive);
DECLARE_CHAT_CMD(do_background);
DECLARE_CHAT_CMD(do_bgcolor);
DECLARE_CHAT_CMD(do_boot);
DECLARE_CHAT_CMD(do_bottom);
DECLARE_CHAT_CMD(do_box);
DECLARE_CHAT_CMD(do_bozo);
DECLARE_CHAT_CMD(do_close);
DECLARE_CHAT_CMD(do_color);
DECLARE_CHAT_CMD(do_commands);
#endif /* _COMMAND_H */
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Sorry I cannot post any reproducible code as it's part of the code of a large project.
The snippet is
struct res_data *getRes(int id) {
struct res_data *ret = malloc(sizeof(*ret));
/*
* res.aa = getAA(), etc...
*/
// print ret got: 0x55ffb23ce000
fprintf(stderr, "return: ret: %p\n", ret);
return ret;
}
Then
struct res_data *data = getRes(id);
fprintf(stderr, "got: %p\n", data);
// print data got: 0xffffffffb23ce000
Why is that? Any possible cause?
Transferring comments in answer.
Diagnosis
I'd lay odds you've not properly declared getRes() in a header that is used both where it is defined and where it is used, so the place where it is used thinks that it got a 32-bit int from getRes(), which it then sign-extended to create the pointer saved in data.
The last 8 hex digits (B23CE000) are the same in both values, but the original pointer in getRes() had some zero-bits in the leading 4 bytes, but that in the calling code has all bits 1, indicating sign-extension.
Moral: make sure you have accurate prototypes in force. Make your compiler insist on them. Heed its warnings!
Here is some code that reproduces the problem — but it is hair-raising to me. I don't normally publish code like this.
main31.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
// Incorrect declaration, but what the compiler infers, more or less
// extern int getRes(int id);
int main(void)
{
struct res_data *data = (struct res_data *)getRes(31);
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)data);
//free(data); // free fails because the pointer is incorrect
return 0;
}
getres31.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
struct res_data
{
int id;
char part2[32];
double part3;
};
extern struct res_data *getRes(int id);
struct res_data *getRes(int id)
{
struct res_data *ret = malloc(sizeof(*ret));
ret->id = id;
ret->part2[0] = '\0';
ret->part3 = 0.0;
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)ret);
return ret;
}
This code is essentially clean, except that the declaration of getRes() should be in a header included in both getres31.c and main31.c.
Compilation and running
Normally, I compile with -Werror set so the warnings would cause the compilation to fail.
$ make so-6051-9209-a
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o main31.o main31.c
main31.c: In function ‘main’:
main31.c:10:48: warning: implicit declaration of function ‘getRes’; did you mean ‘gets’? [-Wimplicit-function-declaration]
10 | struct res_data *data = (struct res_data *)getRes(31);
| ^~~~~~
| gets
main31.c:10:29: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
10 | struct res_data *data = (struct res_data *)getRes(31);
| ^
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o getres31.o getres31.c
gcc -o so-6051-9219-a -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes main31.o getres31.o
$
When run, the output varies:
$ ./so-6051-9219-a
getRes: 0x00007FDF41D02620
main: 0x0000000041D02620
$ ./so-6051-9219-a
getRes: 0x00007F868AC02AA0
main: 0xFFFFFFFF8AC02AA0
$
Sometimes, the value received in main() is interpreted as positive, sometimes as negative, but the value is sign-extended.
Prescription
The fix is to put the declaration of getRes() into a header, and include that header in both source files.
main37.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include "getres37.h"
int main(void)
{
struct res_data *data = getRes(31);
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)data);
free(data);
return 0;
}
Note that it is safe to free the data this time.
getres37.c
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include "getres37.h"
struct res_data
{
int id;
char part2[32];
double part3;
};
struct res_data *getRes(int id)
{
struct res_data *ret = malloc(sizeof(*ret));
ret->id = id;
ret->part2[0] = '\0';
ret->part3 = 0.0;
fprintf(stderr, "%6s: 0x%.16" PRIXPTR "\n", __func__, (uintptr_t)ret);
return ret;
}
getres37.h
#ifndef GETRES37_H_INCLUDED
#define GETRES37_H_INCLUDED
extern struct res_data *getRes(int id);
#endif /* GETRES37_H_INCLUDED */
Compilation and running
$ make so-6051-9219-b
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o main37.o main37.c
gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -c -o getres37.o getres37.c
gcc -o so-6051-9219-b -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes main37.o getres37.o
$
No warnings!
$ ./so-6051-9219-b
getRes: 0x00007FBA11600700
main: 0x00007FBA11600700
$ ./so-6051-9219-b
getRes: 0x00007FED23C02AA0
main: 0x00007FED23C02AA0
$
This time, there's no problem; the value of the pointer in main() matches the value in getRes().
Note that the header declares an opaque (incomplete) type struct res_data and declares a function that returns a pointer to that type. The main() function cannot dereference the pointer it is returned — it doesn't know (or need to know) the details of the structure. That's hidden in the file containing getRes(). This is the way that C supports information hiding. Using an opaque structure type is much safer than the alternative sometimes seen, which is using void * everywhere. That is dangerous as it provides no type safety, unlike the opaque structure types.
Also note that it was easy to create an MCVE (Minimal, Complete, Verifiable Example)
(or MRE or whatever name SO now uses)
or an
SSCCE (Short, Self-Contained, Correct Example). It really didn't require very much code at all. But it does make life so much easier — we don't have to do the guesswork!
JFTR: Testing on a MacBook Pro running macOS Mojave 10.14.6, using GCC 9.2.0 plus Xcode 11.3.1.
The most likely cause for this surprising behavior is a missing prototype for getRes() when you call this function from main().
Declare the function in a header that you include in both files as
extern struct res_data *getRes(int id);
Suddenly started getting this error at link time on some older code. I managed to replicate the problem with a very simple snippet of code:
#include <poll.h>
#include <stdio.h>
typedef struct
{
struct pollfd m_fds[6000];
nfds_t m_count;
} PollWrapper;
static PollWrapper g_pollWrapper;
int main()
{
return poll(g_pollWrapper.m_fds, g_pollWrapper.m_count, 0);
}
Compiling without -flto is fine.
gcc -Wall -O3 -o poll.exe poll.c # gcc 4.8.1-10ubuntu9
# successful
But adding -flto causes an error when linking:
gcc -Wall -O3 -flto -o poll.exe poll.c # gcc 4.8.1-10ubuntu9
# error
gcc -Wall -O3 -flto -o poll.o -o poll.c
# compilation is fine
gcc -Wall -O3 -flto -o poll.exe poll.o
# linking fails
/usr/include/x86_64-linux-gnu/bits/poll2.h: In function `main`:
/usr/include/x86_64-linux-gnu/bits/poll2.h:41:2: warning: call to `__poll_chk_warn` > declared with attribute warning: poll called with fds buffer too small file nfds entries [enabled by default]
return __poll_chk (__fds, __nfds, __timeout, __bos (__fds));
^
Having read related questions, I tried explicitly enabling and disabling the linker plugin, neither had any effect.
This only appears to happen with an array, none of the following have the same problem:
struct pollfd f;
int numfds = poll(&f, g_pollWrapper.m_size, duration);
or
struct pollfd fds[6000];
int numfds = poll(&f, g_pollWrapper.m_size, duration);
etc.
Am I either missing something obvious or is this an LTO defect in my GCC, and if so is there a way I can work around it?
We have some code in spatialite that looks like:
static int cmp_pt_coords (const void *p1, const void *p2)
{
....
}
static gaiaGeomCollPtr auxPolygNodes (gaiaGeomCollPtr geom)
{
....
/* sorting points by coords */
qsort (sorted, count, sizeof (gaiaPointPtr), cmp_pt_coords);
....
}
This is obviously simplified - the real code can be seen at
https://www.gaia-gis.it/fossil/libspatialite/artifact/fe1d6e12c2f98dff23f9df9372afc23f745b50df
The error that I'm getting from gcc (gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)) is
/bin/bash ../../libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I../.. -g -Wall -Werror -fprofile-arcs -ftest-coverage -g -I../../src/headers -fvisibility=hidden -g -Wall -Werror -fprofile-arcs -ftest-coverage -g -MT libsplite_la-spatialite.lo -MD -MP -MF .deps/libsplite_la-spatialite.Tpo -c -o libsplite_la-spatialite.lo `test -f 'spatialite.c' || echo './'`spatialite.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I../.. -g -Wall -Werror -fprofile-arcs -ftest-coverage -g -I../../src/headers -fvisibility=hidden -g -Wall -Werror -fprofile-arcs -ftest-coverage -g -MT libsplite_la-spatialite.lo -MD -MP -MF .deps/libsplite_la-spatialite.Tpo -c spatialite.c -fPIC -DPIC -o .libs/libsplite_la-spatialite.o
spatialite.c: In function 'auxPolygNodes':
spatialite.c:17843:5: error: passing argument 4 of 'qsort' from incompatible pointer type [-Werror]
/usr/include/stdlib.h:761:13: note: expected '__compar_fn_t' but argument is of type 'int (*)(void *, void *)'
cc1: all warnings being treated as errors
I've looked at some previous postings:
What are the parameters in this C qsort function call?
Warning when using qsort in C
However they don't really seem the same (or at least, the way I read the suggestions in those postings is what I think we're already doing here).
I can cast around this, using:
qsort (sorted, count, sizeof (gaiaPointPtr), (__compar_fn_t)cmp_pt_coords);
However I don't see why that should be necessary, and I'm worried about portability to other systems. It seems like the compiler is omitting the const-s from the arguments.
That cast is perfectly fine. GCC isn't smart enough to know that __compar_fn_t is
int (*)(const void *, const void *)
so it issues a warning.
However, __compar_fn_t is not portable -- so if you don't want to use it for casting, you should probably make GCC not warn about this using an appropriate compiler flag.
Or you can see whether __compar_fn_t is defined, and if not, define it yourself:
#ifndef __GNUC__
typedef int (*__compar_fn_t)(const void *, const void *);
#endif
The error probably comes from the visibility flag that you pass to the compiler. Your are saying that all functions in that compilation unit should be hidden. For gcc this changes the function API so your comparison function is then incompatible with the one expected by qsort.
You might want to deal with
#pragma visibility
or
__attribute__((__visibility(default)))
or similar for your comparison function.
The reason for the warning/error is that the GCC prototype of __compar_fn_t is:
typedef int (*__compar_fn_t)(__const void *, __const void );
and not:
typedef int (__compar_fn_t)(const void *, const void *);
Therefore, in order to solve the problem, simply define your function as:
static int cmp_pt_coords (__const void *p1, __const void *p2)