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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits