[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