================
@@ -13010,10 +13010,13 @@ static GVALinkage basicGVALinkageForFunction(const
ASTContext &Context,
if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
isa<CXXConstructorDecl>(FD) &&
- cast<CXXConstructorDecl>(FD)->isInheritingConstructor())
+ cast<CXXConstructorDecl>(FD)->isInheritingConstructor() &&
+ !FD->hasAttr<DLLExportAttr>())
// Our approach to inheriting constructors is fundamentally different from
// that used by the MS ABI, so keep our inheriting constructor thunks
// internal rather than trying to pick an unambiguous mangling for them.
+ // However, dllexport inherited constructors must be externally visible
+ // to match MSVC's behavior.
----------------
chinmaydd wrote:
I believe they are. The MS ABI mangles inherited constructors identically to
regular constructors -- in the sense that it takes into account class name and
parameter types. There is no "inherited from" encoding as far as I can see.
Built a small example (w/ assistance of Claude):
```
// base.h
#pragma once
#ifdef BUILDING_DLL
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
struct DLL_API Base {
int value;
Base(int v);
Base(double v);
};
struct DLL_API Child : public Base {
using Base::Base;
};
```
```
// lib.cpp
#define BUILDING_DLL
#include "base.h"
Base::Base(int v) : value(v) {}
Base::Base(double v) : value(static_cast<int>(v)) {}
```
```
// client.cpp
#include "base.h"
int main() {
Child c1(42);
Child c2(3.14);
return c1.value + c2.value;
}
```
---
MSVC generated thunk:
```
mov dword ptr [rsp+10h], edx ; save int param
mov qword ptr [rsp+8], rcx ; save this
sub rsp, 28h
mov edx, dword ptr [rsp+38h] ; reload int
mov rcx, qword ptr [rsp+30h] ; reload this
call Base::Base(int) ; forward to base
mov rax, qword ptr [rsp+30h] ; return this
add rsp, 28h
ret
```
Clang generated thunk:
```
sub rsp, 38h
mov dword ptr [rsp+34h], edx ; save int param
mov qword ptr [rsp+28h], rcx ; save this
mov rcx, qword ptr [rsp+28h] ; reload this
mov qword ptr [rsp+20h], rcx ; save for return
mov edx, dword ptr [rsp+34h] ; reload int
call Base::Base(int) ; forward to base
mov rax, qword ptr [rsp+20h] ; return this
add rsp, 38h
ret
```
Both are forwarding thunks with the same calling convention (this in rcx, int
in edx), same semantics (forward to base constructor, return this), and same
mangled symbol name. The only differences are minor register scheduling and
frame size, which don't affect ABI compatibility.
https://github.com/llvm/llvm-project/pull/182706
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits