Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to turn "implicit declaration" warnings in $CC into errors?

Tags:

c

gcc

Preamble: My C may be fairly rusty; I first started writing C programs in somewhere around 1993 -- compilers may have been different back then, but I recall that when one attempted to refer to a C function that was not declared, the compiler would abort. This is from memory.

Currently, I am perplexed as to why GCC (4.4.3) is so forgiving on me when I [intentionally] mismatch or omit declaration of bar below, with its definition in bar.c. Because the compiler does not warn me, the program proceeds to a fatal addressing error at runtime -- since bar wants an address and is given an integer, it ends up de-referencing that integer as an address.

A strict compiler, or so I would think, would abort on me with an error. Am I missing something? My build command line is as follows:

cc -o foobar -g -Wall -std=c99 -fexec-charset=ISO-8859-1 -DDEBUG foo.c bar.c

With foo.c:

int main() {
    int a;
    bar(a);
    return 0;
}

and bar.c:

void bar(int * a) {
    *a = 1;
}

I have intentionally omitted declaration of bar and, as mentioned, intentionally pass it an integer (could be anything really) instead of an address that its actual definition would otherwise mandate. Because $(CC) does not stop me, I end up with a segmentation fault (x86, Ubuntu 10.04). I am aware that a compliant C (C99?) compiler would implicitly create an int bar(void) declaration for bar if none otherwise found, but in this case that's obviously not what I want at all!

I want to protect myself from the kind of errors -- where I make the human mistake of mismatching declarations and definitions or omitting the former altogether.

I tried to instead just invoke the compiler without the linking step (with the -c switch) -- but it doesn't matter as compiling still succeeds with warnings. The linker might complain though, but I want the compiler to stop me before that happens.

I do not actually want to turn all my warnings into errors (e.g. with -Werror), because:

  • I could have included the wrong float bar(double a); at the top of foo.c, which would eliminate the warning altogether, but doesn't change the fact that the resulting program crashes; alas, a program that compiles successfully without warnings (even with the -Wall switch) but still is faulty
  • I have and will have other types of warnings that should stay warnings and not prevent successfully building the program
  • It would be dealing with the effect of the problem, rather than the problem itself
  • It's not just the types of warnings, but also particular instances thereof; I wouldn't want to turn a specific warning into an error because in some instances that would not be applicable; this would be too "coarse" of a solution which doesn't take into account the specifics of and the context in which the warning occurred
like image 270
amn Avatar asked Oct 11 '11 10:10

amn


People also ask

How do you fix implicit declaration of error?

Function name typo: Often the function name of the declaration does not exactly match the function name that is being called. For example, startBenchmark() is declared while StartBenchmark() is being called. I recommend to fix this by copy-&-pasting the function name from the declaration to wherever you call it.

What is implicit declaration warning?

If a name appears in a program and is not explicitly declared, it is implicitly declared. The scope of an implicit declaration is determined as if the name were declared in a DECLARE statement immediately following the PROCEDURE statement of the external procedure in which the name is used.


2 Answers

To turn this warning into an error when compiling with gcc, pass the switch -Werror=implicit-function-declaration to the compiler.

Trying to answer your "why" question: yes, it might look odd that this is by default a warning and not an error. This is for historical reasons. For details, see e.g. Why does/did C allow implicit function and typeless variable declarations?, or read it in Ritchie's own words at http://cm.bell-labs.com/who/dmr/chist.html.

like image 186
Carl Avatar answered Sep 23 '22 06:09

Carl


You could probably force additional warnings for gcc:

-Wmissing-prototypes
-Wmissing-declarations

Using both (along with -Werror) will probably help you to avoid such situations, but require some more code writing.

Inspired by this.

EDIT: Example

// file: mis1.c
int main(void)
{
    int a;

    bar(a);

    return 0;
}

// file: mis2.c
#include <stdio.h>

double bar(double a)
{
    printf("%g\n", a);
    return a;
}

Compiling with gcc 3.3.4 (DJGPP) as:

gcc -Wall -Wmissing-prototypes -Wmissing-declarations -Werror mis2.c mis1.c -o mis.exe

Compiler output:

mis2.c:5: warning: no previous prototype for `bar'
mis1.c: In function `main':
mis1.c:6: warning: implicit declaration of function `bar'

Fix? #Include the following file in both files:

// file: mis.h
extern int bar(int);

Recompiling you get:

mis2.c:6: error: conflicting types for `bar'
mis.h:3: error: previous declaration of `bar'

Fix? Define and declare bar everywhere in the same way, correct, for example, mis.h:

// file: mis.h
extern double bar(double);

Likewise you could change bar() in mis2.c to match that of mis.h.

like image 38
Alexey Frunze Avatar answered Sep 23 '22 06:09

Alexey Frunze