Rules for upconverting/downconverting types - c

Are there any rules at a function-level for what numeric types are allowed to be passed to it without a warning? For example, if we take the following two functions:
void take_int(int n){};
void take_double(double n){};
And calling it as:
take_int(4); # as intended
take_double(4.0); # as intended
take_double(4); # have to up-convert int to double
take_int(4.0); # have to down-convert double to int
When would this raise a warning or not be acceptable (ignoring what the actual function does with the values)?

The code you wrote is valid C, so it should be accepted by any compiler.
I tried your code in some recent versions of clang and GCC using Compiler Explorer, with the -Wall -Wextra --pedantic warning options, and none of them gave warnings.
However, the C standard does not specify what warnings a compiler should give, so the warnings you get will depend on what specific compiler you are using, and what version.

Related

clang disable main() prototype checking

Is there a way to disable main() prototype checking in clang?
I mostly using unsigned int type for argc and it was perfectly fine in gcc, but clang complains (it says argc should be int) and not with just a warning but with a non-compilable error.
I know that some standards says the same, but I also know that unsigned int is okay in this case and don't want to mess with this nonsense.
clang uses diagnostic categories. For displaying all of them use:
# clang --print-diagnostic-categories
Then for identifying this specific warning category use
# clang -fdiagnostics-show-category=id
It will display something as:
... return type of 'main' is not 'int' [-Wmain-return-type,2] ...
Rebuild with
# clang -Wno-main-return-type
should solve your problem.
Best regards

GCC warning to identify copying structures that contains pointers

Is there any GCC warning that cautions when I try to copy structures containing pointers with assignment operator instead of deep copying?
The answer is no. See the list of gcc warning options.
Given the same page, warnings are:
Warnings are diagnostic messages that report constructions that are not inherently erroneous but that are risky or suggest there may have been an error.
And shallow copy instead of a deep copy is neither risky nor erroneous as it may be an intended behavior. So there is no reason for such warning option to exist.
What you may want is a static analyzer such as clang's one, though in my knowledge this one doesn't offer that kind of functionality.
I remember seeing precisely such a warning with -Weffc++
Of course, you'd have to be willing to compile in c++ mode. (See below)
Edit I tested it: Sadly, this won't warn about POD (i.e.) C types. Here is the test:
struct HasPointer
{
int* resource;
HasPointer() {};
~HasPointer() {};
};
Compiled with
E:\mingw64>g++ test.c -Weffc++
Outputs
test.c:1:8: warning: 'struct HasPointer' has pointer data members [-Weffc++]
struct HasPointer
^
test.c:1:8: warning: but does not override 'HasPointer(const HasPointer&)' [-Weffc++]
test.c:1:8: warning: or 'operator=(const HasPointer&)' [-Weffc++]
test.c: In constructor 'HasPointer::HasPointer()':
But leaving the ctor/dtor out, the warning isn't even emitted, so this option doesn't work for your code, even in C++ compile mode.
Compiling C code in C++ mode:
(Use extern "C") to achieve binary interoperability. It is usually as simple as
extern "C"
{
# include "my.h"
# include "stuff.h"
// ...
}

implicit int and implicit declaration of functions with gcc compiler

I read in the c99 Standard:
-remove implicit function declaration,
-remove implicit int.
But when I try to compile this code with gcc compiler in c99 mode using -pedantic
main(void){
f(3);
return 0;
}
int f(int a){
....
}
I expect 2 errors, but I just receive 2 warnings:
-warning: return type defaults to ‘int’
-warning: implicit declaration of function ‘f’.
Shouldn't them be errors in c99?
http://gcc.gnu.org/c99status.html
In both situations there's written "done".
Thanks.
The C standard requires a diagnostic for any translation unit containing a violation of a syntax rule or constraint. It does not require such diagnostics to be fatal; the compiler is free to continue processing the source file. The behavior of the resulting executable, if any, is undefined. The standard makes no distinction between warnings and fatal errors.
(The only thing that requires a compiler to reject a source file is the #error directive.)
Conclusion: when compiling C, take warnings very seriously.
I don't believe the compiler is required to produce a fatal error. Use -Werror if you're concerned...
Two points: first, it may (usually does) take a specific set of flags to get a compiler to conform with the standard.
Second, all that's required by the standard is that the implementation issue a "diagnostic" in the case of an error -- but it's up to the implementation to define what is or isn't a diagnostic. It's free to say a "warning" is a diagnostic if it wants to. When a diagnostic is issued, it may quit compiling, or it can compile the code anyway.
Bottom line: what it's doing is probably enough to conform, for whatever that's worth.

warnings when activating the optimization options

I use scanf in a c program to read an int from STDIN:
scanf("%d", &n);
when I compile the c program with optimization enabled I get some warnings:
gcc main.c -lm -lpthread -O2 -o main
main.c: In function ‘main’:
main.c:45: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result
main.c:50: warning: ignoring return value of ‘scanf’, declared with attribute warn_unused_result
but when I remove the optimization options, why don't I get those warnings?
gcc main.c -lm -lpthread -o main
P.S: I'm not using -Wall or something similar.
Changing optimizer settings changes how much (and how) the compiler analyzes your code.
Some program flow analysis is not done when optimization is not enabled (or not set high enough), so the related warnings are not issued.
You'll see that frequently for "unused variable" warnings - these require analysis of the code beyond what is necessary to simply compile it, so you'll ususally only get them with optimization enabled.
(And you really should be compiling with -Wall.)
-Wunused-result is enabled by default: Because you'll actively need to decorate a function with __attribute__ ((warn_unused_result)) to trigger the warning, false positives only occur when it's used too liberally.
Even without passing additional flags, gcc should produce a warning. However, as Mat explained, the compiler doesn't do the necessary control flow analysis without increasing optimization levels.
Fix your code or silence the warning by adding -Wno-unused-result. Casting the return value to void will probably do as well.
To silence the warning in code, you'll need to assign the return value to a dummy variable, which you then can cast to void to avoid a new warning about the unused variable. It's also possible to substitute a C99 compound literal for the explicitly declared variable (tested with gcc 4.5.3).
This is indeed not optimal - I really expected the void-cast I originally porposed to work...

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

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
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.
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.
From the gcc docs on warnings:
-Wimplicit-function-declaration (C and Objective-C only)
Give a warning whenever a function is used before being declared. In C99 mode (-std=c99 or -std=gnu99), this warning is enabled by default and it is made into an error by -pedantic-errors. This warning is also enabled by -Wall.
...
-pedantic-errors (my emphasis) Like -pedantic, except that errors are produced rather than warnings.
...
-pedantic
Issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++. For ISO C, follows the version of the ISO C standard specified by any -std option used.
It looks to me that -pedantic-errors will do what you want (turn these warnings into errors), however it sounds like it will also turn on a host of other checks you may or may not want. =/
The closest I found to a solution to my problem was to simply use the flag -combine which indirectly causes the compiler to abort compilation when attempting to call a function that is missing a prototype or where prototypes mismatch or do not match the definition.
I am afraid it has drawbacks though. Since input files now are combined in one compilation run, one ends up with a single object file, which has some implications of its own. In short, -combine does something more than just fix my problem, and that may be a problem in itself.
You can turn all warning to error with
cc [..] -Werror [..]
. This will partially solve your problem.
I could have included the wrong float bar(double a); at the top of foo.c, which eliminates 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)
and beautifully crashes at runtime.
Herefore it is essential, additional to other measures, to include the same header file (including the prototype) in foo.c and bar.c. This ensures that the correct prototype is applied at both places.

Resources