diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-09-13 20:15:54 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-09-13 20:15:54 +0000 |
commit | 4076dacf1497fb95cb298b9d964fbdbdaf9bde6c (patch) | |
tree | 5b91fb94a2e1a10ffbd30a975bebb9865c88395e | |
parent | f1b8911d35bb2830a13267581d3cbde4b6b85db6 (diff) |
When applying 'delete' on a pointer-to-array type match GCC and EDG behavior and treat it as 'delete[]'.
Also offer a fix-it hint adding '[]'.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113778 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ExprCXX.h | 12 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 13 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 1 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 1 | ||||
-rw-r--r-- | test/CodeGenCXX/delete.cpp | 7 | ||||
-rw-r--r-- | test/SemaCXX/delete.cpp | 9 |
7 files changed, 40 insertions, 5 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 219e2f982b..2ad7285f44 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1107,6 +1107,10 @@ class CXXDeleteExpr : public Expr { bool GlobalDelete : 1; // Is this the array form of delete, i.e. "delete[]"? bool ArrayForm : 1; + // ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied + // to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm + // will be true). + bool ArrayFormAsWritten : 1; // Points to the operator delete overload that is used. Could be a member. FunctionDecl *OperatorDelete; // The pointer expression to be deleted. @@ -1115,15 +1119,17 @@ class CXXDeleteExpr : public Expr { SourceLocation Loc; public: CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm, - FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc) + bool arrayFormAsWritten, FunctionDecl *operatorDelete, + Expr *arg, SourceLocation loc) : Expr(CXXDeleteExprClass, ty, false, false), GlobalDelete(globalDelete), - ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg), - Loc(loc) { } + ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), + OperatorDelete(operatorDelete), Argument(arg), Loc(loc) { } explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { } bool isGlobalDelete() const { return GlobalDelete; } bool isArrayForm() const { return ArrayForm; } + bool isArrayFormAsWritten() const { return ArrayFormAsWritten; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index ab16675986..9edceb820c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2448,6 +2448,8 @@ def warn_delete_incomplete : Warning< "deleting pointer to incomplete type %0 may cause undefined behaviour">; def err_delete_incomplete_class_type : Warning< "deleting incomplete class type %0; no conversions to pointer type">; +def warn_delete_array_type : Warning< + "'delete' applied to a pointer-to-array type %0 treated as delete[]">; def err_no_suitable_delete_member_function_found : Error< "no suitable member %0 in %1">; def err_ambiguous_suitable_delete_member_function_found : Error< diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 382e9bb185..db287515ce 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1438,6 +1438,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // DR599 amends "pointer type" to "pointer to object type" in both cases. FunctionDecl *OperatorDelete = 0; + bool ArrayFormAsWritten = ArrayForm; if (!Ex->isTypeDependent()) { QualType Type = Ex->getType(); @@ -1514,7 +1515,14 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, // of the delete-expression. ] ImpCastExprToType(Ex, Context.getPointerType(Context.VoidTy), CK_NoOp); - + + if (Pointee->isArrayType() && !ArrayForm) { + Diag(StartLoc, diag::warn_delete_array_type) + << Type << Ex->getSourceRange() + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]"); + ArrayForm = true; + } + DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( ArrayForm ? OO_Array_Delete : OO_Delete); @@ -1548,7 +1556,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, - OperatorDelete, Ex, StartLoc)); + ArrayFormAsWritten, OperatorDelete, + Ex, StartLoc)); } /// \brief Check the use of the given variable as a C++ condition in an if, diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index e53bf716a8..a6da3c7296 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1112,6 +1112,7 @@ void ASTStmtReader::VisitCXXDeleteExpr(CXXDeleteExpr *E) { VisitExpr(E); E->GlobalDelete = Record[Idx++]; E->ArrayForm = Record[Idx++]; + E->ArrayFormAsWritten = Record[Idx++]; E->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++])); E->Argument = Reader.ReadSubExpr(); E->Loc = Reader.ReadSourceLocation(Record, Idx); diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index b9a22842b9..3701e0c146 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1121,6 +1121,7 @@ void ASTStmtWriter::VisitCXXDeleteExpr(CXXDeleteExpr *E) { VisitExpr(E); Record.push_back(E->isGlobalDelete()); Record.push_back(E->isArrayForm()); + Record.push_back(E->isArrayFormAsWritten()); Writer.AddDeclRef(E->getOperatorDelete(), Record); Writer.AddStmt(E->getArgument()); Writer.AddSourceLocation(E->getSourceRange().getBegin(), Record); diff --git a/test/CodeGenCXX/delete.cpp b/test/CodeGenCXX/delete.cpp index 1f52a783e6..b8726a863e 100644 --- a/test/CodeGenCXX/delete.cpp +++ b/test/CodeGenCXX/delete.cpp @@ -105,3 +105,10 @@ namespace test2 { delete [] b; } } + +namespace test3 { + void f(int a[10][20]) { + // CHECK: call void @_ZdaPv(i8* + delete a; + } +} diff --git a/test/SemaCXX/delete.cpp b/test/SemaCXX/delete.cpp new file mode 100644 index 0000000000..4567888a37 --- /dev/null +++ b/test/SemaCXX/delete.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: cp %s %t +// RUN: %clang_cc1 -fixit -x c++ %t +// RUN: FileCheck -input-file=%t %s + +void f(int a[10][20]) { + // CHECK: delete[] a; + delete a; // expected-warning {{'delete' applied to a pointer-to-array type}} +} |