Handle C++ delete expressions when the overloaded delete operator is a
"usual deallocation function" with two arguments. CodeGen will have to
handle this case specifically, since the value for the second argument
(the size of the allocated object) may have to be computed at run
time.

Fixes the Sema part of PR4782.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83080 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 183bd8f..5846866 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -589,6 +589,7 @@
                                   DeclarationName Name, Expr** Args,
                                   unsigned NumArgs, DeclContext *Ctx,
                                   bool AllowMissing, FunctionDecl *&Operator) {
+  // FIXME: Change to use LookupQualifiedName!
   DeclContext::lookup_iterator Alloc, AllocEnd;
   llvm::tie(Alloc, AllocEnd) = Ctx->lookup(Name);
   if (Alloc == AllocEnd) {
@@ -602,9 +603,13 @@
   for (; Alloc != AllocEnd; ++Alloc) {
     // Even member operator new/delete are implicitly treated as
     // static, so don't use AddMemberCandidate.
-    if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(*Alloc))
+    if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(*Alloc)) {
       AddOverloadCandidate(Fn, Args, NumArgs, Candidates,
                            /*SuppressUserConversions=*/false);
+      continue;
+    } 
+    
+    // FIXME: Handle function templates
   }
 
   // Do the resolution.
@@ -616,7 +621,7 @@
     // The first argument is size_t, and the first parameter must be size_t,
     // too. This is checked on declaration and can be assumed. (It can't be
     // asserted on, though, since invalid decls are left in there.)
-    for (unsigned i = 1; i < NumArgs; ++i) {
+    for (unsigned i = 0; i < NumArgs; ++i) {
       // FIXME: Passing word to diagnostic.
       if (PerformCopyInitialization(Args[i],
                                     FnDecl->getParamDecl(i)->getType(),
@@ -844,27 +849,27 @@
                                    << Ex->getSourceRange()))
       return ExprError();
 
-    // FIXME: This should be shared with the code for finding the delete
-    // operator in ActOnCXXNew.
-    IntegerLiteral Size(llvm::APInt::getNullValue(
-                        Context.Target.getPointerWidth(0)),
-                        Context.getSizeType(),
-                        SourceLocation());
-    ImplicitCastExpr Cast(Context.getPointerType(Context.VoidTy),
-                          CastExpr::CK_Unknown, &Size, false);
-    Expr *DeleteArg = &Cast;
-
     DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
                                       ArrayForm ? OO_Array_Delete : OO_Delete);
 
     if (Pointee->isRecordType() && !UseGlobal) {
       CXXRecordDecl *Record
         = cast<CXXRecordDecl>(Pointee->getAs<RecordType>()->getDecl());
-      // FIXME: We fail to find inherited overloads.
-      if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,
-                                 &DeleteArg, 1, Record, /*AllowMissing=*/true,
-                                 OperatorDelete))
-        return ExprError();
+      
+      // Try to find operator delete/operator delete[] in class scope.
+      LookupResult Found = LookupQualifiedName(Record, DeleteName, 
+                                               LookupOrdinaryName);
+      // FIXME: Diagnose ambiguity properly
+      assert(!Found.isAmbiguous() && "Ambiguous delete/delete[] not handled");
+      for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+           F != FEnd; ++F) {
+        if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F))
+          if (Delete->isUsualDeallocationFunction()) {
+            OperatorDelete = Delete;
+            break;
+          }
+      }
+      
       if (!Record->hasTrivialDestructor())
         if (const CXXDestructorDecl *Dtor = Record->getDestructor(Context))
           MarkDeclarationReferenced(StartLoc,
@@ -876,7 +881,7 @@
       DeclareGlobalNewDelete();
       DeclContext *TUDecl = Context.getTranslationUnitDecl();
       if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,
-                                 &DeleteArg, 1, TUDecl, /*AllowMissing=*/false,
+                                 &Ex, 1, TUDecl, /*AllowMissing=*/false,
                                  OperatorDelete))
         return ExprError();
     }