aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-11-10 23:47:18 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-11-10 23:47:18 +0000
commitb03bfa55d03ca38922ffedac19225d0832e8d911 (patch)
tree945acd83aaefec693ba3af51b03f29ebdd43320e
parenta0203800ea2f93b2ce00fae24d6deac57617268d (diff)
Diagnose illegally typed operator new/new[].
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86755 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--lib/Sema/SemaDeclCXX.cpp23
-rw-r--r--test/CodeGenCXX/new-operator-phi.cpp2
-rw-r--r--test/SemaCXX/new-delete.cpp28
4 files changed, 54 insertions, 3 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 8b76464db3..285ae8f70d 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2108,6 +2108,10 @@ def err_operator_overload_needs_class_or_enum : Error<
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<
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 25d14a70be..4be5c62ee0 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4006,9 +4006,28 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
// 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_New || Op == OO_Array_New ||
- Op == OO_Delete || Op == OO_Array_Delete)
+ if (Op == OO_Delete || Op == OO_Array_Delete)
return false;
+
+ if (Op == OO_New || Op == OO_Array_New) {
+ bool ret = false;
+ if (FunctionDecl::param_iterator Param = FnDecl->param_begin()) {
+ QualType SizeTy = Context.getCanonicalType(Context.getSizeType());
+ QualType T = Context.getCanonicalType((*Param)->getType());
+ if (!T->isDependentType() && SizeTy != T) {
+ Diag(FnDecl->getLocation(),
+ diag::err_operator_new_param_type) << FnDecl->getDeclName()
+ << SizeTy;
+ ret = true;
+ }
+ }
+ QualType ResultTy = Context.getCanonicalType(FnDecl->getResultType());
+ if (!ResultTy->isDependentType() && ResultTy != Context.VoidPtrTy)
+ return Diag(FnDecl->getLocation(),
+ diag::err_operator_new_result_type) << FnDecl->getDeclName()
+ << Context.VoidPtrTy;
+ return ret;
+ }
// C++ [over.oper]p6:
// An operator function shall either be a non-static member
diff --git a/test/CodeGenCXX/new-operator-phi.cpp b/test/CodeGenCXX/new-operator-phi.cpp
index d4c698d063..03f528cfbe 100644
--- a/test/CodeGenCXX/new-operator-phi.cpp
+++ b/test/CodeGenCXX/new-operator-phi.cpp
@@ -1,7 +1,7 @@
// RUN: clang-cc -emit-llvm-only -verify %s
// PR5454
-class X {static void * operator new(unsigned size) throw(); X(int); };
+class X {static void * operator new(unsigned long size) throw(); X(int); };
int a(), b();
void b(int x)
{
diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp
index 6f3e9effe5..bc385ee607 100644
--- a/test/SemaCXX/new-delete.cpp
+++ b/test/SemaCXX/new-delete.cpp
@@ -137,3 +137,31 @@ class X5 {
public:
void Destroy() const { delete this; }
};
+
+class Base {
+public:
+ static int operator new(unsigned size) throw(); // expected-error {{'operator new' takes type size_t}} \
+ // expected-error {{operator new' must return type 'void *'}}
+ static int operator new[] (unsigned size) throw(); // expected-error {{'operator new[]' takes type size_t}} \
+ // expected-error {{operator new[]' must return type 'void *'}}
+};
+
+class Tier {};
+class Comp : public Tier {};
+
+class Thai : public Base {
+public:
+ Thai(const Tier *adoptDictionary);
+};
+
+void loadEngineFor() {
+ const Comp *dict;
+ new Thai(dict);
+}
+
+template <class T> struct TBase {
+ void* operator new(T size, int); // expected-error {{'operator new' takes type size_t}}
+};
+
+TBase<int> t1; // expected-note {{in instantiation of template class 'struct TBase<int>' requested here}}
+