microsoft / cppwinrt

C++/WinRT
MIT License
1.64k stars 236 forks source link

Weird compiler behaviour with C++/WinRT and modules #1328

Closed yottaawesome closed 1 year ago

yottaawesome commented 1 year ago

Version

v2.0.220110.5

Summary

Firstly, apologies for this one, as it's a bit of an unusual case that I discovered when I was using C++/WinRT in modules at work. I'm aware that C++/WinRT doesn't support modules yet, but this is a bit different, and I suspect the problem is with MSVC rather than C++/WinRT.

Consider the sample code. It's an executable with a simple module that exports a class that has a C++/WinRT type as a private member and also has a user-provided empty default constructor defined in the class. This requires the /std:c++latest compiler setting (you can find a download link of a vcxproj further below if necessary).

When I attempt to compile this code in Visual Studio 17.6.4, it fails with error C2676: binary '==': 'const winrt::guid' does not define this operator or a conversion to a type acceptable to the predefined operator. However, if I move the user-supplied constructor to be defined out of class, the error goes away and the code compiles fine.

I strongly suspect this is an MSVC bug -- where the constructor is defined should not matter. Is this your impression as well?

I have reported it to Microsoft (you can download the repro project from there), but they closed it as "not a bug" with the explanation that a C++/WinRT template must be exported from the module. This explanation doesn't make sense given that I can get the code to compile fine by simply messing with the constructors with no template export required. If it was due to a template export, then I expect the sample to fail to compile regardless of where the constructor is defined.

Anyway, I wanted to get some confirmation that I'm not missing something or going mad.

Thanks, Vasilios

Reproducible example

// main.cpp
import somemodule;

int main()
{
    SomeNamespace::SomeClass obj;
    return 0;
}

// somemodule.ixx
module;

#include <winrt/windows.foundation.h>
#include <winrt/windows.foundation.collections.h>
#include <winrt/windows.data.json.h>

export module somemodule;

export namespace SomeNamespace
{
    class SomeClass
    {
        public:
            SomeClass() {} // Comment this out to fix the issue
            //SomeClass(); // Uncomment this to fix the issue

        private:
            winrt::Windows::Data::Json::JsonObject m_root;
    };
    //SomeClass::SomeClass() {} // Uncomment this to fix the issue
}

Expected behavior

Compilation should succeed or fail regardless of where the class' user-supplied default constructor is defined when using C++/WinRT in the sample code.

Actual behavior

Where the class' user-supplied default constructor is defined affects whether compilation succeeds or fails when using C++/WinRT in the sample code.

Additional comments

No response

kennykerr commented 1 year ago

This would be a question for the Visual C++ team. I suggest you bring this up here:

https://developercommunity.visualstudio.com/cpp

sylveon commented 1 year ago

This is a pretty clear cut compiler bug - nothing cppwinrt can directly do to fix. It would be ideal if you could do a minimum repro without cppwinrt to submit to DevCom.

yottaawesome commented 1 year ago

Yeah, I did report it with a repro (though using C++/WinRT), however, the MSVC team closed it as "not a bug" and informed me it was "by design". Their response didn't address why it compiles fine when fiddling with the constructor and indicated to me that they hadn't fully read what I had written. I did point this out to them, but they didn't respond, and I suspect they simply won't look at it again. At this point, even if they were to acknowledge it as a bug, I'm not sure if they'd even fix it or just dump it into the ever growing "Under consideration" pile of issues.

Anyway, I'm satisfied that it's a compiler bug and there's nothing more to do here, so I'll close this issue.