Close https://github.com/llvm/llvm-project/issues/62943. The root cause for the issue is that we think the associated constraints from the 'same' declaration in different module units are different incorrectly. Since the constraints doesn't know anything about decls and modules, we should fix the problem by getting the associated constraints from the exactly the same declarations from different modules.
100 lines
2.2 KiB
C++
100 lines
2.2 KiB
C++
// RUN: rm -rf %t
|
|
// RUN: mkdir -p %t
|
|
// RUN: split-file %s %t
|
|
//
|
|
// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
|
|
// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-module-interface -o %t/b.pcm
|
|
// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-module-interface \
|
|
// RUN: -fprebuilt-module-path=%t -o %t/c.pcm
|
|
// RUN: %clang_cc1 -std=c++20 %t/use.cpp -fprebuilt-module-path=%t \
|
|
// RUN: -fsyntax-only -verify
|
|
|
|
//--- foo.h
|
|
#ifndef FOO_H
|
|
#define FOO_H
|
|
|
|
template<class _Tp>
|
|
concept __has_member_value_type = requires { typename _Tp::value_type; };
|
|
|
|
template<class _Tp>
|
|
concept __has_member_element_type = requires { typename _Tp::element_type; };
|
|
|
|
template <class _Tp>
|
|
inline constexpr bool is_object_v = __is_object(_Tp);
|
|
|
|
template<class> struct __cond_value_type {};
|
|
|
|
template<class _Tp>
|
|
requires is_object_v<_Tp>
|
|
struct __cond_value_type<_Tp> { using value_type = bool; };
|
|
|
|
template<class> struct indirectly_readable_traits {
|
|
static constexpr int value = false;
|
|
};
|
|
#endif
|
|
|
|
//--- foo.member_value_type.h
|
|
#include "foo.h"
|
|
template<__has_member_value_type _Tp>
|
|
struct indirectly_readable_traits<_Tp> : __cond_value_type<typename _Tp::value_type> {
|
|
static constexpr int value = false;
|
|
};
|
|
|
|
//--- foo.memeber_element_type.h
|
|
#include "foo.h"
|
|
template<__has_member_element_type _Tp>
|
|
struct indirectly_readable_traits<_Tp> : __cond_value_type<typename _Tp::element_type> {
|
|
static constexpr int value = false;
|
|
};
|
|
|
|
template<__has_member_value_type _Tp>
|
|
requires __has_member_element_type<_Tp>
|
|
struct indirectly_readable_traits<_Tp> {
|
|
static constexpr int value = true;
|
|
};
|
|
|
|
//--- foo.a.h
|
|
#include "foo.h"
|
|
#include "foo.member_value_type.h"
|
|
#include "foo.memeber_element_type.h"
|
|
template <typename T>
|
|
using AType = indirectly_readable_traits<T>;
|
|
|
|
//--- a.cppm
|
|
module;
|
|
#include "foo.a.h"
|
|
export module a;
|
|
|
|
export using ::AType;
|
|
|
|
//--- b.cppm
|
|
module;
|
|
#include "foo.h"
|
|
#include "foo.memeber_element_type.h"
|
|
export module b;
|
|
|
|
//--- c.cppm
|
|
export module c;
|
|
|
|
export import a;
|
|
export import b;
|
|
|
|
//--- use.cpp
|
|
// expected-no-diagnostics
|
|
import c;
|
|
|
|
template <typename T>
|
|
class U {
|
|
public:
|
|
using value_type = T;
|
|
using element_type = T;
|
|
};
|
|
|
|
template <typename T>
|
|
class V {
|
|
public:
|
|
};
|
|
|
|
static_assert(!AType<V<int*>>::value);
|
|
static_assert(AType<U<int**>>::value);
|