Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Jul 2025 16:55:36 GMT
From:      Dimitry Andric <dim@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: ffc5ee0f57d5 - main - Merge commit 8ac140f39084 from llvm git (by Younan Zhang):
Message-ID:  <202507211655.56LGta1Z079035@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by dim:

URL: https://cgit.FreeBSD.org/src/commit/?id=ffc5ee0f57d56459df93f4107b9835ae78a546b5

commit ffc5ee0f57d56459df93f4107b9835ae78a546b5
Author:     Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2025-07-21 16:55:23 +0000
Commit:     Dimitry Andric <dim@FreeBSD.org>
CommitDate: 2025-07-21 16:55:23 +0000

    Merge commit 8ac140f39084 from llvm git (by Younan Zhang):
    
      [Clang][NFCI] Cleanup the fix for default function argument substitution (#104911)
    
      (This is one step towards tweaking `getTemplateInstantiationArgs()` as
      discussed in https://github.com/llvm/llvm-project/pull/102922)
    
      We don't always substitute into default arguments while transforming a
      function parameter. In that case, we would preserve the uninstantiated
      expression until after, e.g. building up a CXXDefaultArgExpr and
      instantiate the expression there.
    
      For member function instantiation, this algorithm used to cause a
      problem in that the default argument of an out-of-line member function
      specialization couldn't get properly instantiated. This is because, in
      `getTemplateInstantiationArgs()`, we would give up visiting a function's
      declaration context if the function is a specialization of a member
      template. For example,
    
      ```cpp
      template <class T>
      struct S {
        template <class U>
        void f(T = sizeof(T));
      };
    
      template <> template <class U>
      void S<int>::f(int) {}
      ```
    
      The default argument `sizeof(U)` that lexically appears inside the
      declaration would be copied to the function declaration in the class
      template specialization `S<int>`, as well as to the function's
      out-of-line definition. We use template arguments collected from the
      out-of-line function definition when substituting into the default
      arguments. We would therefore give up the traversal after the function,
      resulting in a single-level template argument of the `f` itself. However
      the default argument here could still reference the template parameters
      of the primary template, hence the error.
    
      In fact, this is similar to constraint checking in some respects: we
      actually want the "whole" template arguments relative to the primary
      template, not those relative to the function definition. So this patch
      adds another flag to indicate `getTemplateInstantiationArgs()` for that.
    
      This patch also consolidates the tests for default arguments and removes
      some unnecessary tests.
    
    This fixes a crash or assertion failure while building tests for the
    devel/hpx port.
    
    PR:             288352
    MFC after:      3 days
---
 .../llvm-project/clang/include/clang/Sema/Sema.h   |  9 ++++++++-
 .../clang/lib/Sema/SemaTemplateInstantiate.cpp     | 23 ++++++++--------------
 .../clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 10 ++++++----
 3 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/contrib/llvm-project/clang/include/clang/Sema/Sema.h b/contrib/llvm-project/clang/include/clang/Sema/Sema.h
index 7bfdaaae45a9..a59a9342341d 100644
--- a/contrib/llvm-project/clang/include/clang/Sema/Sema.h
+++ b/contrib/llvm-project/clang/include/clang/Sema/Sema.h
@@ -13052,12 +13052,19 @@ public:
   /// 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.
+  /// \param ForDefaultArgumentSubstitution indicates we should continue looking
+  /// when encountering a specialized member function template, rather than
+  /// returning immediately.
   MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
       const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
       std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
       bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
       bool ForConstraintInstantiation = false,
-      bool SkipForSpecialization = false);
+      bool SkipForSpecialization = false,
+      bool ForDefaultArgumentSubstitution = false);
 
   /// RAII object to handle the state changes required to synthesize
   /// a function body.
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a09e3be83c45..c2e8ed0c602e 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -269,7 +269,8 @@ HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec,
 Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
                         MultiLevelTemplateArgumentList &Result,
                         const FunctionDecl *Pattern, bool RelativeToPrimary,
-                        bool ForConstraintInstantiation) {
+                        bool ForConstraintInstantiation,
+                        bool ForDefaultArgumentSubstitution) {
   // Add template arguments from a function template specialization.
   if (!RelativeToPrimary &&
       Function->getTemplateSpecializationKindForInstantiation() ==
@@ -299,7 +300,8 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
     // If this function was instantiated from a specialized member that is
     // a function template, we're done.
     assert(Function->getPrimaryTemplate() && "No function template?");
-    if (Function->getPrimaryTemplate()->isMemberSpecialization())
+    if (!ForDefaultArgumentSubstitution &&
+        Function->getPrimaryTemplate()->isMemberSpecialization())
       return Response::Done();
 
     // If this function is a generic lambda specialization, we are done.
@@ -465,7 +467,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
     const NamedDecl *ND, const DeclContext *DC, bool Final,
     std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
     const FunctionDecl *Pattern, bool ForConstraintInstantiation,
-    bool SkipForSpecialization) {
+    bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) {
   assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
   // Accumulate the set of template argument lists in this structure.
   MultiLevelTemplateArgumentList Result;
@@ -507,7 +509,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
                                   SkipForSpecialization);
     } else if (const auto *Function = dyn_cast<FunctionDecl>(CurDecl)) {
       R = HandleFunction(*this, Function, Result, Pattern, RelativeToPrimary,
-                         ForConstraintInstantiation);
+                         ForConstraintInstantiation,
+                         ForDefaultArgumentSubstitution);
     } else if (const auto *Rec = dyn_cast<CXXRecordDecl>(CurDecl)) {
       R = HandleRecordDecl(*this, Rec, Result, Context,
                            ForConstraintInstantiation);
@@ -3231,7 +3234,6 @@ bool Sema::SubstDefaultArgument(
     //   default argument expression appears.
     ContextRAII SavedContext(*this, FD);
     std::unique_ptr<LocalInstantiationScope> LIS;
-    MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;
 
     if (ForCallExpr) {
       // When instantiating a default argument due to use in a call expression,
@@ -3244,19 +3246,10 @@ 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());
-        NewTemplateArgs = getTemplateInstantiationArgs(
-            FD, FD->getDeclContext(), /*Final=*/false,
-            CurrentTemplateArgumentList->asArray(), /*RelativeToPrimary=*/true);
-      }
     }
 
     runWithSufficientStackSpace(Loc, [&] {
-      Result = SubstInitializer(PatternExpr, NewTemplateArgs,
+      Result = SubstInitializer(PatternExpr, TemplateArgs,
                                 /*DirectInit*/ false);
     });
   }
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a12d2eff1d2c..614e6ea12541 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -4659,10 +4659,12 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
   //
   // template<typename T>
   // A<T> Foo(int a = A<T>::FooImpl());
-  MultiLevelTemplateArgumentList TemplateArgs =
-      getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
-                                   /*Final=*/false, /*Innermost=*/std::nullopt,
-                                   /*RelativeToPrimary=*/true);
+  MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
+      FD, FD->getLexicalDeclContext(),
+      /*Final=*/false, /*Innermost=*/std::nullopt,
+      /*RelativeToPrimary=*/true, /*Pattern=*/nullptr,
+      /*ForConstraintInstantiation=*/false, /*SkipForSpecialization=*/false,
+      /*ForDefaultArgumentSubstitution=*/true);
 
   if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true))
     return true;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202507211655.56LGta1Z079035>