[clang] [clang] Fix loss of `dllexport` for exported template specialization (PR #93302)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 31 05:49:09 PDT 2024
zmodem wrote:
I looked at this some more. Here's a slightly reduced version of your test case:
```
template <typename> void foo();
template <typename> void f() {
foo<void>();
}
void g() { f<void>(); }
template <> void __declspec(dllexport) foo<void>() {}
```
What happens (when building with `-fno-delayed-template-parsing`) is something like:
1. The `f()` template gets parsed. Because the call to `foo` is not type-dependent, the call gets resolved to a FunctionDecl for `foo<void>`, which isn't dllexport because that happens later.
2. `g()` calls `f<void>()`, so the latter gets queued up for codegen at the end of the TU.
3. Codegen for `foo<void>` happens, with dllexport.
4. (End of the TU) Codegen for `f<void>` happens. When generating the call to `foo<void>`, it uses the FunctionDecl from step 1). We enter `CodeGenModule::GetOrCreateLLVMFunction`, see that the old `Entry` is dllexport but the new FunctionDecl isn't, and so the attribute gets dropped.
I think the "surprise" is that the latter call to `GetOrCreateLLVMFunction` is using an earlier `FunctionDecl`. Because of that, I'm thinking maybe the fix is to call `getMostRecentDecl` on it, something like:
```
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 489c08a4d481..8fe36305e104 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4554,10 +4554,13 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
}
// Handle dropped DLL attributes.
- if (D && !D->hasAttr<DLLImportAttr>() && !D->hasAttr<DLLExportAttr>() &&
- !shouldMapVisibilityToDLLExport(cast_or_null<NamedDecl>(D))) {
- Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
- setDSOLocal(Entry);
+ if (D) {
+ const Decl *MRD = D->getMostRecentDecl();
+ if (!MRD->hasAttr<DLLImportAttr>() && !MRD->hasAttr<DLLExportAttr>() &&
+ !shouldMapVisibilityToDLLExport(cast<NamedDecl>(MRD))) {
+ Entry->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ setDSOLocal(Entry);
+ }
}
// If there are two attempts to define the same mangled name, issue an
```
If we're concerned about the extra function call in a common codepath, we could only do this if there is a dll attribute on the `Entry`.
https://github.com/llvm/llvm-project/pull/93302
More information about the cfe-commits
mailing list