From f589c2ef367b804019c89945d77f64ec6adf6264 Mon Sep 17 00:00:00 2001 From: Larisse Voufo Date: Wed, 25 Feb 2015 23:48:43 +0000 Subject: [PATCH] Improvement on sized deallocation from r230160: Do not declare sized deallocation functions dependently on whether it is found in global scope. Instead, enforce the branching in emitted code by (1) declaring the functions extern_weak and (2) emitting sized delete expressions as a branching between both forms delete. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@230580 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExprCXX.cpp | 87 +++++++++++++++++-- lib/Sema/SemaExprCXX.cpp | 19 ++-- test/CodeGenCXX/cxx1y-sized-deallocation.cpp | 46 +++++++--- .../implicit-allocation-functions.cpp | 26 +++--- test/CodeGenCXX/pr21754.cpp | 16 ++-- 5 files changed, 147 insertions(+), 47 deletions(-) diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 6852d3afc7..425a968c13 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -1422,6 +1422,71 @@ CodeGenFunction::pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, OperatorDelete, ElementType); } +static void EmitDelete(CodeGenFunction &CGF, + const CXXDeleteExpr *DE, + llvm::Value *Ptr, + QualType ElementType); + +static void EmitSizedDelete(CodeGenFunction &CGF, + const CXXDeleteExpr *DE, + llvm::Value *Ptr, + QualType ElementType, + FunctionDecl* UnsizedDealloc) { + + if (CGF.getLangOpts().DefineSizedDeallocation) { + // The delete operator in use is fixed. So simply emit the delete expr. + EmitDelete(CGF, DE, Ptr, ElementType); + return; + } + + assert(UnsizedDealloc && "We must be emiting a 'sized' delete expr"); + + // Branch off over the value of operator delete: + // Use the sized form if available, and default on the unsized form otherwise. + llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("if.then"); + llvm::BasicBlock *ContBlock = CGF.createBasicBlock("if.end"); + llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("if.else"); + + // Emit the condition. + const FunctionDecl *OpDelFD = DE->getOperatorDelete(); + llvm::Value *OpDelAddr = CGF.CGM.GetAddrOfFunction(OpDelFD); + //llvm::Function *OpDel = dyn_cast(OpDelAddr); + llvm::Value *SDE = CGF.Builder.CreateIsNotNull(OpDelAddr, "sized.del.exists"); + CGF.Builder.CreateCondBr(SDE, ThenBlock, ElseBlock); + + // Emit the 'then' code. + CGF.EmitBlock(ThenBlock); + EmitDelete(CGF, DE, Ptr, ElementType); + CGF.EmitBranch(ContBlock); + + // Compute the 'unsized' delete expr. + CXXDeleteExpr * E = const_cast(DE); + CXXDeleteExpr *UnsizedDE = + new (CGF.getContext()) CXXDeleteExpr(CGF.getContext().VoidTy, + E->isGlobalDelete(), + E->isArrayForm(), + E->isArrayFormAsWritten(), + E->doesUsualArrayDeleteWantSize(), + UnsizedDealloc, + E->getArgument(), + E->getLocStart()); + // Emit the 'else' code. + { + // There is no need to emit line number for an unconditional branch. + auto NL = ApplyDebugLocation::CreateEmpty(CGF); + CGF.EmitBlock(ElseBlock); + } + EmitDelete(CGF, UnsizedDE, Ptr, ElementType); + { + // There is no need to emit line number for an unconditional branch. + auto NL = ApplyDebugLocation::CreateEmpty(CGF); + CGF.EmitBranch(ContBlock); + } + + // Emit the continuation block for code after the if. + CGF.EmitBlock(ContBlock, true); +} + /// Emit the code for deleting a single object. static void EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE, @@ -1581,6 +1646,17 @@ static void EmitArrayDelete(CodeGenFunction &CGF, CGF.PopCleanupBlock(); } +static void EmitDelete(CodeGenFunction &CGF, + const CXXDeleteExpr *DE, + llvm::Value *Ptr, + QualType ElementType) { + if (DE->isArrayForm()) { + EmitArrayDelete(CGF, DE, Ptr, ElementType); + } else { + EmitObjectDelete(CGF, DE, Ptr, ElementType); + } +} + void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { const Expr *Arg = E->getArgument(); llvm::Value *Ptr = EmitScalarExpr(Arg); @@ -1620,11 +1696,12 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { assert(ConvertTypeForMem(DeleteTy) == cast(Ptr->getType())->getElementType()); - if (E->isArrayForm()) { - EmitArrayDelete(*this, E, Ptr, DeleteTy); - } else { - EmitObjectDelete(*this, E, Ptr, DeleteTy); - } + const FunctionDecl *Dealloc = E->getOperatorDelete(); + if (FunctionDecl* UnsizedDealloc = + Dealloc->getCorrespondingUnsizedGlobalDeallocationFunction()) + EmitSizedDelete(*this, E, Ptr, DeleteTy, UnsizedDealloc); + else + EmitDelete(*this, E, Ptr, DeleteTy); EmitBlock(DeleteEnd); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index d24a653b34..c5df3ed016 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2090,15 +2090,6 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, } } - // If the function is sized operator delete and has not already been - // declared, and weak definitions have been disabled, do not declare - // it implicitly. Instead, let deallocation function lookup pick up - // unsized delete. - // FIXME: We should remove this guard once backward compatibility is - // no longer an issue - if (NumParams == 2 && !getLangOpts().DefineSizedDeallocation) - return; - FunctionProtoType::ExtProtoInfo EPI; QualType BadAllocType; @@ -2131,6 +2122,16 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, Alloc->addAttr(VisibilityAttr::CreateImplicit(Context, VisibilityAttr::Default)); + if (NumParams == 2 && !getLangOpts().DefineSizedDeallocation) { + assert(getLangOpts().SizedDeallocation && + "Only sized deallocation can have two parameters"); + + // This declaration should be emited as extern_weak. + LinkageInfo LV = Alloc->getLinkageAndVisibility(); + assert(LV.getLinkage() == clang::ExternalLinkage); + Alloc->addAttr(WeakAttr::CreateImplicit(Context)); + } + if (AddRestrictAttr) Alloc->addAttr( RestrictAttr::CreateImplicit(Context, RestrictAttr::GNU_malloc)); diff --git a/test/CodeGenCXX/cxx1y-sized-deallocation.cpp b/test/CodeGenCXX/cxx1y-sized-deallocation.cpp index 1d021a759f..647a64097a 100644 --- a/test/CodeGenCXX/cxx1y-sized-deallocation.cpp +++ b/test/CodeGenCXX/cxx1y-sized-deallocation.cpp @@ -1,8 +1,6 @@ -// RUN: %clang_cc1 -std=c++1y %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNSIZED -// RUN: %clang_cc1 -std=c++1y %s -emit-llvm -triple x86_64-linux-gnu -o - -DINLIB | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKUND +// RUN: %clang_cc1 -std=c++1y %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKUND // RUN: %clang_cc1 -std=c++1y %s -emit-llvm -triple x86_64-linux-gnu -fdefine-sized-deallocation -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDEF -// RUN: %clang_cc1 -std=c++11 -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNSIZED -// RUN: %clang_cc1 -std=c++11 -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - -DINLIB | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKUND +// RUN: %clang_cc1 -std=c++11 -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKUND // RUN: %clang_cc1 -std=c++11 -fsized-deallocation -fdefine-sized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDEF // RUN: %clang_cc1 -std=c++11 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNSIZED // RUN: %clang_cc1 -std=c++1y %s -emit-llvm -triple x86_64-linux-gnu -fno-sized-deallocation -o - | FileCheck %s --check-prefix=CHECK-UNSIZED @@ -12,11 +10,6 @@ typedef decltype(sizeof(0)) size_t; -#ifdef INLIB -void operator delete(void *, size_t) noexcept; -void operator delete[](void *, size_t) noexcept; -#endif - typedef int A; struct B { int n; }; struct C { ~C() {} }; @@ -54,63 +47,92 @@ template void del(); D::D() {} // CHECK-LABEL: define weak_odr void @_Z3delIiEvv() +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4) +// CHECKUND: call void @_ZdlPv(i8* %{{[^ ]*}}) // CHECK: call void @_ZdaPv(i8* %{{[^ ]*}}) // +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4) +// CHECKUND: call void @_ZdlPv(i8* %{{[^ ]*}}) // CHECK: call void @_ZdaPv(i8* %{{[^ ]*}}) // CHECKDEF-LABEL: define linkonce void @_ZdlPvm(i8*, i64) #{{[0-9]+}} comdat // CHECKDEF: call void @_ZdlPv(i8* %0) -// CHECKUND-LABEL: declare void @_ZdlPvm(i8* +// CHECKUND-LABEL: declare extern_weak void @_ZdlPvm(i8* // CHECK-LABEL: define weak_odr void @_Z3delI1BEvv() +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4) +// CHECKUND: call void @_ZdlPv(i8* %{{[^ ]*}}) // CHECK: call void @_ZdaPv(i8* %{{[^ ]*}}) // +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4) +// CHECKUND: call void @_ZdlPv(i8* %{{[^ ]*}}) // CHECK: call void @_ZdaPv(i8* %{{[^ ]*}}) // CHECK-LABEL: define weak_odr void @_Z3delI1CEvv() +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 1) +// CHECKUND: call void @_ZdlPv(i8* %{{[^ ]*}}) +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdaPvm, void (i8*, i64)* null), // CHECK: mul i64 1, %{{[^ ]*}} // CHECK: add i64 %{{[^ ]*}}, 8 // CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}}) +// CHECKUND: call void @_ZdaPv(i8* %{{[^ ]*}}) // +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 1) +// CHECKUND: call void @_ZdlPv(i8* %{{[^ ]*}}) +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdaPvm, void (i8*, i64)* null), // CHECK: mul i64 1, %{{[^ ]*}} // CHECK: add i64 %{{[^ ]*}}, 8 // CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}}) +// CHECKUND: call void @_ZdaPv(i8* %{{[^ ]*}}) // CHECKDEF-LABEL: define linkonce void @_ZdaPvm(i8*, i64) #{{[0-9]+}} comdat // CHECKDEF: call void @_ZdaPv(i8* %0) -// CHECKUND-LABEL: declare void @_ZdaPvm(i8* +// CHECKUND-LABEL: declare extern_weak void @_ZdaPvm(i8* // CHECK-LABEL: define weak_odr void @_Z3delI1DEvv() +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 8) +// CHECKUND: call void @_ZdlPv(i8* %{{[^ ]*}}) +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdaPvm, void (i8*, i64)* null), // CHECK: mul i64 8, %{{[^ ]*}} // CHECK: add i64 %{{[^ ]*}}, 8 // CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}}) +// CHECKUND: call void @_ZdaPv(i8* %{{[^ ]*}}) // -// CHECK-NOT: Zdl +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), +// CHECKDEF-NOT: Zdl // CHECK: call void %{{.*}} // CHECK-NOT: Zdl +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdaPvm, void (i8*, i64)* null), // CHECK: mul i64 8, %{{[^ ]*}} // CHECK: add i64 %{{[^ ]*}}, 8 // CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}}) +// CHECKUND: call void @_ZdaPv(i8* %{{[^ ]*}}) // CHECK-LABEL: define weak_odr void @_Z3delI1EEvv() +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 1) +// CHECKUND: call void @_ZdlPv(i8* %{{[^ ]*}}) // CHECK: call void @_ZdaPv(i8* %{{[^ ]*}}) // // CHECK: call void @_ZN1EdlEPv(i8* %{{[^ ]*}}) // CHECK: call void @_ZN1EdaEPv(i8* %{{[^ ]*}}) // CHECK-LABEL: define weak_odr void @_Z3delI1FEvv() +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 1) +// CHECKUND: call void @_ZdlPv(i8* %{{[^ ]*}}) +// CHECKUND: br i1 icmp ne (void (i8*, i64)* @_ZdaPvm, void (i8*, i64)* null), // CHECK: mul i64 1, %{{[^ ]*}} // CHECK: add i64 %{{[^ ]*}}, 8 // CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}}) +// CHECKUND: call void @_ZdaPv(i8* %{{[^ ]*}}) // // CHECK: call void @_ZN1FdlEPvm(i8* %{{[^ ]*}}, i64 1) // CHECK: mul i64 1, %{{[^ ]*}} diff --git a/test/CodeGenCXX/implicit-allocation-functions.cpp b/test/CodeGenCXX/implicit-allocation-functions.cpp index d4e9841c1c..3b66a0772b 100644 --- a/test/CodeGenCXX/implicit-allocation-functions.cpp +++ b/test/CodeGenCXX/implicit-allocation-functions.cpp @@ -1,21 +1,15 @@ // RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++11 %s 2>&1 | FileCheck %s -check-prefix=CHECKDEF -check-prefix=CHECK11 // RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++11 -fvisibility hidden %s 2>&1 | FileCheck %s -check-prefix=CHECKHID -check-prefix=CHECK11 -// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 -DINLIB -fno-sized-deallocation %s 2>&1 | FileCheck %s -check-prefix=CHECKDEF -check-prefix=CHECK11 -// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 -DINLIB %s 2>&1 | FileCheck %s -check-prefix=CHECKDEF -check-prefix=CHECK14 -check-prefix=CHECK14UND -// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 -DINLIB -fvisibility hidden %s 2>&1 | FileCheck %s -check-prefix=CHECKHID -check-prefix=CHECK14 -check-prefix=CHECK14UND -// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 -DINLIB -fdefine-sized-deallocation %s 2>&1 | FileCheck %s -check-prefix=CHECKDEF -check-prefix=CHECK14 -check-prefix=CHECK14DEFCOMDAT -// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 -DINLIB -fdefine-sized-deallocation -fvisibility hidden %s 2>&1 | FileCheck %s -check-prefix=CHECKHID -check-prefix=CHECK14 -check-prefix=CHECK14DEFCOMDAT -// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-macosx -o - -std=c++14 -DINLIB -fdefine-sized-deallocation %s | FileCheck %s -check-prefix=CHECKDEF -check-prefix=CHECK14 -check-prefix=CHECK14DEFNOCOMDAT +// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 -fno-sized-deallocation %s 2>&1 | FileCheck %s -check-prefix=CHECKDEF -check-prefix=CHECK11 +// RU N: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 %s 2>&1 | FileCheck %s -check-prefix=CHECKDEF -check-prefix=CHECK14 -check-prefix=CHECK14UND +// RU N: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 -fvisibility hidden %s 2>&1 | FileCheck %s -check-prefix=CHECKHID -check-prefix=CHECK14 -check-prefix=CHECK14UND +// RU N: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 -fdefine-sized-deallocation %s 2>&1 | FileCheck %s -check-prefix=CHECKDEF -check-prefix=CHECK14 -check-prefix=CHECK14DEFCOMDAT +// RU N: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown -o - -std=c++14 -fdefine-sized-deallocation -fvisibility hidden %s 2>&1 | FileCheck %s -check-prefix=CHECKHID -check-prefix=CHECK14 -check-prefix=CHECK14DEFCOMDAT +// RU N: %clang_cc1 -emit-llvm -triple x86_64-apple-macosx -o - -std=c++14 -fdefine-sized-deallocation %s | FileCheck %s -check-prefix=CHECKDEF -check-prefix=CHECK14 -check-prefix=CHECK14DEFNOCOMDAT // PR22419: Implicit sized deallocation functions always have default visibility. // Generalized to all implicit allocation functions. -#ifdef INLIB -typedef decltype(sizeof(0)) size_t; -void operator delete(void *, size_t) noexcept; -void operator delete[](void *, size_t) noexcept; -#endif - // CHECK14-DAG: %struct.A = type { i8 } struct A { }; @@ -28,7 +22,9 @@ void foo(A* is) { is = new A(); // CHECK11-DAG: call void @_ZdlPv(i8* %{{.+}}) + // CHECK14UND-DAG: br i1 icmp ne (void (i8*, i64)* @_ZdlPvm, void (i8*, i64)* null), // CHECK14-DAG: call void @_ZdlPvm(i8* %{{.+}}, i64 1) + // CHECK14UND-DAG: call void @_ZdlPv(i8* %{{.+}}) delete is; } @@ -36,7 +32,7 @@ void foo(A* is) { // CHECK11-DAG: declare void @_ZdlPv(i8*) // CHECK14-DAG: declare noalias i8* @_Znwm(i64) -// CHECK14UND-DAG: declare void @_ZdlPvm(i8*, i64) +// CHECK14UND-DAG: declare extern_weak void @_ZdlPvm(i8*, i64) // CHECK14DEFCOMDAT-DAG: define linkonce void @_ZdlPvm(i8*, i64) #{{[0-9]+}} comdat { // CHECK14DEFCOMDAT-DAG: declare void @_ZdlPv(i8*) // CHECK14DEFNOCOMDAT-DAG: define linkonce void @_ZdlPvm(i8*, i64) #{{[0-9]+}} { @@ -54,7 +50,9 @@ void f(B *p) { p = new B[5]; // CHECK11-DAG: call void @_ZdaPv(i8* %{{.+}}) + // CHECK14UND-DAG: br i1 icmp ne (void (i8*, i64)* @_ZdaPvm, void (i8*, i64)* null), // CHECK14-DAG: call void @_ZdaPvm(i8* %{{.+}}, i64 %{{.+}}) + // CHECK14UND-DAG: call void @_ZdaPv(i8* %{{.+}}) delete[] p; } @@ -62,7 +60,7 @@ void f(B *p) { // CHECK11-DAG: declare void @_ZdaPv(i8*) // CHECK14-DAG: declare noalias i8* @_Znam(i64) -// CHECK14UND-DAG: declare void @_ZdaPvm(i8*, i64) +// CHECK14UND-DAG: declare extern_weak void @_ZdaPvm(i8*, i64) // CHECK14DEF-DAG: define linkonce void @_ZdaPvm(i8*, i64) #{{[0-9]+}} comdat { // CHECK14DEF-DAG: declare void @_ZdaPv(i8*) // CHECK14DEFNOCOMDAT-DAG: define linkonce void @_ZdaPvm(i8*, i64) #{{[0-9]+}} { diff --git a/test/CodeGenCXX/pr21754.cpp b/test/CodeGenCXX/pr21754.cpp index 65ee76559a..61c1969860 100644 --- a/test/CodeGenCXX/pr21754.cpp +++ b/test/CodeGenCXX/pr21754.cpp @@ -1,11 +1,13 @@ -// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++1y -o - %s 2>&1 | FileCheck %s -// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++1y -fdefine-sized-deallocation -o - %s 2>&1 | FileCheck %s -// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++1y -fno-sized-deallocation -o - %s 2>&1 | FileCheck %s -// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++11 -fsized-deallocation -o - %s 2>&1 | FileCheck %s -// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++11 -fsized-deallocation -fdefine-sized-deallocation -o - %s 2>&1 | FileCheck %s -// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++11 -o - %s 2>&1 | FileCheck %s +// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++1y -o - %s 2>&1 | FileCheck %s --check-prefix=CHECKUND +// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++1y -fdefine-sized-deallocation -o - %s 2>&1 | FileCheck %s --check-prefix=CHECKDEF +// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++1y -fno-sized-deallocation -o - %s 2>&1 | FileCheck %s --check-prefix=CHECKNO +// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++11 -fsized-deallocation -o - %s 2>&1 | FileCheck %s --check-prefix=CHECKUND +// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++11 -fsized-deallocation -fdefine-sized-deallocation -o - %s 2>&1 | FileCheck %s --check-prefix=CHECKDEF +// RUN: %clang -cc1 -emit-llvm -triple x86_64-unknown-unknown -std=c++11 -o - %s 2>&1 | FileCheck %s --check-prefix=CHECKNO void operator delete(void*, unsigned long) throw() __attribute__((alias("foo"))); extern "C" void foo(void*, unsigned long) {} -// CHECK-DAG: @_ZdlPvm = alias void (i8*, i64)* @foo +// CHECKUND-DAG: @_ZdlPvm = weak alias void (i8*, i64)* @foo +// CHECKDEF-DAG: @_ZdlPvm = alias void (i8*, i64)* @foo +// CHECKNO-DAG: @_ZdlPvm = alias void (i8*, i64)* @foo -- 2.40.0