Patch to build visible conversion function list lazily and make its 
first use in calling the conversion function on delete statements.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81576 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 073ef94..e878a3d 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -35,6 +35,7 @@
     HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true),
     HasTrivialDestructor(true), Bases(0), NumBases(0), VBases(0), NumVBases(0),
     Conversions(DC, DeclarationName()),
+    VisibleConversions(DC, DeclarationName()),
     TemplateOrInstantiation() { }
 
 CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -282,6 +283,89 @@
   PlainOldData = false;
 }
 
+/// getVisibleConversionFunctions - get all conversion functions visible
+/// in current class; including conversion function templates.
+OverloadedFunctionDecl *
+CXXRecordDecl::getVisibleConversionFunctions(ASTContext &Context,
+                                             CXXRecordDecl *RD) {
+  // If visible conversion list is already evaluated, return it.
+  if (RD == this &&
+      VisibleConversions.function_begin() != VisibleConversions.function_end())
+    return &VisibleConversions;
+    
+  QualType ClassType = Context.getTypeDeclType(this);
+  if (const RecordType *Record = ClassType->getAs<RecordType>()) {
+    OverloadedFunctionDecl *Conversions
+      = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
+    for (OverloadedFunctionDecl::function_iterator
+         Func = Conversions->function_begin(),
+         FuncEnd = Conversions->function_end();
+         Func != FuncEnd; ++Func) {
+      if (FunctionTemplateDecl *ConversionTemplate = 
+            dyn_cast<FunctionTemplateDecl>(*Func)) {
+        RD->addVisibleConversionFunction(Context, ConversionTemplate);
+        continue;
+      }
+      CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
+      bool Candidate = true;
+      // Only those conversions not exact match of conversions in current
+      // class are candidateconversion routines.
+      if (RD != this) {
+        OverloadedFunctionDecl *TopConversions = RD->getConversionFunctions();
+        QualType ConvType = Context.getCanonicalType(Conv->getType());
+        for (OverloadedFunctionDecl::function_iterator
+             TFunc = TopConversions->function_begin(),
+             TFuncEnd = TopConversions->function_end();
+             TFunc != TFuncEnd; ++TFunc) {
+          CXXConversionDecl *TopConv = cast<CXXConversionDecl>(*TFunc);
+          QualType TConvType = Context.getCanonicalType(TopConv->getType());
+          if (ConvType == TConvType) {
+            Candidate = false;
+            break;
+          }
+        }
+      }
+      if (Candidate) {
+        if (FunctionTemplateDecl *ConversionTemplate
+              = Conv->getDescribedFunctionTemplate())
+          RD->addVisibleConversionFunction(Context, ConversionTemplate);
+        else if (!Conv->getPrimaryTemplate()) // ignore specializations
+          RD->addVisibleConversionFunction(Context, Conv);
+      }
+    }
+  }
+  
+  for (CXXRecordDecl::base_class_iterator VBase = vbases_begin(),
+       E = vbases_end(); VBase != E; ++VBase) {
+    CXXRecordDecl *VBaseClassDecl
+      = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
+    VBaseClassDecl->getVisibleConversionFunctions(Context, RD);
+  }
+  for (CXXRecordDecl::base_class_iterator Base = bases_begin(),
+       E = bases_end(); Base != E; ++Base) {
+    if (Base->isVirtual())
+      continue;
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    BaseClassDecl->getVisibleConversionFunctions(Context, RD);
+  }
+  return &VisibleConversions;
+}
+
+void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context,
+                                          CXXConversionDecl *ConvDecl) {
+  assert(!ConvDecl->getDescribedFunctionTemplate() &&
+         "Conversion function templates should cast to FunctionTemplateDecl.");
+  VisibleConversions.addOverload(ConvDecl);
+}
+
+void CXXRecordDecl::addVisibleConversionFunction(ASTContext &Context,
+                                          FunctionTemplateDecl *ConvDecl) {
+  assert(isa<CXXConversionDecl>(ConvDecl->getTemplatedDecl()) &&
+         "Function template is not a conversion function template");
+  VisibleConversions.addOverload(ConvDecl);
+}
+
 void CXXRecordDecl::addConversionFunction(ASTContext &Context,
                                           CXXConversionDecl *ConvDecl) {
   assert(!ConvDecl->getDescribedFunctionTemplate() &&