In many (possibly most) cases the compilation of a C++20 module source will produce two artefacts:
- a BMI (binary module interface) and
- a regular compiled object file (implementing any required functionality for (1).
At present, we carry out two invocations of the front end to accomplish this, first we build the BMI and then we consume that in a second invocation to generate the object.
It would be more efficient if we were able to produce both from a single invocation, and at some future time that would also allow for an optimisation of the BMI content (currently it needs to contain everything necessary to produce the object, where only a sub-set of that is required to carry the module interfaces).
In support of this I have drafted some patches to implement the first stages of this but during discussion @ChuanqiXu has pointed out something that is to me highly surprising and I’d like folks to help understand it.
clang++ -std=c++20 foo.cpp -c -o foo.o
clang++ -std=c++20 -xc++-module foo.cpp --precompile -o foo.pcm
clang++ -std=c++20 foo.pcm -c -o foo.o
I would expect the two objects to be identical (since the source is treated the same way by the FE; the module tag is only needed in the driver), however @ChuanqiXu has observed that there are differences in the handling of ODR checking.
- Is it an original design intent that this difference is seen? (if so, some pointer to the design would be helpful)
- Is it “design creep”? - i.e somehow patches have added this constraint but unintended
- Is it a bug?
A sketch of how my intended change works is that it inserts a multiplex AST consumer that feeds the AST (as existing) to the backend and a deferred PCH writer.
It is my expectation that the AST from the Front End is complete and has relevant errors already raised. It would be very surprising to me that the act of serialising and then deserialising that AST would produce additional error checks/diagnostics (other than failures in the serialization process, of course).
Any help here will be most welcome.