Enforcing ANSI C89 with clang - c

I'm trying to make the C compiler clang go into ANSI C89 mode but without success.
Here is an example session:
$ cat t.c
#include <stdio.h>
int main(void)
{
puts(__FUNCTION__);
return 0;
}
$ gcc -pedantic -std=c89 -Wall t.c
t.c: In function ‘main’:
t.c:5:7: warning: ISO C does not support ‘__FUNCTION__’ predefined identifier [-Wpedantic]
puts(__FUNCTION__);
^~~~~~~~~~~~
$ clang -pedantic -std=c89 -Wall t.c
$ clang --version
clang version 3.8.1-24 (tags/RELEASE_381/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
As you can see, the clang command completes with no warning. Is there a command option that I'm missing here?

It seems as if this specific warning is not emitted by clang, but apparently -std=c89 does toggle ANSI C89 syntax checking.
For example:
inline int foo(int* restrict p)
{
return *p;
}
Will refuse to compile with -std=c89 -pedantic -Wall:
t.c:1:1: error: unknown type name 'inline'
t.c:1:23: error: expected ')'
int foo(int* restrict p)
But will compile without errors using -std=c99.
The non-standard predefined identifiers warning was introduced with GCC 5 (https://gcc.gnu.org/gcc-5/porting_to.html), and apparently clang did not adapt with it.

Related

Why is there no compilation error with those array declarations (C89-C90)?

I want to show that arrays can't be defined with a variable for the length in C89 or C90.
I use GCC on Windows from TDM GCC:
C:\TDM-GCC-64\bin> .\gcc.exe --version
gcc.exe (tdm64-1) 10.3.0
My compilation options are:
gcc.exe -Wall -g -ansi -save-temps -c
I tried:
int main()
{
int i;
int tab[i];
tab[0] = 10;
return 0;
}
But it compiles fine:
gcc.exe -Wall -g -ansi -save-temps -c main.c -o main.o
gcc.exe -o Sandbox.exe main.o
main.c:6:9: warning: variable 'tab' set but not used [-Wunused-but-set-variable]
6 | int tab[i];
| ^~~
main.c:6:5: warning: 'i' is used uninitialized in this function [-Wuninitialized]
6 | int tab[i];
| ^~~
Output file is bin\Debug\Sandbox.exe with size 196.89 KB
Then:
int test(int i)
{
int tab[i];
tab[0] = 10;
return 0;
}
Compiles too:
main.c: In function 'test':
main.c:5:9: warning: variable 'tab' set but not used [-Wunused-but-set-variable]
5 | int tab[i];
| ^~~
Output file is bin\Debug\Sandbox.exe with size 196.90 KB
Or:
int main()
{
volatile int i;
int tab[i];
tab[0] = 10;
return 0;
}
Only this is not compiling:
int main()
{
// Comment
return 0;
}
error: C++ style comments are not allowed in ISO C90
What am I missing?
Thanks!
Variable length array is a GCC extension in older standard versions. Extensions are "compatible" with the standard. If you want to exactly adhere to the standard, i.e. you want to get a message when using an extension, add -pedantic option (and -pedantic-errors for errors).
Gcc docs: https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Variable-Length.html#Variable-Length , https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Warning-Options.html#Warning-Options .
gcc has sloppy standard compliance per default. It defaults to lax C conformance + GNU extensions, equivalent to -std=gnu89 (current version defaults to -std=gnu17).
When you type -ansi it does not mean conforming mode, but rather just the very same thing as -std=c89, "lax C89 mode". This compiler option may disable some GNU extensions... maybe... while keeping others. The difference between -std=c89 and -std=gnu89 is as poorly documented as the rest of gcc. We can read the unfriendly manual and it says:
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
gcc supported variable-length arrays as an extensions even before C99, so switching out the GNU option ought to disable them, but not so... As far as I know, there is no official documentation over what features -std=c89 shuts off or at least I can't find it.
What's important to realize is that -std=c89/-ansi alone does not push gcc into conforming mode! To do that, you need to do -std=c89 -pedantic or if you will -std=c89 -pedantic-errors. After which you'll get a diagnostic like this:
error: ISO C90 forbids variable length array 'tab'
And when compiling with these two options in combination, gcc probably has the best standard compliance of any compiler out there.

How to enable initialized but not used error in GCC

I'm compiling with a command:
gcc grep.c -std=c99 -g -Winit-self -pedantic -w -o main2 && ./main2 lib text.txt
and I wish to receive warnings for initialized but not used variables and functions.
If you use -Wunused-variable it will warn for unused variables. But I recommend using -Wall -Wextra. Then you will get that for free with a bunch of other stuff.
When it comes to unused functions I refer to this: GCC -Wunused-function not working (but other warnings are working)
You can use the -Wunused-but-set-variable option to warn for these.
test.c:
int main(void)
{
int c = 0;
c = 3;
}
Example:
$ gcc test.c -Wunused-but-set-variable -o test
test.c: In function ‘main’:
test.c:3:9: warning: variable ‘c’ set but not used [-Wunused-but-set-variable]
int c = 0;
^

compilation error for avx512, is it a GCC issue?

I am trying to compile the following code with AVX512 intrinsic, but gives me the compile error.
#include <immintrin.h>
static inline __attribute__((always_inline)) void
mov64(uint8_t *dst, const uint8_t *src)
{
__m512i zmm0;
zmm0 = _mm512_load_si512((const void *)src);
_mm512_store_si512((void *)dst, zmm0);
}
The compilation error:
gcc -D_GNU_SOURCE -DINFO_LOG_DEBUG --std=c99 -march=native -O3 -DNDEBUG -m64 -mtune=native -Werror -Wall -Wundef -Wpointer-arith -Wstrict-prototypes -Wnested-externs -fomit-frame-pointer -DTRANSPORT_CONFIG_OPT_HDR='<ci/internal/transport_config_opt_extra.h>' -c src/main.c -o obj/main.o
src/main.c: In function ‘mov64’:
src/main.c:15:9: error: unknown type name ‘__m512i’
__m512i zmm0;
^
src/main.c:17:9: error: implicit declaration of function ‘_mm512_load_si512’ [-Werror=implicit-function-declaration]
zmm0 = _mm512_load_si512((const void *)src);
^
src/main.c:17:9: error: nested extern declaration of ‘_mm512_load_si512’ [-Werror=nested-externs]
src/main.c:18:9: error: implicit declaration of function ‘_mm512_store_si512’ [-Werror=implicit-function-declaration]
_mm512_store_si512((void *)dst, zmm0);
^
src/main.c:18:9: error: nested extern declaration of ‘_mm512_store_si512’ [-Werror=nested-externs]
cc1: all warnings being treated as errors
In addition, if I add -march=native,avx512f or -mavx512f or -march=skylake-avx512, it gives the following error:
src/main.c:1:0: error: bad value (skylake-avx512) for -march= switch
My GCC version is 4.8.5 20150623 and CPU is "Intel(R) Xeon(R) Gold 6154". What should I do to overcome this problem? Thanks in advance..
GCC 4.8 does not support any of the AVX-512 variants. If this is the system compiler from Red Hat Enterprise Linux 7, you can use a new GCC version from Red Hat Developer Toolset, which provides support for later CPU features. (DTS is also available for CentOS.)

Why Clang isn't generating any warnings for an incompatible casting?

I am trying to compile a simple code with gcc and clang. the gcc generates a warning for an incomparable casting (great!). However, clang didn't generate any warnings! I have passed the same arguments for both:
cc -Wall -Wextra tmp3.c
gcc -Wall -Wextra tmp3.c
Am I passing all the necessary options to clang compiler or missing something? The clang documentation isn't a great help!
Code:
int main(void)
{
void *b = (void *)0x12345678;
int a = (int)(unsigned long)b;
int c = (int)b;
return a + c;
}
Clang version 3.8
I have reached out to the clang developers (mailing list). I have got this response:
In C++ mode, Clang errors on the line, same as everyone else. In C
mode, however, conversions are typically more permissive. In this
case, I suspect Clang should generate this warning as well. It’ll
likely require a patch however.

Why is Xcode allowing me to declare C variables anywhere?

I created a basic C project in Xcode and modified the starter code in main.c slightly. I also went into the build settings and told it to use ANSI-C. Here's the code I have:
int main(int argc, const char * argv[])
{
// a statement!
printf("Hello, World!\n");
// shouldn't this cause a compiler error?
// the variable isn't declared at the top of the scope.
int x;
x += 10;
return 0;
}
Obviously, it doesn't do much, but I expected the variable declaration to produce a compiler error (since older versions of C require variable declarations at the beginning of the scope, before other statements). However, Xcode happily compiles it and runs it with neither an error or warning.
I might be making a dumb mistake somewhere, but I'm trying to understand why this code compiles. I've read that C99 and C11 allow you to declare variables anywhere, so this would work, but I explicitly set the project to use ANSI-C. Is this just the way Apple's LLVM compiler works? Or am I missing something elsewhere?
TL;DR You need to add -pedantic (or -Wdeclaration-after-statement) to -ansi to get the warning you want.
Somewhat to my surprise, both clang (from Apple XCode 7.2) and gcc (from GCC 5.3.0, which I built), accept the code when compiled with either -std=c90 or -ansi even though it is not strictly compliant with C90.
However, both complain when told to be -pedantic.
$ clang -ansi -c xyz.c
$ clang -std=c90 -c xyz.c
$ gcc -std=c90 -c xyz.c
$ which gcc
/opt/gcc/v5.3.0/bin/gcc
$ gcc -std=c90 -pedantic -c xyz.c
xyz.c: In function ‘main’:
xyz.c:7:5: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
int x;
^
$ clang -pedantic -std=c90 -c xyz.c
xyz.c:7:9: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
int x;
^
1 warning generated.
$ clang -pedantic -ansi -c xyz.c
xyz.c:7:9: warning: ISO C90 forbids mixing declarations and code [-Wdeclaration-after-statement]
int x;
^
1 warning generated.
$
The file xyz.c is your source code with the comments stripped, #include <stdio.h> added at the top, and int main(void) in place of int main(int argc, char **argv) since the code doesn't use the arguments.
Note that your code has undefined behaviour; incrementing an uninitialized variable is a bad idea.

Resources