Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[ClangCL] Incompatible behavior of explicit template instantiation combined with dllexport #140258

Copy link
Copy link
Open
@kikairoya

Description

@kikairoya
Issue body actions

MSVC does not apply dllexport on explicit template instantiation definition to its inner class but able to override by attaching dllexport explicitly to inner class itself using explicit template instantiation.
Clang-cl emulates former behavior but not latter.

To reproduce:

template <typename T>
struct outer_template {
    static void fn_outer();
    struct inner_class {
        static void fn_inner();
    };
};
template <typename T>
void outer_template<T>::fn_outer() { }
template <typename T>
void outer_template<T>::inner_class::fn_inner() { }

template struct __declspec(dllexport) outer_template<int>;

Compile above with > cl /FA /Fatest.asm /c test.cc produces:

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.44.35207.1 

include listing.inc

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC	?fn_outer@?$outer_template@H@@SAXXZ		; outer_template<int>::fn_outer
PUBLIC	??4?$outer_template@H@@QEAAAEAU0@AEBU0@@Z	; outer_template<int>::operator=
PUBLIC	??4?$outer_template@H@@QEAAAEAU0@$$QEAU0@@Z	; outer_template<int>::operator=
PUBLIC	?fn_inner@inner_class@?$outer_template@H@@SAXXZ	; outer_template<int>::inner_class::fn_inner
; Function compile flags: /Odtp
;	COMDAT ?fn_inner@inner_class@?$outer_template@H@@SAXXZ
_TEXT	SEGMENT
?fn_inner@inner_class@?$outer_template@H@@SAXXZ PROC	; outer_template<int>::inner_class::fn_inner, COMDAT
; File D:\tmp\test.cc
; Line 11
	ret	0
?fn_inner@inner_class@?$outer_template@H@@SAXXZ ENDP	; outer_template<int>::inner_class::fn_inner
_TEXT	ENDS
(snip)
; Function compile flags: /Odtp
;	COMDAT ?fn_outer@?$outer_template@H@@SAXXZ
_TEXT	SEGMENT
?fn_outer@?$outer_template@H@@SAXXZ PROC		; outer_template<int>::fn_outer, COMDAT
; File D:\tmp\test.cc
; Line 9
	ret	0
?fn_outer@?$outer_template@H@@SAXXZ ENDP		; outer_template<int>::fn_outer
_TEXT	ENDS
END

Asm shows outer_template::inner_class::fn_inner was instantiated but > cl test.cc /LD && objdump -p test.dll shows

(snip)
[Ordinal/Name Pointer] Table -- Ordinal Base 1
                  Ordinal   Hint Name
        [   0] +base[   1]  0000 ??4?$outer_template@H@@QEAAAEAU0@$$QEAU0@@Z
        [   1] +base[   2]  0001 ??4?$outer_template@H@@QEAAAEAU0@AEBU0@@Z
        [   2] +base[   3]  0002 ?fn_outer@?$outer_template@H@@SAXXZ

The Function Table (interpreted .pdata section contents)
(snip)

means outer_template::inner_class::fn_inner was instantiated but NOT exported. (this is the former described behavior).
In case of clang-cl, > clang-cl /FA /Fa6.asm /c test.cc shows

(snip)
	.def	"?fn_outer@?$outer_template@H@@SAXXZ";
	.scl	2;
	.type	32;
	.endef
	.section	.text,"xr",discard,"?fn_outer@?$outer_template@H@@SAXXZ"
	.globl	"?fn_outer@?$outer_template@H@@SAXXZ" # -- Begin function ?fn_outer@?$outer_template@H@@SAXXZ
	.p2align	4
"?fn_outer@?$outer_template@H@@SAXXZ":  # @"?fn_outer@?$outer_template@H@@SAXXZ"
# %bb.0:
	ret
                                        # -- End function
	.def	"?fn_inner@inner_class@?$outer_template@H@@SAXXZ";
	.scl	2;
	.type	32;
	.endef
	.section	.text,"xr",discard,"?fn_inner@inner_class@?$outer_template@H@@SAXXZ"
	.globl	"?fn_inner@inner_class@?$outer_template@H@@SAXXZ" # -- Begin function ?fn_inner@inner_class@?$outer_template@H@@SAXXZ
	.p2align	4
"?fn_inner@inner_class@?$outer_template@H@@SAXXZ": # @"?fn_inner@inner_class@?$outer_template@H@@SAXXZ"
# %bb.0:
	ret
                                        # -- End function
	.section	.drectve,"yni"
	.ascii	" /DEFAULTLIB:libcmt.lib"
	.ascii	" /DEFAULTLIB:oldnames.lib"
	.ascii	" /EXPORT:\"??4?$outer_template@H@@QEAAAEAU0@AEBU0@@Z\""
	.ascii	" /EXPORT:\"??4?$outer_template@H@@QEAAAEAU0@$$QEAU0@@Z\""
	.ascii	" /EXPORT:\"?fn_outer@?$outer_template@H@@SAXXZ\""
	.addrsig

says outer_template::inner_class::fn_inner was instantiated but not exported correctly.

In contrast, modifying to

(snip)
template struct __declspec(dllexport) outer_template<int>::inner_class;
template struct __declspec(dllexport) outer_template<int>;

results by MSVC

(snip)
[Ordinal/Name Pointer] Table -- Ordinal Base 1
                  Ordinal   Hint Name
        [   0] +base[   1]  0000 ??4?$outer_template@H@@QEAAAEAU0@$$QEAU0@@Z
        [   1] +base[   2]  0001 ??4?$outer_template@H@@QEAAAEAU0@AEBU0@@Z
        [   2] +base[   3]  0002 ??4inner_class@?$outer_template@H@@QEAAAEAU01@$$QEAU01@@Z
        [   3] +base[   4]  0003 ??4inner_class@?$outer_template@H@@QEAAAEAU01@AEBU01@@Z
        [   4] +base[   5]  0004 ?fn_inner@inner_class@?$outer_template@H@@SAXXZ
        [   5] +base[   6]  0005 ?fn_outer@?$outer_template@H@@SAXXZ

The Function Table (interpreted .pdata section contents)
(snip)

says outer_template::inner_class::fn_inner was exported (latter described behavior) but compiling with clang-cl shows error

test.cc(13,17): error: an attribute list cannot appear here
   13 | template struct __declspec(dllexport) outer_template<int>::inner_class;
      |                 ^~~~~~~~~~~~~~~~~~~~~
test.cc(14,17): warning: duplicate explicit instantiation of 'inner_class' ignored as a Microsoft extension [-Wmicrosoft-template]
   14 | template struct outer_template<int>;
      |                 ^
test.cc(13,60): note: previous explicit instantiation is here
   13 | template struct __declspec(dllexport) outer_template<int>::inner_class;
      |                                                            ^
1 warning and 1 error generated.

Clang-cl should allow attaching and adding __declspec(dllexport) to inner class by using explicit template instantiation definition.

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"Language frontend issues, e.g. anything involving "Sema"diverges-from:msvcDoes the clang frontend diverge from msvc on this issueDoes the clang frontend diverge from msvc on this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.