[clang] 72ac907 - [C++20] [Modules] Use the canonical decl when getting associated constraints

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 21 02:01:41 PDT 2023


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);


        


More information about the cfe-commits mailing list