Force a C compiler to produce integer narrowing warning - c

Let's consider the following example:
#include <stdio.h>
void func(unsigned char c) {
printf("0x%x\n", c);
}
int main() {
int val = 0x11223344;
func(val);
}
To my best knowledge, there is no way I can force gcc nor clang, to show a warning on the statement func(val) about the narrowing int -> unsigned char that will happen there. Not even by compiling with -Wall -Wextra -pedantic. The question targets mainly C code, but it is worth including the C++ world in the discussion as well (see the note below).
C++ Note
I'm well aware that in C++ exists a kind-of workaround using the uniform initialization syntax:
func({val});
But that does not solve my problem because:
for preexisting code, it requires changes
for new code, it would require using {} everywhere
Question 1
Is there any arcane option to achieve that when compiling C or C++ code? I'm fine also with a non-standard solution as long as it works with gcc or clang and it does not require changing the code. Note: I'm not looking for tricky C++ solutions using custom integer types with or without macros that wrap primitive types. I'm looking for something like a command-line option or a pragma. Again, the question is mostly for C code, but it's worth exploring any C++ solutions too.
Question 2 (fall-back)
If the reality turns out to be that (as suspected) no such solution exists, I'd be super-curious to understand why. I can't believe that such an option was just never considered to be implemented. There should be a list of reasonable arguments against it, that I just can't think of. But the thing is that the option could be simply non-standard like -fwrapv and people could use it only where it is really needed.

Is -Wconversion what you're looking for?
You can see the behavior here, with a lot of cases.

Related

GCC how to stop false positive warning implicit-function-declaration for functions in ROM?

I want to get rid of all implicit-function-declaration warnings in my codebase. But there is a problem because some functions are
programmed into the microcontroller ROM at the factory and during linking a linker script provides only the function address. These functions are called by code in the SDK.
During compilation gcc of course emits the warning implicit-function-declaration. How can I get rid of this warning?
To be clear I understand why the warning is there and what does it mean. But in this particular case the developers of SDK guarantee that the code will work with implicit rules (i.e. implicit function takes only ints and returns an int). So this warning is a false positive.
This is gnu-C-99 only, no c++.
Ideas:
Guess the argument types, write a prototype in a header and include that?
Tell gcc to treat such functions as false positive with some gcc attribute?
You can either create a prototype function in a header, or suppress the warnings with the following:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
/* line where GCC complains about implicit function declaration */
#pragma GCC diagnostic pop
Write a small program that generates a header file romfunctions.h from the linker script, with a line like this
int rom_function();
for each symbol defined by the ROM. Run this program from your Makefiles. Change all of the files that use these functions to include romfunctions.h. This way, if the linker script changes, you don't have to update the header file by hand.
Because most of my programming expertise was acquired by self-study, I intentionally have become somewhat anal about resolving non-fatal warnings, specifically to avoid picking up bad coding habits. But, this has revealed to me that such bad coding habits are quite common, even from formally trained programmers. In particular, for someone like me who is also anal about NOT using MS Windows, my self-study of so-called platform-independent code such as OpenGL and Vulkan has revealed a WORLD of bad coding habits, particularly as I examine code written assuming the student was using Visual Studio and a Windows C/C++ compiler.
Recently, I encountered NUMEROUS non-fatal warnings as I designed an Ubuntu Qt Console implementation of an online example of how to use SPIR-V shaders with OpenGL. I finally threw in the towel and added the following lines to my qmake .PRO file to get rid of the non-fatal-warnings (after, first, studying each one and convincing myself it could be safely ignored) :
QMAKE_CFLAGS += -Wno-implicit-function-declaration
-Wno-address-of-packed-member
[Completely written due to commends]
You are compiling the vendor SDK with your own code. This is not typically what you want to do.
What you do is you build their SDK files with gcc -c -Wno-implicit-function-declaration and and your own files with gcc -c or possibly gcc -o output all-your-c-files all-their-o-files.
C does not require that declarations be prototypes, so you can get rid of the problem (which should be a hard error, not a warning, since implicit declarations are not valid C) by using a non-prototype declaration, which requires only knowing the return type. For example:
int foo();
Since "implicit declarations" were historically treated as returning int, you can simply use int for all of them.
If you are using C program, use
#include <stdio.h>

GCC optimization flag problems

I am having a problem with some C code built with gcc compiler. The code in question has an enum, whose values are used as cases in a switch statement to configure an object. Fairly standard stuff.
When I compile the code using the -O0 option flag, everything builds and runs correctly no problem. However, when the flag is set to -O2 the code no longer works as expected.
When I step through the code and put a watch on the local variables, the enum, which should be only be one of three enum values, is actually -104! This causes the program to fail to configure the object.
Has anyone encountered this before who could provide some guidance? I haven't encountered this before and would appreciate if someone could explain why the compiler does this so I can make any necessary changes.
Snippet of code in question:
value = 0u;
switch(test_config) {
case DISABLE:
break;
case INTERNAL:
value = 1u;
break;
case EXTERNAL:
value = 2u;
break;
default:
valid = FALSE;
break;
}
if (valid) {
configure_test(value);
}
Enum in question:
typedef enum {
DISABLE,
INTERNAL,
EXTERNAL
} test_config_t;
This is the code that is causing the problem. I initially didn't include it because I didn't want the question to be please fix my code, rather I have been googling looking for reasons why gcc optimisation flags would produce different results for the same piece of code and haven't found anything particularly helpful. Also I am not at my computer and had to type this on my phone which also doesn't help. So I came here because there are experts here who know way more than me that could point me in the right direction.
Some more info that I probably should have included. The code runs on hardware which also might be the problem and I am looking into that as well. When ran from FSBL the code works with -O0, but not with -O2. So it may be hardware, but then I don't know why it works one way not the other.
You don't give enough details (since your question don't show any actual code, it should have some MCVE) but you very probably have some undefined behavior and you should be scared.
Remember that C11 or C99 (like most programming languages) is defined by an explicit specification (not only by the concrete behaviour observed on your code) written in English and partly defining the runtime behaviour of a valid C program. Read n1570.
I strongly recommend reading Lattner's blog What Every C programmer should know about Undefined Behavior before even touching or compiling your source code.
I recommend at least compiling with (nearly) all warnings and debug info, e.g. with gcc -Wall -Wextra -g, then improve the code to get no warnings, and run it under the gdb debugger and valgrind. Read more about Invoking GCC. You may also use (temporarily) some sanitizer instrumentation options, notably -fsanitize=undefined and -fsanitize=address. You could also add -std=gnu99 and -pedantic to your compiler flags. Notice that gdb watchpoints are a very useful debugger feature to find why a value has changed or is unexpected.
When you compile for release or for benchmarking with optimizations enabled, keep also the warning flags (so compile with gcc -O2 -Wall -Wextra); optimizations might give extra warnings which you should also correct. BTW, GCC accepts both -O2 and -g at the same time.
When you observe such issues, question first your own code before suspecting the compiler (because compilers are very well tested; I found only one compiler bug in almost 40 years of programming).

MinGW compiler doesn't need function declarations?

I have these two files:
// first.c
int main(void) {
putint(3);
}
and
// second.c
#include <stdio.h>
void putint(int n) {
printf("%d",n);
getchar();
}
When I run gcc 4.6.1 under Win XP:
gcc first.c second.c -o program.exe
It has no problem and writes 3 to stdout. It doesn't need putint declaration in first.c. How is this possible? Is this standard behavior?
I have tested this on MSVC 2008 Express and it runs only with the declaration as expected.
// first.c
void putint(int);
int main(void) {
putint(3);
}
Solved, thanks for hints, these options helped to show the warning:
-Wimplicit
-std=c99 (MinGW 4.6 still uses gnu90 by default)
This is a legacy "feature" of C that should not be used as of several decades ago. You should use a compiler with settings that will warn you if you do something like this. Gcc has several switches that you should specify when using it & one of them will give you a warning for this.
Edit: I haven't been using gcc myself, but switches that you should check out are -pedantic, -Wall, -Wextra, and -std.
The compiler that is accepting this is assuming, per the old language definition, that since you didn't see fit to tell it otherwise, the function a) returns an int value and b) since you pass it an int (or if you passed it something that could be promoted to an int) the function expects that argument to be an int.
As #veer correctly points out, this should generally work in your particular case. In other cases, however, differences between the implicit assumptions for a function without a prototype and the function's actual signature would make things go boom.
This isn't just for MinGW, but all standard versions of gcc. As noted, this is legal in C89; gcc defaults to 'gnu89' (not 99), which also accepts the code without warning. If you switch to c99 or gnu99 (or later, such as c11) you'll get a warning by default, but it will still compile.
As is noted by others, this is standard behavior for C conforming compilers. Naming your files .c partially puts it in C mode. It'll have fun things like "built-in functions" (printf() etc.) and all sorts of legacy C things.
I'd like to add to what others have said that I experienced recently, though. MS expressly dropped support for C past C90, and their C90 support is poor to say the least. I'm not entirely sure standard ANSI C90 codebases would compile under newer VS's, because it is basically the C++ compiler with lots of stuff disabled (whereas GCC actually has a C compiler). They did this in order to promote C++. If you want to use real C, you can't really do it in MS Visual Studio, any edition, unless you want to be declaring all your variables at the start of functions, etc.

restrict qualifier compilation error

I am using Code::Blocks 10.05, and mingw. It seems the compiler does not recognized restrict qualifier and return "error: expected ';', ',' or ')' before 'src'". Do I need to pass any compiler option in order to compile it correctly?
int inet_pton4 (const char *restrict src, unsigned char *restrict dst)
p/s: it seems mingw does not support inet_pton4, so i tried to integrate an open-source version into my code.
If your compiler does not support the restrict keyword, just take that keyword out (a).
It's used to indicate to the compiler that you (the developer) promise that the pointers follow certain properties involving aliasing, and this, in turn, allows the compiler to perform certain optimisations that would otherwise not necessarily be safe.
If you leave off that keyword in a compiler that supports it, it prevents those optimisations (slight downside).
If you leave it off for compilers that don't support that keyword, the downside is nil (since they don't support those optimisations anyway) and the upside is considerable, as in "it will compile for you" :-)
(a) You may want to ensure you're compiling in C99 mode first. While it may be true that you're using an older gcc that doesn't understand restrict, it's equally possible that you're not compiling in C99 mode, such as with -std=c99 (gcc docs seem to indicate that restrict has been supported even back to version 3.0).
If, for some reason you cannot activate C99 mode, I think gcc has an extension that allows you to use __restrict.
Since restrict is new in C99, and since, as #paxdiablo points out, omitting the restrict keyword doesn't really hurt anything, you can do this:
#if __STDC_VERSION__ < 199901L
#define restrict /* nothing */
#endif
Put this in a header that's #included by everything in your project (or at least by everything that uses restrict).
This should let your code compile with any C compiler, whether it supports C99 or not. It should even work for a compiler that doesn't define __STDC_VERSION__.
But, since you're using MinGW, which uses gcc, using gcc --std=c99 should also solve the problem (as #paxdiablo also points out).
You can safely do both. (And the #if solution is likely to be useful to others.)

Adding a pass to gcc?

Has anybody added a pass to gcc ? or not really a pass but adding an option to do some nasty things... :-) ...
I still have the same problem about calling a function just before returning from another...so I would like to investigate it by implementing something in gcc...
Cheers.
EDIT: Adding a pass to a compiler means revisiting the tree to perform some optimizations or some analysis. I would like to emulate the behavior of __cyg_profile_func_exit but only for some functions and be able to access the original return value.
So I'm going to try to enhance my question. I would like to emulate really basic AOSD-like behavior. AOSD or Aspect oriented programming enables to add crosscutting concerns (debugging is a cross-cutting concern).
int main(int argc, char ** argv) {
return foo(argc);
}
int foo(int arg_num) {
int result = arg_num > 3 ? arg_num : 42;
return result;
}
int dbg(int returned) {
printf("Return %d", returned);
}
I would like to be able to say, I'd like to trigger the dbg function after function foo has been executed. The problem is how to tell the compiler to modify the control flow and execute dbg. dbg should be executed between return and foo(argc) ...
That's really like __cyg_profile_function_exit but only in some cases (and the problem in __cyg_profile_function_exit is that you cannot easily see and modify the returned value).
If you still are interested in adding a GCC pass, you can start reading up GCC Wiki material just about that:
http://gcc.gnu.org/wiki/WritingANewPass and "Implementing Passes" from http://www.airs.com/dnovillo/200711-GCC-Internals/ on how to, well, add a pass.
The intermediate representation you are interested in is called GIMPLE. Some introduction is at http://www.airs.com/dnovillo/200711-GCC-Internals/200711-GCC-Internals-3-IR.pdf
Other information at http://gcc.gnu.org/wiki/GettingStarted
Just for future reference: Upcoming versions of gcc (4.4.0+) will provide support for plugins specifically meant for use cases such as adding optimization passes to the compiler without having to bootstrap the whole compiler.
May 6, 2009:GCC can now be extended using a generic plugin framework on host platforms that support dynamically loadable objects.
(see gcc.gnu.org)
To answer your question: gcc is a pretty popular compiler platform to do compiler research on, so yes, I'm sure someone has done it.
However, I don't think this is something done in a weekend. Hooking into gcc's code-generation is not something you'd do over the weekend. (I'm not sure what your scope is and how much time you're willing to invest.) If you really do want to hack gcc to do what you want, you most certainly want to start by discussing it on one of the gcc mailing lists.
Tips: don't assume that people have read your other questions. If you want to refer to a question, please add a link to it if you want people to find it.
Do you need to use GCC? LLVM looks like it would work. It is written in C++, and it is very easy to write a pass.
It's an interesting question. I'm going to address concepts around the question rather than answer the question directly because, well, I don't know that much about gcc internals.
You've probably already explored some higher-level manipulation of the source code to achieve what you want to accomplish; some kind of
int main(int argc, char ** argv) {
return dbg(foo(argc));
}
inserted with with a macro on the function "foo", perhaps. If you're looking for a compiler hack, though, then you probably don't want to modify source.
There are some gcc extensions discussed here that sound a bit like what you're going for. If gcc has anything that does what you want, it'll probably be documented in the C-language extensions area of the documentation. I couldn't find anything that sounded exactly like what you've described, but perhaps since you understand best what you're looking for, you'll know better how to find it.
A gdb script would do a pretty good job of outputting debug, but it sounds like you've got bigger plans than simply doing printf's. Inserting significant logic into the code seems to be what you're after.
Which reminds me of some dynamic linker tricks I've come across recently. Library interposing could insert code around function calls without affecting the original source. The example I've encountered was on Solaris, but there is probably an analog on other platforms.
Just came across the -finstrument-functions option documented here
-finstrument-functions
Generate instrumentation calls for entry and exit to functions. Just after function
entry and just before function exit, the following profiling functions will be called
with the address of the current function and its call site. (On some platforms,
__builtin_return_address does not work beyond the current function, so the call site
information may not be available to the profiling functions otherwise.)
void __cyg_profile_func_enter (void *this_fn,
void *call_site);
void __cyg_profile_func_exit (void *this_fn,
void *call_site);
But I guess this doesn't work because you are not able to modify the return value from the profiling functions.
The GCC, the GNU Compiler Collection, is a large suite, and I don't think hacking up its source code is your answer for find problems in a single application.
It sounds like you are looking more-so for debugging or profiling tools, such as gdb, and its various front-ends (xgdb, ddd) and and gprof. Memory / Bounds checking tools like electric fence, glibc's memcheck, valgrind, and mudflap might help if this is a memory or pointer issues. Enabling compiler flags for warnings and newer C standards might be useful -std=c99 -Wall -pedantic.
I cannot understand what you mean by
I still have the same problem about
calling a function just before
returning from another.
So I am not certain what you are looking for. Can you give a trivial or pseudo-code example?
I.e.
#include <stdio.h>
void a(void) {
b();
}
void b(void) {
printf("Hello World\n");
}
int main(int ac, char *av[]) {
a();
return 0;
}

Resources