Improve support for overloaded operator templates.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74390 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 0dd68fe..a53e420 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -679,7 +679,7 @@
     OR_Deleted              ///< Overload resoltuion refers to a deleted function.
   };
 
-  typedef llvm::SmallPtrSet<FunctionDecl *, 16> FunctionSet;
+  typedef llvm::SmallPtrSet<AnyFunctionDecl, 16> FunctionSet;
   typedef llvm::SmallPtrSet<NamespaceDecl *, 16> AssociatedNamespaceSet;
   typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
 
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index cc9e783..e99217e 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1604,9 +1604,17 @@
 
   for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end();
        Op != OpEnd; ++Op) {
-    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op))
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) {
       if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
         Functions.insert(FD); // FIXME: canonical FD
+    } else if (FunctionTemplateDecl *FunTmpl 
+                 = dyn_cast<FunctionTemplateDecl>(*Op)) {
+      // FIXME: friend operators?
+      // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate, 
+      // later?
+      if (!FunTmpl->getDeclContext()->isRecord())
+        Functions.insert(FunTmpl);
+    }
   }
 }
 
@@ -1649,11 +1657,10 @@
     //        lookup (11.4).
     DeclContext::lookup_iterator I, E;
     for (llvm::tie(I, E) = (*NS)->lookup(Context, Name); I != E; ++I) {
-      FunctionDecl *Func = dyn_cast<FunctionDecl>(*I);
-      if (!Func)
-        break;
-
-      Functions.insert(Func);
+      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
+        Functions.insert(Func);
+      else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))
+        Functions.insert(FunTmpl);
     }
   }
   
@@ -1662,11 +1669,10 @@
     for (llvm::tie(I, E) 
            = Context.getTranslationUnitDecl()->lookup(Context, Name); 
          I != E; ++I) {
-      FunctionDecl *Func = dyn_cast<FunctionDecl>(*I);
-      if (!Func)
-        break;
-      
-      Functions.insert(Func);
+      if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I))
+        Functions.insert(Func);
+      else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I))
+        Functions.insert(FunTmpl);
     }
   }
 }
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index fcc1557..e240c04 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -2161,9 +2161,15 @@
                                  bool SuppressUserConversions) {
   for (FunctionSet::const_iterator F = Functions.begin(), 
                                 FEnd = Functions.end();
-       F != FEnd; ++F)
-    AddOverloadCandidate(*F, Args, NumArgs, CandidateSet, 
-                         SuppressUserConversions);
+       F != FEnd; ++F) {
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F))
+      AddOverloadCandidate(FD, Args, NumArgs, CandidateSet, 
+                           SuppressUserConversions);
+    else
+      AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*F), Args, 
+                                   NumArgs, CandidateSet, 
+                                   SuppressUserConversions);
+  }
 }
 
 /// AddMethodCandidate - Adds the given C++ member function to the set
@@ -3405,8 +3411,11 @@
   for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
                                    CandEnd = CandidateSet.end();
        Cand != CandEnd; ++Cand)
-    if (Cand->Function)
+    if (Cand->Function) {
       Functions.insert(Cand->Function);
+      if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
+        Functions.insert(FunTmpl);
+    }
 
   ArgumentDependentLookup(Name, Args, NumArgs, Functions);
 
@@ -3415,15 +3424,23 @@
   for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
                                    CandEnd = CandidateSet.end();
        Cand != CandEnd; ++Cand)
-    if (Cand->Function)
+    if (Cand->Function) {
       Functions.erase(Cand->Function);
+      if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
+        Functions.erase(FunTmpl);
+    }
 
   // For each of the ADL candidates we found, add it to the overload
   // set.
   for (FunctionSet::iterator Func = Functions.begin(),
                           FuncEnd = Functions.end();
-       Func != FuncEnd; ++Func)
-    AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet);
+       Func != FuncEnd; ++Func) {
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func))
+      AddOverloadCandidate(FD, Args, NumArgs, CandidateSet);
+    else
+      AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func), Args, 
+                                   NumArgs, CandidateSet);
+  }
 }
 
 /// isBetterOverloadCandidate - Determines whether the first overload