Force compile error in G++ for undeclared functions - c++

I've installed GCC 4.8 using this method on my Mac. Everything works fine except that for certain functions like scanf and printf, the program compiles fine without any error/warning even when I did not include their respective libraries like cstdio. Is there any way that I can do to for GCC (more specifically G++, as I am dealing with C++ programs) to throw an error when such code is being fed? The following code compiles fine on my machine:
#include <iostream>
//Notice I did not include cstdio but my program uses printf later on
int main()
{
printf("Hello World!\n");
return 0;
}
I was given the suggestion to use -Werror-implicit-function-declaration -Werror or -Wall -Werror, but they don't work.

-Wimplicit-function-declaration -Werror works for me. There must be some other problems as well.
h2co3-macbook:~ h2co3$ cat baz.c
#ifndef BAILZ_OUT
#include <stdio.h>
#endif
int main()
{
printf("Hello world!\n");
return 0;
}
h2co3-macbook:~ h2co3$ gcc -o baz baz.c -Wimplicit-function-declaration -Werror
h2co3-macbook:~ h2co3$ echo $?
0
h2co3-macbook:~ h2co3$ gcc -o baz baz.c -Wimplicit-function-declaration -Werror -DBAILZ_OUT
cc1: warnings being treated as errors
baz.c: In function ‘main’:
baz.c:7: warning: implicit declaration of function ‘printf’
baz.c:7: warning: incompatible implicit declaration of built-in function ‘printf’
h2co3-macbook:~ h2co3$ echo $?
1
h2co3-macbook:~ h2co3$

The reason you get no diagnostic is that <iostream> is including the declaration of printf, which it seems to do with the c++0x or c++11 flags.
This compiles on a gcc 4.8 snapshot with the following command line:
g++ -Wall -Wextra -pedantic-errors -std=c++0x
#include <iostream>
int main()
{
printf("Hello World!\n");
return 0;
}
If you comment out the <iostream> include, or remove the C++11 compilation flags, you get an error.
impl_decl.cpp: In function 'int main()':
impl_decl.cpp:5:28: error: 'printf' was not declared in this scope

From the Annex C/Compatibility of the C++ standard from 2003:
C.1 C++ and ISO C:
C.1.3 Clause 5: expressions [diff.expr]
5.2.2
Change: Implicit declaration of functions is not allowed
Rationale: The type-safe nature of C++.
That means that implicit declarations must cause a compilation error in C++.
I'm guessing you're compiling not C++ files, but C files and you're doing that in some pre-C99 mode, which is the default in gcc. The C standard from 1999 disallows implicit declarations as well.
You may want to pass to gcc a combination of these options: -std=c99 -Werror.

Related

Why does C allow me to call an undeclared function? [duplicate]

This question already has answers here:
Why the error of - calling the function before being declared, is not shown?
(3 answers)
Closed 4 years ago.
I have two files: test1.c, and test2.c, which contains the main() function.
test1.c:
#include <stdio.h> // printf() function declaration/prototype
// function definition
void say_hello() {
printf("\tHello, world!\n");
}
test2.c:
#include <stdio.h> // printf() function declaration/prototype
int main() {
printf("Inside main()\n");
say_hello();
return 0;
}
And this is my makefile:
a.out: test1.o test2.o
$(CXX) -o a.out test1.o test2.o
test1.o: test1.c
$(CXX) -c test1.c
test2.o: test2.c
$(CXX) -c test2.c
Now it should be clear where the problem lies: The main() function in test2.c calls say_hello() without declaring it!
I run the following command, to use the gcc compiler:
make CXX=gcc
I get this warning to the screen:
gcc -c test1.c
gcc -c test2.c
test2.c: In function ‘main’:
test2.c:16:3: warning: implicit declaration of function ‘say_hello’ [-Wimplicit-function-declaration]
say_hello();
^
gcc -o a.out test1.o test2.o
Although the *.o files got compiled and linked into the executable. That's weird. Imagine my surprise when I run the a.out file, and I see that main() successfully called say_hello(), a function which is not declared inside of main's translation unit, as if there were no issue at all! I reason that since say_hello() was not previously declared in test2.c, it should not allowed to be called by main() at all. Notice that I've added comments to the #include <stdio.h>. These preprocessor directives include the function declarations/prototypes, which extend their scope into the corresponding *.c files. That is why we are able to use them. No function declaration/prototype == no scope in that translation unit, or so I thought until now.
Then I compiled the above code as C++ code:
make CXX=g++
I get this error to the screen:
test2.c: In function ‘int main()’:
test2.c:16:13: error: ‘say_hello’ was not declared in this scope
say_hello();
^
makefile:18: recipe for target 'test2.o' failed
make: *** [test2.o] Error 1
g++ does what it's supposed to do, and stops the compilation process. But gcc did not do this! What's going on? Is it a perk of the C programming language? Is it an issue with the compiler?
Simple, because C allows undeclared functions to be called and C++ does not. Either way, gcc warns you and you may want to take warnings seriously.

C++: what is wrong with abs

After a long time trace of my program I finally found that abs is the blameable part of my program. What should I expect from this code? why do I get:
x=0.1
|x|=0
#include <iostream>
int main()
{
double x=0.1;
std::cout<<"x="<<x<<std::endl;
std::cout<<"|x|="<<abs(x)<<std::endl;
return 0;
}
You may be wondering "But why I didnt get warning on g++ -g -Wall -Wfatal-errors -Wextra -std=c++11 test.cpp -o ./bin/test -lboost_filesystem -lboost_system?"
Turns out Wall isn't quite "all".
g++ -g -Wconversion -std=c++11 test.cpp -o tester -lboost_filesystem -lboost_system
test.cpp: In function ‘int main()’:
test.cpp:7:29: warning: conversion to ‘int’ from ‘double’ may alter its value [-Wconversion]
std::cout<<"|x|="<<abs(x)<<std::endl;
^
clang-3.6's diagnostic is clearer still, and no explicit opt-in required:
$ clang++ -std=c++11 test.cpp -o tester
test.cpp:8:24: warning: using integer absolute value function 'abs' when argument is of floating point type [-Wabsolute-value]
std::cout<<"|x|="<<abs(x)<<std::endl;
^
test.cpp:8:24: note: use function 'std::abs' instead
std::cout<<"|x|="<<abs(x)<<std::endl;
^~~
std::abs
test.cpp:8:24: note: include the header <cmath> or explicitly provide a declaration for 'std::abs'
1 warning generated.
You're using the abs defined in <cstdlib>, which only works on integers.
Use the abs defined in <cmath> instead. It works on floating point values.

Missing "missing sentinel" warning for exec in C++11

GCC will helpfully warn you if you forget to include the NULL sentinel at the end of a call to one of the exec(3) functions:
#include <unistd.h>
int main(int argc, char **argv)
{
execlp("test", "test", "arg1");
}
Sample compiler output for GCC 4.8:
$ g++ test.cc -Wformat
test.cc: In function ‘int main(int, char**)’:
test.cc:4:32: warning: missing sentinel in function call [-Wformat=]
execlp("test", "test", "arg1");
^
$
However, if you compile in C++11 mode, no diagnostic is printed:
$ g++ test.cc -std=c++11 -Wformat
$
Why is this warning not available in C++11? Is there any way to get it back?
execlp is not a standard C function. For the compiler to recognize it as a "standard" function, for which it knows what the arguments should look like, you need -std=gnu++11 instead of -std=c++11. Note that the default is -std=gnu++98. Glibc could improve the situation by specifying the sentinel attribute on the declaration of execlp.

gcc/g++ are giving different response to empty main function

I am using
g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
If I make a cpp and c file that contains only
int main(const int argc, const char *const argv[])
{
}
and compile it with g++ -Wall test_warnings.cpp I get no warning.
If I compile it with gcc -Wall test_warnings.c I get the warning you would expect:
test_warnings.c: In function ‘main’:
test_warnings.c:4:1: warning: control reaches end of non-void function [-Wreturn-type]
The same behavior is exhibited if -Wreturn-type is used instead of -Wall.
Why isn't g++ giving me a warning that the return is missing?
Because C and C++ are different languages.
In C++, reaching the end of main() without executing a return statement is equivalent to executing return 0;.
In C, as of the 1990 ISO standard, falling off the end of main() returns an undefined status to the calling environment.
C99 changed this, essentially adopting the C++ rule -- but gcc doesn't implement C99 by default. (Try compiling with -std=c99.)
In any case, it can't hurt to add a return 0; statement to the end of main().

Forcing GCC 4.x to treat -Wreturn-type as an error without enabling -Werror?

Suppose we have the following code:
#if !defined(__cplusplus)
# error This file should be compiled as C++
#endif
#include <stdio.h>
#include <string>
//#define USE_CXX_CLASS
#ifdef USE_CXX_CLASS
class SomeClass
{
public:
SomeClass() {}
~SomeClass() {}
std::string GetSomeString()
{
// case #1
}
};
#endif // USE_CXX_CLASS
int foo()
{
// case #2
}
int
main (int argc, char *argv[])
{
(void)argc;
(void)argv;
#ifdef USE_CXX_CLASS
SomeClass someInstance;
someInstance.GetSomeString();
#endif // USE_CXX_CLASS
foo();
return 0;
}
And suppose that it were to be compiled the C++ compiler (and not the C compiler) from GCC version 4.2.1 with the options -Wreturn-type -Werror=return-type. If the above code is compiled as is without first uncommenting the //#define USE_CXX_CLASS line above, then you will see a warning but no error:
.../gcc-4.2.1/bin/g++ -g -fPIC -Wreturn-type -Werror=return-type test.cpp -c -o test.o
test.cpp: In function 'int foo()':
test.cpp:26: warning: control reaches end of non-void function
But if the //#define USE_CXX_CLASS line is uncommented, then the warning is treated as an error:
.../gcc-4.2.1/bin/g++ -g -fPIC -Wreturn-type -Werror=return-type test.cpp -c -o test.o
test.cpp: In member function 'std::string SomeClass::GetSomeString()':
test.cpp:18: error: no return statement in function returning non-void [-Wreturn-type]
gmake: *** [test.o] Error 1
Yes, one is a non-member function (case #2), and the other is a C++ function (case #1). IMO, that should not matter. I want both conditions treated as an error, and I don't want to add -Werror or -Wall at this point in time (probably will do so later, but that is out of scope of this question).
My sub-questions are:
Is there some GCC switch that I am missing that should work? (No I do not want to use #pragma's.)
Is this a bug that has been addressed in a more recent version of GCC?
For reference, I have already poured through other similar questions already, including the following:
Why does flowing off the end of a non-void function without returning a value not produce a compiler error?
C question: no warning?
Is a return statement mandatory for C++ functions that do not return void?
It has been fixed, it works well with g++ 9.3: both member functions and free functions are treated as error with -Wall -Werror=return-type
I do see an error even w/o the USE_CXX_CLASS flag. i.e. g++ is consistent with the error for both class member functions and non member functions.
g++ (GCC) 4.4.3 20100127 (Red Hat 4.4.3-4)
It seems to me that what you need is a shell script wrapper around gcc.
Name it something like gcc-wrapper and g++-wrapper.
In your Makefile set CC and CXX to the wrappers.
Have the wrapper invoke GCC and pipe its output to another program which will search for your desired warning strings.
Have the search program exit with an error when it finds the warning.