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

Matheus Izvekov via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 30 14:51:21 PDT 2024


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

> 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>.

So far correct, yes.

> 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>.

Well not exactly. The problem here is that in this call:
```C++
cica(A<0>{}, 0);
```
Due to ADL, we find the declaration of `cica` in the explicit specialization `A<0>`, instead of the more recent one created in the explicit instantiation `A<1>`.

We end up crashing because starting from the instantiation of the second declaration of cica, we find the pattern for the first declaration, which has incorrect template context as you remarked above.

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

For the most part yes, but the more interesting changes in `SemaTemplateInstantiateDecl.cpp` are dealing with a more complicated case. What happens in:

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

Ie: when we instantiate `A<1>`, we have already implicitly instantiated the cica declaration for `A<0>`, and on the second call to `cica`, that is the implicit instantiation that we are going to find, and again we are going to find the wrong pattern for it and crash.

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


More information about the cfe-commits mailing list