[this question has one SO duplicate I can find, but that answer is plain wrong, see the C code below.]
I understand extern "C" does not produce C code in the middle of your C++. It is just a linkage directive.
I have a few of these extern "C" tales to tell, but here is one that bothers me today. This is a completely up-to-date VS2019, and this is the code:
#ifdef __cplusplus
extern "C" {
#endif
// NOTE: in here it is still C++ code,
// extern "C" is a linkage directive
typedef struct Test Test;
struct Test {
const /* remove this const and MSVC makes no warning */
uint32_t x;
} ;
/*
MSVC throws warning C4190: 'make_Test' has C-linkage specified,
but returns UDT 'Test' which is incompatible with C
: see declaration of 'Test'
*/
inline constexpr Test make_Test(uint32_t x)
{
return Test{ x };
}
#ifdef __cplusplus
}
#endif
int main(const int argc, const char * argv[])
{
constexpr auto test_{ make_Test(42) };
return 42 ;
}
That comment about that const is the gist of my question.
MSVC extern "C" is largely (completely?) undocumented. Thus I am unable to tell if, I am breaking some rule in this undocumented zone? Many claim this is some kind of "not fully implemented" C11 in there?
AFAIK having that const for a C11 (or any other C) struct member type is quite OK. And good old G++ could not care less: https://wandbox.org/permlink/7XfH2i21Yfnb7BDw of course.
Is this just a bug in VS2019, or I made a bug?
Update
Even if I move the implementation of make_Test into separate C file, and explicitly compile it as C, this Warning will stay the same.
About that 'answer' from the same question from before. C can have const struct data members, and of course, C structs can be list initialized when made. See the code below:
// gcc prog.c -Wall -Wextra -std=gnu11 "-Wno-unused-parameter" "-Wno-unused-variable"
#include <stdlib.h>
typedef struct Test { const long x; } Test;
static struct Test make_Test(long x)
{
struct Test test_ = { x } ;
return test_;
}
int main(const int argc, const char * argv[])
{
struct Test test_ = make_Test(42) ;
return 42;
}