Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C++20] [Modules] Cannot export type_info/operator new/operator delete #90620

Closed
huangqinjin opened this issue Apr 30, 2024 · 13 comments
Closed
Labels
clang:modules C++20 modules and Clang Header Modules

Comments

@huangqinjin
Copy link
Contributor

huangqinjin commented Apr 30, 2024

test.cppm

module;

#include <stddef.h>

export module test;

extern "C++"
{
    export class type_info;                                 // 0

    export void* operator new(size_t);                      // 1
    export void* operator new[](size_t);                    // 2
    export void operator delete(void*) noexcept;            // 3
    export void operator delete[](void*) noexcept;          // 4

    export void operator delete(void*, size_t) noexcept;    // 5
    export void operator delete[](void*, size_t) noexcept;  // 6
}

targeting x86_64-linux-gnu

✗ clang --target=x86_64-linux-gnu -std=c++20 --precompile test.cppm
test.cppm:11:18: error: cannot export redeclaration 'operator new' here since the previous declaration is not exported
   11 |     export void* operator new(size_t);                      // 1
      |                  ^
note: previous declaration is here
test.cppm:12:18: error: cannot export redeclaration 'operator new[]' here since the previous declaration is not exported
   12 |     export void* operator new[](size_t);                    // 2
      |                  ^
note: previous declaration is here
test.cppm:13:17: error: cannot export redeclaration 'operator delete' here since the previous declaration is not exported
   13 |     export void operator delete(void*) noexcept;            // 3
      |                 ^
note: previous declaration is here
test.cppm:14:17: error: cannot export redeclaration 'operator delete[]' here since the previous declaration is not exported
   14 |     export void operator delete[](void*) noexcept;          // 4
      |                 ^
note: previous declaration is here
4 errors generated.

targeting x86_64-windows-msvc

✗ clang --target=x86_64-windows-msvc -std=c++20 --precompile test.cppm
test.cppm:9:18: error: cannot export redeclaration 'type_info' here since the previous declaration is not exported
    9 |     export class type_info;                                 // 0
      |                  ^
note: previous declaration is here
test.cppm:11:18: error: cannot export redeclaration 'operator new' here since the previous declaration is not exported
   11 |     export void* operator new(size_t);                      // 1
      |                  ^
note: previous declaration is here
test.cppm:12:18: error: cannot export redeclaration 'operator new[]' here since the previous declaration is not exported
   12 |     export void* operator new[](size_t);                    // 2
      |                  ^
note: previous declaration is here
test.cppm:13:17: error: cannot export redeclaration 'operator delete' here since the previous declaration is not exported
   13 |     export void operator delete(void*) noexcept;            // 3
      |                 ^
note: previous declaration is here
test.cppm:14:17: error: cannot export redeclaration 'operator delete[]' here since the previous declaration is not exported
   14 |     export void operator delete[](void*) noexcept;          // 4
      |                 ^
note: previous declaration is here
5 errors generated.

The strange thing is that other overloads of operator new and operator delete can be exported without error.
Edit: Clang does not enable sized deallocation by default, adding -fsized-deallocation to the command line will cause 5 & 6 failed also.

@EugeneZelenko EugeneZelenko added clang:modules C++20 modules and Clang Header Modules and removed new issue labels Apr 30, 2024
@llvmbot
Copy link
Member

llvmbot commented Apr 30, 2024

@llvm/issue-subscribers-clang-modules

Author: None (huangqinjin)

#### `test.cppm`
module;

#include &lt;stddef.h&gt;

export module test;

extern "C++"
{
    export class type_info;                                 // 0

    export void* operator new(size_t);                      // 1
    export void* operator new[](size_t);                    // 2
    export void operator delete(void*) noexcept;            // 3
    export void operator delete[](void*) noexcept;          // 4

    export void operator delete(void*, size_t) noexcept;    // 5
    export void operator delete[](void*, size_t) noexcept;  // 6
}

targeting x86_64-linux-gnu

✗ clang --target=x86_64-linux-gnu -std=c++20 --precompile test.cppm
test.cppm:11:18: error: cannot export redeclaration 'operator new' here since the previous declaration is not exported
   11 |     export void* operator new(size_t);                      // 1
      |                  ^
note: previous declaration is here
test.cppm:12:18: error: cannot export redeclaration 'operator new[]' here since the previous declaration is not exported
   12 |     export void* operator new[](size_t);                    // 2
      |                  ^
note: previous declaration is here
test.cppm:13:17: error: cannot export redeclaration 'operator delete' here since the previous declaration is not exported
   13 |     export void operator delete(void*) noexcept;            // 3
      |                 ^
note: previous declaration is here
test.cppm:14:17: error: cannot export redeclaration 'operator delete[]' here since the previous declaration is not exported
   14 |     export void operator delete[](void*) noexcept;          // 4
      |                 ^
note: previous declaration is here
4 errors generated.

targeting x86_64-windows-msvc

✗ clang --target=x86_64-windows-msvc -std=c++20 --precompile test.cppm
test.cppm:9:18: error: cannot export redeclaration 'type_info' here since the previous declaration is not exported
    9 |     export class type_info;                                 // 0
      |                  ^
note: previous declaration is here
test.cppm:11:18: error: cannot export redeclaration 'operator new' here since the previous declaration is not exported
   11 |     export void* operator new(size_t);                      // 1
      |                  ^
note: previous declaration is here
test.cppm:12:18: error: cannot export redeclaration 'operator new[]' here since the previous declaration is not exported
   12 |     export void* operator new[](size_t);                    // 2
      |                  ^
note: previous declaration is here
test.cppm:13:17: error: cannot export redeclaration 'operator delete' here since the previous declaration is not exported
   13 |     export void operator delete(void*) noexcept;            // 3
      |                 ^
note: previous declaration is here
test.cppm:14:17: error: cannot export redeclaration 'operator delete[]' here since the previous declaration is not exported
   14 |     export void operator delete[](void*) noexcept;          // 4
      |                 ^
note: previous declaration is here
5 errors generated.

The strange thing is that other overloads of operator new and operator delete can be exported without error.

@ChuanqiXu9
Copy link
Member

I am not sure about typeinfo but I roughtly remember these operator new and deletes are special and implicitly declarared for every module units. So the behavior about operator new and delete is more or less correct if I remember correctly.

For typeinfo, I am not sure if this is the problme of headers in windows.

@ChuanqiXu9
Copy link
Member

Yeah, the replaceable operator new and delete are implicit declared: https://eel.is/c++draft/basic.stc.dynamic and replace it doesn't require to export it. So I think the behavior is correct.

If we can find typeinfo in the header's of windows, we can close the issue.

@huangqinjin
Copy link
Contributor Author

Yeah, the replaceable operator new and delete are implicit declared: https://eel.is/c++draft/basic.stc.dynamic and replace it doesn't require to export it. So I think the behavior is correct.

But below two overloads can be exported.

export void operator delete(void*, size_t) noexcept;    // 5
export void operator delete[](void*, size_t) noexcept;  // 6

@huangqinjin
Copy link
Contributor Author

If we can find typeinfo in the header's of windows, we can close the issue.

I don't understand this, does it mean type_info is also implicit declared?

@huangqinjin
Copy link
Contributor Author

Yeah, the replaceable operator new and delete are implicit declared: https://eel.is/c++draft/basic.stc.dynamic and replace it doesn't require to export it. So I think the behavior is correct.

But below two overloads can be exported.

export void operator delete(void*, size_t) noexcept;    // 5
export void operator delete[](void*, size_t) noexcept;  // 6

Ok, it is because clang does not enable sized deallocation by default, adding -fsized-deallocation to the command line will cause them failed also.

@ChuanqiXu9
Copy link
Member

If we can find typeinfo in the header's of windows, we can close the issue.

I don't understand this, does it mean type_info is also implicit declared?

I mean, if we can find typeinfo in stddef.h from windows, we can close this.

@huangqinjin
Copy link
Contributor Author

stddef.h is a C header, it unlikely contains class type_info.

Pointed out by microsoft/STL#4643, the declaration is ineh.h.

@ChuanqiXu9
Copy link
Member

Fine. Then it looks like the behavior of clang is good. I'll close the issue. Feel free to reopen this if you have different opinions.

@huangqinjin
Copy link
Contributor Author

It doesn't explain where is the previous declaration. Does clang include eh.h implicitly?

@ChuanqiXu9
Copy link
Member

hmm, I am not sure. It might be windows specific.

@ChuanqiXu9 ChuanqiXu9 reopened this May 6, 2024
@huangqinjin
Copy link
Contributor Author

@ChuanqiXu9 This issue is no longer repeatable with Clang 19, could you please confirm and point out which change fixed this issue, thanks.

@ChuanqiXu9
Copy link
Member

Probably e0d66c2?

And I'll close this. Thanks for updating.

huangqinjin added a commit to huangqinjin/cxxmodules that referenced this issue Nov 11, 2024
Clang 19 allows to export redeclarations within language linkage.
llvm/llvm-project#98583

Exporting implicitly declared `type_info`/`operator new`/`operator delete` is no longer illegal.
llvm/llvm-project#90620

Clang 19.1.1 with VS 17.11 supports `import std`.
- llvm/llvm-project#108732
- microsoft/STL#4626
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:modules C++20 modules and Clang Header Modules
Projects
None yet
Development

No branches or pull requests

4 participants