[clang] Allow weak/selectany external definitions in header units. (PR #162713)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 9 11:24:32 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (akrieger)
<details>
<summary>Changes</summary>
weak and selectany are mechanisms for allowing the linker to resolve ODR violations. [module.import/6] states
> A header unit shall not contain a definition of a non-inline function or variable whose name has external linkage.
But this prevents compiling any headers with such weak symbols defined. These occur in eg. some Windows SDK headers like `DirectXMath.h`.
```
#ifndef XMGLOBALCONST
#if defined(__GNUC__) && !defined(__MINGW32__)
#define XMGLOBALCONST extern const __attribute__((weak))
#else
#define XMGLOBALCONST extern const __declspec(selectany)
#endif
#endif
XMGLOBALCONST XMVECTORF32 g_XMSinCoefficients0 = { { { -0.16666667f, +0.0083333310f, -0.00019840874f, +2.7525562e-06f } } };
```
Proposed solution: Do not emit `diag::err_extern_def_in_header_unit` if the `FD` or `VDecl` have either `SelectAnyAttr` or `WeakAttr`.
---
Full diff: https://github.com/llvm/llvm-project/pull/162713.diff
2 Files Affected:
- (modified) clang/lib/Sema/SemaDecl.cpp (+4-2)
- (modified) clang/test/CXX/module/module.import/p6.cpp (+13)
``````````diff
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6eaf7b9435491..0063bd51aa612 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13822,7 +13822,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
!VDecl->isInvalidDecl() && VDecl->isThisDeclarationADefinition() &&
VDecl->getFormalLinkage() == Linkage::External && !VDecl->isInline() &&
!VDecl->isTemplated() && !isa<VarTemplateSpecializationDecl>(VDecl) &&
- !VDecl->getInstantiatedFromStaticDataMember()) {
+ !VDecl->getInstantiatedFromStaticDataMember() &&
+ !(VDecl->hasAttr<SelectAnyAttr>() || VDecl->hasAttr<WeakAttr>())) {
Diag(VDecl->getLocation(), diag::err_extern_def_in_header_unit);
VDecl->setInvalidDecl();
}
@@ -16162,7 +16163,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
!FD->isInvalidDecl() && !FD->isInlined() &&
BodyKind != FnBodyKind::Delete && BodyKind != FnBodyKind::Default &&
FD->getFormalLinkage() == Linkage::External && !FD->isTemplated() &&
- !FD->isTemplateInstantiation()) {
+ !FD->isTemplateInstantiation() &&
+ !(FD->hasAttr<SelectAnyAttr>() || FD->hasAttr<WeakAttr>())) {
assert(FD->isThisDeclarationADefinition());
Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);
FD->setInvalidDecl();
diff --git a/clang/test/CXX/module/module.import/p6.cpp b/clang/test/CXX/module/module.import/p6.cpp
index cb2d799e5b565..9e378a5fe7759 100644
--- a/clang/test/CXX/module/module.import/p6.cpp
+++ b/clang/test/CXX/module/module.import/p6.cpp
@@ -3,6 +3,9 @@
// RUN: %clang_cc1 -std=c++20 -x c++-header %t/bad-header-unit.h \
// RUN: -emit-header-unit -o %t/bad-header-unit.pcm -verify
+// RUN: %clang_cc1 -std=c++20 -x c++-header %t/bad-header-unit-declspec.h \
+// RUN: -emit-header-unit -o %t/bad-header-unit.pcm -verify \
+// RUN: -fdeclspec
//--- bad-header-unit.h
@@ -77,3 +80,13 @@ template <typename T> bool b() {
}
inline bool B = b<int>();
+
+__attribute__((weak)) int weak_fun_definition() { return 42; }
+
+__attribute__((weak)) int weak_var_definition = 42;
+
+//--- bad-header-unit-declspec.h
+
+/* The cases below should compile without diagnostics. */
+
+__declspec(selectany) int selectany_var_definition = 42; // expected-no-diagnostics
``````````
</details>
https://github.com/llvm/llvm-project/pull/162713
More information about the cfe-commits
mailing list