[lld] [flang] [clang] [clang-tools-extra] [libc] [libcxx] [llvm] [lldb] [compiler-rt] [concepts] Set up an instantiation scope for constraint expression comparison (PR #79698)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 30 01:23:46 PST 2024


https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/79698

>From 39f64e6fa02392415f0e2776166d4451346e7e81 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Sun, 28 Jan 2024 01:17:32 +0800
Subject: [PATCH] [concepts] Set up an instantiation scope for constraint
 expression comparison

This is a follow-up for the comparison of constraints on out-of-line
function template definitions. We require the instantiation of a
ParmVarDecl while transforming the expression if that Decl gets
referenced by a DeclRefExpr. However, we're not actually performing
the class or function template instantiation at the time of such
comparison. Therefore, let's map these parameters to themselves so
that they get preserved after the substitution.

Fixes https://github.com/llvm/llvm-project/issues/74447.
---
 clang/docs/ReleaseNotes.rst                   |  3 +++
 clang/lib/Sema/SemaConcept.cpp                |  9 ++++++++
 .../SemaTemplate/concepts-out-of-line-def.cpp | 22 +++++++++++++++++++
 3 files changed, 34 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index aa06e2b60ce91..3c5856788e717 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -128,6 +128,9 @@ Bug Fixes to C++ Support
 - Fixed a bug where variables referenced by requires-clauses inside
   nested generic lambdas were not properly injected into the constraint scope.
   (`#73418 <https://github.com/llvm/llvm-project/issues/73418>`_)
+- Fixed a crash where substituting into a requires-expression that refers to function
+  parameters during the equivalence determination of two constraint expressions.
+  (`#74447 <https://github.com/llvm/llvm-project/issues/74447>`)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 88fc846c89e42..19a460f411757 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -797,6 +797,15 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
   if (Inst.isInvalid())
     return nullptr;
 
+  // Set up a dummy 'instantiation' scope in the case of reference to function
+  // parameters that the surrounding function hasn't been instantiated yet. Note
+  // this may happen while we're comparing two templates' constraint
+  // equivalence.
+  LocalInstantiationScope ScopeForParameters(S);
+  if (auto *FD = llvm::dyn_cast<FunctionDecl>(DeclInfo.getDecl()))
+    for (auto *PVD : FD->parameters())
+      ScopeForParameters.InstantiatedLocal(PVD, PVD);
+
   std::optional<Sema::CXXThisScopeRAII> ThisScope;
   if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext()))
     ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index c4e8e6f720c49..7323ad8d9ef2c 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -536,3 +536,25 @@ void X<T>::bar(decltype(requires { requires something_interesting<T>; })) {}
 template <class T>
 void X<T>::bar(decltype(requires { requires is_not_same_v<T, int>; })) {}
 } // namespace GH74314
+
+namespace GH74447 {
+template <typename T> struct S {
+  template <typename... U, int V>
+  void test(T target, U... value)
+    requires requires {
+      target;
+      sizeof...(value) == 1;
+      V == 2;
+    };
+};
+
+template <typename T>
+template <typename... U, int V>
+void S<T>::test(T target, U... value)
+  requires requires {
+    target;
+    sizeof...(value) == 1;
+    V == 2;
+  }
+{}
+} // namespace GH74447



More information about the cfe-commits mailing list