Author: Chuanqi Xu Date: 2023-06-21T17:00:56+08:00 New Revision: 72ac90715876e2963af899cbb883bad1e07b67bd
URL: https://github.com/llvm/llvm-project/commit/72ac90715876e2963af899cbb883bad1e07b67bd DIFF: https://github.com/llvm/llvm-project/commit/72ac90715876e2963af899cbb883bad1e07b67bd.diff LOG: [C++20] [Modules] Use the canonical decl when getting associated constraints 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. Added: clang/test/Modules/pr62943.cppm Modified: clang/lib/Sema/SemaConcept.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 25884838d632c..f562e85009282 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1155,6 +1155,11 @@ void Sema::DiagnoseUnsatisfiedConstraint( const NormalizedConstraint * Sema::getNormalizedAssociatedConstraints( NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) { + // In case the ConstrainedDecl comes from modules, it is necessary to use + // the canonical decl to avoid diff erent atomic constraints with the 'same' + // declarations. + ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl()); + auto CacheEntry = NormalizationCache.find(ConstrainedDecl); if (CacheEntry == NormalizationCache.end()) { auto Normalized = diff --git a/clang/test/Modules/pr62943.cppm b/clang/test/Modules/pr62943.cppm new file mode 100644 index 0000000000000..27868b78220f5 --- /dev/null +++ b/clang/test/Modules/pr62943.cppm @@ -0,0 +1,99 @@ +// 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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits