This is an archive of the discontinued LLVM Phabricator instance.

[C++20] [Modules] Trying to compare the trailing require clause of the primary template when performing ODR checking
ClosedPublic

Authored by ChuanqiXu on Feb 23 2023, 1:52 AM.

Details

Summary

Close https://github.com/llvm/llvm-project/issues/60890.

For the following example:

export module a;
 
export template<typename T>
struct a {
	friend void aa(a) requires(true) {
	}
};
export module b;

import a;

struct b {
	a<int> m;
};
export module c;

import a;

struct c {
	void f() const {
		aa(a<int>());
	}
};
import a;
import b;
import c;

void d() {
	aa(a<int>());
}

The current clang will reject this incorrectly. The reason is that the require clause will be replaced with the evaluated version (https://github.com/llvm/llvm-project/blob/efae3174f09560353fb0f3d528bcbffe060d5438/clang/lib/Sema/SemaConcept.cpp#L664-L665). In module 'b', the friend function is instantiated but not used so the require clause of the friend function is (true). However, in module 'c', the friend function is used so the require clause is true. So deserializer classify these two function to two different functions instead of one. Then here is the bug report.

The proposed solution is to try to compare the trailing require clause of the primary template when performing ODR checking.

Diff Detail

Event Timeline

ChuanqiXu created this revision.Feb 23 2023, 1:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 23 2023, 1:52 AM
ChuanqiXu requested review of this revision.Feb 23 2023, 1:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 23 2023, 1:52 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
ChuanqiXu edited the summary of this revision. (Show Details)Feb 23 2023, 1:52 AM

I think the problem is more that we are modifying the expression in the AST. I don't think now that we have the 'deferred concepts instantiation' that we should be storing/saving the updated requires clause back to the AST, right? We should be re-evaluating it (with a cache!).

Woops, I just saw my fixme :D I forgot we needed to do that for comparison of constraints. That said I dont think you need to store it, I think we can just pick up the 'original' one from the primary template. I did work at one point to make sure that the get-instantiated-from-template stuff worked correctly for friends like that.

ChuanqiXu updated this revision to Diff 500046.Feb 23 2023, 7:26 PM

Address comments:

  • Don't store the original trailing require clause. Trying to get the trailing require clause of the primary template function when ODR checking instead.
ChuanqiXu retitled this revision from [C++20] [Modules] Provide OriginalTrailingRequiresClause for serializer to perform ODR-Checking correctly to [C++20] [Modules] Trying to compare the trailing require clause of the primary template when performing ODR checking.Feb 23 2023, 7:27 PM
ChuanqiXu edited the summary of this revision. (Show Details)

Yeah, it looks better indeed to not store additional information.

That looks reasonable to me, though I fear all the libcxx failures are going to be related to this, please make sure to check them out!

That looks reasonable to me, though I fear all the libcxx failures are going to be related to this, please make sure to check them out!

I tested locally that the libcxx failures are not related to this patch after I reverted this change.

That looks reasonable to me, though I fear all the libcxx failures are going to be related to this, please make sure to check them out!

I tested locally that the libcxx failures are not related to this patch after I reverted this change.

Maybe you can rebase and push a change to trigger the bots again.

ChuanqiXu updated this revision to Diff 500703.Feb 27 2023, 1:37 AM

Rebase and push again to trigger the bot.

This is another revision (https://reviews.llvm.org/D144707) which shouldn't be related with libcxx's modular build. So the failures should be irrelevant with the revision. @erichkeane @royjacobson Do you think it makes sense to land this revision in this case?

This is another revision (https://reviews.llvm.org/D144707) which shouldn't be related with libcxx's modular build. So the failures should be irrelevant with the revision. @erichkeane @royjacobson Do you think it makes sense to land this revision in this case?

Ah, sorry, I meant to come back to this and let you know... The libcxx modules builds are broken for an unknown reason unrelated to this. Feel free to land this.

This is another revision (https://reviews.llvm.org/D144707) which shouldn't be related with libcxx's modular build. So the failures should be irrelevant with the revision. @erichkeane @royjacobson Do you think it makes sense to land this revision in this case?

Ah, sorry, I meant to come back to this and let you know... The libcxx modules builds are broken for an unknown reason unrelated to this. Feel free to land this.

Thanks~

ChuanqiXu accepted this revision.Feb 28 2023, 7:15 AM
This revision is now accepted and ready to land.Feb 28 2023, 7:15 AM
This revision was landed with ongoing or failed builds.Feb 28 2023, 7:42 AM
This revision was automatically updated to reflect the committed changes.
rsmith added a subscriber: rsmith.Mar 30 2023, 2:53 PM
rsmith added inline comments.
clang/lib/AST/ASTContext.cpp
6704

If this is necessary here, I'd expect it to be necessary in a lot of other places too. (For example, we perform basically the same comparison when doing redeclaration checking.) Which declarations have the wrong requires-clause attached to them? Why would the requires-clause be modified from the one written in the original declaration?

(I could imagine this happening for explicit instantiations, where the requires clause might not be specified at all, but we could address that by looking at the canonical declaration for a trailing requires-clause, rather than looking at the template pattern.)