For a C++ delete expression where the operand is of class type that
has a single conversion to pointer-to-object type, implicitly convert
to that pointer-to-object type (C++ [expr.delete]p1).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81401 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 25dc769..d08d445 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -717,9 +717,10 @@
 Action::OwningExprResult
 Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
                      bool ArrayForm, ExprArg Operand) {
-  // C++ 5.3.5p1: "The operand shall have a pointer type, or a class type
-  //   having a single conversion function to a pointer type. The result has
-  //   type void."
+  // C++ [expr.delete]p1:
+  //   The operand shall have a pointer type, or a class type having a single
+  //   conversion function to a pointer type. The result has type void.
+  //
   // DR599 amends "pointer type" to "pointer to object type" in both cases.
 
   FunctionDecl *OperatorDelete = 0;
@@ -728,8 +729,40 @@
   if (!Ex->isTypeDependent()) {
     QualType Type = Ex->getType();
 
-    if (Type->isRecordType()) {
-      // FIXME: Find that one conversion function and amend the type.
+    if (const RecordType *Record = Type->getAs<RecordType>()) {
+      // FIXME: Inherited conversion functions!
+      llvm::SmallVector<CXXConversionDecl *, 4> ObjectPtrConversions;
+      
+      OverloadedFunctionDecl *Conversions
+        = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions();
+      for (OverloadedFunctionDecl::function_iterator
+             Func = Conversions->function_begin(),
+             FuncEnd = Conversions->function_end();
+           Func != FuncEnd; ++Func) {
+        // Skip over templated conversion functions; they aren't considered.
+        if (isa<FunctionTemplateDecl>(*Func))
+          continue;
+        
+        CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
+        
+        QualType ConvType = Conv->getConversionType().getNonReferenceType();
+        if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>())
+          if (ConvPtrType->getPointeeType()->isObjectType())
+            ObjectPtrConversions.push_back(Conv);
+      }
+      
+      if (ObjectPtrConversions.size() == 1) {
+        // We have a single conversion to a pointer-to-object type. Perform
+        // that conversion.
+        Operand.release();
+        if (PerformImplicitConversion(Ex, 
+                            ObjectPtrConversions.front()->getConversionType(), 
+                                      "converting"))
+          return ExprError();
+        
+        Operand = Owned(Ex);
+        Type = Ex->getType();
+      }
     }
 
     if (!Type->isPointerType())