LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 48704 - Default to C11 standard and missing __STDC_NO_THREADS__ ( windows)
Summary: Default to C11 standard and missing __STDC_NO_THREADS__ ( windows)
Status: REOPENED
Alias: None
Product: clang
Classification: Unclassified
Component: C (show other bugs)
Version: 11.0
Hardware: PC Windows XP
: P normal
Assignee: Unassigned Clang Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-01-10 10:29 PST by PpHd
Modified: 2021-10-19 08:41 PDT (History)
9 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description PpHd 2021-01-10 10:29:25 PST
Since the switch to default to C11, compliant program fails to build **by default** (without forcing another mode) on windows:

  #if defined(__STDC_VERSION__) && \
      (__STDC_VERSION__ >= 201102L) && \
      !defined(__STDC_NO_THREADS__)
  #  include <threads.h>
  #endif

[ build with only "clang.exe -c test.c"  ]

It is probably the same for other predefined macros.

This may be a library issue, but is it ok to default to C11 if there is known library issue for such support?
Comment 1 Reid Kleckner 2021-01-11 11:43:49 PST
Well, there is always __has_include(<threads.h>).

Do you think that defining __STDC_NO_THREADS__ is a promise that there cannot be threads in a program? As a programmer, a "no threads" macro seems like something that would be used to turn off expensive library synchronization. In that case, I don't think the compiler can define this macro on Windows, because there are threads on Windows, it's just the library support which may be missing.

One day maybe Visual C++ will provide threads.h, so the most we can do is do the __has_include test internally in the compiler to power this macro.
Comment 2 PpHd 2021-01-11 13:06:14 PST
> Do you think that defining __STDC_NO_THREADS__ is a promise that there cannot be threads in a program?

 No.
 Defining __STDC_NO_THREADS__ indicates that the implementation does not support the <threads.h> header (cf. ยง6.10.8.3 of C11)
 __STDC_NO_ATOMICS__ & __STDC_NO_COMPLEX__ are probably also missing.
Comment 3 Aaron Ballman 2021-10-17 06:37:35 PDT
> One day maybe Visual C++ will provide threads.h, so the most we can do is do the __has_include test internally in the compiler to power this macro.

We really can't even do that much because 7.26.1p2 says: "Implementations that define the macro __STDC_NO_THREADS__ need not provide this header nor support any of its facilities."

Note how it doesn't say implementations that define the macro to a particular value, just whether implementations define the macro at all.

The trouble is: Clang doesn't ship the full C implementation, it only ships the compiler and the library portions that need to come from the compiler, which does not include <threads.h>. We rely on the target platform to provide the rest of the C standard library interfaces, so the compiler doesn't know whether to define the macro or not. Some versions of glibc support <threads.h> and some do not, no version of MSVC CRT supports <threads.h> currently, etc.

Users have to rely on the C standard library implementation to provide this macro or not.
Comment 4 PpHd 2021-10-17 10:22:19 PDT
Then shouldn't clang-cl (not clang) switch back to C99 (or C89) for the default language mode as clang-cl is only for MSVC CRT?
Comment 5 Aaron Ballman 2021-10-18 04:19:44 PDT
(In reply to PpHd from comment #4)
> Then shouldn't clang-cl (not clang) switch back to C99 (or C89) for the
> default language mode as clang-cl is only for MSVC CRT?

clang-cl is a drop-in replacement for cl.exe, so it should default to whatever default language mode is claimed by cl.exe. From my testing:

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>cat test.c
int main(void) {
  return __STDC_VERSION__;
}

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>cl test.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
test.c(2): error C2065: '__STDC_VERSION__': undeclared identifier

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>cl test.c /std:c11
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 14.29.30133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>test.exe

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>echo %errorlevel%
201112

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>cl test.c /std:c17
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 14.29.30133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>test.exe

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>echo %errorlevel%
201710

So it seems as though cl doesn't set __STDC_VERSION__ at all by default unless you pass a command line flag to it. I don't know if we want to emulate that behavior or not (my inclination is that we should emulate it, but I don't use clang-cl myself).

Then I checked to see if maybe they do the same shenanigans with __STDC_NO_THREADS__:

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>cat test.c
int main(void) {
  return __STDC_NO_THREADS__;
}

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>cl test.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
test.c(2): error C2065: '__STDC_NO_THREADS__': undeclared identifier

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>cl test.c /std:c11
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 14.29.30133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>test.exe

c:\Users\aballman\OneDrive - Intel Corporation\Desktop>echo %errorlevel%
1

So it looks like Microsoft does define __STDC_NO_THREADS__ but only when explicitly set to C11 or C17 mode, and not when compiling for C in general. This behavior makes no sense to me, because Microsoft does not support threads.h in older language modes and this macro is a reserved identifier so they're free to define it in any language mode where it makes sense.

Adding some clang-cl folks to weigh in with their thoughts.
Comment 6 Hans Wennborg 2021-10-19 08:41:52 PDT
> So it seems as though cl doesn't set __STDC_VERSION__ at all by default unless you pass a command line flag to it. I don't know if we want to emulate that behavior or not (my inclination is that we should emulate it, but I don't use clang-cl myself).

Hmm, similar to __STDC__ I guess, which they don't set unless /Za is passed according to the docs.




As for __STDC_NO_THREADS__, it's true that since clang doesn't provide the standard library it can't really answer the question of whether threads.h exists, but it does know if it's targeting an "msvc environment", and could perhaps set the macro based on that. Something like: https://reviews.llvm.org/D112081