llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.09k stars 12k forks source link

Error about declaration in module following declaration in the global module #72038

Open rnikander opened 1 year ago

rnikander commented 1 year ago

I found this while trying to use the kqueue API on macOS, but here is a minimal example that shows the same thing, I think, without needing the include.

There seems to a weird situation in C++ where you have to write struct kevent instead of just kevent, in order to declare a variable, because the C library has a struct and function with the same name.

minimal.ccm

module;
// #include <sys/event.h>
struct kevent { };      // <-- something like this is in that header on macOS
void kevent(int x);     // <--
export module my_mod;
struct kevent evt;

And in my shell:

/Dev/llvm-project/build/bin/clang++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk -std=c++2b --precompile minimal.ccm -o minimal.pcm
minimal.ccm:6:8: error: declaration of 'kevent' in module my_mod follows declaration in the global module
    6 | struct kevent evt;
      |        ^
minimal.ccm:3:8: note: previous declaration is here
    3 | struct kevent { };
      |        ^
1 error generated.

This seems like a workaround...

module;
#include <sys/event.h>
using Renamed = struct kevent;
export module my_mod;
Renamed my_event; 
llvmbot commented 1 year ago

@llvm/issue-subscribers-clang-modules

Author: None (rnikander)

I found this while trying to use the `kqueue` API on macOS, but here is a minimal example that shows the same thing, I think, without needing the include. There seems to a weird situation in C++ where you have to write `struct kevent` instead of just `kevent`, in order to declare a variable, because the C library has a struct and function with the same name. `minimal.ccm` ``` module; // #include <sys/event.h> struct kevent { }; // <-- something like this is in that header on macOS void kevent(int x); // <-- export module my_mod; struct kevent evt; ``` And in my shell: ```console /Dev/llvm-project/build/bin/clang++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.0.sdk -std=c++2b --precompile minimal.ccm -o minimal.pcm minimal.ccm:6:8: error: declaration of 'kevent' in module my_mod follows declaration in the global module 6 | struct kevent evt; | ^ minimal.ccm:3:8: note: previous declaration is here 3 | struct kevent { }; | ^ 1 error generated. ``` This seems like a workaround... ```c++ module; #include <sys/event.h> using Renamed = struct kevent; export module my_mod; Renamed my_event; ```
redmms commented 3 months ago

It's connected with the fact that everything is written to a global module because of ABI and is unlikely to be solved in the nearest future, am I right or not?

ChuanqiXu9 commented 3 months ago

It's connected with the fact that everything is written to a global module because of ABI and is unlikely to be solved in the nearest future, am I right or not?

Yeah it looks true.

ChuanqiXu9 commented 3 months ago

I am also slightly surprised since it looks like the compiler think struct kevent evt; is a declaration... I need to check it.