compiler-explorer / compiler-explorer

Run compilers interactively from your web browser and interact with the assembly
https://godbolt.org/
BSD 2-Clause "Simplified" License
16.41k stars 1.74k forks source link

[BUG]: Using C11's `threads.h` with MSVC triggers spurious errors #6176

Open mcilloni opened 8 months ago

mcilloni commented 8 months ago

Describe the bug

I've noticed that MSVC (both ARM and X64) does not build cleanly whenever threads.h is included (with the /std:c11 flag on):

#include <stdarg.h>
#include <stdio.h>
#include <threads.h>

thread_local int x;

int tx(void *d) {
    x += 2;

    return 0;
}

int main(void) {
    thrd_t t;

    thrd_create(&t, tx, NULL);

    return 0;
}

This code builds cleanly on CL 19.38 with the /std:c11 flag, but fails to build on Compiler Explorer (both MSVC 19.38 and latest) with:

example.c
C:/data/msvc/14.38.33133/include\threads.h(12): warning C4083: expected ')'; found identifier '_UCRT_DISABLED_WARNINGS'
C:/data/msvc/14.38.33133/include\threads.h(20): error C2143: syntax error: missing '{' before 'enum [tag]'
<source>(5): error C2054: expected '(' to follow '_UCRT_RESTORE_CLANG_WARNINGS'
<source>(5): error C2085: 'x': not in formal parameter list
<source>(7): error C2085: 'tx': not in formal parameter list
<source>(7): error C2143: syntax error: missing ';' before '{'
<source>(16): error C2065: 'tx': undeclared identifier
<source>(16): warning C4047: 'function': 'thrd_start_t' differs in levels of indirection from 'int'
<source>(16): warning C4024: 'thrd_create': different types for formal and actual parameter 2
Compiler returned: 2

I guess that that #define is somehow breaking threads.h and preventing this snippet from parsing?

Thanks a lot and keep up the great work btw!

Steps to reproduce

  1. Visit goldbolt
  2. Select msvc v19.38, either x64 or arm64
  3. Paste in the following snippet:
#include <stdarg.h>
#include <stdio.h>
#include <threads.h>

thread_local int x;

int tx(void *d) {
    x += 2;

    return 0;
}

int main(void) {
    thrd_t t;

    thrd_create(&t, tx, NULL);

    return 0;
}

Expected behavior

The snippet compiles cleanly, like it does locally when running cl.exe /std:c11 file.c

Reproduction link

https://godbolt.org/z/rheE8rPdv

Screenshots

Not applicable

Operating System

No response

Browser version

Firefox 123.0

partouf commented 8 months ago

The preprocessor says that bit of code looks like this:

#line 10 "C:/data/msvc/14.38.33133/include\\threads.h"

#pragma warning(push)
#pragma warning(disable : _UCRT_DISABLED_WARNINGS)
_UCRT_DISABLE_CLANG_WARNINGS
__pragma(pack(push, 8))

But I have no idea what it's supposed to look like or if this compiler supports that header file.

mcilloni commented 8 months ago

The preprocessor says that bit of code looks like this:

#line 10 "C:/data/msvc/14.38.33133/include\\threads.h"

#pragma warning(push)
#pragma warning(disable : _UCRT_DISABLED_WARNINGS)
_UCRT_DISABLE_CLANG_WARNINGS
__pragma(pack(push, 8))

But I have no idea what it's supposed to look like or if this compiler supports that header file.

MSVC has fully supported C11 Threads since last September. It is part of the standard C library, and both CL and Clang compile that snippet fine with the latest stable MSVC runtime.

threads.h starts with

// Copyright (c) Microsoft Corporation. All rights reserved.

#pragma once
#define _THREADS_H

#include <vcruntime.h>
#include <corecrt.h>
#include <stdint.h>
#include <time.h>

#pragma warning(push)
#pragma warning(disable : _UCRT_DISABLED_WARNINGS)
_UCRT_DISABLE_CLANG_WARNINGS
_CRT_BEGIN_C_HEADER

#ifndef __cplusplus
#define thread_local _Thread_local
#endif

but it does not look any different to me from any other UCRT header honestly.

partouf commented 8 months ago

The workaround is this: https://godbolt.org/z/coYh6PrE5

So I defined the missing defines from some randomly googled source, but I'm not sure why they are missing as soon as you include threads.h and not when including other headers.

I also had to "disable unknown pragma warnings" with #pragma warning(disable:4068) because apparently 'clang' is not a known pragma at this point, also strange.

jeremy-rifkin commented 4 months ago

It looks like now with our hosted msvc we're getting

<source>(3): fatal error C1083: Cannot open include file: 'threads.h': No such file or directory
partouf commented 4 months ago

it doesn't appear to be part of compiler's default installation, we'll have to see if it shows up on later versions, or that maybe it's part of an extra module