[cfe-commits] r91180 - in /cfe/trunk: include/clang/AST/CanonicalType.h include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclCXX.cpp test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp test/CXX/special/class.free/p6.cpp

Anders Carlsson andersca at mac.com
Fri Dec 11 15:23:25 PST 2009


Author: andersca
Date: Fri Dec 11 17:23:22 2009
New Revision: 91180

URL: http://llvm.org/viewvc/llvm-project?rev=91180&view=rev
Log:
Improve diagnostics for malformed delete operator function declarations.

Added:
    cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp
Modified:
    cfe/trunk/include/clang/AST/CanonicalType.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/special/class.free/p6.cpp

Modified: cfe/trunk/include/clang/AST/CanonicalType.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/CanonicalType.h?rev=91180&r1=91179&r2=91180&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/CanonicalType.h (original)
+++ cfe/trunk/include/clang/AST/CanonicalType.h Fri Dec 11 17:23:22 2009
@@ -172,6 +172,12 @@
 /// \brief Represents a canonical, potentially-qualified type.
 typedef CanQual<Type> CanQualType;
 
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+                                           CanQualType T) {
+  DB << static_cast<QualType>(T);
+  return DB;
+}
+
 //----------------------------------------------------------------------------//
 // Internal proxy classes used by canonical types
 //----------------------------------------------------------------------------//

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=91180&r1=91179&r2=91180&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Dec 11 17:23:22 2009
@@ -2220,10 +2220,6 @@
 def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">;
 def err_operator_overload_static : Error<
   "overloaded %0 cannot be a static member function">;
-def err_operator_new_param_type : Error<
-  "%0 takes type size_t (%1) as first parameter">;
-def err_operator_new_result_type : Error<
-  "%0 must return type %1">;
 def err_operator_overload_default_arg : Error<
   "parameter of overloaded %0 cannot have a default argument">;
 def err_operator_overload_must_be : Error<
@@ -2236,6 +2232,19 @@
   "parameter of overloaded post-%select{increment|decrement}1 operator must "
   "have type 'int' (not %0)">;
 
+// C++ allocation and deallocation functions.
+def err_operator_new_delete_declared_in_namespace : Error<
+  "%0 cannot be declared inside a namespace">;
+def err_operator_new_delete_declared_static : Error<
+  "%0 cannot be declared static in global scope">;
+def err_operator_new_delete_invalid_result_type : Error<
+  "%0 must return type %1">;
+def err_operator_new_delete_too_few_parameters : Error<
+  "%0 must have at least one parameter.">;
+def err_operator_new_param_type : Error<
+  "%0 takes type size_t (%1) as first parameter">;
+def err_operator_delete_param_type : Error<
+  "%0 takes type %1 as first parameter">;
 
 // C++ conversion functions
 def err_conv_function_not_member : Error<

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=91180&r1=91179&r2=91180&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Dec 11 17:23:22 2009
@@ -4604,6 +4604,52 @@
   }
 }
 
+static bool
+CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
+  // C++ [basic.stc.dynamic.deallocation]p1:
+  //   A program is ill-formed if deallocation functions are declared in a
+  //   namespace scope other than global scope or declared static in global 
+  //   scope.
+  const DeclContext *DC = FnDecl->getDeclContext()->getLookupContext();
+  if (isa<NamespaceDecl>(DC)) {
+    return SemaRef.Diag(FnDecl->getLocation(), 
+                        diag::err_operator_new_delete_declared_in_namespace)
+      << FnDecl->getDeclName();
+  } else if (isa<TranslationUnitDecl>(DC) && 
+             FnDecl->getStorageClass() == FunctionDecl::Static) {
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_declared_static)
+      << FnDecl->getDeclName();
+  }
+
+  // C++ [basic.stc.dynamic.deallocation]p2:
+  //   Each deallocation function shall return void and its first parameter 
+  //   shall be void*.
+  QualType ResultType = FnDecl->getResultType();
+  if (!ResultType->isDependentType() && !ResultType->isVoidType()) {
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_invalid_result_type) 
+      << FnDecl->getDeclName() << SemaRef.Context.VoidTy;
+  }
+
+  if (FnDecl->getNumParams() == 0) {
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_too_few_parameters)
+      << FnDecl->getDeclName();
+  }
+
+  QualType FirstParamType = 
+    SemaRef.Context.getCanonicalType(FnDecl->getParamDecl(0)->getType());
+  if (!FirstParamType->isDependentType() && 
+      FirstParamType != SemaRef.Context.VoidPtrTy) {
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_delete_param_type)
+      << FnDecl->getDeclName() << SemaRef.Context.VoidPtrTy;
+  }
+  
+  return false;
+}
+
 /// CheckOverloadedOperatorDeclaration - Check whether the declaration
 /// of this overloaded operator is well-formed. If so, returns false;
 /// otherwise, emits appropriate diagnostics and returns true.
@@ -4619,9 +4665,14 @@
   //   described completely in 3.7.3. The attributes and restrictions
   //   found in the rest of this subclause do not apply to them unless
   //   explicitly stated in 3.7.3.
-  // FIXME: Write a separate routine for checking this. For now, just allow it.
-  if (Op == OO_Delete || Op == OO_Array_Delete)
+  if (Op == OO_Delete || Op == OO_Array_Delete) {
+    return CheckOperatorDeleteDeclaration(*this, FnDecl);
+      FnDecl->setInvalidDecl();
+      return true;
+    }
+    
     return false;
+  }
   
   if (Op == OO_New || Op == OO_Array_New) {
     bool ret = false;
@@ -4638,8 +4689,8 @@
     QualType ResultTy = Context.getCanonicalType(FnDecl->getResultType());
     if (!ResultTy->isDependentType() && ResultTy != Context.VoidPtrTy)
       return Diag(FnDecl->getLocation(),
-                  diag::err_operator_new_result_type) << FnDecl->getDeclName()
-                  << static_cast<QualType>(Context.VoidPtrTy);
+                  diag::err_operator_new_delete_invalid_result_type) 
+        << FnDecl->getDeclName() << Context.VoidPtrTy;
     return ret;
   }
 

Added: cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp?rev=91180&view=auto

==============================================================================
--- cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p1.cpp Fri Dec 11 17:23:22 2009
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct A {
+  void operator delete(void*);
+};
+
+namespace NS {
+  void operator delete(void *); // expected-error {{'operator delete' cannot be declared inside a namespace}}
+}
+
+static void operator delete(void *); // expected-error {{'operator delete' cannot be declared static in global scope}}

Modified: cfe/trunk/test/CXX/special/class.free/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.free/p6.cpp?rev=91180&r1=91179&r2=91180&view=diff

==============================================================================
--- cfe/trunk/test/CXX/special/class.free/p6.cpp (original)
+++ cfe/trunk/test/CXX/special/class.free/p6.cpp Fri Dec 11 17:23:22 2009
@@ -2,7 +2,7 @@
 #include <stddef.h>
 
 struct A {
-  void operator delete(size_t) {
+  void operator delete(void*) {
     (void)this; // expected-error {{invalid use of 'this' outside of a nonstatic member function}}
   }
   void operator delete[](void*) {





More information about the cfe-commits mailing list