On Thu, 19 Mar 2020, Liu Hao wrote:

在 2020/3/19 20:35, Martin Storsjö 写道:
For C++, the generated .h encloses this block in 'extern "C" { .. }'
anyway, and as these are variable definitions (with DECLSPEC_SELECTANY,
avoiding duplicate definitions even though it's in a header), not
declarations, GCC (and possibly clang as well) warn when the definition
also contains the 'extern' attribute.

This fixes the same warning as d551b7d85ec63c0fa33f1a51ec5157722709fc53
tried to fix, without overriding the EXTERN_C macro, which affected
other headers.

Signed-off-by: Martin Storsjö <[email protected]>
---


The first patch looks good - but it can't be pushed unless we find a
workaround for this issue.

Well, technically, if reverted we just get warnings - but right now with EXTERN_C being clobbered, I'm running into cases with duplicate definitions elsewhere, with compilers that default to -fno-common. So on its own, it trades brokenness for some warnings. But yeah, we want to fix the warnings.

In C++ a variable (object or reference) having namespace scope and being
declared with `const` and without `volatile` or `extern` has internal
linkage (as if it was declared `static const`) [1]. This is true
regardless whether it is inside an `extern "C"` block or not.

Oh, I didn't know this, thanks for catching it. Indeed, in this form, the header after my patches makes both GCC and Clang error out with errors like "error: ‘selectany’ attribute applies only to initialized variables with external linkage".

If these constant objects had internal linkage, then for example
`&MFPKEY_CLSID` in two different source files will yield two different
values due to duplication.

From my experience the best solution would look like this, which works
both in C and C++:
```
extern const PROPERTYKEY MFPKEY_CLSID;
             // declaration with `extern`
DECLSPEC_SELECTANY const PROPERTYKEY MFPKEY_CLSID
 = { ... };  // definition with `__selectany__`
```

But this requires the declarator to be written twice.

A different alternative is to define a different macro to be used here, like this:

#ifndef __DEFINE_CONST_EXTERN
#ifdef __cplusplus
#define __DEFINE_CONST_EXTERN extern "C" const
#else
#define __DEFINE_CONST_EXTERN const
#endif
#endif

(A quick grep didn't find any preexisting define with that semantic.)

Right now, out of the combinations {GCC,Clang} x {C,C++}, only GCC in C mode warns on a line like "extern __declspec(selectany) const PROPERTYKEY MFPKEY_CLSID = { ... };". So if including extern only in C++ mode, due to the differing linkage rules for const variables, this should avoid all warnings and avoid duplicating the list of declarations.

What do you think, is that preferrable, or should we just bite the bullet and add explicit declarations?

// Martin

_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to