mizvekov created this revision.
Herald added a subscriber: martong.
Herald added a reviewer: shafik.
Herald added a reviewer: aaron.ballman.
Herald added a reviewer: NoQ.
Herald added a project: All.
mizvekov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

WIP - Not ready for review

Signed-off-by: Matheus Izvekov <mizve...@gmail.com>

Depends on D134113 <https://reviews.llvm.org/D134113>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134115

Files:
  clang/include/clang/AST/ASTImporter.h
  clang/include/clang/AST/Expr.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/Sema/SemaCast.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/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTReaderStmt.cpp
  clang/lib/Serialization/ASTWriterStmt.cpp

Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -911,6 +911,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/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1027,6 +1027,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
@@ -8847,6 +8847,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/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3740,6 +3740,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:
@@ -3749,8 +3754,9 @@
       !ParamType->isMemberFunctionPointerType()) {
     if (Ovl->hasExplicitTemplateArgs()) {
       // But we can still look for an explicit specialization.
-      if (FunctionDecl *ExplicitSpec
-            = S.ResolveSingleFunctionTemplateSpecialization(Ovl))
+      if (FunctionDecl *ExplicitSpec =
+              S.ResolveSingleFunctionTemplateSpecialization(
+                  Ovl, ExplicitTemplateArgs))
         return GetTypeOfFunction(S, R, ExplicitSpec);
     }
 
@@ -3762,10 +3768,6 @@
     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) {
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -7475,7 +7475,7 @@
         if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
           return ExprError();
 
-        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn, nullptr);
         ArgType = Arg->getType();
       } else
         return ExprError();
@@ -7527,7 +7527,7 @@
         if (DiagnoseUseOfDecl(Fn, Arg->getBeginLoc()))
           return ExprError();
 
-        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn, nullptr);
         ArgType = Arg->getType();
       } else
         return ExprError();
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -6332,7 +6332,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 +6351,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 +6396,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 +6931,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 +6968,7 @@
   Candidate.IsSurrogate = false;
   Candidate.IgnoreObjectArgument = false;
   Candidate.ExplicitCallArguments = Args.size();
+  Candidate.Deduced = Deduced;
 
   unsigned NumParams = Proto->getNumParams();
 
@@ -7146,7 +7145,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 +7225,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
@@ -12075,15 +12075,20 @@
         FailedCandidates(OvlExpr->getNameLoc(), /*ForTakingAddress=*/true) {
     ExtractUnqualifiedFunctionTypeFromTargetType();
 
+    if (OvlExpr->hasExplicitTemplateArgs())
+      OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);
+
     if (TargetFunctionType->isFunctionType()) {
       if (UnresolvedMemberExpr *UME = dyn_cast<UnresolvedMemberExpr>(OvlExpr))
         if (!UME->isImplicitAccess() &&
-            !S.ResolveSingleFunctionTemplateSpecialization(UME))
+            (!OvlExpr->hasExplicitTemplateArgs() ||
+             !S.ResolveSingleFunctionTemplateSpecialization(
+                 UME, OvlExplicitTemplateArgs)))
           StaticMemberFunctionFromBoundPointer = true;
     } else if (OvlExpr->hasExplicitTemplateArgs()) {
       DeclAccessPair dap;
       if (FunctionDecl *Fn = S.ResolveSingleFunctionTemplateSpecialization(
-              OvlExpr, false, &dap)) {
+              OvlExpr, OvlExplicitTemplateArgs, /*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
@@ -12102,9 +12107,6 @@
       return;
     }
 
-    if (OvlExpr->hasExplicitTemplateArgs())
-      OvlExpr->copyTemplateArgumentsInto(OvlExplicitTemplateArgs);
-
     if (FindAllFunctionsThatMatchTargetTypeExactly()) {
       // C++ [over.over]p4:
       //   If more than one function is selected, [...]
@@ -12590,7 +12592,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 +12610,9 @@
 ///
 /// 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,
+    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 +12620,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
@@ -12699,50 +12697,53 @@
   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);
+
+    DeclAccessPair found;
+    if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
+            ovl.Expression, ExplicitTemplateArgs, /*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, nullptr);
+
+      // If desired, do function-to-pointer decay.
+      if (doFunctionPointerConversion) {
+        SingleFunctionExpression = DefaultFunctionArrayLvalueConversion(
+            SingleFunctionExpression.get());
+        if (SingleFunctionExpression.isInvalid()) {
+          SrcExpr = ExprError();
+          return true;
+        }
+      }
     }
   }
 
@@ -13255,7 +13256,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 +13315,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 +14584,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 +15200,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 +15214,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 +15230,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 +15265,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 +15290,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;
 
@@ -15370,10 +15376,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
@@ -8261,9 +8261,8 @@
       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, nullptr);
       // We might get back another placeholder expression if we resolved to a
       // builtin.
       if (!CurInit.isInvalid())
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);
 
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -4250,7 +4250,7 @@
     if (DiagnoseUseOfDecl(Fn, From->getBeginLoc()))
       return ExprError();
 
-    From = FixOverloadedFunctionReference(From, Found, Fn);
+    From = FixOverloadedFunctionReference(From, Found, Fn, nullptr);
 
     // 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
@@ -9967,7 +9967,7 @@
     DeclAccessPair DAP;
     if (FunctionDecl *FD = ResolveAddressOfOverloadedFunction(
             RHS.get(), LHSType, /*Complain=*/false, DAP))
-      RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD);
+      RHS = FixOverloadedFunctionReference(RHS.get(), DAP, FD, nullptr);
     else
       return Incompatible;
   }
@@ -14258,14 +14258,18 @@
       }
 
       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);
+        if (ResolveSingleFunctionTemplateSpecialization(Ovl,
+                                                        ExplicitTemplateArgs))
+          return Context.OverloadTy;
+      }
+      Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+          << OrigOp.get()->getSourceRange();
+      return QualType();
     }
 
     if (PTy->getKind() == BuiltinType::UnknownAny)
@@ -19183,8 +19187,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())
@@ -19201,7 +19205,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: {
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -3599,9 +3599,13 @@
       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;
+      ULE->copyTemplateArgumentsInto(ExplicitTemplateArgs);
+      FD = S.ResolveSingleFunctionTemplateSpecialization(
+          ULE, ExplicitTemplateArgs, /*Complain=*/true);
+    }
     NI = ULE->getNameInfo();
     if (!FD) {
       S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -1808,7 +1808,8 @@
       return TC_Failed;
     }
 
-    SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);
+    SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn,
+                                                  nullptr);
     if (!SrcExpr.isUsable()) {
       msg = 0;
       return TC_Failed;
@@ -2885,7 +2886,8 @@
     DeclAccessPair DAP;
     if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction(
             SrcExpr.get(), DestType, /*Complain=*/true, DAP))
-      SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD);
+      SrcExpr =
+          Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD, nullptr);
     else
       return;
     assert(SrcExpr.isUsable());
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
@@ -1612,11 +1612,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 +1635,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 +1648,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
@@ -7951,6 +7951,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 +7976,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 +9656,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
@@ -3882,7 +3882,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,
@@ -3897,16 +3898,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,
@@ -4042,10 +4043,9 @@
   bool resolveAndFixAddressOfSingleOverloadCandidate(
       ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
 
-  FunctionDecl *
-  ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
-                                              bool Complain = false,
-                                              DeclAccessPair *Found = nullptr);
+  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(
+      OverloadExpr *ovl, TemplateArgumentListInfo &ExplicitTemplateArgs,
+      bool Complain = false, DeclAccessPair *Found = nullptr);
 
   bool ResolveAndFixSingleFunctionTemplateSpecialization(
       ExprResult &SrcExpr, bool DoFunctionPointerConversion = false,
@@ -4053,12 +4053,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,
@@ -5703,22 +5704,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,
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/AST/Expr.h
===================================================================
--- clang/include/clang/AST/Expr.h
+++ clang/include/clang/AST/Expr.h
@@ -3175,6 +3175,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 +3202,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 +3226,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 +3253,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