[clang] [Clang][Concepts] Fix a constraint comparison regression for out-of-line ClassTemplateDecls (PR #102587)

via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 9 02:02:16 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Younan Zhang (zyn0217)

<details>
<summary>Changes</summary>

Since 98191d7c, we have been comparing constraints on out-of-line class template declarations by recovering surrounding template arguments from the DeclContext if neither the new declaration nor its template arguments are available.

However, there is a problem in that the out-of-line class template is introduced from its lexical context rather than the semantic context.
    
This results in a discrepancy: out-of-line constraint expressions are not substituted while their corresponding inline expressions are transformed, hence the bogus error.

This patch fixes that by introspecting these template arguments from the semantic context, regardless of it being a friend declaration - we have handled friends in `getTemplateInstantiationArgs()`.

Fixes #<!-- -->102320

---
Full diff: https://github.com/llvm/llvm-project/pull/102587.diff


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+2) 
- (modified) clang/lib/Sema/SemaConcept.cpp (+7-4) 
- (modified) clang/test/SemaTemplate/concepts-out-of-line-def.cpp (+21) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0f1a4c1851911d..cb92ba25d1633f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -186,6 +186,8 @@ Bug Fixes to C++ Support
   substitutions in concepts, so it doesn't incorrectly complain of missing
   module imports in those situations. (#GH60336)
 - Fix init-capture packs having a size of one before being instantiated. (#GH63677)
+- Clang now properly compares constraints on an out of line class template
+  declaration definition. (#GH102320)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index d4c9d044985e34..2871f78868aea7 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -948,7 +948,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
     Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
     const Expr *ConstrExpr) {
   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
-      DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
+      DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
       /*Innermost=*/std::nullopt,
       /*RelativeToPrimary=*/true,
       /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
@@ -971,9 +971,12 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
   // this may happen while we're comparing two templates' constraint
   // equivalence.
   LocalInstantiationScope ScopeForParameters(S);
-  if (auto *FD = DeclInfo.getDecl()->getAsFunction())
-    for (auto *PVD : FD->parameters())
-      ScopeForParameters.InstantiatedLocal(PVD, PVD);
+  if (const NamedDecl *D = DeclInfo.getDecl()) {
+    const FunctionDecl *FD = D->getAsFunction();
+    if (FD)
+      for (auto *PVD : FD->parameters())
+        ScopeForParameters.InstantiatedLocal(PVD, PVD);
+  }
 
   std::optional<Sema::CXXThisScopeRAII> ThisScope;
 
diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index 0142efcdc3ee86..5ea1ff79e572bc 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -599,3 +599,24 @@ template <class DerT>
 unsigned long DerivedCollection<DerTs...>::index() {}
 
 } // namespace GH72557
+
+namespace GH102320 {
+
+template <class, class>
+concept Constrained = true;
+
+template <class T> class C {
+  template <Constrained<T>> class D;
+  template <class U>
+    requires Constrained<T, U>
+  class E;
+};
+
+template <class T> template <Constrained<T>> class C<T>::D {};
+
+template <class T>
+template <class U>
+  requires Constrained<T, U>
+class C<T>::E {};
+
+} // namespace GH102320

``````````

</details>


https://github.com/llvm/llvm-project/pull/102587


More information about the cfe-commits mailing list