Skip to content

Commit 09b66ca

Browse files
committed
retro_atomic: shield <atomic> include from caller's extern "C"
ui_qt.cpp wraps RetroArch headers in extern "C" { ... } when CXX_BUILD is not defined. In non-unity builds the chain ui_qt.cpp (extern "C") -> menu_driver.h -> gfx_thumbnail.h -> retro_atomic.h -> <atomic> ends up parsing libstdc++ <atomic> under C linkage, producing dozens of "template with C linkage" errors on g++. The same hazard exists for any C++ TU that wraps RetroArch headers in extern "C", and is currently masked elsewhere only because no other such TU happens to pull in a header that reaches retro_atomic.h. Fix at the header level so every caller is protected, not just ui_qt.cpp: - Add RETRO_BEGIN_DECLS_CXX / RETRO_END_DECLS_CXX to retro_common_api.h. They expand to extern "C++" { ... } in C++ mode (with CXX_BUILD off) and to nothing otherwise, mirroring the existing RETRO_BEGIN_DECLS / RETRO_END_DECLS pair. - Use them around the <atomic> / <cstddef> include in retro_atomic.h's C++11 backend. The standard headers parse at C++ linkage regardless of any surrounding extern "C" the caller imposes; the rest of the file (typedefs and macros, no function declarations) is unaffected. The previous comment claiming "no need for RETRO_BEGIN_DECLS / extern \"C\" wrapping ... the wrapper would actively break that path" addressed only half the problem -- the file's own wrapping -- and missed that the caller's wrapper leaks into the <atomic> include. Updated to reflect the real constraint.
1 parent a340c70 commit 09b66ca

2 files changed

Lines changed: 19 additions & 4 deletions

File tree

libretro-common/include/retro_atomic.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#ifndef __LIBRETRO_SDK_ATOMIC_H
2424
#define __LIBRETRO_SDK_ATOMIC_H
2525

26+
#include <retro_common_api.h>
27+
2628
/* Minimal portable atomic operations for SPSC patterns.
2729
*
2830
* This header consolidates the ad-hoc atomic shims previously duplicated
@@ -321,10 +323,12 @@
321323
#endif
322324

323325
/* The header contains only macros and integer typedefs; there are no
324-
* function declarations and therefore no need for RETRO_BEGIN_DECLS /
325-
* extern "C" wrapping. In particular the C++11 backend below
326-
* #includes <atomic>, whose templates cannot be declared with C
327-
* linkage, so the wrapper would actively break that path. */
326+
* function declarations and therefore no need for RETRO_BEGIN_DECLS
327+
* around the file. The C++11 backend below #includes <atomic>, whose
328+
* templates cannot be declared with C linkage; if a caller wraps its
329+
* #include of this header in extern "C" { ... } (e.g. ui_qt.cpp under
330+
* !CXX_BUILD), libstdc++ <atomic> emits dozens of "template with C
331+
* linkage" errors. RETRO_BEGIN_DECLS_CXX below escapes that. */
328332

329333
/* ---- C11 <stdatomic.h> ------------------------------------------------- */
330334
#if defined(RETRO_ATOMIC_BACKEND_C11)
@@ -359,8 +363,10 @@ typedef atomic_size_t retro_atomic_size_t;
359363
/* ---- C++11 <atomic> --------------------------------------------------- */
360364
#elif defined(RETRO_ATOMIC_BACKEND_CXX11)
361365

366+
RETRO_BEGIN_DECLS_CXX
362367
#include <atomic>
363368
#include <cstddef>
369+
RETRO_END_DECLS_CXX
364370
/* This header is included by C++ TUs in C++11+ mode (gated on
365371
* __cplusplus >= 201103L or _MSVC_LANG >= 201103L). We use the
366372
* std::atomic_* free-function forms rather than the member-function

libretro-common/include/retro_common_api.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ special technique is called for.
4040

4141
#define RETRO_BEGIN_DECLS
4242
#define RETRO_END_DECLS
43+
#define RETRO_BEGIN_DECLS_CXX
44+
#define RETRO_END_DECLS_CXX
4345

4446
#ifdef __cplusplus
4547

@@ -50,6 +52,13 @@ special technique is called for.
5052
#undef RETRO_END_DECLS
5153
#define RETRO_BEGIN_DECLS extern "C" {
5254
#define RETRO_END_DECLS }
55+
/* Force C++ linkage for a region inside a header that may be included
56+
* from within a caller's extern "C" { ... } block -- needed when the
57+
* region pulls in a C++ standard library header (e.g. <atomic>). */
58+
#undef RETRO_BEGIN_DECLS_CXX
59+
#undef RETRO_END_DECLS_CXX
60+
#define RETRO_BEGIN_DECLS_CXX extern "C++" {
61+
#define RETRO_END_DECLS_CXX }
5362
#endif
5463

5564
#else

0 commit comments

Comments
 (0)