MinGW GCC does not emit a warning for undefined functions - c

For some reason, when calling certain functions for which I have not included the appropriate header file, I do not always get a compile-time "function is not declared / defined" error. It's a real source of headaches. Most recently, calling glfwGetTime() returned zero when the header was not included, but correct values when it was, wasting a lot of debugging time.
I've noticed that when compiling same code under Linux / native GCC, these tend to be caught.
Here are my compiler options:
CFLAGS = -I$(LIBDIR) $(INCLUDES) -std=c11 -m$(BITS) -fms-extensions -fopenmp -Wall -Wextra -Wimplicit-function-declaration -Werror -Wmissing-prototypes -Wpointer-arith -Wcast-qual -Wstrict-prototypes -Wlogical-op -Wcast-align -Wconversion -Wpedantic -Wfloat-equal -w -O0 -MMD
Any ideas why these aren't being caught at compile? P.S. This is NOT related to printf().

Related

PostgreSQL C Extensions without -Wdeclaration-after-statement

Currently, when I compile my extension I get,
warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
57 | uint32 n = fctx->n;
PostgreSQL currently uses -Wdeclaration-after-statement during compilation. They set this option specifically in their pgxs global make file on my machine that's at,
/usr/lib/postgresql/13/lib/pgxs/src/Makefile.global
It is set with their CFLAGS,
CFLAGS = -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer
Is there anyway to disable -Wdeclaration-after-statement or does every PostgreSQL extension author have to adopt this same convention? Can I override CFLAGS in my extension?
Probably you can override it by the instructions described in the link
The variable PG_CFLAGS will be appended to CFLAGS, so just add -Wno-declaration-after-statement
I was able to squelch these warnings by ending my extension's Makefile like,
PG_CFLAGS += $(PERMIT_DECLARATION_AFTER_STATEMENT)
include $(PGXS)
RhodiumToad provided an alternative way after include $(PGXS)
include $(PGXS)
$(OBJS): CFLAGS += $(PERMIT_DECLARATION_AFTER_STATEMENT)
Thanks goes out RhodiumToad on ircs://irc.libera.chat:6697/#postgresql, he goes on to say
configure tests whether -Wno-declaration-after-statement works and sets up that variable accordingly well actually I think it checks for -Wdeclaration-after-statement and if that works, assumes -Wno-... works too you can put that rule after including $(PGXS), so you can make it conditional on $(MAJORVERSION) if need be or conditional on PERMIT_DECLARATION_AFTER_STATEMENT being defined

undefined reference for inline function [duplicate]

I am getting a really odd error from GCC 4.8.1 with inline functions.
I have two near-identical inline functions defined in header files (debug.h and error.h) in src/include/, with the only difference being what they print - one prefixes DEBUG: to the message, and the other %s: error: %s (program name, error message). When defining the functions both inline, and compiling a debug build (so it sets the macro DEBUG=1), I get lots of undefined reference errors:
src/main_debug.o
gcc -osrc/main_debug.o src/main.c -c -Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g -DCC="\"gcc\"" -DCFLAGS="\"-Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g\"" -DDEBUG=1 -DBTCWATCH_VERSION="\"0.0.1\""
src/lib/btcapi_debug.o
gcc -osrc/lib/btcapi_debug.o src/lib/btcapi.c -c -Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g -DCC="\"gcc\"" -DCFLAGS="\"-Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g\"" -DDEBUG=1
src/lib/libbtcapi_debug.a
ar rc src/lib/libbtcapi_debug.a src/lib/btcapi_debug.o
ranlib src/lib/libbtcapi_debug.a
src/lib/cmdlineutils_debug.o
gcc -o src/lib/cmdlineutils_debug.o src/lib/cmdlineutils.c -c -Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g -DCC="\"gcc\"" -DCFLAGS="\"-Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g\"" -DDEBUG=1
src/lib/libcmdlineutils_debug.a
ar rc src/lib/libcmdlineutils_debug.a src/lib/cmdlineutils_debug.o
ranlib src/lib/libcmdlineutils_debug.a
debug
gcc -obtcwatch-debug src/main_debug.o -Lsrc/lib/ -lbtcapi_debug -lcmdlineutils_debug -lcurl -ljansson
src/main_debug.o: In function `main':
/home/marcoms/btcwatch/src/main.c:148: undefined reference to `debug'
src/main_debug.o:/home/marcoms/btcwatch/src/main.c:185: more undefined references to `debug' follow
collect2: error: ld returned 1 exit status
make: *** [debug] Error 1
But changing debug()'s definition to static inline removes the errors. But I have never received any errors from error()'s definition, although its defenition is inline, and not static inline.
The definitions are all in headers (i.e. not prototyped)
According to the manual, passing -std=gnu11 enables C99 instead of GNU inline semantics.
This means inline, static inline and extern inline all behave differently. In particular, inline expects an external definition in a separate translation unit (which you can provide without duplicating the definition - see this answer).

Why is make not rebuilding when source files are changed?

I am currently attempting problem set 4 (speller) from the CS50 course. It is the first problem set where we have multiple header files and multiple source files, so they gave us a Makefile to use, to compile each .c file into .o, then link the .o files to form the compiled binary.
This is the makefile
speller:
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o speller.o speller.c
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o dictionary.o dictionary.c
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o speller speller.o dictionary.o
Output of ls:
dictionaries dictionary.h keys speller speller.o dictionary.c dictionary.o Makefile speller.c texts
When I run make for the first time, it compiles speller no problems. However, when I make changes in dictionary.c and save it (In particular, I purposely screwed up all my printf() calls to printasdasdsa() yeah you get it) and I run make, it keeps saying make: 'speller' is up to date, and just refuses to rebuild even though I made changes to dictionary.c's source.
Any idea what's wrong with the way I'm building speller? Is there something wrong with my makefile?
I know that there's a way to force make to rebuild by passing the "-B" flag, but is it convention to always do it that way whenever you make a change in your code?
This is the task: https://docs.cs50.net/2019/x/psets/4/speller/hashtable/speller.html
Make only rebuilds a target if the target does not exist, or the target is older than one of its dependencies. In your case you have a target speller, with no dependencies. The first time you run it, make checks, and doesn't find it, so it builds it. The next time you build, it checks, the file exists, and since it does not have any dependencies, it does not rebuild. You would want to do something like:
speller: speller.c dictionary.c
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o speller.o speller.c
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o dictionary.o dictionary.c
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o speller speller.o dictionary.o
Or, better yet:
speller: speller.o dictionary.o
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -o speller speller.o dictionary.o
speller.o: speller.c
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o speller.o speller.c
dictionary.o: dictionary.c
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o dictionary.o dictionary.c
Which would not rebuild the .o files unless the .c files changed, and would not rebuild the app unless one of the .o files was rebuilt. Note that neither of these two handle any header files. If your .c files include any local headers, those need to be added to the dependencies as well.
#HardcoreHenry explains make's behavior very well in his answer (do not accept this one over that). I want to point out, however, that make has a fair amount of built-in smarts about building software, to the extent that it can do relatively simple builds without any Makefile at all. Moreover, when you do write a Makefile, it is usually considered good style to minimize repetition.
Thus, I'd suggest this as an even better alternative:
CC = clang
CFLAGS = -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 \
-Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare \
-Wno-unused-parameter -Wno-unused-variable -Wshadow
speller: speller.o dictionary.o
$(CC) -o $# $(CFLAGS) speller.o dictionary.o
That relies on make knowing how to build object files from C source files (which it does) and using the C compiler and and flags specified by the CC and CFLAGS variables when it does so (which it will). It also uses the special variable $#, which, in a rule's recipe, expands to the name of the rule's target. Some versions of make offer even a bit more opportunity to DRY this out.
Among other things, note how the compiler and build flags are specified once each, and near the top. Now if you ever want to change those, you can do it in one easy-to-find place.
You need to add dependencies. When using GNU make, you can skip the .o step for small projects and compile the program as a whole
speller: speller.c dictionary.c
${CLANG} ${CFLAGS} ${LDFLAGS} $(filter %.c,$^) -o $# ${LIBS}

Clang libFuzzer Undefined Reference to `__sanitizer_cov_trace_const_cmp8'

I can successfully compile Nginx with the following variables in the makefile
CC = clang-6.0
CFLAGS = -pipe -O -Wall -Wextra -Wpointer-arith -Wconditional-uninitialized -Wno-unused-parameter -Werror -g
When attempting to use -fsanitize=fuzzer or -fsanitize=fuzzer-no-link and changing my Makefile to:
CFLAGS = -pipe -fsantizer=fuzzer-no-link -O -Wall -Wextra -Wpointer-arith -Wconditional-uninitialized -Wno-unused-parameter -Werror -g
I get numerous undefined references to __sancov_lowest_stack and to __sanitizer_cov_trace_const_cmp8
How would I fix this? Which libraries am I missing?
You have to add sanitizer flags like -fsanitize=fuzzer to your CFLAGS and your LDFLAGS.
If they aren't passed to the linker but just to the compiler you get tons of undefined symbol errors for sanitizer runtime library functions (like the one you quoted in your question).
Note that when using -fsanitizer=fuzzer it makes sense to combine it with the Adress Sanitizer (i.e. -fsanitizer=fuzzer,address).
Also, with libFuzzer, you have to provide your own fuzzer callback function LLVMFuzzerTestOneInput() and omit a main() function.
You need to link against honggfuzz/libhfuzz/libhfuzz.a.

undefined reference when calling inline function

I am getting a really odd error from GCC 4.8.1 with inline functions.
I have two near-identical inline functions defined in header files (debug.h and error.h) in src/include/, with the only difference being what they print - one prefixes DEBUG: to the message, and the other %s: error: %s (program name, error message). When defining the functions both inline, and compiling a debug build (so it sets the macro DEBUG=1), I get lots of undefined reference errors:
src/main_debug.o
gcc -osrc/main_debug.o src/main.c -c -Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g -DCC="\"gcc\"" -DCFLAGS="\"-Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g\"" -DDEBUG=1 -DBTCWATCH_VERSION="\"0.0.1\""
src/lib/btcapi_debug.o
gcc -osrc/lib/btcapi_debug.o src/lib/btcapi.c -c -Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g -DCC="\"gcc\"" -DCFLAGS="\"-Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g\"" -DDEBUG=1
src/lib/libbtcapi_debug.a
ar rc src/lib/libbtcapi_debug.a src/lib/btcapi_debug.o
ranlib src/lib/libbtcapi_debug.a
src/lib/cmdlineutils_debug.o
gcc -o src/lib/cmdlineutils_debug.o src/lib/cmdlineutils.c -c -Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g -DCC="\"gcc\"" -DCFLAGS="\"-Wall -Wextra -Wpedantic -std=gnu11 -march=native -Og -g\"" -DDEBUG=1
src/lib/libcmdlineutils_debug.a
ar rc src/lib/libcmdlineutils_debug.a src/lib/cmdlineutils_debug.o
ranlib src/lib/libcmdlineutils_debug.a
debug
gcc -obtcwatch-debug src/main_debug.o -Lsrc/lib/ -lbtcapi_debug -lcmdlineutils_debug -lcurl -ljansson
src/main_debug.o: In function `main':
/home/marcoms/btcwatch/src/main.c:148: undefined reference to `debug'
src/main_debug.o:/home/marcoms/btcwatch/src/main.c:185: more undefined references to `debug' follow
collect2: error: ld returned 1 exit status
make: *** [debug] Error 1
But changing debug()'s definition to static inline removes the errors. But I have never received any errors from error()'s definition, although its defenition is inline, and not static inline.
The definitions are all in headers (i.e. not prototyped)
According to the manual, passing -std=gnu11 enables C99 instead of GNU inline semantics.
This means inline, static inline and extern inline all behave differently. In particular, inline expects an external definition in a separate translation unit (which you can provide without duplicating the definition - see this answer).

Resources