https://github.com/akrieger updated https://github.com/llvm/llvm-project/pull/162713
>From 0134ee7777a87f3773b7bcc1d72c0ebabca668bc Mon Sep 17 00:00:00 2001 From: Andrew Krieger <[email protected]> Date: Thu, 9 Oct 2025 13:33:22 -0700 Subject: [PATCH] Allow weak/selectany external definitions in header units. 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`. --- clang/lib/Sema/SemaDecl.cpp | 10 ++++++++-- clang/test/CXX/module/module.import/p6.cpp | 13 +++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6eaf7b9435491..b008f263f6a34 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13822,7 +13822,10 @@ 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() && + // The intent of the above section seems to be to prevent ODR issues. + // Weak symbols do the same but are not part of the c++ spec. + !(VDecl->hasAttr<SelectAnyAttr>() || VDecl->hasAttr<WeakAttr>())) { Diag(VDecl->getLocation(), diag::err_extern_def_in_header_unit); VDecl->setInvalidDecl(); } @@ -16162,7 +16165,10 @@ 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() && + // The intent of the above section seems to be to prevent ODR issues. + // Weak symbols do the same but are not part of the c++ spec. + !(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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
