diff options
| author | Anders Carlsson <andersca@mac.com> | 2009-12-11 23:23:22 +0000 |
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2009-12-11 23:23:22 +0000 |
| commit | 12308f41e7e26e091950d868d0d2e00a2892fbf0 (patch) | |
| tree | 9e3df94dbf50fafc9333181c3361b84c1a034b44 /clang/lib/Sema/SemaDeclCXX.cpp | |
| parent | f5303fe492116d077e6e1fabbde6f95ffa173010 (diff) | |
| download | bcm5719-llvm-12308f41e7e26e091950d868d0d2e00a2892fbf0.tar.gz bcm5719-llvm-12308f41e7e26e091950d868d0d2e00a2892fbf0.zip | |
Improve diagnostics for malformed delete operator function declarations.
llvm-svn: 91180
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 59 |
1 files changed, 55 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 5a7cba00e5f..32e391d8d03 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4604,6 +4604,52 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, } } +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 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { // 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 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { 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; } |

