[clang] [clang] check deduction consistency when partial ordering function templates (PR #100692)

via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 23 06:34:15 PDT 2024


================
@@ -5395,11 +5520,100 @@ static QualType GetImplicitObjectParameterType(ASTContext &Context,
   return Context.getLValueReferenceType(RawType);
 }
 
+static TemplateDeductionResult CheckDeductionConsistency(
+    Sema &S, FunctionTemplateDecl *FTD, int ArgIdx, QualType P, QualType A,
+    ArrayRef<TemplateArgument> DeducedArgs, bool CheckConsistency) {
+  MultiLevelTemplateArgumentList MLTAL(FTD, DeducedArgs,
+                                       /*Final=*/true);
+  if (ArgIdx != -1)
+    if (auto *MD = dyn_cast<CXXMethodDecl>(FTD->getTemplatedDecl());
+        MD && MD->isImplicitObjectMemberFunction())
+      ArgIdx -= 1;
+  Sema::ArgumentPackSubstitutionIndexRAII PackIndex(
+      S, ArgIdx != -1 ? ::getPackIndexForParam(S, FTD, MLTAL, ArgIdx) : -1);
+  bool IsIncompleteSubstitution = false;
+  QualType InstP = S.SubstType(P, MLTAL, FTD->getLocation(), FTD->getDeclName(),
+                               &IsIncompleteSubstitution);
+  if (InstP.isNull())
+    return TemplateDeductionResult::SubstitutionFailure;
+  if (!CheckConsistency)
+    return TemplateDeductionResult::Success;
+  if (IsIncompleteSubstitution)
+    return TemplateDeductionResult::Incomplete;
+
+  // [temp.deduct.call]/4 - Check we produced a consistent deduction.
+  // This handles just the cases that can appear when partial ordering.
+  if (auto *PA = dyn_cast<PackExpansionType>(A);
+      PA && !isa<PackExpansionType>(InstP))
+    A = PA->getPattern();
+  if (!S.Context.hasSameType(
+          S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType()),
+          S.Context.getUnqualifiedArrayType(A.getNonReferenceType())))
+    return TemplateDeductionResult::NonDeducedMismatch;
+  return TemplateDeductionResult::Success;
+}
+
+template <class T>
+static TemplateDeductionResult FinishTemplateArgumentDeduction(
+    Sema &S, FunctionTemplateDecl *FTD,
+    SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+    TemplateDeductionInfo &Info, T &&CheckDeductionConsistency) {
+  // Unevaluated SFINAE context.
+  EnterExpressionEvaluationContext Unevaluated(
+      S, Sema::ExpressionEvaluationContext::Unevaluated);
+  Sema::SFINAETrap Trap(S);
+
+  Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(FTD));
+
+  // C++ [temp.deduct.type]p2:
+  //   [...] or if any template argument remains neither deduced nor
+  //   explicitly specified, template argument deduction fails.
+  bool IsIncomplete = false;
+  SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder;
+  if (auto Result = ConvertDeducedTemplateArguments(
+          S, FTD, /*IsDeduced=*/true, Deduced, Info, SugaredBuilder,
+          CanonicalBuilder, /*CurrentInstantiationScope=*/nullptr,
+          /*NumAlreadyConverted=*/0, &IsIncomplete);
+      Result != TemplateDeductionResult::Success)
+    return Result;
+
+  // Form the template argument list from the deduced template arguments.
+  TemplateArgumentList *SugaredDeducedArgumentList =
+      TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder);
+  TemplateArgumentList *CanonicalDeducedArgumentList =
+      TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder);
+
+  Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList);
+
+  // Substitute the deduced template arguments into the argument
+  // and verify that the instantiated argument is both valid
+  // and equivalent to the parameter.
+  LocalInstantiationScope InstScope(S);
+
+  if (auto TDR = CheckDeductionConsistency(S, FTD, SugaredBuilder);
+      TDR != TemplateDeductionResult::Success)
+    return TDR;
+
+  // C++20 [temp.deduct]p5 - Only check constraints when all parameters have
+  // been deduced.
+  if (!IsIncomplete) {
----------------
cor3ntin wrote:

```
if (IsIncomplete)
  return TemplateDeductionResult::Success;
```

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


More information about the cfe-commits mailing list