[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