[clang] [clang] Redeclare function templates instances per primary template (PR #110387)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 29 22:54:02 PDT 2024


================
@@ -3949,28 +3949,15 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
       TemplateArgumentList::CreateCopy(Context, CanonicalBuilder);
   Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList);
 
+  FunctionTemplate = FunctionTemplate->getMostRecentDecl();
+
----------------
zyn0217 wrote:

So this is where the magic happens:

To help us get a bigger picture of the patch, let's take an example from your test case,

```cpp
namespace t1 {
  template<int N> struct A {
    template<class C> friend auto cica(const A<N-1>&, C) {
      return N;
    }
  };

  template<> struct A<0> {
    template<class C> friend auto cica(const A<0>&, C);
  };

  void test() {

    (void)A<1>{};
    cica(A<0>{}, 0);
  }
} // namespace t1
```

Previously, we would crash in `BuildExpressionFromIntegralTemplateArgument()` because we're trying to substitute the NTTP `N` in the return expression with a template argument `<int>`. That is due to an incorrect MLTAL provided by `getTemplateInstantiationArgs()`, when instantiating the function definition of `cica` for the purpose of return type deduction.

The MLTAL is missing the outer `N` because the collected template arguments are from a friend function whose parent is an explicit template specialization, `template <> struct A<0>`. And we don't do anything else for an explicit specialization, so we're left with only one level of template arguments, which is just `<int>`.

The approach here did the trick that, instead of instantiating the function from the explicit specialization, it finds the declaration that is created by the last implicit instantiation of the corresponding explicit specialization, namely the specialization for `A<N>`.

I presume changes elsewhere are tweaking to adapt the new behavior here, right?

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


More information about the cfe-commits mailing list