More improvement in building list of visible conversion
functions for a class when needed.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81624 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index abb5505..591f856 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -17,6 +17,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -293,47 +294,48 @@
   if (const RecordType *Record = ClassType->getAs<RecordType>()) {
     OverloadedFunctionDecl *Conversions
       = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
+    llvm::SmallPtrSet<QualType, 8> TopConversionsTypeSet;
+    bool inTopClass = (RD == this);
+    if (!inTopClass && 
+        (Conversions->function_begin() != Conversions->function_end())) {
+      // populate the TypeSet with the type of current class's conversions.
+      OverloadedFunctionDecl *TopConversions = RD->getConversionFunctions();
+      for (OverloadedFunctionDecl::function_iterator
+           TFunc = TopConversions->function_begin(),
+           TFuncEnd = TopConversions->function_end();
+           TFunc != TFuncEnd; ++TFunc) {
+        NamedDecl *TopConv = TFunc->get();
+        QualType TConvType;
+        if (FunctionTemplateDecl *TConversionTemplate =
+            dyn_cast<FunctionTemplateDecl>(TopConv))
+          TConvType = 
+            getASTContext().getCanonicalType(
+                          TConversionTemplate->getTemplatedDecl()->getType());
+        else 
+          TConvType = 
+            getASTContext().getCanonicalType(
+                                        cast<FunctionDecl>(TopConv)->getType());
+        TopConversionsTypeSet.insert(TConvType);
+      }
+    }
+    
     for (OverloadedFunctionDecl::function_iterator
          Func = Conversions->function_begin(),
          FuncEnd = Conversions->function_end();
          Func != FuncEnd; ++Func) {
       NamedDecl *Conv = Func->get();
-      bool Candidate = true;
       // Only those conversions not exact match of conversions in current
       // class are candidateconversion routines.
-      // FIXME. This is a O(n^2) algorithm. 
-      if (RD != this) {
-        OverloadedFunctionDecl *TopConversions = RD->getConversionFunctions();
-        QualType ConvType;
-        FunctionDecl *FD;
-        if (FunctionTemplateDecl *ConversionTemplate = 
-              dyn_cast<FunctionTemplateDecl>(Conv))
-          FD = ConversionTemplate->getTemplatedDecl();
-        else
-          FD = cast<FunctionDecl>(Conv);
-        ConvType = getASTContext().getCanonicalType(FD->getType());
-        
-        for (OverloadedFunctionDecl::function_iterator
-             TFunc = TopConversions->function_begin(),
-             TFuncEnd = TopConversions->function_end();
-             TFunc != TFuncEnd; ++TFunc) {
-          
-          NamedDecl *TopConv = TFunc->get();
-          FunctionDecl *TFD;
-          QualType TConvType;
-          if (FunctionTemplateDecl *TConversionTemplate =
-                dyn_cast<FunctionTemplateDecl>(TopConv))
-            TFD = TConversionTemplate->getTemplatedDecl();
-          else 
-            TFD = cast<FunctionDecl>(TopConv);
-          TConvType = getASTContext().getCanonicalType(TFD->getType());
-          if (ConvType == TConvType) {
-            Candidate = false;
-            break;
-          }
-        }
-      }
-      if (Candidate) {
+      QualType ConvType;
+      if (FunctionTemplateDecl *ConversionTemplate = 
+            dyn_cast<FunctionTemplateDecl>(Conv))
+        ConvType = 
+          getASTContext().getCanonicalType(
+                            ConversionTemplate->getTemplatedDecl()->getType());
+      else
+        ConvType = 
+          getASTContext().getCanonicalType(cast<FunctionDecl>(Conv)->getType());
+      if (inTopClass || !TopConversionsTypeSet.count(ConvType)) {
         if (FunctionTemplateDecl *ConversionTemplate =
               dyn_cast<FunctionTemplateDecl>(Conv))
           RD->addVisibleConversionFunction(ConversionTemplate);