[C++20] [Modules] Trying to compare the trailing require clause from the primary...
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>
Tue, 28 Feb 2023 15:14:51 +0000 (23:14 +0800)
committerChuanqi Xu <yedeng.yd@linux.alibaba.com>
Tue, 28 Feb 2023 15:41:48 +0000 (23:41 +0800)
commit9e50578ba43c49ee13ac3bb7d4868565824f9b29
tree5eec39b3545e2c22d9fcb095f23c9f5362c83c3e
parentedeb0f49794c63d22a4c7fd6d2672c8544038dca
[C++20] [Modules] Trying to compare the trailing require clause from the primary template function

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.

Reviewed By: erichkeane

Differential Revision: https://reviews.llvm.org/D144626
clang/lib/AST/ASTContext.cpp
clang/test/Modules/pr60890.cppm [new file with mode: 0644]