diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-11-10 23:47:18 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-11-10 23:47:18 +0000 |
commit | b03bfa55d03ca38922ffedac19225d0832e8d911 (patch) | |
tree | 945acd83aaefec693ba3af51b03f29ebdd43320e | |
parent | a0203800ea2f93b2ce00fae24d6deac57617268d (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.td | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 23 | ||||
-rw-r--r-- | test/CodeGenCXX/new-operator-phi.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/new-delete.cpp | 28 |
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}} + |