diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -673,7 +673,9 @@ [[delete]] x; } )cpp"; - EXPECT_DECLS("CXXDeleteExpr", "void operator delete(void *) noexcept"); + // Sized deallocation is enabled by default in C++14 onwards. + EXPECT_DECLS("CXXDeleteExpr", + "void operator delete(void *, unsigned long) noexcept"); } TEST_F(TargetDeclTest, DependentExprs) { diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc-new-delete-overloads.cpp @@ -13,13 +13,13 @@ void *operator new(size_t size) noexcept(false); struct T { - // Sized deallocations are not enabled by default, and so this new/delete pair + // Sized deallocations are enabled by default, and so this new/delete pair // does not match. However, we expect only one warning, for the new, because // the operator delete is a placement delete and we do not warn on mismatching // placement operations. // CHECK-MESSAGES: :[[@LINE+1]]:9: warning: declaration of 'operator new' has no matching declaration of 'operator delete' at the same scope void *operator new(size_t size) noexcept; - void operator delete(void *ptr, size_t) noexcept; // ok only if sized deallocation is enabled + void operator delete(void *ptr) noexcept; }; struct U { diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -235,6 +235,10 @@ are now treated as compiler builtins and implemented directly, rather than instantiating the definition from the standard library. +C++14 Feature Support +^^^^^^^^^^^^^^^^^^^^^ +- Sized deallocation is enabled by default in C++14 onwards. + C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ - Diagnose consteval and constexpr issues that happen at namespace scope. This diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -480,6 +480,7 @@ // Key paths that are constant during parsing of options with the same key path prefix. defvar cplusplus = LangOpts<"CPlusPlus">; defvar cpp11 = LangOpts<"CPlusPlus11">; +defvar cpp14 = LangOpts<"CPlusPlus14">; defvar cpp17 = LangOpts<"CPlusPlus17">; defvar cpp20 = LangOpts<"CPlusPlus20">; defvar c99 = LangOpts<"C99">; @@ -2402,9 +2403,9 @@ PosFlag, NegFlag>; defm sized_deallocation : BoolFOption<"sized-deallocation", - LangOpts<"SizedDeallocation">, DefaultFalse, - PosFlag, - NegFlag>; + LangOpts<"SizedDeallocation">, Default, + PosFlag, + NegFlag, BothFlags<[CC1Option]>>; defm aligned_allocation : BoolFOption<"aligned-allocation", LangOpts<"AlignedAllocation">, Default, PosFlag, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6551,8 +6551,8 @@ Args.addOptInFlag(CmdArgs, options::OPT_frelaxed_template_template_args, options::OPT_fno_relaxed_template_template_args); - // -fsized-deallocation is off by default, as it is an ABI-breaking change for - // most platforms. + // -fsized-deallocation is on by default in C++14 onwards and otherwise off + // by default. Args.addOptInFlag(CmdArgs, options::OPT_fsized_deallocation, options::OPT_fno_sized_deallocation); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4070,6 +4070,16 @@ if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ)) Opts.RandstructSeed = A->getValue(0); + // TODO: If there is no provided sized-deallocation option, we disable the + // default behavior for Apple targets currently. This may be changed when we + // are able to enable reliance on sized deallocation functions automatically + // whenever the deployment target is greater than or equal to required + // versions. + if (!Args.getLastArg(options::OPT_fsized_deallocation, + options::OPT_fno_sized_deallocation)) + Opts.SizedDeallocation = Opts.SizedDeallocation && + T.getVendor() != llvm::Triple::VendorType::Apple; + return Diags.getNumErrors() == NumErrorsBefore; } diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -2333,7 +2333,7 @@ // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *) noexcept" +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -166,7 +166,7 @@ // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' ::delete p; - // CHECK: CXXDeleteExpr 0x{{[^ ]*}} 'void' global Function 0x{{[^ ]*}} 'operator delete' 'void (void *) noexcept' + // CHECK: CXXDeleteExpr 0x{{[^ ]*}} 'void' global Function 0x{{[^ ]*}} 'operator delete' 'void (void *, unsigned long) noexcept' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *' diff --git a/clang/test/AST/ast-dump-stmt-json.cpp b/clang/test/AST/ast-dump-stmt-json.cpp --- a/clang/test/AST/ast-dump-stmt-json.cpp +++ b/clang/test/AST/ast-dump-stmt-json.cpp @@ -994,7 +994,7 @@ // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *) noexcept" +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1369,7 +1369,7 @@ // CHECK-NEXT: "kind": "FunctionDecl", // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "type": { -// CHECK-NEXT: "qualType": "void (void *) noexcept" +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: "inner": [ @@ -1718,7 +1718,6 @@ // CHECK-NEXT: "end": {} // CHECK-NEXT: }, // CHECK-NEXT: "isImplicit": true, -// CHECK-NEXT: "isUsed": true, // CHECK-NEXT: "name": "operator delete", // CHECK-NEXT: "mangledName": "_ZdlPv", // CHECK-NEXT: "type": { @@ -1804,6 +1803,124 @@ // CHECK-NEXT: } +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "isUsed": true, +// CHECK-NEXT: "name": "operator delete", +// CHECK-NEXT: "mangledName": "_ZdlPvm", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void *" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VisibilityAttr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "implicit": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } + +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "operator delete", +// CHECK-NEXT: "mangledName": "_ZdlPvmSt11align_val_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void *, unsigned long, std::align_val_t) noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void *" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "std::align_val_t" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VisibilityAttr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "implicit": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } + // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionDecl", // CHECK-NEXT: "loc": {}, @@ -1898,6 +2015,123 @@ // CHECK-NEXT: } +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "operator delete[]", +// CHECK-NEXT: "mangledName": "_ZdaPvm", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void *, unsigned long) noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void *" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VisibilityAttr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "implicit": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } + +// CHECK-NOT: {{^}}Dumping +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "name": "operator delete[]", +// CHECK-NEXT: "mangledName": "_ZdaPvmSt11align_val_t", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void *, unsigned long, std::align_val_t) noexcept" +// CHECK-NEXT: }, +// CHECK-NEXT: "inner": [ +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void *" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "unsigned long" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "ParmVarDecl", +// CHECK-NEXT: "loc": {}, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "isImplicit": true, +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "std::align_val_t" +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: { +// CHECK-NEXT: "id": "0x{{.*}}", +// CHECK-NEXT: "kind": "VisibilityAttr", +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "end": {} +// CHECK-NEXT: }, +// CHECK-NEXT: "implicit": true +// CHECK-NEXT: } +// CHECK-NEXT: ] +// CHECK-NEXT: } + // CHECK-NOT: {{^}}Dumping // CHECK: "kind": "FunctionTemplateDecl", // CHECK-NEXT: "loc": { diff --git a/clang/test/CodeGenCXX/cxx1y-sized-deallocation.cpp b/clang/test/CodeGenCXX/cxx1y-sized-deallocation.cpp --- a/clang/test/CodeGenCXX/cxx1y-sized-deallocation.cpp +++ b/clang/test/CodeGenCXX/cxx1y-sized-deallocation.cpp @@ -3,10 +3,11 @@ // RUN: %clang_cc1 -no-opaque-pointers -std=c++11 -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s // RUN: %clang_cc1 -no-opaque-pointers -std=c++14 -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s -// Check that we don't used sized deallocation without -fsized-deallocation and -// C++14. -// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNSIZED -// RUN: %clang_cc1 -no-opaque-pointers -std=c++14 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNSIZED +// Check that we don't used sized deallocation with -fno-sized-deallocation or without C++14. +// RUN: %clang_cc1 -no-opaque-pointers -std=c++11 %s -emit-llvm -triple x86_64-linux-gnu -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-UNSIZED +// RUN: %clang_cc1 -no-opaque-pointers -std=c++14 %s -emit-llvm -triple x86_64-linux-gnu -fno-sized-deallocation -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-UNSIZED // CHECK-UNSIZED-NOT: _ZdlPvm // CHECK-UNSIZED-NOT: _ZdaPvm diff --git a/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp b/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp --- a/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp +++ b/clang/test/CodeGenCXX/cxx2a-destroying-delete.cpp @@ -111,10 +111,10 @@ // CHECK-MSABI-LABEL: define {{.*}}@"?j@@ J *j() { // CHECK-ITANIUM: invoke {{.*}}@_ZN1JC1Ev( - // CHECK-ITANIUM: call {{.*}}@_ZdlPv( + // CHECK-ITANIUM: call {{.*}}@_ZdlPvm( // CHECK-NOT: } // CHECK-MSABI: invoke {{.*}}@"??0J@@Q{{AE|EAA}}@XZ"( - // CHECK-MSABI: call {{.*}}@"??3@YAXP{{E?}}AX@Z"( + // CHECK-MSABI: call {{.*}}@"??3@YAXP{{E?}}AX{{I|_K}}@Z"( return new J; // CHECK: } } diff --git a/clang/test/CodeGenCXX/delete-two-arg.cpp b/clang/test/CodeGenCXX/delete-two-arg.cpp --- a/clang/test/CodeGenCXX/delete-two-arg.cpp +++ b/clang/test/CodeGenCXX/delete-two-arg.cpp @@ -47,7 +47,9 @@ // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8, i8* [[T2]], i32 -4 // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i32* // CHECK-NEXT: [[T5:%.*]] = load i32, i32* [[T4]] - // CHECK-NEXT: call void @_ZdaPv(i8* noundef [[T3]]) + // CHECK-NEXT: [[T6:%.*]] = mul i32 4, [[T5]] + // CHECK-NEXT: [[T7:%.*]] = add i32 [[T6]], 4 + // CHECK-NEXT: call void @_ZdaPvj(i8* noundef [[T3]], i32 noundef [[T7]]) // CHECK-NEXT: br label ::delete[] p; } diff --git a/clang/test/CodeGenCXX/dllimport.cpp b/clang/test/CodeGenCXX/dllimport.cpp --- a/clang/test/CodeGenCXX/dllimport.cpp +++ b/clang/test/CodeGenCXX/dllimport.cpp @@ -203,7 +203,7 @@ // Functions //===----------------------------------------------------------------------===// -// GNU-DAG: declare dso_local void @_ZdlPv(i8*) +// GNU-DAG: declare dso_local void @_ZdlPv{{j|y}}(i8*, i{{32|64}}) // Import function declaration. // MSC-DAG: declare dllimport void @"?decl@@YAXXZ"() @@ -356,7 +356,7 @@ __declspec(dllimport) inline int *ReferencingImportedNew() { return new int[2]; } // MO1-DAG: define available_externally dllimport i32* @"?ReferencingImportedNew@@YAPAHXZ" __declspec(dllimport) inline int *ReferencingImportedDelete() { delete (int*)nullptr; } -// MO1-DAG: define available_externally dllimport i32* @"?ReferencingImportedDelete@@YAPAHXZ" +// MO1-DAG: declare dllimport i32* @"?ReferencingImportedDelete@@YAPAHXZ" USE(ReferencingImportedNew) USE(ReferencingImportedDelete) struct ClassWithDtor { ~ClassWithDtor() {} }; diff --git a/clang/test/CodeGenCXX/new.cpp b/clang/test/CodeGenCXX/new.cpp --- a/clang/test/CodeGenCXX/new.cpp +++ b/clang/test/CodeGenCXX/new.cpp @@ -15,7 +15,7 @@ } // CHECK: declare noundef nonnull i8* @_Znwm(i64 noundef) [[ATTR_NOBUILTIN:#[^ ]*]] -// CHECK: declare void @_ZdlPv(i8* noundef) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] +// CHECK: declare void @_ZdlPvm(i8* noundef, i64 noundef) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] // CHECK: declare noundef nonnull i8* @_Znam(i64 noundef) [[ATTR_NOBUILTIN]] // CHECK: declare void @_ZdaPv(i8* noundef) [[ATTR_NOBUILTIN_NOUNWIND]] @@ -192,7 +192,7 @@ // CHECK: store i64 200 delete[] new (nothrow) Alloc[10][20]; // CHECK: call noalias noundef nonnull i8* @_Znwm - // CHECK: call void @_ZdlPv(i8* + // CHECK: call void @_ZdlPvm(i8* noundef {{%.*}}, i64 noundef 1) delete new bool; // CHECK: ret void } @@ -325,7 +325,7 @@ void f() { // CHECK: call noalias noundef nonnull i8* @_Znwm(i64 noundef 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] int *p = new int; // expected-note {{allocated with 'new' here}} - // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]] + // CHECK: call void @_ZdlPvm({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]] delete p; // CHECK: call noalias noundef nonnull i8* @_Znam(i64 noundef 12) [[ATTR_BUILTIN_NEW]] diff --git a/clang/test/CodeGenCoroutines/coro-alloc-exp-namespace.cpp b/clang/test/CodeGenCoroutines/coro-alloc-exp-namespace.cpp --- a/clang/test/CodeGenCoroutines/coro-alloc-exp-namespace.cpp +++ b/clang/test/CodeGenCoroutines/coro-alloc-exp-namespace.cpp @@ -72,7 +72,8 @@ // CHECK: br i1 %[[NeedDealloc]], label %[[FreeBB:.+]], label %[[Afterwards:.+]] // CHECK: [[FreeBB]]: - // CHECK: call void @_ZdlPv(i8* noundef %[[MEM]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[MEM]], i64 noundef %[[SIZE]]) // CHECK: br label %[[Afterwards]] // CHECK: [[Afterwards]]: @@ -101,7 +102,8 @@ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin( // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) - // CHECK: call void @_ZdlPv(i8* noundef %[[MEM]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[MEM]], i64 noundef %[[SIZE]]) co_return; } diff --git a/clang/test/CodeGenCoroutines/coro-alloc.cpp b/clang/test/CodeGenCoroutines/coro-alloc.cpp --- a/clang/test/CodeGenCoroutines/coro-alloc.cpp +++ b/clang/test/CodeGenCoroutines/coro-alloc.cpp @@ -70,7 +70,8 @@ // CHECK: br i1 %[[NeedDealloc]], label %[[FreeBB:.+]], label %[[Afterwards:.+]] // CHECK: [[FreeBB]]: - // CHECK: call void @_ZdlPv(i8* noundef %[[MEM]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[MEM]], i64 noundef %[[SIZE]]) // CHECK: br label %[[Afterwards]] // CHECK: [[Afterwards]]: @@ -99,7 +100,8 @@ // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin( // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]]) - // CHECK: call void @_ZdlPv(i8* noundef %[[MEM]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[MEM]], i64 noundef %[[SIZE]]) co_return; } diff --git a/clang/test/CodeGenCoroutines/coro-cleanup-exp-namespace.cpp b/clang/test/CodeGenCoroutines/coro-cleanup-exp-namespace.cpp --- a/clang/test/CodeGenCoroutines/coro-cleanup-exp-namespace.cpp +++ b/clang/test/CodeGenCoroutines/coro-cleanup-exp-namespace.cpp @@ -81,11 +81,13 @@ // CHECK: [[Cleanup]]: // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_typeD1Ev( // CHECK: %[[Mem0:.+]] = call i8* @llvm.coro.free( - // CHECK: call void @_ZdlPv(i8* noundef %[[Mem0]] + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[Mem0]], i64 noundef %[[SIZE]]) // CHECK: [[Dealloc]]: - // CHECK: %[[Mem:.+]] = call i8* @llvm.coro.free( - // CHECK: call void @_ZdlPv(i8* noundef %[[Mem]]) + // CHECK: %[[Mem:.+]] = call i8* @llvm.coro.free( + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[Mem]], i64 noundef %[[SIZE]]) co_return; } diff --git a/clang/test/CodeGenCoroutines/coro-cleanup.cpp b/clang/test/CodeGenCoroutines/coro-cleanup.cpp --- a/clang/test/CodeGenCoroutines/coro-cleanup.cpp +++ b/clang/test/CodeGenCoroutines/coro-cleanup.cpp @@ -79,11 +79,13 @@ // CHECK: [[Cleanup]]: // CHECK: call void @_ZNSt16coroutine_traitsIJvEE12promise_typeD1Ev( // CHECK: %[[Mem0:.+]] = call i8* @llvm.coro.free( - // CHECK: call void @_ZdlPv(i8* noundef %[[Mem0]] + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[Mem0]], i64 noundef %[[SIZE]]) // CHECK: [[Dealloc]]: // CHECK: %[[Mem:.+]] = call i8* @llvm.coro.free( - // CHECK: call void @_ZdlPv(i8* noundef %[[Mem]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[Mem]], i64 noundef %[[SIZE]]) co_return; } diff --git a/clang/test/CodeGenCoroutines/coro-gro-exp-namespace.cpp b/clang/test/CodeGenCoroutines/coro-gro-exp-namespace.cpp --- a/clang/test/CodeGenCoroutines/coro-gro-exp-namespace.cpp +++ b/clang/test/CodeGenCoroutines/coro-gro-exp-namespace.cpp @@ -68,7 +68,8 @@ // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJiEE12promise_typeD1Ev( // CHECK: %[[Mem:.+]] = call i8* @llvm.coro.free( - // CHECK: call void @_ZdlPv(i8* noundef %[[Mem]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[Mem]], i64 noundef %[[SIZE]]) // CHECK: coro.ret: // CHECK: %[[LoadRet:.+]] = load i32, i32* %[[RetVal]] diff --git a/clang/test/CodeGenCoroutines/coro-gro.cpp b/clang/test/CodeGenCoroutines/coro-gro.cpp --- a/clang/test/CodeGenCoroutines/coro-gro.cpp +++ b/clang/test/CodeGenCoroutines/coro-gro.cpp @@ -66,7 +66,8 @@ // CHECK: call void @_ZNSt16coroutine_traitsIJiEE12promise_typeD1Ev( // CHECK: %[[Mem:.+]] = call i8* @llvm.coro.free( - // CHECK: call void @_ZdlPv(i8* noundef %[[Mem]]) + // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64() + // CHECK: call void @_ZdlPvm(i8* noundef %[[Mem]], i64 noundef %[[SIZE]]) // CHECK: coro.ret: // CHECK: %[[LoadRet:.+]] = load i32, i32* %[[RetVal]] diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp --- a/clang/test/SemaCXX/MicrosoftExtensions.cpp +++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -567,11 +567,17 @@ virtual ~PR34109_class() {} }; +#if !defined(__cpp_sized_deallocation) void operator delete(void *) throw(); // expected-note@-1 {{previous declaration is here}} __declspec(dllexport) void operator delete(void *) throw(); // expected-error@-1 {{redeclaration of 'operator delete' cannot add 'dllexport' attribute}} - +#else +void operator delete(void *, unsigned int) throw(); +// expected-note@-1 {{previous declaration is here}} +__declspec(dllexport) void operator delete(void *, unsigned int) throw(); +// expected-error@-1 {{redeclaration of 'operator delete' cannot add 'dllexport' attribute}} +#endif void PR34109(int* a) { delete a; } diff --git a/clang/test/SemaCXX/builtin-operator-new-delete.cpp b/clang/test/SemaCXX/builtin-operator-new-delete.cpp --- a/clang/test/SemaCXX/builtin-operator-new-delete.cpp +++ b/clang/test/SemaCXX/builtin-operator-new-delete.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++1z -fno-sized-deallocation -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c++03 -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c++03 -faligned-allocation -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s diff --git a/clang/test/SemaCXX/unavailable_aligned_allocation.cpp b/clang/test/SemaCXX/unavailable_aligned_allocation.cpp --- a/clang/test/SemaCXX/unavailable_aligned_allocation.cpp +++ b/clang/test/SemaCXX/unavailable_aligned_allocation.cpp @@ -74,32 +74,35 @@ // expected-note@-21 {{if you supply your own aligned allocation functions}} // expected-error-re@-22 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-23 {{if you supply your own aligned allocation functions}} - +#if !defined(ZOS) // expected-error-re@-24 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} // expected-note@-25 {{if you supply your own aligned allocation functions}} - -// expected-error-re@-26 {{aligned allocation function of type 'void *(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} -// expected-note@-27 {{if you supply your own aligned allocation functions}} -// expected-error-re@-28 {{aligned deallocation function of type 'void (void *, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} -// expected-note@-29 {{if you supply your own aligned allocation functions}} - -// expected-error-re@-29 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +#else +// expected-error@-27 {{aligned deallocation function of type 'void (void *, std::size_t, std::align_val_t) noexcept' is not available on z/OS}} +// expected-note@-28 {{if you supply your own aligned allocation functions}} +#endif +// expected-error-re@-29 {{aligned allocation function of type 'void *(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} // expected-note@-30 {{if you supply your own aligned allocation functions}} -// expected-error-re@-31 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} +// expected-error-re@-31 {{aligned deallocation function of type 'void (void *, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} // expected-note@-32 {{if you supply your own aligned allocation functions}} -// expected-error-re@-33 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} -// expected-note@-34 {{if you supply your own aligned allocation functions}} -// expected-error-re@-35 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} -// expected-note@-36 {{if you supply your own aligned allocation functions}} +// expected-error-re@-32 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +// expected-note@-33 {{if you supply your own aligned allocation functions}} +// expected-error-re@-34 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} +// expected-note@-35 {{if you supply your own aligned allocation functions}} -// expected-error-re@-37 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} -// expected-note@-38 {{if you supply your own aligned allocation functions}} +// expected-error-re@-36 {{aligned allocation function of type 'void *(unsigned long, enum std::align_val_t)' is {{only|not}} available on}} +// expected-note@-37 {{if you supply your own aligned allocation functions}} +// expected-error-re@-38 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} +// expected-note@-39 {{if you supply your own aligned allocation functions}} -// expected-error-re@-39 {{aligned allocation function of type 'void *(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} -// expected-note@-40 {{if you supply your own aligned allocation functions}} -// expected-error-re@-41 {{aligned deallocation function of type 'void (void *, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} -// expected-note@-42 {{if you supply your own aligned allocation functions}} +// expected-error-re@-40 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is {{only|not}} available on}} +// expected-note@-41 {{if you supply your own aligned allocation functions}} + +// expected-error-re@-42 {{aligned allocation function of type 'void *(std::size_t, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} +// expected-note@-43 {{if you supply your own aligned allocation functions}} +// expected-error-re@-44 {{aligned deallocation function of type 'void (void *, std::align_val_t, const std::nothrow_t &) noexcept' is {{only|not}} available on}} +// expected-note@-45 {{if you supply your own aligned allocation functions}} #endif @@ -155,7 +158,7 @@ // expected-error@-15 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is only available on macOS 10.14 or newer}}} // expected-note@-16 {{if you supply your own aligned allocation functions}} #elif defined(ZOS) -// expected-error@-18 {{aligned deallocation function of type 'void (void *, enum std::align_val_t) noexcept' is not available on z/OS}}} +// expected-error@-18 {{aligned deallocation function of type 'void (void *, std::size_t, std::align_val_t) noexcept' is not available on z/OS}}} // expected-note@-19 {{if you supply your own aligned allocation functions}} #endif #endif @@ -212,4 +215,10 @@ void testOveraligned2() { auto p = new ((std::align_val_t)8) OveralignedS; delete p; +#ifdef NO_ERRORS +// expected-no-diagnostics +#elif defined(ZOS) +// expected-error@-4 {{aligned deallocation function of type 'void (void *, std::size_t, std::align_val_t) noexcept' is not available on z/OS}} +// expected-note@-5 {{if you supply your own aligned allocation functions}} +#endif } diff --git a/clang/unittests/StaticAnalyzer/CallEventTest.cpp b/clang/unittests/StaticAnalyzer/CallEventTest.cpp --- a/clang/unittests/StaticAnalyzer/CallEventTest.cpp +++ b/clang/unittests/StaticAnalyzer/CallEventTest.cpp @@ -81,7 +81,7 @@ } )", Diags)); - EXPECT_EQ(Diags, "test.CXXDeallocator: NumArgs: 1\n"); + EXPECT_EQ(Diags, "test.CXXDeallocator: NumArgs: 2\n"); } } // namespace diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -578,12 +578,11 @@

-(7): In Clang 3.7 and later, sized deallocation is only enabled -if the user passes the -fsized-deallocation flag. The user must -supply definitions of the sized deallocation functions, either by providing them -explicitly or by using a C++ standard library that does. libstdc++ -added these functions in version 5.0, and libc++ added them in -version 3.7. +(7): The user must supply definitions of the sized deallocation +functions, either by providing them explicitly or by using a C++ standard library +that does. libstdc++ added these functions in version 5.0, and +libc++ added them in version 3.7. The user can also use the +-fno-sized-deallocation option to disable sized deallocation.

diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp --- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array14.pass.cpp @@ -10,9 +10,10 @@ // UNSUPPORTED: sanitizer-new-delete, c++03, c++11 -// NOTE: Clang does not enable sized-deallocation in C++14 and beyond by -// default. It is only enabled when -fsized-deallocation is given. -// XFAIL: clang, apple-clang +// XFAIL: apple-clang + +// Sized deallocation was added in macOS 10.12 and aligned OSes. +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11}} #include #include