================
@@ -1216,10 +1308,225 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
             ->getDeductionCandidateKind() == DeductionCandidate::Aggregate)
       continue;
 
-    BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc);
+    BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc,
+                                    DeducingTemplate, DerivedClassMapperType);
   }
 }
 
+void DeclareImplicitDeductionGuidesFromInheritedConstructors(
+    Sema &SemaRef, TemplateDecl *Template, ClassTemplateDecl *Pattern,
+    TypeSourceInfo *BaseTSI, unsigned BaseIdx) {
+  auto &Context = SemaRef.Context;
+  DeclContext *DC = Template->getDeclContext();
+  const auto *BaseTST = 
BaseTSI->getType()->getAs<TemplateSpecializationType>();
+  if (!BaseTST)
+    return;
+  SourceLocation BaseLoc = BaseTSI->getTypeLoc().getBeginLoc();
+
+  TemplateDecl *BaseTD = BaseTST->getTemplateName().getAsTemplateDecl();
+  if (!BaseTD)
+    return;
+
+  // Subsitute any parameters with default arguments not present in the base,
+  // since partial specializations cannot have default parameters
----------------
antangelo wrote:

Consider this example:

```c++
template<class T>
struct Base {
    Base(T t);
};

template<class InBase = int, class NotInBase = int>
struct A : public Base<InBase> {
    using Base<InBase>::Base;
};

A a(10);
```
(accepted by gcc: https://godbolt.org/z/jbj1WMq9d)

To my understanding of the standard, we should generate:
```c++
template<class InBase = int, class NotInBase = int>
using Alias = Base<InBase>;

template<typename T> class CC;
template<typename InBase, typename NotInBase>
class CC<Base<InBase>> {
    typedef A<InBase, NotInBase> type;
};
```
along with the transformed alias deduction guides. With these in place, that 
deduction will fail, because it is not possible to instantiate the partial 
specialization of `CC<R>` for the deduction guide return type `R` (which is 
`Base<InBase>` in practice).

The reason this substitution fails is because `NotInBase` cannot be determined 
from `Base<InBase>`. Since partial specializations cannot have default 
arguments, the fact that `NotInBase` is defaulted in the derived class is not 
respected.

The solution I came up with for this problem is to rewrite the template 
parameters to substitute in these template arguments which have defaults in the 
derived class, but do not appear in the base. Then, the partial specialization 
member typedef can refer to them directly. In practice, these arguments cannot 
be deduced to anything else anyway.

This issue does not exist for defaulted parameters that do appear in the base-- 
those will substitute fine into the partial specialization. I also opted not to 
bail in the case where there is a template parameter with no default that does 
not appear in the base; the template is not deducible in this case, but I opt 
to generate a deduction guide anyway so we can emit a diagnostic.

The TPL does indeed still contain the default arguments, but clang's 
implementation as it is will ignore them. I agree that we probably shouldn't 
rely on this, though.

https://github.com/llvm/llvm-project/pull/98788
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to