mizvekov updated this revision to Diff 464434.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134115/new/

https://reviews.llvm.org/D134115

Files:
  clang/include/clang/AST/ASTImporter.h
  clang/include/clang/AST/Expr.h
  clang/include/clang/Sema/Initialization.h
  clang/include/clang/Sema/Overload.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/Expr.cpp
  clang/lib/Analysis/BodyFarm.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/Sema/SemaCUDA.cpp
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/TreeTransform.h
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTReaderStmt.cpp
  clang/lib/Serialization/ASTWriterDecl.cpp
  clang/lib/Serialization/ASTWriterStmt.cpp

Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -621,7 +621,8 @@
   if ((!E->hasTemplateKWAndArgsInfo()) && (!E->hasQualifier()) &&
       (E->getDecl() == E->getFoundDecl()) &&
       nk == DeclarationName::Identifier &&
-      !E->refersToEnclosingVariableOrCapture() && !E->isNonOdrUse()) {
+      !E->refersToEnclosingVariableOrCapture() && !E->isNonOdrUse() &&
+      !E->getConvertedArgs()) {
     AbbrevToUse = Writer.getDeclRefExprAbbrev();
   }
 
@@ -636,6 +637,10 @@
                              E->getTrailingObjects<TemplateArgumentLoc>());
 
   Record.AddDeclRef(E->getDecl());
+  if (E->ConvertedArgs)
+    Record.AddTemplateArgumentList(E->ConvertedArgs);
+  else
+    Record.push_back(0);
   Record.AddSourceLocation(E->getLocation());
   Record.AddDeclarationNameLoc(E->DNLoc, E->getDecl()->getDeclName());
   Code = serialization::EXPR_DECL_REF;
@@ -911,6 +916,10 @@
   Record.push_back(E->hadMultipleCandidates());
   Record.push_back(E->isNonOdrUse());
   Record.AddSourceLocation(E->getOperatorLoc());
+  if (E->Deduced)
+    Record.AddTemplateArgumentList(E->Deduced);
+  else
+    Record.push_back(0);
 
   if (HasFoundDecl) {
     DeclAccessPair FoundDecl = E->getFoundDecl();
Index: clang/lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -2311,6 +2311,7 @@
   Abv->Add(BitCodeAbbrevOp(0)); // RefersToEnclosingVariableOrCapture
   Abv->Add(BitCodeAbbrevOp(0)); // NonOdrUseReason
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef
+  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConvertedArgs
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
   DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv));
 
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -595,6 +595,7 @@
   E->DeclRefExprBits.HadMultipleCandidates = Record.readInt();
   E->DeclRefExprBits.RefersToEnclosingVariableOrCapture = Record.readInt();
   E->DeclRefExprBits.NonOdrUseReason = Record.readInt();
+
   unsigned NumTemplateArgs = 0;
   if (E->hasTemplateKWAndArgsInfo())
     NumTemplateArgs = Record.readInt();
@@ -612,6 +613,7 @@
         E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
 
   E->D = readDeclAs<ValueDecl>();
+  E->ConvertedArgs = Record.readTemplateArgumentList();
   E->setLocation(readSourceLocation());
   E->DNLoc = Record.readDeclarationNameLoc(E->getDecl()->getDeclName());
 }
@@ -1027,6 +1029,7 @@
   E->MemberExprBits.HadMultipleCandidates = Record.readInt();
   E->MemberExprBits.NonOdrUseReason = Record.readInt();
   E->MemberExprBits.OperatorLoc = Record.readSourceLocation();
+  E->Deduced = Record.readTemplateArgumentList();
 
   if (HasQualifier || HasFoundDecl) {
     DeclAccessPair FoundDecl;
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -8844,6 +8844,15 @@
     TemplArgs.push_back(readTemplateArgument(Canonicalize));
 }
 
+const TemplateArgumentList *
+ASTRecordReader::readTemplateArgumentList(bool Canonicalize) {
+  SmallVector<TemplateArgument, 8> Args;
+  readTemplateArgumentList(Args, Canonicalize);
+  if (Args.size() == 0)
+    return nullptr;
+  return TemplateArgumentList::CreateCopy(getContext(), Args);
+}
+
 /// Read a UnresolvedSet structure.
 void ASTRecordReader::readUnresolvedSet(LazyASTUnresolvedSet &Set) {
   unsigned NumDecls = readInt();
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -563,6 +563,9 @@
                         NamedDecl *FirstQualifierInScope = nullptr,
                         bool AllowInjectedClassName = false);
 
+  Optional<TemplateArgument>
+  TransformTemplateArgument(const TemplateArgument &Arg);
+
   /// Transform the given template argument.
   ///
   /// By default, this operation transforms the type, expression, or
@@ -2496,11 +2499,12 @@
                                 ValueDecl *VD,
                                 const DeclarationNameInfo &NameInfo,
                                 NamedDecl *Found,
-                                TemplateArgumentListInfo *TemplateArgs) {
+                                TemplateArgumentListInfo *TemplateArgs,
+                                const TemplateArgumentList *ConvertedArgs) {
     CXXScopeSpec SS;
     SS.Adopt(QualifierLoc);
     return getSema().BuildDeclarationNameExpr(SS, NameInfo, VD, Found,
-                                              TemplateArgs);
+                                              TemplateArgs, ConvertedArgs);
   }
 
   /// Build a new expression in parentheses.
@@ -4373,6 +4377,76 @@
   llvm_unreachable("overloaded function decl survived to here");
 }
 
+template <typename Derived>
+Optional<TemplateArgument>
+TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
+  switch (auto Kind = Arg.getKind()) {
+  case TemplateArgument::Null:
+    llvm_unreachable("Unexpected TemplateArgument Null");
+  case TemplateArgument::Expression:
+    llvm_unreachable("Unexpected TemplateArgument Expr");
+
+  case TemplateArgument::Pack: {
+    SmallVector<TemplateArgument, 4> Args(Arg.getPackAsArray());
+    for (auto &I : Args) {
+      const auto Arg = getDerived().TransformTemplateArgument(I);
+      if (!Arg)
+        return None;
+      I = *Arg;
+    }
+    return TemplateArgument(
+        TemplateArgumentList::CreateCopy(getSema().Context, Args)->asArray());
+  }
+
+  case TemplateArgument::Integral:
+  case TemplateArgument::NullPtr:
+  case TemplateArgument::Declaration: {
+    QualType T = Arg.getNonTypeTemplateArgumentType();
+    QualType NewT = getDerived().TransformType(T);
+    if (NewT.isNull())
+      return None;
+
+    ValueDecl *D = Arg.getKind() == TemplateArgument::Declaration
+                       ? Arg.getAsDecl()
+                       : nullptr;
+    ValueDecl *NewD = D ? cast_or_null<ValueDecl>(getDerived().TransformDecl(
+                              getDerived().getBaseLocation(), D))
+                        : nullptr;
+    if (D && !NewD)
+      return None;
+    if (NewT == T && D == NewD)
+      return Arg;
+    if (Kind == TemplateArgument::Integral)
+      return TemplateArgument(getSema().Context, Arg.getAsIntegral(), NewT);
+    if (Kind == TemplateArgument::NullPtr)
+      return TemplateArgument(NewT, /*IsNullPtr=*/true);
+    assert(Kind == TemplateArgument::Declaration);
+    return TemplateArgument(NewD, NewT);
+  }
+  case TemplateArgument::Type:
+    if (QualType T = getDerived().TransformType(Arg.getAsType()); !T.isNull())
+      return TemplateArgument(T);
+    return None;
+  case TemplateArgument::Template: {
+    CXXScopeSpec SS;
+    if (TemplateName Template = getDerived().TransformTemplateName(
+            SS, Arg.getAsTemplate(), SourceLocation());
+        !Template.isNull())
+      return TemplateArgument(Template);
+    return None;
+  }
+  case TemplateArgument::TemplateExpansion: {
+    CXXScopeSpec SS;
+    if (TemplateName Template = getDerived().TransformTemplateName(
+            SS, Arg.getAsTemplateOrTemplatePattern(), SourceLocation());
+        !Template.isNull())
+      return TemplateArgument(Template, Arg.getNumTemplateExpansions());
+    return None;
+  }
+  }
+  llvm_unreachable("Unexpected Template Kind");
+}
+
 template<typename Derived>
 void TreeTransform<Derived>::InventTemplateArgumentLoc(
                                          const TemplateArgument &Arg,
@@ -4393,39 +4467,15 @@
 
   case TemplateArgument::Integral:
   case TemplateArgument::NullPtr:
-  case TemplateArgument::Declaration: {
+  case TemplateArgument::Declaration:
     // Transform a resolved template argument straight to a resolved template
     // argument. We get here when substituting into an already-substituted
     // template type argument during concept satisfaction checking.
-    QualType T = Arg.getNonTypeTemplateArgumentType();
-    QualType NewT = getDerived().TransformType(T);
-    if (NewT.isNull())
-      return true;
-
-    ValueDecl *D = Arg.getKind() == TemplateArgument::Declaration
-                       ? Arg.getAsDecl()
-                       : nullptr;
-    ValueDecl *NewD = D ? cast_or_null<ValueDecl>(getDerived().TransformDecl(
-                              getDerived().getBaseLocation(), D))
-                        : nullptr;
-    if (D && !NewD)
-      return true;
-
-    if (NewT == T && D == NewD)
-      Output = Input;
-    else if (Arg.getKind() == TemplateArgument::Integral)
-      Output = TemplateArgumentLoc(
-          TemplateArgument(getSema().Context, Arg.getAsIntegral(), NewT),
-          TemplateArgumentLocInfo());
-    else if (Arg.getKind() == TemplateArgument::NullPtr)
-      Output = TemplateArgumentLoc(TemplateArgument(NewT, /*IsNullPtr=*/true),
-                                   TemplateArgumentLocInfo());
-    else
-      Output = TemplateArgumentLoc(TemplateArgument(NewD, NewT),
-                                   TemplateArgumentLocInfo());
-
-    return false;
-  }
+    if (const auto Out = getDerived().TransformTemplateArgument(Arg)) {
+      Output = TemplateArgumentLoc(*Out, TemplateArgumentLocInfo());
+      return false;
+    }
+    return true;
 
   case TemplateArgument::Type: {
     TypeSourceInfo *DI = Input.getTypeSourceInfo();
@@ -6690,6 +6740,7 @@
             ArgIterator(*this, ConvertedArgs.begin()),
             ArgIterator(*this, ConvertedArgs.end()), NewTemplateArgs))
       return QualType();
+    assert(NewTemplateArgs.size() != 0);
   } else {
     using ArgIterator =
         TemplateArgumentLocContainerIterator<TemplateSpecializationTypeLoc>;
@@ -10581,9 +10632,22 @@
                                                 TransArgs))
       return ExprError();
   }
+  const TemplateArgumentList *NewConvertedArgs = nullptr;
+  if (const TemplateArgumentList *OldConvertedArgs = E->getConvertedArgs()) {
+    assert(OldConvertedArgs->size() != 0);
+    SmallVector<TemplateArgument, 4> NewArgs(OldConvertedArgs->asArray());
+    for (auto I : NewArgs) {
+      const auto Arg = getDerived().TransformTemplateArgument(I);
+      if (!Arg)
+        return ExprError();
+      I = *Arg;
+    }
+    NewConvertedArgs =
+        TemplateArgumentList::CreateCopy(getSema().Context, NewArgs);
+  }
 
-  return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo,
-                                         Found, TemplateArgs);
+  return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo, Found,
+                                         TemplateArgs, NewConvertedArgs);
 }
 
 template<typename Derived>
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3687,7 +3687,8 @@
 /// Gets the type of a function for template-argument-deducton
 /// purposes when it's considered as part of an overload set.
 static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R,
-                                  FunctionDecl *Fn) {
+                                  FunctionDecl *Fn,
+                                  ArrayRef<TemplateArgument> Args) {
   // We may need to deduce the return type of the function now.
   if (S.getLangOpts().CPlusPlus14 && Fn->getReturnType()->isUndeducedType() &&
       S.DeduceReturnType(Fn, R.Expression->getExprLoc(), /*Diagnose*/ false))
@@ -3728,6 +3729,11 @@
   if (R.IsAddressOfOperand)
     TDF |= TDF_IgnoreQualifiers;
 
+  // Gather the explicit template arguments, if any.
+  TemplateArgumentListInfo ExplicitTemplateArgs;
+  if (Ovl->hasExplicitTemplateArgs())
+    Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+
   // C++0x [temp.deduct.call]p6:
   //   When P is a function type, pointer to function type, or pointer
   //   to member function type:
@@ -3737,28 +3743,27 @@
       !ParamType->isMemberFunctionPointerType()) {
     if (Ovl->hasExplicitTemplateArgs()) {
       // But we can still look for an explicit specialization.
-      if (FunctionDecl *ExplicitSpec
-            = S.ResolveSingleFunctionTemplateSpecialization(Ovl))
-        return GetTypeOfFunction(S, R, ExplicitSpec);
+      const TemplateArgumentList *ConvertedArgs;
+      if (FunctionDecl *ExplicitSpec =
+              S.ResolveSingleFunctionTemplateSpecialization(
+                  Ovl, ExplicitTemplateArgs, ConvertedArgs))
+        return GetTypeOfFunction(S, R, ExplicitSpec, ConvertedArgs->asArray());
     }
 
     DeclAccessPair DAP;
     if (FunctionDecl *Viable =
             S.resolveAddressOfSingleOverloadCandidate(Arg, DAP))
-      return GetTypeOfFunction(S, R, Viable);
+      return GetTypeOfFunction(S, R, Viable, None);
 
     return {};
   }
 
-  // Gather the explicit template arguments, if any.
-  TemplateArgumentListInfo ExplicitTemplateArgs;
-  if (Ovl->hasExplicitTemplateArgs())
-    Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
   QualType Match;
   for (UnresolvedSetIterator I = Ovl->decls_begin(),
          E = Ovl->decls_end(); I != E; ++I) {
     NamedDecl *D = (*I)->getUnderlyingDecl();
 
+    const TemplateArgumentList *ConvertedArgs = nullptr;
     if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
       //   - If the argument is an overload set containing one or more
       //     function templates, the parameter is treated as a
@@ -3774,10 +3779,12 @@
         continue;
 
       D = Specialization;
+      ConvertedArgs = Info.takeSugared();
     }
 
     FunctionDecl *Fn = cast<FunctionDecl>(D);
-    QualType ArgType = GetTypeOfFunction(S, R, Fn);
+    QualType ArgType = GetTypeOfFunction(
+        S, R, Fn, ConvertedArgs ? ConvertedArgs->asArray() : None);
     if (ArgType.isNull()) continue;
 
     // Function-to-pointer conversion.
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -4583,14 +4583,15 @@
 /// a given template-id.
 struct PartialSpecMatchResult {
   VarTemplatePartialSpecializationDecl *Partial;
-  TemplateArgumentList *Args;
+  TemplateArgumentList *CanonicalArgs, *SugaredArgs;
 };
 } // end anonymous namespace
 
 DeclResult
 Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
                          SourceLocation TemplateNameLoc,
-                         const TemplateArgumentListInfo &TemplateArgs) {
+                         const TemplateArgumentListInfo &TemplateArgs,
+                         const TemplateArgumentList *&ConvertedArgs) {
   assert(Template && "A variable template id without template?");
 
   // Check that the template argument list is well-formed for this template.
@@ -4608,6 +4609,8 @@
           TemplateArgs, CanonicalConverted))
     return DeclResult();
 
+  ConvertedArgs = TemplateArgumentList::CreateCopy(Context, SugaredConverted);
+
   // Find the variable template specialization declaration that
   // corresponds to these arguments.
   void *InsertPos = nullptr;
@@ -4623,9 +4626,11 @@
   // the set of specializations, based on the closest partial specialization
   // that it represents. That is,
   VarDecl *InstantiationPattern = Template->getTemplatedDecl();
-  TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack,
-                                       CanonicalConverted);
-  TemplateArgumentList *InstantiationArgs = &TemplateArgList;
+  TemplateArgumentList SugaredArgList(TemplateArgumentList::OnStack,
+                                      SugaredConverted);
+  TemplateArgumentList CanonicalArgList(TemplateArgumentList::OnStack,
+                                        CanonicalConverted);
+  TemplateArgumentList *InstantiationArgs = &CanonicalArgList;
   bool AmbiguousPartialSpec = false;
   typedef PartialSpecMatchResult MatchResult;
   SmallVector<MatchResult, 4> Matched;
@@ -4646,7 +4651,7 @@
     TemplateDeductionInfo Info(FailedCandidates.getLocation());
 
     if (TemplateDeductionResult Result =
-            DeduceTemplateArguments(Partial, TemplateArgList, Info)) {
+            DeduceTemplateArguments(Partial, SugaredArgList, Info)) {
       // Store the failed-deduction information for use in diagnostics, later.
       // TODO: Actually use the failed-deduction info?
       FailedCandidates.addCandidate().set(
@@ -4656,7 +4661,8 @@
     } else {
       Matched.push_back(PartialSpecMatchResult());
       Matched.back().Partial = Partial;
-      Matched.back().Args = Info.takeCanonical();
+      Matched.back().SugaredArgs = Info.takeSugared();
+      Matched.back().CanonicalArgs = Info.takeCanonical();
     }
   }
 
@@ -4699,7 +4705,7 @@
 
     // Instantiate using the best variable template partial specialization.
     InstantiationPattern = Best->Partial;
-    InstantiationArgs = Best->Args;
+    InstantiationArgs = Best->CanonicalArgs;
   } else {
     //   -- If no match is found, the instantiation is generated
     //      from the primary template.
@@ -4724,9 +4730,10 @@
 
     // Print the matching partial specializations.
     for (MatchResult P : Matched)
+      // FIXME: Use SugaredArgs here.
       Diag(P.Partial->getLocation(), diag::note_partial_spec_match)
           << getTemplateArgumentBindingsText(P.Partial->getTemplateParameters(),
-                                             *P.Args);
+                                             *P.CanonicalArgs);
     return true;
   }
 
@@ -4745,9 +4752,9 @@
                          const DeclarationNameInfo &NameInfo,
                          VarTemplateDecl *Template, SourceLocation TemplateLoc,
                          const TemplateArgumentListInfo *TemplateArgs) {
-
+  const TemplateArgumentList *ConvertedArgs;
   DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(),
-                                       *TemplateArgs);
+                                       *TemplateArgs, ConvertedArgs);
   if (Decl.isInvalid())
     return ExprError();
 
@@ -4761,7 +4768,8 @@
 
   // Build an ordinary singleton decl ref.
   return BuildDeclarationNameExpr(SS, NameInfo, Var,
-                                  /*FoundD=*/nullptr, TemplateArgs);
+                                  /*FoundD=*/nullptr, TemplateArgs,
+                                  ConvertedArgs);
 }
 
 void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
@@ -7438,13 +7446,14 @@
          ->isFunctionType())) {
 
     if (Arg->getType() == Context.OverloadTy) {
-      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType,
-                                                                true,
-                                                                FoundResult)) {
+      const TemplateArgumentList *ConvertedArgs;
+      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(
+              Arg, ParamType, true, FoundResult, ConvertedArgs)) {
         if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
           return ExprError();
 
-        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        Arg =
+            FixOverloadedFunctionReference(Arg, FoundResult, Fn, ConvertedArgs);
         ArgType = Arg->getType();
       } else
         return ExprError();
@@ -7489,14 +7498,15 @@
            "Only object references allowed here");
 
     if (Arg->getType() == Context.OverloadTy) {
-      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg,
-                                                 ParamRefType->getPointeeType(),
-                                                                true,
-                                                                FoundResult)) {
+      const TemplateArgumentList *ConvertedArgs;
+      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(
+              Arg, ParamRefType->getPointeeType(), true, FoundResult,
+              ConvertedArgs)) {
         if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
           return ExprError();
 
-        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        Arg =
+            FixOverloadedFunctionReference(Arg, FoundResult, Fn, ConvertedArgs);
         ArgType = Arg->getType();
       } else
         return ExprError();
@@ -10276,8 +10286,10 @@
       TemplateArgumentListInfo TemplateArgs =
           makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
 
-      DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
-                                          D.getIdentifierLoc(), TemplateArgs);
+      const TemplateArgumentList *ConvertedArgs;
+      DeclResult Res =
+          CheckVarTemplateId(PrevTemplate, TemplateLoc, D.getIdentifierLoc(),
+                             TemplateArgs, ConvertedArgs);
       if (Res.isInvalid())
         return true;
 
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -1720,9 +1720,9 @@
 
   if (FromType == S.Context.OverloadTy) {
     DeclAccessPair AccessPair;
-    if (FunctionDecl *Fn
-          = S.ResolveAddressOfOverloadedFunction(From, ToType, false,
-                                                 AccessPair)) {
+    const TemplateArgumentList *ConvertedArgs;
+    if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(
+            From, ToType, false, AccessPair, ConvertedArgs)) {
       // We were able to resolve the address of the overloaded function,
       // so we can convert to the type of that function.
       FromType = Fn->getType();
@@ -4757,8 +4757,9 @@
   // type of the resulting function.
   if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
     DeclAccessPair Found;
-    if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Init, DeclType,
-                                                                false, Found))
+    const TemplateArgumentList *ConvertedArgs;
+    if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(
+            Init, DeclType, false, Found, ConvertedArgs))
       T2 = Fn->getType();
   }
 
@@ -5234,8 +5235,9 @@
       // type of the resulting function.
       if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
         DeclAccessPair Found;
+        const TemplateArgumentList *ConvertedArgs;
         if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(
-                                   Init, ToType, false, Found))
+                Init, ToType, false, Found, ConvertedArgs))
           T2 = Fn->getType();
       }
 
@@ -6332,7 +6334,7 @@
     OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
     bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions,
     ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions,
-    OverloadCandidateParamOrder PO) {
+    OverloadCandidateParamOrder PO, const TemplateArgumentList *Deduced) {
   const FunctionProtoType *Proto
     = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>());
   assert(Proto && "Functions without a prototype cannot be overloaded");
@@ -6351,7 +6353,7 @@
       AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(),
                          Expr::Classification::makeSimpleLValue(), Args,
                          CandidateSet, SuppressUserConversions,
-                         PartialOverloading, EarlyConversions, PO);
+                         PartialOverloading, EarlyConversions, PO, Deduced);
       return;
     }
     // We treat a constructor like a non-member function, since its object
@@ -6396,6 +6398,7 @@
   Candidate.IsADLCandidate = IsADLCandidate;
   Candidate.IgnoreObjectArgument = false;
   Candidate.ExplicitCallArguments = Args.size();
+  Candidate.Deduced = Deduced;
 
   // Explicit functions are not actually candidates at all if we're not
   // allowing them in this context, but keep them around so we can point
@@ -6930,16 +6933,13 @@
 /// both @c a1 and @c a2. If @p SuppressUserConversions, then don't
 /// allow user-defined conversions via constructors or conversion
 /// operators.
-void
-Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
-                         CXXRecordDecl *ActingContext, QualType ObjectType,
-                         Expr::Classification ObjectClassification,
-                         ArrayRef<Expr *> Args,
-                         OverloadCandidateSet &CandidateSet,
-                         bool SuppressUserConversions,
-                         bool PartialOverloading,
-                         ConversionSequenceList EarlyConversions,
-                         OverloadCandidateParamOrder PO) {
+void Sema::AddMethodCandidate(
+    CXXMethodDecl *Method, DeclAccessPair FoundDecl,
+    CXXRecordDecl *ActingContext, QualType ObjectType,
+    Expr::Classification ObjectClassification, ArrayRef<Expr *> Args,
+    OverloadCandidateSet &CandidateSet, bool SuppressUserConversions,
+    bool PartialOverloading, ConversionSequenceList EarlyConversions,
+    OverloadCandidateParamOrder PO, const TemplateArgumentList *Deduced) {
   const FunctionProtoType *Proto
     = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>());
   assert(Proto && "Methods without a prototype cannot be overloaded");
@@ -6970,6 +6970,7 @@
   Candidate.IsSurrogate = false;
   Candidate.IgnoreObjectArgument = false;
   Candidate.ExplicitCallArguments = Args.size();
+  Candidate.Deduced = Deduced;
 
   unsigned NumParams = Proto->getNumParams();
 
@@ -7146,7 +7147,7 @@
   AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
                      ActingContext, ObjectType, ObjectClassification, Args,
                      CandidateSet, SuppressUserConversions, PartialOverloading,
-                     Conversions, PO);
+                     Conversions, PO, Info.takeSugared());
 }
 
 /// Determine whether a given function template has a simple explicit specifier
@@ -7226,10 +7227,11 @@
   // Add the function template specialization produced by template argument
   // deduction as a candidate.
   assert(Specialization && "Missing function template specialization?");
-  AddOverloadCandidate(
-      Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions,
-      PartialOverloading, AllowExplicit,
-      /*AllowExplicitConversions*/ false, IsADLCandidate, Conversions, PO);
+  AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet,
+                       SuppressUserConversions, PartialOverloading,
+                       AllowExplicit,
+                       /*AllowExplicitConversions*/ false, IsADLCandidate,
+                       Conversions, PO, Info.takeSugared());
 }
 
 /// Check that implicit conversion sequences can be formed for each argument
@@ -12057,7 +12059,10 @@
   OverloadExpr::FindResult OvlExprInfo;
   OverloadExpr *OvlExpr;
   TemplateArgumentListInfo OvlExplicitTemplateArgs;
-  SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
+  SmallVector<
+      std::tuple<DeclAccessPair, FunctionDecl *, const TemplateArgumentList *>,
+      4>
+      Matches;
   TemplateSpecCandidateSet FailedCandidates;
 
 public:
@@ -12075,15 +12080,22 @@
         FailedCandidates(OvlExpr->getNameLoc(), /*ForTakingAddress=*/true) {
     ExtractUnqualifiedFunctionTypeFromTargetType();
 
+    if (OvlExpr->hasExplicitTemplateArgs())
+      OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);
+
+    const TemplateArgumentList *ConvertedArgs;
     if (TargetFunctionType->isFunctionType()) {
       if (UnresolvedMemberExpr *UME = dyn_cast<UnresolvedMemberExpr>(OvlExpr))
         if (!UME->isImplicitAccess() &&
-            !S.ResolveSingleFunctionTemplateSpecialization(UME))
+            (!OvlExpr->hasExplicitTemplateArgs() ||
+             !S.ResolveSingleFunctionTemplateSpecialization(
+                 UME, OvlExplicitTemplateArgs, ConvertedArgs)))
           StaticMemberFunctionFromBoundPointer = true;
     } else if (OvlExpr->hasExplicitTemplateArgs()) {
       DeclAccessPair dap;
       if (FunctionDecl *Fn = S.ResolveSingleFunctionTemplateSpecialization(
-              OvlExpr, false, &dap)) {
+              OvlExpr, OvlExplicitTemplateArgs, ConvertedArgs,
+              /*Complain=*/false, &dap)) {
         if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn))
           if (!Method->isStatic()) {
             // If the target type is a non-function type and the function found
@@ -12097,14 +12109,11 @@
               return;
           }
 
-        Matches.push_back(std::make_pair(dap, Fn));
+        Matches.push_back({dap, Fn, ConvertedArgs});
       }
       return;
     }
 
-    if (OvlExpr->hasExplicitTemplateArgs())
-      OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);
-
     if (FindAllFunctionsThatMatchTargetTypeExactly()) {
       // C++ [over.over]p4:
       //   If more than one function is selected, [...]
@@ -12146,15 +12155,17 @@
     // Same algorithm as overload resolution -- one pass to pick the "best",
     // another pass to be sure that nothing is better than the best.
     auto Best = Matches.begin();
-    for (auto I = Matches.begin()+1, E = Matches.end(); I != E; ++I)
-      if (isBetterCandidate(I->second, Best->second))
+    for (auto I = Matches.begin() + 1, E = Matches.end(); I != E; ++I)
+      if (isBetterCandidate(std::get<1>(*I), std::get<1>(*Best)))
         Best = I;
 
-    const FunctionDecl *BestFn = Best->second;
-    auto IsBestOrInferiorToBest = [this, BestFn](
-        const std::pair<DeclAccessPair, FunctionDecl *> &Pair) {
-      return BestFn == Pair.second || isBetterCandidate(BestFn, Pair.second);
-    };
+    const FunctionDecl *BestFn = std::get<1>(*Best);
+    auto IsBestOrInferiorToBest =
+        [this, BestFn](const std::tuple<DeclAccessPair, FunctionDecl *,
+                                        const TemplateArgumentList *> &Tuple) {
+          return BestFn == std::get<1>(Tuple) ||
+                 isBetterCandidate(BestFn, std::get<1>(Tuple));
+        };
 
     // Note: We explicitly leave Matches unmodified if there isn't a clear best
     // option, so we can potentially give the user a better error
@@ -12221,7 +12232,7 @@
     if (!S.checkAddressOfFunctionIsAvailable(Specialization))
       return false;
 
-    Matches.push_back(std::make_pair(CurAccessFunPair, Specialization));
+    Matches.push_back({CurAccessFunPair, Specialization, Info.takeSugared()});
     return true;
   }
 
@@ -12261,8 +12272,9 @@
       // If we're in C, we need to support types that aren't exactly identical.
       if (!S.getLangOpts().CPlusPlus ||
           candidateHasExactlyCorrectType(FunDecl)) {
-        Matches.push_back(std::make_pair(
-            CurAccessFunPair, cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
+        Matches.push_back({CurAccessFunPair,
+                           cast<FunctionDecl>(FunDecl->getCanonicalDecl()),
+                           nullptr});
         FoundNonTemplateFunction = true;
         return true;
       }
@@ -12319,7 +12331,8 @@
 
     UnresolvedSet<4> MatchesCopy; // TODO: avoid!
     for (unsigned I = 0, E = Matches.size(); I != E; ++I)
-      MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
+      MatchesCopy.addDecl(std::get<1>(Matches[I]),
+                          std::get<0>(Matches[I]).getAccess());
 
     // TODO: It looks like FailedCandidates does not serve much purpose
     // here, since the no_viable diagnostic has index 0.
@@ -12327,15 +12340,16 @@
         MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates,
         SourceExpr->getBeginLoc(), S.PDiag(),
         S.PDiag(diag::err_addr_ovl_ambiguous)
-            << Matches[0].second->getDeclName(),
+            << std::get<1>(Matches[0])->getDeclName(),
         S.PDiag(diag::note_ovl_candidate)
             << (unsigned)oc_function << (unsigned)ocs_described_template,
         Complain, TargetFunctionType);
 
     if (Result != MatchesCopy.end()) {
       // Make it the first and only element
-      Matches[0].first = Matches[Result - MatchesCopy.begin()].first;
-      Matches[0].second = cast<FunctionDecl>(*Result);
+      const auto &Old = Matches[Result - MatchesCopy.begin()];
+      Matches[0] = {std::get<0>(Old), cast<FunctionDecl>(*Result),
+                    std::get<2>(Old)};
       Matches.resize(1);
     } else
       HasComplained |= Complain;
@@ -12345,7 +12359,7 @@
     //   [...] any function template specializations in the set are
     //   eliminated if the set also contains a non-template function, [...]
     for (unsigned I = 0, N = Matches.size(); I != N; ) {
-      if (Matches[I].second->getPrimaryTemplate() == nullptr)
+      if (std::get<1>(Matches[I])->getPrimaryTemplate() == nullptr)
         ++I;
       else {
         Matches[I] = Matches[--N];
@@ -12426,12 +12440,18 @@
 
   FunctionDecl* getMatchingFunctionDecl() const {
     if (Matches.size() != 1) return nullptr;
-    return Matches[0].second;
+    return std::get<1>(Matches[0]);
   }
 
   const DeclAccessPair* getMatchingFunctionAccessPair() const {
     if (Matches.size() != 1) return nullptr;
-    return &Matches[0].first;
+    return &std::get<0>(Matches[0]);
+  }
+
+  const TemplateArgumentList *getMatchingFunctionConvertedArgs() const {
+    if (Matches.size() != 1)
+      return nullptr;
+    return std::get<2>(Matches[0]);
   }
 };
 }
@@ -12451,12 +12471,10 @@
 /// This routine returns the resulting FunctionDecl if it could be
 /// resolved, and NULL otherwise. When @p Complain is true, this
 /// routine will emit diagnostics if there is an error.
-FunctionDecl *
-Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
-                                         QualType TargetType,
-                                         bool Complain,
-                                         DeclAccessPair &FoundResult,
-                                         bool *pHadMultipleCandidates) {
+FunctionDecl *Sema::ResolveAddressOfOverloadedFunction(
+    Expr *AddressOfExpr, QualType TargetType, bool Complain,
+    DeclAccessPair &FoundResult, const TemplateArgumentList *&ConvertedArgs,
+    bool *pHadMultipleCandidates) {
   assert(AddressOfExpr->getType() == Context.OverloadTy);
 
   AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType,
@@ -12478,6 +12496,7 @@
     if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
       ResolveExceptionSpec(AddressOfExpr->getExprLoc(), FPT);
     FoundResult = *Resolver.getMatchingFunctionAccessPair();
+    ConvertedArgs = Resolver.getMatchingFunctionConvertedArgs();
     if (Complain) {
       if (Resolver.IsStaticMemberFunctionFromBoundPointer())
         Resolver.ComplainIsStaticMemberFunctionFromBoundPointer();
@@ -12590,7 +12609,7 @@
   // for both.
   DiagnoseUseOfDecl(Found, E->getExprLoc());
   CheckAddressOfMemberAccess(E, DAP);
-  Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found);
+  Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found, nullptr);
   if (DoFunctionPointerConversion && Fixed->getType()->isFunctionType())
     SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false);
   else
@@ -12608,10 +12627,10 @@
 ///
 /// If no template-ids are found, no diagnostics are emitted and NULL is
 /// returned.
-FunctionDecl *
-Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
-                                                  bool Complain,
-                                                  DeclAccessPair *FoundResult) {
+FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(
+    OverloadExpr *ovl, TemplateArgumentListInfo &ExplicitTemplateArgs,
+    const TemplateArgumentList *&ConvertedArgs, bool Complain,
+    DeclAccessPair *FoundResult) {
   // C++ [over.over]p1:
   //   [...] [Note: any redundant set of parentheses surrounding the
   //   overloaded function name is ignored (5.1). ]
@@ -12619,12 +12638,9 @@
   //   [...] The overloaded function name can be preceded by the &
   //   operator.
 
-  // If we didn't actually find any template-ids, we're done.
-  if (!ovl->hasExplicitTemplateArgs())
-    return nullptr;
+  // Specializations must have template args.
+  assert(ovl->hasExplicitTemplateArgs());
 
-  TemplateArgumentListInfo ExplicitTemplateArgs;
-  ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
   TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
 
   // Look through all of the overloaded functions, searching for one
@@ -12675,6 +12691,7 @@
 
     Matched = Specialization;
     if (FoundResult) *FoundResult = I.getPair();
+    ConvertedArgs = Info.takeSugared();
   }
 
   if (Matched &&
@@ -12699,50 +12716,55 @@
   assert(SrcExpr.get()->getType() == Context.OverloadTy);
 
   OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr.get());
-
-  DeclAccessPair found;
   ExprResult SingleFunctionExpression;
-  if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
-                           ovl.Expression, /*complain*/ false, &found)) {
-    if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getBeginLoc())) {
-      SrcExpr = ExprError();
-      return true;
-    }
+  if (ovl.Expression->hasExplicitTemplateArgs()) {
+    TemplateArgumentListInfo ExplicitTemplateArgs;
+    ovl.Expression->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+
+    const TemplateArgumentList *ConvertedArgs;
+    DeclAccessPair found;
+    if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
+            ovl.Expression, ExplicitTemplateArgs, ConvertedArgs,
+            /*Complain=*/false, &found)) {
+      if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getBeginLoc())) {
+        SrcExpr = ExprError();
+        return true;
+      }
 
-    // It is only correct to resolve to an instance method if we're
-    // resolving a form that's permitted to be a pointer to member.
-    // Otherwise we'll end up making a bound member expression, which
-    // is illegal in all the contexts we resolve like this.
-    if (!ovl.HasFormOfMemberPointer &&
-        isa<CXXMethodDecl>(fn) &&
-        cast<CXXMethodDecl>(fn)->isInstance()) {
-      if (!complain) return false;
-
-      Diag(ovl.Expression->getExprLoc(),
-           diag::err_bound_member_function)
-        << 0 << ovl.Expression->getSourceRange();
-
-      // TODO: I believe we only end up here if there's a mix of
-      // static and non-static candidates (otherwise the expression
-      // would have 'bound member' type, not 'overload' type).
-      // Ideally we would note which candidate was chosen and why
-      // the static candidates were rejected.
-      SrcExpr = ExprError();
-      return true;
-    }
+      // It is only correct to resolve to an instance method if we're
+      // resolving a form that's permitted to be a pointer to member.
+      // Otherwise we'll end up making a bound member expression, which
+      // is illegal in all the contexts we resolve like this.
+      if (!ovl.HasFormOfMemberPointer && isa<CXXMethodDecl>(fn) &&
+          cast<CXXMethodDecl>(fn)->isInstance()) {
+        if (!complain)
+          return false;
 
-    // Fix the expression to refer to 'fn'.
-    SingleFunctionExpression =
-        FixOverloadedFunctionReference(SrcExpr.get(), found, fn);
+        Diag(ovl.Expression->getExprLoc(), diag::err_bound_member_function)
+            << 0 << ovl.Expression->getSourceRange();
 
-    // If desired, do function-to-pointer decay.
-    if (doFunctionPointerConversion) {
-      SingleFunctionExpression =
-        DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.get());
-      if (SingleFunctionExpression.isInvalid()) {
+        // TODO: I believe we only end up here if there's a mix of
+        // static and non-static candidates (otherwise the expression
+        // would have 'bound member' type, not 'overload' type).
+        // Ideally we would note which candidate was chosen and why
+        // the static candidates were rejected.
         SrcExpr = ExprError();
         return true;
       }
+
+      // Fix the expression to refer to 'fn'.
+      SingleFunctionExpression = FixOverloadedFunctionReference(
+          SrcExpr.get(), found, fn, ConvertedArgs);
+
+      // If desired, do function-to-pointer decay.
+      if (doFunctionPointerConversion) {
+        SingleFunctionExpression = DefaultFunctionArrayLvalueConversion(
+            SingleFunctionExpression.get());
+        if (SingleFunctionExpression.isInvalid()) {
+          SrcExpr = ExprError();
+          return true;
+        }
+      }
     }
   }
 
@@ -13255,7 +13277,8 @@
     SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl);
     if (SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()))
       return ExprError();
-    Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
+    Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl,
+                                                (*Best)->Deduced);
     return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
                                          ExecConfig, /*IsExecConfig=*/false,
                                          (*Best)->IsADLCandidate);
@@ -13313,7 +13336,8 @@
     // We emitted an error for the unavailable/deleted function call but keep
     // the call in the AST.
     FunctionDecl *FDecl = (*Best)->Function;
-    Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
+    Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl,
+                                                (*Best)->Deduced);
     return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, RParenLoc,
                                          ExecConfig, /*IsExecConfig=*/false,
                                          (*Best)->IsADLCandidate);
@@ -14581,7 +14605,8 @@
     if (!Succeeded)
       return BuildRecoveryExpr(chooseRecoveryType(CandidateSet, &Best));
 
-    MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
+    MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method,
+                                              Best->Deduced);
 
     // If overload resolution picked a static member, build a
     // non-member call based on that function.
@@ -15196,11 +15221,13 @@
 /// perhaps a '&' around it). We have resolved the overloaded function
 /// to the function declaration Fn, so patch up the expression E to
 /// refer (possibly indirectly) to Fn. Returns the new expr.
-Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
-                                           FunctionDecl *Fn) {
+Expr *
+Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
+                                     FunctionDecl *Fn,
+                                     const TemplateArgumentList *Deduced) {
   if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
-    Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(),
-                                                   Found, Fn);
+    Expr *SubExpr =
+        FixOverloadedFunctionReference(PE->getSubExpr(), Found, Fn, Deduced);
     if (SubExpr == PE->getSubExpr())
       return PE;
 
@@ -15208,8 +15235,8 @@
   }
 
   if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
-    Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(),
-                                                   Found, Fn);
+    Expr *SubExpr =
+        FixOverloadedFunctionReference(ICE->getSubExpr(), Found, Fn, Deduced);
     assert(Context.hasSameType(ICE->getSubExpr()->getType(),
                                SubExpr->getType()) &&
            "Implicit cast type cannot be determined from overload");
@@ -15224,8 +15251,8 @@
 
   if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) {
     if (!GSE->isResultDependent()) {
-      Expr *SubExpr =
-          FixOverloadedFunctionReference(GSE->getResultExpr(), Found, Fn);
+      Expr *SubExpr = FixOverloadedFunctionReference(GSE->getResultExpr(),
+                                                     Found, Fn, Deduced);
       if (SubExpr == GSE->getResultExpr())
         return GSE;
 
@@ -15259,7 +15286,7 @@
         // UnresolvedLookupExpr holding an overloaded member function
         // or template.
         Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
-                                                       Found, Fn);
+                                                       Found, Fn, Deduced);
         if (SubExpr == UnOp->getSubExpr())
           return UnOp;
 
@@ -15284,8 +15311,8 @@
             UnOp->getOperatorLoc(), false, CurFPFeatureOverrides());
       }
     }
-    Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
-                                                   Found, Fn);
+    Expr *SubExpr =
+        FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn, Deduced);
     if (SubExpr == UnOp->getSubExpr())
       return UnOp;
 
@@ -15315,7 +15342,7 @@
 
     DeclRefExpr *DRE = BuildDeclRefExpr(
         Fn, Type, ValueKind, ULE->getNameInfo(), ULE->getQualifierLoc(),
-        Found.getDecl(), ULE->getTemplateKeywordLoc(), TemplateArgs);
+        Found.getDecl(), ULE->getTemplateKeywordLoc(), TemplateArgs, Deduced);
     DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1);
     return DRE;
   }
@@ -15337,7 +15364,7 @@
         DeclRefExpr *DRE = BuildDeclRefExpr(
             Fn, Fn->getType(), VK_LValue, MemExpr->getNameInfo(),
             MemExpr->getQualifierLoc(), Found.getDecl(),
-            MemExpr->getTemplateKeywordLoc(), TemplateArgs);
+            MemExpr->getTemplateKeywordLoc(), TemplateArgs, Deduced);
         DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1);
         return DRE;
       } else {
@@ -15370,10 +15397,11 @@
   llvm_unreachable("Invalid reference to overloaded function");
 }
 
-ExprResult Sema::FixOverloadedFunctionReference(ExprResult E,
-                                                DeclAccessPair Found,
-                                                FunctionDecl *Fn) {
-  return FixOverloadedFunctionReference(E.get(), Found, Fn);
+ExprResult
+Sema::FixOverloadedFunctionReference(ExprResult E, DeclAccessPair Found,
+                                     FunctionDecl *Fn,
+                                     const TemplateArgumentList *Deduced) {
+  return FixOverloadedFunctionReference(E.get(), Found, Fn, Deduced);
 }
 
 bool clang::shouldEnforceArgLimit(bool PartialOverloading,
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -3594,17 +3594,16 @@
   return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization;
 }
 
-void
-InitializationSequence
-::AddAddressOverloadResolutionStep(FunctionDecl *Function,
-                                   DeclAccessPair Found,
-                                   bool HadMultipleCandidates) {
+void InitializationSequence ::AddAddressOverloadResolutionStep(
+    FunctionDecl *Function, DeclAccessPair Found,
+    const TemplateArgumentList *ConvertedArgs, bool HadMultipleCandidates) {
   Step S;
   S.Kind = SK_ResolveAddressOfOverloadedFunction;
   S.Type = Function->getType();
   S.Function.HadMultipleCandidates = HadMultipleCandidates;
   S.Function.Function = Function;
   S.Function.FoundDecl = Found;
+  S.Function.ConvertedArgs = ConvertedArgs;
   Steps.push_back(S);
 }
 
@@ -4255,13 +4254,12 @@
   if (S.Context.getCanonicalType(UnqualifiedSourceType) ==
         S.Context.OverloadTy) {
     DeclAccessPair Found;
+    const TemplateArgumentList *ConvertedArgs;
     bool HadMultipleCandidates = false;
-    if (FunctionDecl *Fn
-        = S.ResolveAddressOfOverloadedFunction(Initializer,
-                                               UnqualifiedTargetType,
-                                               false, Found,
-                                               &HadMultipleCandidates)) {
-      Sequence.AddAddressOverloadResolutionStep(Fn, Found,
+    if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(
+            Initializer, UnqualifiedTargetType, false, Found, ConvertedArgs,
+            &HadMultipleCandidates)) {
+      Sequence.AddAddressOverloadResolutionStep(Fn, Found, ConvertedArgs,
                                                 HadMultipleCandidates);
       SourceType = Fn->getType();
       UnqualifiedSourceType = SourceType.getUnqualifiedType();
@@ -6083,11 +6081,12 @@
     AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy);
   } else if (ICS.isBad()) {
     DeclAccessPair dap;
+    const TemplateArgumentList *ConvertedArgs;
     if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) {
       AddZeroInitializationStep(Entity.getType());
     } else if (Initializer->getType() == Context.OverloadTy &&
                !S.ResolveAddressOfOverloadedFunction(Initializer, DestType,
-                                                     false, dap))
+                                                     false, dap, ConvertedArgs))
       SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
     else if (Initializer->getType()->isFunctionType() &&
              isExprAnUnaddressableFunction(S, Initializer))
@@ -8261,9 +8260,9 @@
       S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl);
       if (S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation()))
         return ExprError();
-      CurInit = S.FixOverloadedFunctionReference(CurInit,
-                                                 Step->Function.FoundDecl,
-                                                 Step->Function.Function);
+      CurInit = S.FixOverloadedFunctionReference(
+          CurInit, Step->Function.FoundDecl, Step->Function.Function,
+          Step->Function.ConvertedArgs);
       // We might get back another placeholder expression if we resolved to a
       // builtin.
       if (!CurInit.isInvalid())
@@ -9136,10 +9135,9 @@
 
   case FK_AddressOfOverloadFailed: {
     DeclAccessPair Found;
-    S.ResolveAddressOfOverloadedFunction(OnlyArg,
-                                         DestType.getNonReferenceType(),
-                                         true,
-                                         Found);
+    const TemplateArgumentList *ConvertedArgs;
+    S.ResolveAddressOfOverloadedFunction(
+        OnlyArg, DestType.getNonReferenceType(), true, Found, ConvertedArgs);
     break;
   }
 
Index: clang/lib/Sema/SemaExprMember.cpp
===================================================================
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -897,12 +897,13 @@
     SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
     bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
     QualType Ty, ExprValueKind VK, ExprObjectKind OK,
-    const TemplateArgumentListInfo *TemplateArgs) {
+    const TemplateArgumentListInfo *TemplateArgs,
+    const TemplateArgumentList *Deduced) {
   NestedNameSpecifierLoc NNS =
       SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc();
   return BuildMemberExpr(Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member,
                          FoundDecl, HadMultipleCandidates, MemberNameInfo, Ty,
-                         VK, OK, TemplateArgs);
+                         VK, OK, TemplateArgs, Deduced);
 }
 
 MemberExpr *Sema::BuildMemberExpr(
@@ -910,13 +911,14 @@
     SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
     bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
     QualType Ty, ExprValueKind VK, ExprObjectKind OK,
-    const TemplateArgumentListInfo *TemplateArgs) {
+    const TemplateArgumentListInfo *TemplateArgs,
+    const TemplateArgumentList *Deduced) {
   assert((!IsArrow || Base->isPRValue()) &&
          "-> base must be a pointer prvalue");
-  MemberExpr *E =
-      MemberExpr::Create(Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc,
-                         Member, FoundDecl, MemberNameInfo, TemplateArgs, Ty,
-                         VK, OK, getNonOdrUseReasonInCurrentContext(Member));
+  MemberExpr *E = MemberExpr::Create(
+      Context, Base, IsArrow, OpLoc, NNS, TemplateKWLoc, Member, FoundDecl,
+      MemberNameInfo, TemplateArgs, Deduced, Ty, VK, OK,
+      getNonOdrUseReasonInCurrentContext(Member));
   E->setHadMultipleCandidates(HadMultipleCandidates);
   MarkMemberReferenced(E);
 
@@ -1146,8 +1148,10 @@
       return ExprError();
     }
 
-    DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc,
-                                          MemberNameInfo.getLoc(), *TemplateArgs);
+    const TemplateArgumentList *ConvertedArgs;
+    DeclResult VDecl =
+        CheckVarTemplateId(VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(),
+                           *TemplateArgs, ConvertedArgs);
     if (VDecl.isInvalid())
       return ExprError();
 
@@ -1164,7 +1168,7 @@
     return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var,
                            FoundDecl, /*HadMultipleCandidates=*/false,
                            MemberNameInfo, Var->getType().getNonReferenceType(),
-                           VK_LValue, OK_Ordinary, TemplateArgs);
+                           VK_LValue, OK_Ordinary, TemplateArgs, ConvertedArgs);
   }
 
   // We found something that we didn't expect. Complain.
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -2774,7 +2774,10 @@
 
   FoundDelete.suppressDiagnostics();
 
-  SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches;
+  SmallVector<
+      std::tuple<DeclAccessPair, FunctionDecl *, const TemplateArgumentList *>,
+      2>
+      Matches;
 
   // Whether we're looking for a placement operator delete is dictated
   // by whether we selected a placement operator new, not by whether
@@ -2824,6 +2827,7 @@
                              DEnd = FoundDelete.end();
          D != DEnd; ++D) {
       FunctionDecl *Fn = nullptr;
+      const TemplateArgumentList *ConvertedArgs = nullptr;
       if (FunctionTemplateDecl *FnTmpl =
               dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
         // Perform template argument deduction to try to match the
@@ -2832,14 +2836,15 @@
         if (DeduceTemplateArguments(FnTmpl, nullptr, ExpectedFunctionType, Fn,
                                     Info))
           continue;
+        ConvertedArgs = Info.takeSugared();
       } else
         Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
 
       if (Context.hasSameType(adjustCCAndNoReturn(Fn->getType(),
                                                   ExpectedFunctionType,
-                                                  /*AdjustExcpetionSpec*/true),
+                                                  /*AdjustExcpetionSpec=*/true),
                               ExpectedFunctionType))
-        Matches.push_back(std::make_pair(D.getPair(), Fn));
+        Matches.push_back({D.getPair(), Fn, ConvertedArgs});
     }
 
     if (getLangOpts().CUDA)
@@ -2859,12 +2864,12 @@
         /*WantAlign*/ hasNewExtendedAlignment(*this, AllocElemType),
         &BestDeallocFns);
     if (Selected)
-      Matches.push_back(std::make_pair(Selected.Found, Selected.FD));
+      Matches.push_back({Selected.Found, Selected.FD, nullptr});
     else {
       // If we failed to select an operator, all remaining functions are viable
       // but ambiguous.
       for (auto Fn : BestDeallocFns)
-        Matches.push_back(std::make_pair(Fn.Found, Fn.FD));
+        Matches.push_back({Fn.Found, Fn.FD, nullptr});
     }
   }
 
@@ -2873,7 +2878,7 @@
   //   function, that function will be called; otherwise, no
   //   deallocation function will be called.
   if (Matches.size() == 1) {
-    OperatorDelete = Matches[0].second;
+    OperatorDelete = std::get<1>(Matches[0]);
 
     // C++1z [expr.new]p23:
     //   If the lookup finds a usual deallocation function (3.7.4.2)
@@ -2912,7 +2917,7 @@
     }
 
     CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(),
-                          Matches[0].first);
+                          std::get<0>(Matches[0]));
   } else if (!Matches.empty()) {
     // We found multiple suitable operators. Per [expr.new]p20, that means we
     // call no 'operator delete' function, but we should at least warn the user.
@@ -2921,8 +2926,8 @@
       << DeleteName << AllocElemType;
 
     for (auto &Match : Matches)
-      Diag(Match.second->getLocation(),
-           diag::note_member_declared_here) << DeleteName;
+      Diag(std::get<1>(Match)->getLocation(), diag::note_member_declared_here)
+          << DeleteName;
   }
 
   return false;
@@ -4242,15 +4247,16 @@
   // Resolve overloaded function references.
   if (Context.hasSameType(FromType, Context.OverloadTy)) {
     DeclAccessPair Found;
-    FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType,
-                                                          true, Found);
+    const TemplateArgumentList *ConvertedArgs;
+    FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true,
+                                                          Found, ConvertedArgs);
     if (!Fn)
       return ExprError();
 
     if (DiagnoseUseOfDecl(Fn, From->getBeginLoc()))
       return ExprError();
 
-    From = FixOverloadedFunctionReference(From, Found, Fn);
+    From = FixOverloadedFunctionReference(From, Found, Fn, ConvertedArgs);
 
     // We might get back another placeholder expression if we resolved to a
     // builtin.
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -2007,11 +2007,12 @@
                        const DeclarationNameInfo &NameInfo,
                        const CXXScopeSpec *SS, NamedDecl *FoundD,
                        SourceLocation TemplateKWLoc,
-                       const TemplateArgumentListInfo *TemplateArgs) {
+                       const TemplateArgumentListInfo *TemplateArgs,
+                       const TemplateArgumentList *ConvertedArgs) {
   NestedNameSpecifierLoc NNS =
       SS ? SS->getWithLocInContext(Context) : NestedNameSpecifierLoc();
   return BuildDeclRefExpr(D, Ty, VK, NameInfo, NNS, FoundD, TemplateKWLoc,
-                          TemplateArgs);
+                          TemplateArgs, ConvertedArgs);
 }
 
 // CUDA/HIP: Check whether a captured reference variable is referencing a
@@ -2078,13 +2079,16 @@
                        const DeclarationNameInfo &NameInfo,
                        NestedNameSpecifierLoc NNS, NamedDecl *FoundD,
                        SourceLocation TemplateKWLoc,
-                       const TemplateArgumentListInfo *TemplateArgs) {
+                       const TemplateArgumentListInfo *TemplateArgs,
+                       const TemplateArgumentList *ConvertedArgs) {
   bool RefersToCapturedVariable = isa<VarDecl, BindingDecl>(D) &&
                                   NeedToCaptureVariable(D, NameInfo.getLoc());
 
-  DeclRefExpr *E = DeclRefExpr::Create(
-      Context, NNS, TemplateKWLoc, D, RefersToCapturedVariable, NameInfo, Ty,
-      VK, FoundD, TemplateArgs, getNonOdrUseReasonInCurrentContext(D));
+  assert(!TemplateArgs || ConvertedArgs);
+  DeclRefExpr *E = DeclRefExpr::Create(Context, NNS, TemplateKWLoc, D,
+                                       RefersToCapturedVariable, NameInfo, Ty,
+                                       VK, FoundD, TemplateArgs, ConvertedArgs,
+                                       getNonOdrUseReasonInCurrentContext(D));
   MarkDeclRefReferenced(E);
 
   // C++ [except.spec]p17:
@@ -3223,7 +3227,7 @@
       !R.getAsSingle<FunctionTemplateDecl>() &&
       !ShouldLookupResultBeMultiVersionOverload(R))
     return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(),
-                                    R.getRepresentativeDecl(), nullptr,
+                                    R.getRepresentativeDecl(), nullptr, nullptr,
                                     AcceptInvalidDecl);
 
   // We only need to check the declaration if there's exactly one
@@ -3256,10 +3260,11 @@
 ExprResult Sema::BuildDeclarationNameExpr(
     const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
     NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs,
-    bool AcceptInvalidDecl) {
+    const TemplateArgumentList *ConvertedArgs, bool AcceptInvalidDecl) {
   assert(D && "Cannot refer to a NULL declaration");
   assert(!isa<FunctionTemplateDecl>(D) &&
          "Cannot refer unambiguously to a function template");
+  assert(!TemplateArgs || ConvertedArgs);
 
   SourceLocation Loc = NameInfo.getLoc();
   if (CheckDeclInExpr(*this, Loc, D)) {
@@ -3496,7 +3501,7 @@
 
   return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD,
                           /*FIXME: TemplateKWLoc*/ SourceLocation(),
-                          TemplateArgs);
+                          TemplateArgs, ConvertedArgs);
 }
 
 static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
@@ -6748,7 +6753,7 @@
         Fn = DeclRefExpr::Create(
             Context, FDecl->getQualifierLoc(), SourceLocation(), FDecl, false,
             SourceLocation(), FDecl->getType(), Fn->getValueKind(), FDecl,
-            nullptr, DRE->isNonOdrUse());
+            nullptr, nullptr, DRE->isNonOdrUse());
       }
     }
   } else if (isa<MemberExpr>(NakedFn))
@@ -9964,9 +9969,10 @@
     // As a set of extensions to C, we support overloading on functions. These
     // functions need to be resolved here.
     DeclAccessPair DAP;
+    const TemplateArgumentList *ConvertedArgs;
     if (FunctionDecl *FD = ResolveAddressOfOverloadedFunction(
-            RHS.get(), LHSType, /*Complain=*/false, DAP))
-      RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD);
+            RHS.get(), LHSType, /*Complain=*/false, DAP, ConvertedArgs))
+      RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD, ConvertedArgs);
     else
       return Incompatible;
   }
@@ -14257,14 +14263,19 @@
       }
 
       OverloadExpr *Ovl = cast<OverloadExpr>(E);
-      if (isa<UnresolvedMemberExpr>(Ovl))
-        if (!ResolveSingleFunctionTemplateSpecialization(Ovl)) {
-          Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
-            << OrigOp.get()->getSourceRange();
-          return QualType();
-        }
-
-      return Context.OverloadTy;
+      if (!isa<UnresolvedMemberExpr>(Ovl))
+        return Context.OverloadTy;
+      if (Ovl->hasExplicitTemplateArgs()) {
+        TemplateArgumentListInfo ExplicitTemplateArgs;
+        Ovl->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+        const TemplateArgumentList *ConvertedArgs;
+        if (ResolveSingleFunctionTemplateSpecialization(
+                Ovl, ExplicitTemplateArgs, ConvertedArgs))
+          return Context.OverloadTy;
+      }
+      Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+          << OrigOp.get()->getSourceRange();
+      return QualType();
     }
 
     if (PTy->getKind() == BuiltinType::UnknownAny)
@@ -19140,7 +19151,8 @@
         S.Context, DRE->getQualifierLoc(), DRE->getTemplateKeywordLoc(),
         DRE->getDecl(), DRE->refersToEnclosingVariableOrCapture(),
         DRE->getNameInfo(), DRE->getType(), DRE->getValueKind(),
-        DRE->getFoundDecl(), CopiedTemplateArgs(DRE), NOUR);
+        DRE->getFoundDecl(), CopiedTemplateArgs(DRE), DRE->getConvertedArgs(),
+        NOUR);
   }
 
   case Expr::FunctionParmPackExprClass: {
@@ -19186,8 +19198,8 @@
           S.Context, Base.get(), ME->isArrow(), ME->getOperatorLoc(),
           ME->getQualifierLoc(), ME->getTemplateKeywordLoc(),
           ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(),
-          CopiedTemplateArgs(ME), ME->getType(), ME->getValueKind(),
-          ME->getObjectKind(), ME->isNonOdrUse());
+          CopiedTemplateArgs(ME), ME->getDeduced(), ME->getType(),
+          ME->getValueKind(), ME->getObjectKind(), ME->isNonOdrUse());
     }
 
     if (ME->getMemberDecl()->isCXXInstanceMember())
@@ -19204,7 +19216,8 @@
         S.Context, ME->getBase(), ME->isArrow(), ME->getOperatorLoc(),
         ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), ME->getMemberDecl(),
         ME->getFoundDecl(), ME->getMemberNameInfo(), CopiedTemplateArgs(ME),
-        ME->getType(), ME->getValueKind(), ME->getObjectKind(), NOUR);
+        ME->getDeduced(), ME->getType(), ME->getValueKind(),
+        ME->getObjectKind(), NOUR);
   }
 
   case Expr::BinaryOperatorClass: {
@@ -20748,7 +20761,8 @@
             FD, FD->getType(), VK_LValue, DRE->getNameInfo(),
             DRE->hasQualifier() ? &SS : nullptr, DRE->getFoundDecl(),
             DRE->getTemplateKeywordLoc(),
-            DRE->hasExplicitTemplateArgs() ? &TemplateArgs : nullptr);
+            DRE->hasExplicitTemplateArgs() ? &TemplateArgs : nullptr,
+            DRE->getConvertedArgs());
       }
     }
 
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3599,9 +3599,14 @@
       return;
     }
   } else if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(E)) {
-    if (ULE->hasExplicitTemplateArgs())
+    if (ULE->hasExplicitTemplateArgs()) {
       S.Diag(Loc, diag::warn_cleanup_ext);
-    FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true);
+      TemplateArgumentListInfo ExplicitTemplateArgs;
+      const TemplateArgumentList *ConvertedArgs;
+      ULE->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+      FD = S.ResolveSingleFunctionTemplateSpecialization(
+          ULE, ExplicitTemplateArgs, ConvertedArgs, /*Complain=*/true);
+    }
     NI = ULE->getNameInfo();
     if (!FD) {
       S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -6899,7 +6899,7 @@
   DeclRefExpr *NewDRE = DeclRefExpr::Create(
       Context, DRE->getQualifierLoc(), SourceLocation(), NewBuiltinDecl,
       /*enclosing*/ false, DRE->getLocation(), Context.BuiltinFnTy,
-      DRE->getValueKind(), nullptr, nullptr, DRE->isNonOdrUse());
+      DRE->getValueKind(), nullptr, nullptr, nullptr, DRE->isNonOdrUse());
 
   // Set the callee in the CallExpr.
   // FIXME: This loses syntactic information.
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -1720,9 +1720,9 @@
   bool WasOverloadedFunction = false;
   DeclAccessPair FoundOverload;
   if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
-    if (FunctionDecl *Fn
-          = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false,
-                                                    FoundOverload)) {
+    const TemplateArgumentList *ConvertedArgs;
+    if (FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(
+            SrcExpr.get(), DestType, false, FoundOverload, ConvertedArgs)) {
       CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
       SrcType = Self.Context.getMemberPointerType(Fn->getType(),
                       Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
@@ -1799,16 +1799,16 @@
   if (WasOverloadedFunction) {
     // Resolve the address of the overloaded function again, this time
     // allowing complaints if something goes wrong.
-    FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
-                                                               DestType,
-                                                               true,
-                                                               FoundOverload);
+    const TemplateArgumentList *ConvertedArgs;
+    FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(
+        SrcExpr.get(), DestType, true, FoundOverload, ConvertedArgs);
     if (!Fn) {
       msg = 0;
       return TC_Failed;
     }
 
-    SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);
+    SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn,
+                                                  ConvertedArgs);
     if (!SrcExpr.isUsable()) {
       msg = 0;
       return TC_Failed;
@@ -2773,10 +2773,10 @@
   if (tcr != TC_Success && msg != 0) {
     if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
       DeclAccessPair Found;
-      FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
-                                DestType,
-                                /*Complain*/ true,
-                                Found);
+      const TemplateArgumentList *ConvertedArgs;
+      FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(
+          SrcExpr.get(), DestType,
+          /*Complain*/ true, Found, ConvertedArgs);
       if (Fn) {
         // If DestType is a function type (not to be confused with the function
         // pointer type), it will be possible to resolve the function address,
@@ -2882,10 +2882,12 @@
 
   // Overloads are allowed with C extensions, so we need to support them.
   if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
+    const TemplateArgumentList *ConvertedArgs;
     DeclAccessPair DAP;
     if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction(
-            SrcExpr.get(), DestType, /*Complain=*/true, DAP))
-      SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD);
+            SrcExpr.get(), DestType, /*Complain=*/true, DAP, ConvertedArgs))
+      SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD,
+                                                    ConvertedArgs);
     else
       return;
     assert(SrcExpr.isUsable());
Index: clang/lib/Sema/SemaCUDA.cpp
===================================================================
--- clang/lib/Sema/SemaCUDA.cpp
+++ clang/lib/Sema/SemaCUDA.cpp
@@ -271,25 +271,28 @@
 
 void Sema::EraseUnwantedCUDAMatches(
     const FunctionDecl *Caller,
-    SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) {
+    SmallVectorImpl<std::tuple<DeclAccessPair, FunctionDecl *,
+                               const TemplateArgumentList *>> &Matches) {
   if (Matches.size() <= 1)
     return;
 
-  using Pair = std::pair<DeclAccessPair, FunctionDecl*>;
+  using Tuple =
+      std::tuple<DeclAccessPair, FunctionDecl *, const TemplateArgumentList *>;
 
   // Gets the CUDA function preference for a call from Caller to Match.
-  auto GetCFP = [&](const Pair &Match) {
-    return IdentifyCUDAPreference(Caller, Match.second);
+  auto GetCFP = [&](const Tuple &Match) {
+    return IdentifyCUDAPreference(Caller, std::get<1>(Match));
   };
 
   // Find the best call preference among the functions in Matches.
   CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(
-      Matches.begin(), Matches.end(),
-      [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); }));
+      Matches.begin(), Matches.end(), [&](const Tuple &M1, const Tuple &M2) {
+        return GetCFP(M1) < GetCFP(M2);
+      }));
 
   // Erase all functions with lower priority.
   llvm::erase_if(Matches,
-                 [&](const Pair &Match) { return GetCFP(Match) < BestCFP; });
+                 [&](const Tuple &Match) { return GetCFP(Match) < BestCFP; });
 }
 
 /// When an implicitly-declared special member has to invoke more than one
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -1603,7 +1603,8 @@
     return DeclRefExpr::Create(
         CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
         /*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(),
-        ME->getType(), ME->getValueKind(), nullptr, nullptr, ME->isNonOdrUse());
+        ME->getType(), ME->getValueKind(), nullptr, nullptr, nullptr,
+        ME->isNonOdrUse());
   }
   return nullptr;
 }
Index: clang/lib/Analysis/BodyFarm.cpp
===================================================================
--- clang/lib/Analysis/BodyFarm.cpp
+++ clang/lib/Analysis/BodyFarm.cpp
@@ -230,8 +230,8 @@
       C, base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
       SourceLocation(), MemberDecl, FoundDecl,
       DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
-      /* TemplateArgumentListInfo=*/ nullptr, MemberDecl->getType(), ValueKind,
-      OK_Ordinary, NOUR_None);
+      /* TemplateArgumentListInfo=*/nullptr, /*Deduced=*/nullptr,
+      MemberDecl->getType(), ValueKind, OK_Ordinary, NOUR_None);
 }
 
 ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) {
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -401,7 +401,8 @@
                          ExprValueKind VK, SourceLocation L,
                          const DeclarationNameLoc &LocInfo,
                          NonOdrUseReason NOUR)
-    : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D), DNLoc(LocInfo) {
+    : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D), ConvertedArgs(nullptr),
+      DNLoc(LocInfo) {
   DeclRefExprBits.HasQualifier = false;
   DeclRefExprBits.HasTemplateKWAndArgsInfo = false;
   DeclRefExprBits.HasFoundDecl = false;
@@ -419,9 +420,12 @@
                          bool RefersToEnclosingVariableOrCapture,
                          const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
                          const TemplateArgumentListInfo *TemplateArgs,
-                         QualType T, ExprValueKind VK, NonOdrUseReason NOUR)
+                         const TemplateArgumentList *ConvertedArgs, QualType T,
+                         ExprValueKind VK, NonOdrUseReason NOUR)
     : Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D),
-      DNLoc(NameInfo.getInfo()) {
+      ConvertedArgs(ConvertedArgs), DNLoc(NameInfo.getInfo()) {
+  assert(!TemplateArgs || ConvertedArgs);
+  assert(!ConvertedArgs || ConvertedArgs->size() != 0);
   DeclRefExprBits.Loc = NameInfo.getLoc();
   DeclRefExprBits.HasQualifier = QualifierLoc ? 1 : 0;
   if (QualifierLoc)
@@ -457,22 +461,21 @@
                                  SourceLocation NameLoc, QualType T,
                                  ExprValueKind VK, NamedDecl *FoundD,
                                  const TemplateArgumentListInfo *TemplateArgs,
+                                 const TemplateArgumentList *ConvertedArgs,
                                  NonOdrUseReason NOUR) {
   return Create(Context, QualifierLoc, TemplateKWLoc, D,
                 RefersToEnclosingVariableOrCapture,
-                DeclarationNameInfo(D->getDeclName(), NameLoc),
-                T, VK, FoundD, TemplateArgs, NOUR);
+                DeclarationNameInfo(D->getDeclName(), NameLoc), T, VK, FoundD,
+                TemplateArgs, ConvertedArgs, NOUR);
 }
 
-DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
-                                 NestedNameSpecifierLoc QualifierLoc,
-                                 SourceLocation TemplateKWLoc, ValueDecl *D,
-                                 bool RefersToEnclosingVariableOrCapture,
-                                 const DeclarationNameInfo &NameInfo,
-                                 QualType T, ExprValueKind VK,
-                                 NamedDecl *FoundD,
-                                 const TemplateArgumentListInfo *TemplateArgs,
-                                 NonOdrUseReason NOUR) {
+DeclRefExpr *DeclRefExpr::Create(
+    const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
+    SourceLocation TemplateKWLoc, ValueDecl *D,
+    bool RefersToEnclosingVariableOrCapture,
+    const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
+    NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs,
+    const TemplateArgumentList *ConvertedArgs, NonOdrUseReason NOUR) {
   // Filter out cases where the found Decl is the same as the value refenenced.
   if (D == FoundD)
     FoundD = nullptr;
@@ -486,9 +489,10 @@
           TemplateArgs ? TemplateArgs->size() : 0);
 
   void *Mem = Context.Allocate(Size, alignof(DeclRefExpr));
-  return new (Mem) DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
-                               RefersToEnclosingVariableOrCapture, NameInfo,
-                               FoundD, TemplateArgs, T, VK, NOUR);
+  return new (Mem)
+      DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
+                  RefersToEnclosingVariableOrCapture, NameInfo, FoundD,
+                  TemplateArgs, ConvertedArgs, T, VK, NOUR);
 }
 
 DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context,
@@ -1612,11 +1616,13 @@
 
 MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
                        ValueDecl *MemberDecl,
-                       const DeclarationNameInfo &NameInfo, QualType T,
+                       const DeclarationNameInfo &NameInfo,
+                       const TemplateArgumentList *Deduced, QualType T,
                        ExprValueKind VK, ExprObjectKind OK,
                        NonOdrUseReason NOUR)
     : Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl),
-      MemberDNLoc(NameInfo.getInfo()), MemberLoc(NameInfo.getLoc()) {
+      Deduced(Deduced), MemberDNLoc(NameInfo.getInfo()),
+      MemberLoc(NameInfo.getLoc()) {
   assert(!NameInfo.getName() ||
          MemberDecl->getDeclName() == NameInfo.getName());
   MemberExprBits.IsArrow = IsArrow;
@@ -1633,7 +1639,8 @@
     NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
     ValueDecl *MemberDecl, DeclAccessPair FoundDecl,
     DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs,
-    QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR) {
+    const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK,
+    ExprObjectKind OK, NonOdrUseReason NOUR) {
   bool HasQualOrFound = QualifierLoc || FoundDecl.getDecl() != MemberDecl ||
                         FoundDecl.getAccess() != MemberDecl->getAccess();
   bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
@@ -1645,7 +1652,7 @@
 
   void *Mem = C.Allocate(Size, alignof(MemberExpr));
   MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl,
-                                       NameInfo, T, VK, OK, NOUR);
+                                       NameInfo, Deduced, T, VK, OK, NOUR);
 
   // FIXME: remove remaining dependence computation to computeDependence().
   auto Deps = E->getDependence();
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -7041,6 +7041,7 @@
   auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
   auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
   auto ToDecl = importChecked(Err, E->getDecl());
+  auto ToConvertedArgs = importChecked(Err, E->getConvertedArgs());
   auto ToLocation = importChecked(Err, E->getLocation());
   auto ToType = importChecked(Err, E->getType());
   if (Err)
@@ -7067,7 +7068,8 @@
   auto *ToE = DeclRefExpr::Create(
       Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToDecl,
       E->refersToEnclosingVariableOrCapture(), ToLocation, ToType,
-      E->getValueKind(), ToFoundD, ToResInfo, E->isNonOdrUse());
+      E->getValueKind(), ToFoundD, ToResInfo, ToConvertedArgs,
+      E->isNonOdrUse());
   if (E->hadMultipleCandidates())
     ToE->setHadMultipleCandidates(true);
   return ToE;
@@ -7951,6 +7953,7 @@
   auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
   auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
   auto ToMemberDecl = importChecked(Err, E->getMemberDecl());
+  auto ToDeduced = importChecked(Err, E->getDeduced());
   auto ToType = importChecked(Err, E->getType());
   auto ToDecl = importChecked(Err, E->getFoundDecl().getDecl());
   auto ToName = importChecked(Err, E->getMemberNameInfo().getName());
@@ -7975,7 +7978,7 @@
   return MemberExpr::Create(Importer.getToContext(), ToBase, E->isArrow(),
                             ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc,
                             ToMemberDecl, ToFoundDecl, ToMemberNameInfo,
-                            ResInfo, ToType, E->getValueKind(),
+                            ResInfo, ToDeduced, ToType, E->getValueKind(),
                             E->getObjectKind(), E->isNonOdrUse());
 }
 
@@ -9655,6 +9658,17 @@
   return Importer.ImportAPValue(FromValue);
 }
 
+llvm::Expected<TemplateArgumentList *>
+ASTImporter::Import(const TemplateArgumentList *ArgList) {
+  ASTNodeImporter Importer(*this);
+  if (!ArgList)
+    return nullptr;
+  SmallVector<TemplateArgument, 4> ToArgs(ArgList->size());
+  if (auto Res = Importer.ImportTemplateArguments(ArgList->asArray(), ToArgs))
+    return std::move(Res);
+  return TemplateArgumentList::CreateCopy(ToContext, ToArgs);
+}
+
 Error ASTImporter::ImportDefinition(Decl *From) {
   ExpectedDecl ToOrErr = Import(From);
   if (!ToOrErr)
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3885,7 +3885,8 @@
                             bool AllowExplicitConversion = false,
                             ADLCallKind IsADLCandidate = ADLCallKind::NotADL,
                             ConversionSequenceList EarlyConversions = None,
-                            OverloadCandidateParamOrder PO = {});
+                            OverloadCandidateParamOrder PO = {},
+                            const TemplateArgumentList *Deduced = nullptr);
   void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
                       ArrayRef<Expr *> Args,
                       OverloadCandidateSet &CandidateSet,
@@ -3900,16 +3901,16 @@
                           OverloadCandidateSet& CandidateSet,
                           bool SuppressUserConversion = false,
                           OverloadCandidateParamOrder PO = {});
-  void AddMethodCandidate(CXXMethodDecl *Method,
-                          DeclAccessPair FoundDecl,
+  void AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
                           CXXRecordDecl *ActingContext, QualType ObjectType,
                           Expr::Classification ObjectClassification,
                           ArrayRef<Expr *> Args,
-                          OverloadCandidateSet& CandidateSet,
+                          OverloadCandidateSet &CandidateSet,
                           bool SuppressUserConversions = false,
                           bool PartialOverloading = false,
                           ConversionSequenceList EarlyConversions = None,
-                          OverloadCandidateParamOrder PO = {});
+                          OverloadCandidateParamOrder PO = {},
+                          const TemplateArgumentList *Deduced = nullptr);
   void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
                                   DeclAccessPair FoundDecl,
                                   CXXRecordDecl *ActingContext,
@@ -4033,10 +4034,9 @@
   QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType);
 
   FunctionDecl *
-  ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
-                                     QualType TargetType,
-                                     bool Complain,
-                                     DeclAccessPair &Found,
+  ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
+                                     bool Complain, DeclAccessPair &Found,
+                                     const TemplateArgumentList *&ConvertedArgs,
                                      bool *pHadMultipleCandidates = nullptr);
 
   FunctionDecl *
@@ -4045,10 +4045,10 @@
   bool resolveAndFixAddressOfSingleOverloadCandidate(
       ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
 
-  FunctionDecl *
-  ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
-                                              bool Complain = false,
-                                              DeclAccessPair *Found = nullptr);
+  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(
+      OverloadExpr *ovl, TemplateArgumentListInfo &ExplicitTemplateArgs,
+      const TemplateArgumentList *&ConvertedArgs, bool Complain = false,
+      DeclAccessPair *Found = nullptr);
 
   bool ResolveAndFixSingleFunctionTemplateSpecialization(
       ExprResult &SrcExpr, bool DoFunctionPointerConversion = false,
@@ -4056,12 +4056,13 @@
       QualType DestTypeForComplaining = QualType(),
       unsigned DiagIDForComplaining = 0);
 
-  Expr *FixOverloadedFunctionReference(Expr *E,
-                                       DeclAccessPair FoundDecl,
-                                       FunctionDecl *Fn);
-  ExprResult FixOverloadedFunctionReference(ExprResult,
-                                            DeclAccessPair FoundDecl,
-                                            FunctionDecl *Fn);
+  Expr *FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl,
+                                       FunctionDecl *Fn,
+                                       const TemplateArgumentList *Deduced);
+  ExprResult
+  FixOverloadedFunctionReference(ExprResult, DeclAccessPair FoundDecl,
+                                 FunctionDecl *Fn,
+                                 const TemplateArgumentList *Deduced);
 
   void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
                                    ArrayRef<Expr *> Args,
@@ -5472,14 +5473,15 @@
                    const CXXScopeSpec *SS = nullptr,
                    NamedDecl *FoundD = nullptr,
                    SourceLocation TemplateKWLoc = SourceLocation(),
-                   const TemplateArgumentListInfo *TemplateArgs = nullptr);
+                   const TemplateArgumentListInfo *TemplateArgs = nullptr,
+                   const TemplateArgumentList *ConvertedArgs = nullptr);
   DeclRefExpr *
   BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
                    const DeclarationNameInfo &NameInfo,
-                   NestedNameSpecifierLoc NNS,
-                   NamedDecl *FoundD = nullptr,
+                   NestedNameSpecifierLoc NNS, NamedDecl *FoundD = nullptr,
                    SourceLocation TemplateKWLoc = SourceLocation(),
-                   const TemplateArgumentListInfo *TemplateArgs = nullptr);
+                   const TemplateArgumentListInfo *TemplateArgs = nullptr,
+                   const TemplateArgumentList *ConvertedArgs = nullptr);
 
   ExprResult
   BuildAnonymousStructUnionMemberReference(
@@ -5523,6 +5525,7 @@
       const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D,
       NamedDecl *FoundD = nullptr,
       const TemplateArgumentListInfo *TemplateArgs = nullptr,
+      const TemplateArgumentList *ConvertedArgs = nullptr,
       bool AcceptInvalidDecl = false);
 
   ExprResult BuildLiteralOperatorCall(LookupResult &R,
@@ -5706,22 +5709,20 @@
                                    UnqualifiedId &Member,
                                    Decl *ObjCImpDecl);
 
-  MemberExpr *
-  BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
-                  const CXXScopeSpec *SS, SourceLocation TemplateKWLoc,
-                  ValueDecl *Member, DeclAccessPair FoundDecl,
-                  bool HadMultipleCandidates,
-                  const DeclarationNameInfo &MemberNameInfo, QualType Ty,
-                  ExprValueKind VK, ExprObjectKind OK,
-                  const TemplateArgumentListInfo *TemplateArgs = nullptr);
-  MemberExpr *
-  BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
-                  NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
-                  ValueDecl *Member, DeclAccessPair FoundDecl,
-                  bool HadMultipleCandidates,
-                  const DeclarationNameInfo &MemberNameInfo, QualType Ty,
-                  ExprValueKind VK, ExprObjectKind OK,
-                  const TemplateArgumentListInfo *TemplateArgs = nullptr);
+  MemberExpr *BuildMemberExpr(
+      Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS,
+      SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
+      bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
+      QualType Ty, ExprValueKind VK, ExprObjectKind OK,
+      const TemplateArgumentListInfo *TemplateArgs = nullptr,
+      const TemplateArgumentList *Deduced = nullptr);
+  MemberExpr *BuildMemberExpr(
+      Expr *Base, bool IsArrow, SourceLocation OpLoc,
+      NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
+      ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates,
+      const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK,
+      ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr,
+      const TemplateArgumentList *Deduced = nullptr);
 
   void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
   bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn,
@@ -7992,7 +7993,8 @@
   DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
                                 SourceLocation TemplateLoc,
                                 SourceLocation TemplateNameLoc,
-                                const TemplateArgumentListInfo &TemplateArgs);
+                                const TemplateArgumentListInfo &TemplateArgs,
+                                const TemplateArgumentList *&ConvertedArgs);
 
   /// Form a reference to the specialization of the given variable template
   /// corresponding to the specified argument list, or a null-but-valid result
@@ -12799,7 +12801,8 @@
   /// calling priority.
   void EraseUnwantedCUDAMatches(
       const FunctionDecl *Caller,
-      SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches);
+      SmallVectorImpl<std::tuple<DeclAccessPair, FunctionDecl *,
+                                 const TemplateArgumentList *>> &Matches);
 
   /// Given a implicit special member, infer its CUDA target from the
   /// calls it needs to make to underlying base/field special members.
Index: clang/include/clang/Sema/Overload.h
===================================================================
--- clang/include/clang/Sema/Overload.h
+++ clang/include/clang/Sema/Overload.h
@@ -885,6 +885,9 @@
       StandardConversionSequence FinalConversion;
     };
 
+    /// Deduced Arguments for Function Templates.
+    const TemplateArgumentList *Deduced;
+
     /// Get RewriteKind value in OverloadCandidateRewriteKind type (This
     /// function is to workaround the spurious GCC bitfield enum warning)
     OverloadCandidateRewriteKind getRewriteKind() const {
Index: clang/include/clang/Sema/Initialization.h
===================================================================
--- clang/include/clang/Sema/Initialization.h
+++ clang/include/clang/Sema/Initialization.h
@@ -939,6 +939,7 @@
       bool HadMultipleCandidates;
       FunctionDecl *Function;
       DeclAccessPair FoundDecl;
+      const TemplateArgumentList *ConvertedArgs;
     };
 
     union {
@@ -1237,9 +1238,10 @@
   ///
   /// \param Function the function to which the overloaded function reference
   /// resolves.
-  void AddAddressOverloadResolutionStep(FunctionDecl *Function,
-                                        DeclAccessPair Found,
-                                        bool HadMultipleCandidates);
+  void
+  AddAddressOverloadResolutionStep(FunctionDecl *Function, DeclAccessPair Found,
+                                   const TemplateArgumentList *ConvertedArgs,
+                                   bool HadMultipleCandidates);
 
   /// Add a new step in the initialization that performs a derived-to-
   /// base cast.
Index: clang/include/clang/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -1232,6 +1232,8 @@
   /// The declaration that we are referencing.
   ValueDecl *D;
 
+  const TemplateArgumentList *ConvertedArgs;
+
   /// Provides source/type location info for the declaration name
   /// embedded in D.
   DeclarationNameLoc DNLoc;
@@ -1256,7 +1258,8 @@
               SourceLocation TemplateKWLoc, ValueDecl *D,
               bool RefersToEnlosingVariableOrCapture,
               const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
-              const TemplateArgumentListInfo *TemplateArgs, QualType T,
+              const TemplateArgumentListInfo *TemplateArgs,
+              const TemplateArgumentList *ConvertedArgs, QualType T,
               ExprValueKind VK, NonOdrUseReason NOUR);
 
   /// Construct an empty declaration reference expression.
@@ -1275,6 +1278,7 @@
          bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc,
          QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr,
          const TemplateArgumentListInfo *TemplateArgs = nullptr,
+         const TemplateArgumentList *ConvertedArgs = nullptr,
          NonOdrUseReason NOUR = NOUR_None);
 
   static DeclRefExpr *
@@ -1284,6 +1288,7 @@
          const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
          NamedDecl *FoundD = nullptr,
          const TemplateArgumentListInfo *TemplateArgs = nullptr,
+         const TemplateArgumentList *ConvertedArgs = nullptr,
          NonOdrUseReason NOUR = NOUR_None);
 
   /// Construct an empty declaration reference expression.
@@ -1391,6 +1396,8 @@
     return getTrailingObjects<TemplateArgumentLoc>();
   }
 
+  const TemplateArgumentList *getConvertedArgs() const { return ConvertedArgs; }
+
   /// Retrieve the number of template arguments provided as part of this
   /// template-id.
   unsigned getNumTemplateArgs() const {
@@ -3175,6 +3182,8 @@
   /// In X.F, this is the decl referenced by F.
   ValueDecl *MemberDecl;
 
+  const TemplateArgumentList *Deduced;
+
   /// MemberDNLoc - Provides source/type location info for the
   /// declaration name embedded in MemberDecl.
   DeclarationNameLoc MemberDNLoc;
@@ -3200,21 +3209,20 @@
 
   MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
              ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo,
-             QualType T, ExprValueKind VK, ExprObjectKind OK,
-             NonOdrUseReason NOUR);
+             const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK,
+             ExprObjectKind OK, NonOdrUseReason NOUR);
   MemberExpr(EmptyShell Empty)
       : Expr(MemberExprClass, Empty), Base(), MemberDecl() {}
 
 public:
-  static MemberExpr *Create(const ASTContext &C, Expr *Base, bool IsArrow,
-                            SourceLocation OperatorLoc,
-                            NestedNameSpecifierLoc QualifierLoc,
-                            SourceLocation TemplateKWLoc, ValueDecl *MemberDecl,
-                            DeclAccessPair FoundDecl,
-                            DeclarationNameInfo MemberNameInfo,
-                            const TemplateArgumentListInfo *TemplateArgs,
-                            QualType T, ExprValueKind VK, ExprObjectKind OK,
-                            NonOdrUseReason NOUR);
+  static MemberExpr *
+  Create(const ASTContext &C, Expr *Base, bool IsArrow,
+         SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
+         SourceLocation TemplateKWLoc, ValueDecl *MemberDecl,
+         DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo,
+         const TemplateArgumentListInfo *TemplateArgs,
+         const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK,
+         ExprObjectKind OK, NonOdrUseReason NOUR);
 
   /// Create an implicit MemberExpr, with no location, qualifier, template
   /// arguments, and so on. Suitable only for non-static member access.
@@ -3225,7 +3233,8 @@
     return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
                   SourceLocation(), MemberDecl,
                   DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()),
-                  DeclarationNameInfo(), nullptr, T, VK, OK, NOUR_None);
+                  DeclarationNameInfo(), nullptr, nullptr, T, VK, OK,
+                  NOUR_None);
   }
 
   static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier,
@@ -3251,6 +3260,8 @@
     return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl;
   }
 
+  const TemplateArgumentList *getDeduced() const { return Deduced; }
+
   /// Determines whether this member expression actually had
   /// a C++ nested-name-specifier prior to the name of the member, e.g.,
   /// x->Base::foo.
Index: clang/include/clang/AST/ASTImporter.h
===================================================================
--- clang/include/clang/AST/ASTImporter.h
+++ clang/include/clang/AST/ASTImporter.h
@@ -480,6 +480,13 @@
     /// error.
     llvm::Expected<APValue> Import(const APValue &FromValue);
 
+    /// Import the given C++ TemplateArgumentList from the "from"
+    /// context into the "to" context.
+    ///
+    /// \returns The equivalent initializer in the "to" context, or the import
+    /// error.
+    llvm::Expected<TemplateArgumentList *> Import(const TemplateArgumentList *);
+
     /// Import the definition of the given declaration, including all of
     /// the declarations it contains.
     [[nodiscard]] llvm::Error ImportDefinition(Decl *From);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to