[cfe-commits] r91244 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/AST/Decl.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp test/SemaCXX/new-delete.cpp

Anders Carlsson andersca at mac.com
Sun Dec 13 09:53:43 PST 2009


Author: andersca
Date: Sun Dec 13 11:53:43 2009
New Revision: 91244

URL: http://llvm.org/viewvc/llvm-project?rev=91244&view=rev
Log:
More improvements to checking allocation and deallocation functions.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp
    cfe/trunk/test/SemaCXX/new-delete.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Dec 13 11:53:43 2009
@@ -2250,6 +2250,8 @@
   "use size_t (%1) instead">;
 def err_operator_new_param_type : Error<
   "%0 takes type size_t (%1) as first parameter">;
+def err_operator_new_default_arg: Error<
+  "parameter of %0 cannot have a default argument">;
 def err_operator_delete_dependent_param_type : Error<
   "%0 cannot take a dependent type as first parameter; use %1 instead">;
 def err_operator_delete_param_type : Error<

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=91244&r1=91243&r2=91244&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sun Dec 13 11:53:43 2009
@@ -95,8 +95,8 @@
   if (const Expr *E = getInit())
     return E->getSourceRange();
   
-  if (const Expr *E = getUninstantiatedDefaultArg())
-    return E->getSourceRange();
+  if (hasUninstantiatedDefaultArg())
+    return getUninstantiatedDefaultArg()->getSourceRange();
     
   return SourceRange();
 }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Dec 13 11:53:43 2009
@@ -4624,33 +4624,83 @@
   return false;
 }
 
+static inline bool
+CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
+                            CanQualType ExpectedResultType,
+                            CanQualType ExpectedFirstParamType,
+                            unsigned DependentParamTypeDiag,
+                            unsigned InvalidParamTypeDiag) {
+  QualType ResultType = 
+    FnDecl->getType()->getAs<FunctionType>()->getResultType();
+
+  // Check that the result type is not dependent.
+  if (ResultType->isDependentType())
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_dependent_result_type)
+    << FnDecl->getDeclName() << ExpectedResultType;
+
+  // Check that the result type is what we expect.
+  if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_invalid_result_type) 
+    << FnDecl->getDeclName() << ExpectedResultType;
+  
+  // A function template must have at least 2 parameters.
+  if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                      diag::err_operator_new_delete_template_too_few_parameters)
+        << FnDecl->getDeclName();
+  
+  // The function decl must have at least 1 parameter.
+  if (FnDecl->getNumParams() == 0)
+    return SemaRef.Diag(FnDecl->getLocation(),
+                        diag::err_operator_new_delete_too_few_parameters)
+      << FnDecl->getDeclName();
+ 
+  // Check the the first parameter type is not dependent.
+  QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
+  if (FirstParamType->isDependentType())
+    return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag)
+      << FnDecl->getDeclName() << ExpectedFirstParamType;
+
+  // Check that the first parameter type is what we expect.
+  if (SemaRef.Context.getCanonicalType(FirstParamType) != 
+      ExpectedFirstParamType)
+    return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
+    << FnDecl->getDeclName() << ExpectedFirstParamType;
+  
+  return false;
+}
+
 static bool
-CheckOperatorNewDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
+CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
   // C++ [basic.stc.dynamic.allocation]p1:
   //   A program is ill-formed if an allocation function is declared in a
   //   namespace scope other than global scope or declared static in global 
   //   scope.
   if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
     return true;
-  
-  bool ret = false;
-  if (FunctionDecl::param_iterator Param = FnDecl->param_begin()) {
-    QualType SizeTy = 
-      SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType());
-    QualType T = SemaRef.Context.getCanonicalType((*Param)->getType());
-    if (!T->isDependentType() && SizeTy != T) {
-      SemaRef.Diag(FnDecl->getLocation(),
-                   diag::err_operator_new_param_type) << FnDecl->getDeclName()
-        << SizeTy;
-      ret = true;
-    }
-  }
-  QualType ResultTy = SemaRef.Context.getCanonicalType(FnDecl->getResultType());
-  if (!ResultTy->isDependentType() && ResultTy != SemaRef.Context.VoidPtrTy)
+
+  CanQualType SizeTy = 
+    SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType());
+
+  // C++ [basic.stc.dynamic.allocation]p1:
+  //  The return type shall be void*. The first parameter shall have type 
+  //  std::size_t.
+  if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy, 
+                                  SizeTy,
+                                  diag::err_operator_new_dependent_param_type,
+                                  diag::err_operator_new_param_type))
+    return true;
+
+  // C++ [basic.stc.dynamic.allocation]p1:
+  //  The first parameter shall not have an associated default argument.
+  if (FnDecl->getParamDecl(0)->hasDefaultArg())
     return SemaRef.Diag(FnDecl->getLocation(),
-                        diag::err_operator_new_delete_invalid_result_type) 
-      << FnDecl->getDeclName() << SemaRef.Context.VoidPtrTy;
-  return ret;
+                        diag::err_operator_new_default_arg)
+      << FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange();
+
+  return false;
 }
 
 static bool
@@ -4665,25 +4715,11 @@
   // 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())
-    return SemaRef.Diag(FnDecl->getLocation(),
-                        diag::err_operator_new_delete_dependent_result_type)
-      << FnDecl->getDeclName() << SemaRef.Context.VoidTy;
-    
-  if (!ResultType->isVoidType())
-    return SemaRef.Diag(FnDecl->getLocation(),
-                        diag::err_operator_new_delete_invalid_result_type) 
-      << FnDecl->getDeclName() << SemaRef.Context.VoidTy;
-
-  if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2)
-    return SemaRef.Diag(FnDecl->getLocation(),
-                      diag::err_operator_new_delete_template_too_few_parameters)
-        << FnDecl->getDeclName();
-  else if (FnDecl->getNumParams() == 0)
-    return SemaRef.Diag(FnDecl->getLocation(),
-                        diag::err_operator_new_delete_too_few_parameters)
-      << FnDecl->getDeclName();
+  if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy, 
+                                  SemaRef.Context.VoidPtrTy,
+                                 diag::err_operator_delete_dependent_param_type,
+                                 diag::err_operator_delete_param_type))
+    return true;
 
   QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
   if (FirstParamType->isDependentType())
@@ -4758,14 +4794,10 @@
   if (Op != OO_Call) {
     for (FunctionDecl::param_iterator Param = FnDecl->param_begin();
          Param != FnDecl->param_end(); ++Param) {
-      if ((*Param)->hasUnparsedDefaultArg())
-        return Diag((*Param)->getLocation(),
-                    diag::err_operator_overload_default_arg)
-          << FnDecl->getDeclName();
-      else if (Expr *DefArg = (*Param)->getDefaultArg())
+      if ((*Param)->hasDefaultArg())
         return Diag((*Param)->getLocation(),
                     diag::err_operator_overload_default_arg)
-          << FnDecl->getDeclName() << DefArg->getSourceRange();
+          << FnDecl->getDeclName() << (*Param)->getDefaultArgRange();
     }
   }
 

Modified: cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp?rev=91244&r1=91243&r2=91244&view=diff

==============================================================================
--- cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp (original)
+++ cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.allocation/p1.cpp Sun Dec 13 11:53:43 2009
@@ -10,3 +10,35 @@
 }
 
 static void *operator new(size_t); // expected-error {{'operator new' cannot be declared static in global scope}}
+
+struct B {
+  void operator new(size_t);  // expected-error {{'operator new' must return type 'void *'}}
+};
+
+struct C {
+  void *operator new(); // expected-error {{'operator new' must have at least one parameter}}
+};
+
+struct D {
+  void *operator new(bool); // expected-error {{'operator new' takes type size_t ('unsigned long') as first parameter}}
+};
+
+struct E {
+  void *operator new(size_t = 0); // expected-error {{parameter of 'operator new' cannot have a default argument}}
+};
+
+struct F {
+  template<typename T> void *operator new(size_t, int);
+};
+
+struct G {
+  template<typename T> T operator new(size_t, int); // expected-error {{'operator new' cannot have a dependent return type; use 'void *' instead}}
+};
+
+struct H {
+  template<typename T> void *operator new(T, int); // expected-error {{'operator new' cannot take a dependent type as first parameter; use size_t}}
+};
+
+struct I {
+  template<typename T> void *operator new(size_t); // expected-error {{'operator new' template must have at least two parameters}}
+};

Modified: cfe/trunk/test/SemaCXX/new-delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=91244&r1=91243&r2=91244&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/new-delete.cpp (original)
+++ cfe/trunk/test/SemaCXX/new-delete.cpp Sun Dec 13 11:53:43 2009
@@ -140,10 +140,8 @@
 
 class Base {
 public:
-  static int operator new(signed char) throw(); // expected-error {{'operator new' takes type size_t}} \
-						  // expected-error {{operator new' must return type 'void *'}}
-  static int operator new[] (signed char) throw(); // expected-error {{'operator new[]' takes type size_t}} \
-						     // expected-error {{operator new[]' must return type 'void *'}}
+  static void *operator new(signed char) throw(); // expected-error {{'operator new' takes type size_t}}
+  static int operator new[] (size_t) throw(); // expected-error {{operator new[]' must return type 'void *'}}
 };
 
 class Tier {};
@@ -160,9 +158,11 @@
 }
 
 template <class T> struct TBase {
-  void* operator new(T size, int); // expected-error {{'operator new' takes type size_t}}
+  void* operator new(T size, int); // expected-error {{'operator new' cannot take a dependent type as first parameter; use size_t}}\
+                                   // expected-error {{'operator new' takes type size_t}}
 };
 
+// FIXME: We should not try to instantiate operator new, since it is invalid.
 TBase<int> t1; // expected-note {{in instantiation of template class 'struct TBase<int>' requested here}}
 
 class X6 {





More information about the cfe-commits mailing list