Enable compiler warning when using double underscore - c

Let's assume the following code
int __foo(void) {
return 0;
}
int _BAR(void) {
return 3;
}
int main(void) {
return __foo() & _BAR();
}
Double underscore and a single underscore followed by an uppercase letter symbols are reserved and therefore not allowed (This is a C++ question, but it also mentions the C rules).
I tried -Wall -Wextra -pedantic options on gcc and -Weverything option on clang, both do not warn about this.
Is there any way to enable a compiler warning for this?

GCC and Clang appear not to offer such a feature.
The documentation for GCC warning messages is here (for version 8.2; to seek documentation for other versions, start here). None of them mention checking for reserved identifiers or identifiers that begin with an underscore followed by an underscore or capital letter, except certain special cases (such as the built-in __FILE__) that are not useful for this question.
Clang’s documentation is here (that appears to be a link for the current version, so expected it to be updated in the future). It similarly has no mention of checking for reserved identifiers.
In Clang, -Weverything enables all diagnostics, so, if no diagnostic appears when compiling sample code with -Weverything, the desired diagnostic is not implemented in Clang.
There does not appear to be any reason a compiler cannot do this. Clang does track where source text originates. For example, if macro expansions result in a syntax error, Clang prints multiple diagnostic lines showing the names, line numbers, and file names of the macros involved. Furthermore, Clang suppresses warnings in system headers and can be told to treat additional files (such as headers for libraries) similarly with #pragma clang system_header. So it seems feasible for Clang to produce a warning for any reserved identifier that does not originate in a system header. The lack of such a feature may be due to lack of demand.

A compiler can't practically warn you of this. Once the preprocessor has included any standard library files (which can of course contain double underscores), the compiler doesn't really know the origins of such code.
A good IDE or static analyser can warn you however.

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>

How can I specify to gcc that {} init in C shouldn't compile?

with gcc using -std=gnu99, the following code compiles:
void f()
{
struct X data = {};
// do something with data
}
Is this valid C ?
Is this a gnu extension ?
How can I tell gcc to not accept this kind of init ?
I want to ensure compatibility with other compilers (like visual 2015 for example)
If you want to reject code containing GNU-specific extensions, use -std=c99 -pedantic-errors (-pedantic will issue diagnostics for non-standard extensions, but it won't necessarily reject the code outright). However, if you want to guarantee ISO conformance, be aware that this isn't a 100% solution. From the gcc man page:
Some users try to use -pedantic to check programs for strict ISO C conformance. They soon find that it does not do quite what they want: it finds some non-ISO practices, but not all---only those for which ISO C requires a diagnostic, and some others for which diagnostics have been added.
A feature to report any failure to conform to ISO C might be useful in some instances, but would require considerable additional work and would be quite different from -pedantic. We don't have plans to support such a feature in the near future.
The -pedantic option will cause a warning to be displayed in this case, and -Werror will cause all warnings to be treated as errors.
For example:
x1.c: In function ‘f’:
x1.c:11:19: error: ISO C forbids empty initializer braces [-Werror=pedantic]
struct X data = {};
No, the empty initializer is not standard C. It is a gcc extension. See this for a detailed description.
By specifying -std=gnu99, you allowed the GNU extensions to be used. You can force the compiler to only allow the standard conforming code, by specifying -std=cXX option.
From the gcc online manual (emphasis mine)
-std=
The compiler can accept several base standards, such as ‘c90’ or ‘c++98’, and GNU dialects of those standards, such as ‘gnu90’ or ‘gnu++98’. When a base standard is specified, the compiler accepts all programs following that standard plus those using GNU extensions that do not contradict it. For example, -std=c90 turns off certain features of GCC that are incompatible with ISO C90, such as the asm and typeof keywords, but not other GNU extensions that do not have a meaning in ISO C90, such as omitting the middle term of a ?: expression. On the other hand, when a GNU dialect of a standard is specified, all features supported by the compiler are enabled, even when those features change the meaning of the base standard. As a result, some strict-conforming programs may be rejected. The particular standard is used by -Wpedantic to identify which features are GNU extensions given that version of the standard. For example -std=gnu90 -Wpedantic warns about C++ style ‘//’ comments, while -std=gnu99 -Wpedantic does not.

The difference between -pedantic-errors and -Werror=pedantic in gcc

What is the difference between using -pedantic-errors and -Werror=pedantic in gcc?
According to the documentation of GCC there is a difference:
-pedantic-errors
Give an error whenever the base standard (see -Wpedantic) requires a diagnostic, in some cases where there is undefined behavior at compile-time and in some other cases that do not
prevent compilation of programs that are valid according to the
standard. This is not equivalent to -Werror=pedantic, since there are
errors enabled by this option and not enabled by the latter and vice
versa.
What errors are included by -pedantic-errors, but not by -Werror=pedantic?
What errors are included by -Werror=pedantic, but not by -pedantic-errors?
Any example of both types of errors?
A little insight as to why the two options exist separately in chapter 14:
Some ISO C testsuites report failure when the compiler does not produce an error
message for a certain program
ISO C requires a “diagnostic” message for certain kinds of invalid programs, but a
warning is defined by GCC to count as a diagnostic. If GCC produces a warning but
not an error, that is correct ISO C support. If testsuites call this “failure”, they should
be run with the GCC option ‘-pedantic-errors’, which will turn these warnings into
errors.
So it sounds like there's some ISO C rules that are not explicitly marked as invalid C but instead valid-ish C. These are the rules that -pedantic-errors makes into errors that -Werror=pendantic doesn't. You'll have to look at ISO C standard for more information on that.
As far as what errors are turned on/off as documented by GCC, there is but 1 that has -pendantic-errors explicitly:
-Wno-implicit-function-declaration
(C and Objective-C only)
This option controls warnings when a function is used before being declared. This warning is enabled by default in C99 and later dialects of C, and also by -Wall. The warning is made into an error by -pedantic-errors.
Note: however it seems that not all the authors of the manual have the same idea. In section 2 it talks about -pendantic-errors as if it WAS the same:
to obtain all the diagnostics required by the standard, you should
also specify ‘-pedantic’ (or ‘-pedantic-errors’ if you want them to be errors rather than
warnings).
So I believe you've discovered an editorial discrepancy.

How to disable gnu extensions for clang?

I've tried "-U__GNUC__", but the preprocessor's output still contains "__attribute__" or something like that. How to make the compiler discard those non-standard things? My OS is OS X 10.10 and when I run the compiler with option "-U__GNUC__", it complains:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/sys/cdefs.h:81:2:
warning:
"Unsupported compiler detected" [-W#warnings]
#warning "Unsupported compiler detected"
You probably cannot do that.
You might try to compile with clang -std=c11 -pedantic-errors -Wall -Wextra -Werrors; see here; this should prohibit __attribute__ in your user code, but still allow it in system headers.
Notice that according to standards, identifiers starting with _ are implementation reserved and should not be used in standard conforming application code.
Hence your implementation (e.g. standard C or standard C++ library) can (and probably does) use them. And several __attribute__-s in system headers are useful for the optimizations done by the compiler e.g. the compiler can optimize your use of malloc because system headers probably declare malloc with __attribute__((malloc)), 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.)

Resources