]> granicus.if.org Git - clang/commitdiff
Factor finding a deallocation function for a record type out into a separate function.
authorAnders Carlsson <andersca@mac.com>
Sun, 15 Nov 2009 18:45:20 +0000 (18:45 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 15 Nov 2009 18:45:20 +0000 (18:45 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@88857 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaExprCXX.cpp

index d736dfbac5a8fdff21304fe68e699d9db6b753d4..0dd106ecafb9695683f223a49e5c9f1e66980db8 100644 (file)
@@ -2112,6 +2112,9 @@ public:
   void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
                                        QualType Argument);
 
+  bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, 
+                                DeclarationName Name, FunctionDecl* &Operator);
+
   /// ActOnCXXDelete - Parsed a C++ 'delete' expression
   virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc,
                                           bool UseGlobal, bool ArrayForm,
index f5ce44e106330c79154b08eb0ee2fa192321e723..d0279538e3af79c876eb0fe0ea081f2d066c4676 100644 (file)
@@ -753,6 +753,59 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
   ((DeclContext *)TUScope->getEntity())->addDecl(Alloc);
 }
 
+bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
+                                    DeclarationName Name,
+                                    FunctionDecl* &Operator) {
+  LookupResult Found;
+  // Try to find operator delete/operator delete[] in class scope.
+  LookupQualifiedName(Found, RD, Name, LookupOrdinaryName);
+  
+  if (Found.isAmbiguous()) {
+    DiagnoseAmbiguousLookup(Found, Name, StartLoc);
+    return true;
+  }
+
+  for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+       F != FEnd; ++F) {
+    if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F))
+      if (Delete->isUsualDeallocationFunction()) {
+        Operator = Delete;
+        return false;
+      }
+  }
+
+  // We did find operator delete/operator delete[] declarations, but
+  // none of them were suitable.
+  if (!Found.empty()) {
+    Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
+      << Name << RD;
+        
+    for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
+         F != FEnd; ++F) {
+      Diag((*F)->getLocation(), 
+           diag::note_delete_member_function_declared_here)
+        << Name;
+    }
+
+    return true;
+  }
+
+  // Look for a global declaration.
+  DeclareGlobalNewDelete();
+  DeclContext *TUDecl = Context.getTranslationUnitDecl();
+  
+  CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation());
+  Expr* DeallocArgs[1];
+  DeallocArgs[0] = &Null;
+  if (FindAllocationOverload(StartLoc, SourceRange(), Name,
+                             DeallocArgs, 1, TUDecl, /*AllowMissing=*/false,
+                             Operator))
+    return true;
+
+  assert(Operator && "Did not find a deallocation function!");
+  return false;
+}
+
 /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
 /// @code ::delete ptr; @endcode
 /// or
@@ -844,52 +897,21 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
     DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
                                       ArrayForm ? OO_Array_Delete : OO_Delete);
 
-    LookupResult Found;
-    if (Pointee->isRecordType() && !UseGlobal) {
-      CXXRecordDecl *Record
-        = cast<CXXRecordDecl>(Pointee->getAs<RecordType>()->getDecl());
-      
-      // Try to find operator delete/operator delete[] in class scope.
-      LookupQualifiedName(Found, Record, DeleteName, LookupOrdinaryName);
-      
-      if (Found.isAmbiguous()) {
-        DiagnoseAmbiguousLookup(Found, DeleteName, StartLoc);
-        return ExprError();
-      }
-      
-      // FIXME: Diagnose ambiguity properly
-      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 (!OperatorDelete && !Found.empty()) {
-        // We did find operator delete/operator delete[] declarations, but
-        // none of them were suitable.
-        Diag(StartLoc, diag::err_no_suitable_delete_member_function_found)
-        << DeleteName << Record;
-        
-        for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();
-             F != FEnd; ++F) {
-          Diag((*F)->getLocation(), 
-               diag::note_delete_member_function_declared_here)
-          << DeleteName;
-        }
+    if (const RecordType *RT = Pointee->getAs<RecordType>()) {
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+      if (!UseGlobal && 
+          FindDeallocationFunction(StartLoc, RD, DeleteName, OperatorDelete))
         return ExprError();
-      }
       
-      if (!Record->hasTrivialDestructor())
-        if (const CXXDestructorDecl *Dtor = Record->getDestructor(Context))
+      if (!RD->hasTrivialDestructor())
+        if (const CXXDestructorDecl *Dtor = RD->getDestructor(Context))
           MarkDeclarationReferenced(StartLoc,
                                     const_cast<CXXDestructorDecl*>(Dtor));
     }
-
+    
     if (!OperatorDelete) {
-      // Didn't find a member overload. Look for a global one.
+      // Look for a global declaration.
       DeclareGlobalNewDelete();
       DeclContext *TUDecl = Context.getTranslationUnitDecl();
       if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName,