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.
Related
I'm following a tutorial on learning C. I'm currently using a Mac with clang 11.0.3. It is in C99 by default (I'm getting the error: warning: implicit declaration of function 'of' is invalid in C99
[-Wimplicit-function-declaration].)
I'm using xcode 11.5.
How do I update/change the default of clang to C11 or higher?
You can look up the documentation with man clang on your system or online on the Clang website (https://clang.org → “Getting started” → “User's Manual” link on the left).
clang supports the -std option, which changes what language mode clang uses. The supported modes for C are c89, gnu89, c99, gnu99, c11, gnu11, c17, gnu17, c2x, gnu2x, and various aliases for those modes. If no -std option is specified, clang defaults to gnu17 mode.
Note that since you're seeing C99 as the language version, your IDE is likely passing a -std option already. I don't know where to control compiler options in Xcode but Setting C compile flags in xcode might help.
The Clang documentation is not always complete or clear. Many features of Clang mimic GCC, and GCC often has better documentation. The section on C dialect options in the GCC manual has more information about -std and its values. You need to be careful because Clang doesn't always work exactly like GCC, but the GCC documentation is often helpful as long as you remember that it may not always apply to Clang.
None of this will help you anyway because switching from C99 to C11 wouldn't fix this particular error. Implicit function declarations are a deprecated feature in C89 which was made invalid in C99, and of is not a new keyword in C11, so either your code is bad-style C89 or more likely there's a typo and of should not be a function name.
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.
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.
Is there any way to compile C code with c89 standard NOT c99 in Xcode (or another way with terminal)?
I've searched in Xcode settings but I didn't find any way to choose compiler or standard.
You should add -pedantic-errors to Other C flags in your project settings, like so:
Of course, don't forget to set the C language dialect to C89 as well.
This will give you the appropriate compile time errors when you try to compile something that is not valid C89.
Optionally, if you want Xcode to compile your code regardless of incompatibilities, but only give you yellow warnings at the problematic lines, use -pedantic instead of -pedantic-errors.
In a nutshell, these flags make the compiler stick to the language standard more strictly, as opposed to the default behavior, which is to attempt compiling the code any way possible.
I hope this helps :)
Source
(even though they mention this in the context of GCC, but the same flags apply for Clang as well)
I'm interested in the effects of compiling valid C99 code with a C11 compiler. Is there any practical difference?
As an example, could changing
gcc -c -pedantic -std=c99 source.c
to
gcc -c -pedantic -std=c11 source.c
achieve anything, where source.c is valid C99? Could this introduce regressions, or give optimisations for free?
I'm interested specifically in gcc, although answers addressing other compilers are most welcome.
I used the C11 Wikipedia page as a quick check to see the difference between C99 and C11.
I do notice that gets is removed in C11, so that's one possible regression. The only other one I can see is if the code does something like version detection that's not future-proof, like #if __STDC_VERSION__ == 199901L .
Backwards compatibility is considered very important for the committee that maintains the C standard.
You can expect that a strictly conforming program written according to the preceding standard will function identically when compiled with the settings for the new standard, unless
the program uses a feature that was removed (gets when moving from C99 to C11)
the program uses a feature that was made optional and is not provided by the compiler (e.g. complex types or VLA's)
The latter is unlikely to really hit you, because it is not expected that compilers that had these features will remove them now they are optional. It is more likely that if a compiler in C11 mode doesn't support VLA's, then it also doesn't do so in C99 mode (and will be non-conforming to C99 in that respect).
For programs that aren't strictly conforming (the majority of real programs), you also have to check that the new additions don't interfere with your code. Things to watch out for are:
New standard headers that have the same name as your own headers
Incorrect use of reserved identifiers that have been given a use in the new standard. In particular, identifiers that start with an underscore and a capital letter