https://github.com/zyn0217 created 
https://github.com/llvm/llvm-project/pull/102922

`getTemplateInstantiationArgs()` takes two parameters `ND` and `DC` to 
determine the starting point of a traversal. Previously, `DC` would be ignored 
in the presence of `ND`, and the next declaration context would almost always 
be the semantic context of `DC` if `Innermost` is specified.

Actually, we could harness `DC` to describe where we want to go after placing 
an `Innermost` template argument list, because `DC` was never used if `ND` is 
present, but anyhow we still have passed in `ND` with the semantic declaration 
context at the caller sides.

This way, we could implement machinery to collect the complete template 
arguments for constraint checking, without having to instantiate the function 
declaration first, which is in preparation for CWG 2369.

>From 401c6a9f7d740db7fb530386d0753d434033e133 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7...@gmail.com>
Date: Mon, 12 Aug 2024 23:32:34 +0800
Subject: [PATCH] [Clang][NFCI] Refactor getTemplateInstantiationArgs()

This is in preparation of implementing CWG 2369.
---
 clang/include/clang/Sema/Sema.h            | 12 +++++++++---
 clang/lib/Sema/SemaConcept.cpp             |  2 +-
 clang/lib/Sema/SemaTemplate.cpp            |  2 +-
 clang/lib/Sema/SemaTemplateInstantiate.cpp | 19 +++++++++----------
 4 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2ec6367eccea01..352b26b0739ffb 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13033,11 +13033,14 @@ class Sema final : public SemaBase {
   /// instantiation arguments.
   ///
   /// \param DC In the event we don't HAVE a declaration yet, we instead 
provide
-  ///  the decl context where it will be created.  In this case, the 
`Innermost`
-  ///  should likely be provided.  If ND is non-null, this is ignored.
+  ///  the decl context where it will be created.  In this case, the \p
+  ///  Innermost should likely be provided.  If \p ND is non-null and \p
+  ///  Innermost is NULL, this is ignored.
   ///
   /// \param Innermost if non-NULL, specifies a template argument list for the
-  /// template declaration passed as ND.
+  /// template declaration passed as \p ND. The next declaration context would
+  /// be switched to \p DC if present; otherwise, it would be the semantic
+  /// declaration context of \p ND.
   ///
   /// \param RelativeToPrimary true if we should get the template
   /// arguments relative to the primary template, even when we're
@@ -13053,6 +13056,9 @@ class Sema final : public SemaBase {
   /// ForConstraintInstantiation indicates we should continue looking when
   /// encountering a lambda generic call operator, and continue looking for
   /// arguments on an enclosing class template.
+  ///
+  /// \param SkipForSpecialization when specified, any template specializations
+  /// in a traversal would be ignored.
   MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
       const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
       std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index d4c9d044985e34..929555e94dc35d 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -1482,7 +1482,7 @@ substituteParameterMappings(Sema &S, NormalizedConstraint 
&N,
 static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
                                         const ConceptSpecializationExpr *CSE) {
   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
-      CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),
+      CSE->getNamedConcept(), CSE->getNamedConcept()->getDeclContext(),
       /*Final=*/true, CSE->getTemplateArguments(),
       /*RelativeToPrimary=*/true,
       /*Pattern=*/nullptr,
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 1346a4a3f0012a..e6191c8c1397bd 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5582,7 +5582,7 @@ bool Sema::CheckTemplateArgumentList(
     CXXThisScopeRAII(*this, RD, ThisQuals, RD != nullptr);
 
     MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
-        Template, NewContext, /*Final=*/true, SugaredConverted,
+        Template, Template->getDeclContext(), /*Final=*/true, SugaredConverted,
         /*RelativeToPrimary=*/true,
         /*Pattern=*/nullptr,
         /*ForConceptInstantiation=*/true);
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index de470739ab78e7..1a1c7dcdb73d0d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -489,9 +489,10 @@ MultiLevelTemplateArgumentList 
Sema::getTemplateInstantiationArgs(
     //
     // where parameter C has a depth of 1 but the substituting argument `int`
     // has a depth of 0.
-    if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl))
-      HandleDefaultTempArgIntoTempTempParam(TTP, Result);
-    CurDecl = Response::UseNextDecl(CurDecl).NextDecl;
+    bool ShouldChangeDecl = !isa<TemplateTemplateParmDecl>(CurDecl);
+    if (ShouldChangeDecl)
+      CurDecl = DC ? Decl::castFromDeclContext(DC)
+                   : Response::UseNextDecl(CurDecl).NextDecl;
   }
 
   while (!CurDecl->isFileContextDecl()) {
@@ -3242,15 +3243,13 @@ bool Sema::SubstDefaultArgument(
           /*ForDefinition*/ false);
       if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
         return true;
-      const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
-      if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) {
-        TemplateArgumentList *CurrentTemplateArgumentList =
-            TemplateArgumentList::CreateCopy(getASTContext(),
-                                             TemplateArgs.getInnermost());
+      // FIXME: Investigate if we shall validate every FunctionTemplateDecl
+      // along the getInstantiatedFromMemberTemplate() chain.
+      if (auto *PrimaryTemplate = FD->getPrimaryTemplate();
+          PrimaryTemplate && PrimaryTemplate->isOutOfLine())
         NewTemplateArgs = getTemplateInstantiationArgs(
             FD, FD->getDeclContext(), /*Final=*/false,
-            CurrentTemplateArgumentList->asArray(), 
/*RelativeToPrimary=*/true);
-      }
+            TemplateArgs.getInnermost(), /*RelativeToPrimary=*/true);
     }
 
     runWithSufficientStackSpace(Loc, [&] {

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to