GCC is non-conforming? - c

I know that very few compilers actually support C11 threads (which is sad, but whatever). The C11 standard demands that an implementation that doesn't support threads defines __STDC_NO_THREADS__. Yet this program seems to give an error:
#include <stdio.h>
#ifndef __STDC_NO_THREADS__
#include <threads.h> //error is here
#endif // __STDC_NO_THREADS__
int main(void)
{
#ifdef __STDC_NO_THREADS__
printf("There are no threads");
#else
printf("There are threads");
#endif // __STDC_NO_THREADS__
}
//Error at line 3: fatal error: threads.h: No such file or directory
Compiler version is GCC 9.2.0 (Windows 10 x64), with __STDC_VERSION__ = 201710L (so it is C17). If you cannot tell, the problem is that my compiler doesn't define either __STDC_NO_THREADS__ or <threads.h>, which doesn't conform to C11. What could the problem be?

Pre-C11 compilers and libraries will not define __STDC_NO_THREADS__, nor will post-C11 ones with support for threading. So a correct check needs to look like this:
#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
#include <threads.h>
Otherwise older versions of the compiler/library will not work. In your case, you seem to be using Mingw under Windows, in which case the non-compliant Microsoft CRT is used (it does not conform to C99 and beyond).
Later versions of gcc using later versions of libc seem to work correctly with the original code.
Please note that gcc is not to be regarded as a conforming implementation unless you compile with -std=c17 -pedantic-errors. I don't think it matters in this specific case.

Related

Detect if compiler is truly GCC (__GNUC__ is defined by other compilers too)

How can I detect if the compiler is truly GCC, and not something pretending to be GCC, using the C preprocessor?
Motivation
Normally, I would test for __GNUC__. However, several compilers that claim to be compatible with GCC will define this, even though they are not fully compatible. Examples are Clang, Intel compiler, PGI.
At this time, I am looking to mark some enum values as deprecated, and I used an approach similar to the following:
#if __GNUC__ >= 6 || defined(__clang__)
#define DEPRECATED_ENUMVAL __attribute__ ((deprecated))
#else
#define DEPRECATED_ENUMVAL
#endif
enum Foo {
A = 0,
B DEPRECATED_ENUMVAL = A
};
This works in GCC version 6 and later, hence the check for __GNUC__ >= 6. However, it does not work with recent Intel and PGI compilers, even though both of those define __GNUC__ to be 7.
It seems that it would be safest to try to detect if I am dealing with specific versions versions of actual GCC or Clang, and restrict the deprecation attribute to them only. How can I detect an actual GCC?

Using snprintf with C90

Is there a way instruct the the compiler that:
The language is C90
The declarations of stdio.h are those of C99 (including snprintf)
With cc -std=c90 -Wall (on a source file using snprintf), an annoying warning is issued (sometimes, depending on the compiler/environment, with a confusing hint that stdio.h should be included, even if it already is), but the linker finds snprintf anyway. I understand what is happening, that is not the question.
Using strict c90 (language) and snprintf (library function) is technically well possible, but I do not know how to instruct the compiler accordingly. In other words, I would like to distinguish between language compliance and library compliance.
Remark: I assume that the language used in the C99 stdio.h header file is actually C90, and that it could thus be included by a C90 source file. Does anything prevent it?
I would prefer a solution with a generic include <stdio.h>, for the sake of portability.
Yes, though it's a bit of a weird thing to do.
You can define _ISOC99_SOURCE to signal that you want C99 functions to be defined.
Example:
#define _ISOC99_SOURCE
#include <features.h>
#include <stdio.h>
int main() {
char buf[10];
snprintf(buf, 4, "foo");
puts(buf);
return 0;
}
Compile it like so:
$ gcc -std=c90 -Wall test.c
$ ./a.out
foo
This will work in gcc 10.3.0 and clang 11.0.0. In terms of library compatibility, it has only been tested with glibc, and not musl or other versions of the standard library.
No.
A generic #include <stdio.h> for a C90 compiler needs not declare snprintf.
Before you argue that it's not a C90 compiler, keep in mind that you are requesting that it acts as one usng -std=c90. A compiler acting as a C90 compiler needs not do anything that a C90 compiler wouldn't do.
There is therefore no generic solution.
There may be compiler-specific solutions, including adding the following:
int snprintf( char * buffer, size_t bufsz, const char * format, ... );

implicit declaration error even after including required header

I get the following error when I run my code:
error: implicit declaration of function ‘mkdtemp’ [-Werror=implicit-function-declaration]
This occurs even after including the correct header files for mkdtemp():
#include <stdlib.h>
Any ideas why this might be occurring?
The <stdlib.h> header is mandated by the C standard. The C standard makes no reference to a mkdtemp() function. If you're using gcc -std=c11 or some similar option, only the definitions provided by the C standard are exposed. If you compile using gcc -std=gnu11, then you'll get an indeterminate set of extension features enabled (and mkdtemp() would be one of them).
Since mkdtemp() is a POSIX function, you can explicitly request it by defining the appropriate enabling macro before including any standard header. A command-line option -D_XOPEN_SOURCE=700 would (probably) do the job, for example; there's also the option of using -D_POSIX_C_SOURCE=200809 but remembering the correct number is harder (it is the date of the POSIX 2008 standard as year and month).
Or you can place the appropriate #define at the top of the file:
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
#endif
or:
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
These stanzas allow you to override the POSIX version on the command line. Simply writing the #define without the conditional around it would generate a warning (or error) for a non-benign redefinition of the macro.
There used to be major differences between the POSIX and X/Open functionality — X/Open included some things that POSIX doesn't. This distinction is smaller these days, and generally, you'll not get into trouble using the X/Open macro.
There are other enabling macros for other platforms, but one of these two will enable the declaration of mkdtemp(). On Linux (RHEL 7.x), /usr/include/features.h) documents these enabling macros:
/* These are defined by the user (or the compiler)
to specify the desired environment:
__STRICT_ANSI__ ISO Standard C.
_ISOC99_SOURCE Extensions to ISO C89 from ISO C99.
_ISOC11_SOURCE Extensions to ISO C99 from ISO C11.
_POSIX_SOURCE IEEE Std 1003.1.
_POSIX_C_SOURCE If ==1, like _POSIX_SOURCE; if >=2 add IEEE Std 1003.2;
if >=199309L, add IEEE Std 1003.1b-1993;
if >=199506L, add IEEE Std 1003.1c-1995;
if >=200112L, all of IEEE 1003.1-2004
if >=200809L, all of IEEE 1003.1-2008
_XOPEN_SOURCE Includes POSIX and XPG things. Set to 500 if
Single Unix conformance is wanted, to 600 for the
sixth revision, to 700 for the seventh revision.
_XOPEN_SOURCE_EXTENDED XPG things and X/Open Unix extensions.
_LARGEFILE_SOURCE Some more functions for correct standard I/O.
_LARGEFILE64_SOURCE Additional functionality from LFS for large files.
_FILE_OFFSET_BITS=N Select default filesystem interface.
_BSD_SOURCE ISO C, POSIX, and 4.3BSD things.
_SVID_SOURCE ISO C, POSIX, and SVID things.
_ATFILE_SOURCE Additional *at interfaces.
_GNU_SOURCE All of the above, plus GNU extensions.
_REENTRANT Select additionally reentrant object.
_THREAD_SAFE Same as _REENTRANT, often used by other systems.
_FORTIFY_SOURCE If set to numeric value > 0 additional security
measures are defined, according to level.
Note, too, that the manual page for mkdtemp() shows what is needed:
NAME
mkdtemp - create a unique temporary directory
SYNOPSIS
#include <stdlib.h>
char *mkdtemp(char *template);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
mkdtemp():
_BSD_SOURCE
|| /* Since glibc 2.10: */
(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
What I called 'enabling macros' are also known as 'Feature Test' macros.
See also POSIX System Interfaces: General Information: The Compilation Environment.

Warning Implicit Declaration of posix_memalign

I am using GCC 4.9 on ubuntu 15.04. I am coding in eclipse CDT. This is a C program with the dialect set to c99. For some reason my compiler keeps warning me about this...
warning: implicit declaration of function ‘posix_memalign’ [-Wimplicit-function-declaration]
I am not sure why. I have #include<stdlib.h> at the top and when I use eclipse the ctrl+click posix_memalign it takes me to the function declaration in stdlib.h. Why am I getting this warning?
I just tried changing the dialext to std=gnu99 and this fixed the issue. Is posix_memalign not included with c99?
The #define _POSIX_C_SOURCE 200809L and other feature test macros have to be defined before any #include lines.
This is because the macros tell the standard C library headers which features it should provide in addition/instead of the standard C library features; the features are "locked" at the point of #include.
posix_memalign() is provided by stdlib.h, but only if POSIX.1-2001 or later are enabled; this means defining _POSIX_C_SOURCE as 200112L or larger (the L is there because it is an integer constant of long type), or _XOPEN_SOURCE with 600 or larger.
The error shown only occurs when
The macros were not defined when stdlib.h was included
or
stdlib.h was not included
or
The C library implementation does not provide POSIX.1 features
Using GCC in Ubuntu, it has to be one of the first two, because the C library most definitely does provide these POSIX.1 features.

How to #ifdef by CompilerType ? GCC or VC++

I used #ifdef Win32 for safe calls alike sprintf_s but now I want to build project with MinGW and it's just wrong now. I need to use #ifdef VC++ or somehow like that. Is it possible?
#ifdef __clang__
/*code specific to clang compiler*/
#elif __GNUC__
/*code for GNU C compiler */
#elif _MSC_VER
/*usually has the version number in _MSC_VER*/
/*code specific to MSVC compiler*/
#elif __BORLANDC__
/*code specific to borland compilers*/
#elif __MINGW32__
/*code specific to mingw compilers*/
#endif
See the "Microsoft-Specific Predefined Macros" table of Visual C predefined macros
You could check for _MSC_VER.
Preferably, you should resort to using portable symbols. I understand sometimes those symbols may not be defined, so you can see the Predef project for an extensive list of preprocessor macros regarding standards, compilers, libraries, operating systems and architectures that aren't portable.
However, the function you specifically mention in this question has been included within the C11 standard as a part of Annex K.3, the bounds-checking interfaces (library).
K.3.1.1p2 states:
The functions, macros, and types declared or defined in K.3 and its subclauses are declared and defined by their respective headers if __STDC_WANT_LIB_EXT1__ is defined as a macro which expands to the integer constant 1 at the point in the source file where the appropriate header is first included
Thus, you should place preference upon checking __STDC_WANT_LIB_EXT1__, and only use compiler-specific symbols when that doesn't exist.

Resources