C++14: Disable sized deallocation by default due to ABI breakage
authorReid Kleckner <reid@kleckner.net>
Fri, 20 Mar 2015 00:31:07 +0000 (00:31 +0000)
committerReid Kleckner <reid@kleckner.net>
Fri, 20 Mar 2015 00:31:07 +0000 (00:31 +0000)
There are no widely deployed standard libraries providing sized
deallocation functions, so we have to punt and ask the user if they want
us to use sized deallocation. In the future, when such libraries are
deployed, we can teach the driver to detect them and enable this
feature.

N3536 claimed that a weak thunk from sized to unsized deallocation could
be emitted to avoid breaking backwards compatibility with standard
libraries not providing sized deallocation. However, this approach and
other variations don't work in practice.

With the weak function approach, the thunk has to have default
visibility in order to ensure that it is overridden by other DSOs
providing sized deallocation. Weak, default visibility symbols are
particularly expensive on MachO, so John McCall was considering
disabling this feature by default on Darwin. It also changes behavior
ELF linking behavior, causing certain otherwise unreferenced object
files from an archive to be pulled into the link.

Our second approach was to use an extern_weak function declaration and
do an inline conditional branch at the deletion call site. This doesn't
work because extern_weak only works on MachO if you have some archive
providing the default value of the extern_weak symbol. Arranging to
provide such an archive has the same challenges as providing the symbol
in the standard library. Not to mention that extern_weak doesn't really
work on COFF.

Reviewers: rsmith, rjmccall

Differential Revision: http://reviews.llvm.org/D8467

llvm-svn: 232788

17 files changed:
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/Decl.h
clang/include/clang/Basic/LangOptions.def
clang/include/clang/Driver/CC1Options.td
clang/include/clang/Driver/Options.td
clang/lib/AST/Decl.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Driver/Tools.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/CXX/drs/dr412.cpp
clang/test/CodeGenCXX/cxx1y-sized-deallocation.cpp
clang/test/CodeGenCXX/implicit-allocation-functions.cpp [deleted file]
clang/test/CodeGenCXX/pr21754.cpp [deleted file]
clang/test/Lexer/cxx-features.cpp
clang/www/cxx_status.html

index 5727a35..90655d4 100644 (file)
@@ -62,6 +62,11 @@ about them. The improvements since the 3.5 release include:
 New Compiler Flags
 ------------------
 
+The sized deallocation feature of C++14 is now controlled by the
+``-fsized-deallocation`` flag. This feature relies on library support that
+isn't yet widely deployed, so the user must supply an extra flag to get the
+extra functionality.
+
 The option ....
 
 
index 5380339..009335d 100644 (file)
@@ -1861,11 +1861,6 @@ public:
   ///    allocation function. [...]
   bool isReplaceableGlobalAllocationFunction() const;
 
-  /// \brief Determine whether this function is a sized global deallocation
-  /// function in C++1y. If so, find and return the corresponding unsized
-  /// deallocation function.
-  FunctionDecl *getCorrespondingUnsizedGlobalDeallocationFunction() const;
-
   /// Compute the language linkage.
   LanguageLinkage getLanguageLinkage() const;
 
index 21de1e3..f9c372c 100644 (file)
@@ -165,7 +165,6 @@ LANGOPT(CUDAAllowHostCallsFromHostDevice, 1, 0, "Allow host device functions to
 
 LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators")
 LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions")
-LANGOPT(DefineSizedDeallocation , 1, 0, "generate weak definitions of sized delete")
 BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision")
 BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records")
 BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form")
index 11e6942..6b785b4 100644 (file)
@@ -518,12 +518,6 @@ def fdeprecated_macro : Flag<["-"], "fdeprecated-macro">,
   HelpText<"Defines the __DEPRECATED macro">;
 def fno_deprecated_macro : Flag<["-"], "fno-deprecated-macro">,
   HelpText<"Undefines the __DEPRECATED macro">;
-def fsized_deallocation : Flag<["-"], "fsized-deallocation">,
-  HelpText<"Enable C++14 sized global deallocation functions">;
-def fno_sized_deallocation: Flag<["-"], "fno-sized-deallocation">,
-  HelpText<"Disable sized deallocation functions">;
-def fdefine_sized_deallocation: Flag<["-"], "fdefine-sized-deallocation">,
-  HelpText<"Allow compiler-generated definition of sized deallocation functions">;
 def fobjc_subscripting_legacy_runtime : Flag<["-"], "fobjc-subscripting-legacy-runtime">,
   HelpText<"Allow Objective-C array and dictionary subscripting in legacy runtime">;
 def vtordisp_mode_EQ : Joined<["-"], "vtordisp-mode=">,
index 20b1c43..5a37a64 100644 (file)
@@ -830,6 +830,9 @@ def fapplication_extension : Flag<["-"], "fapplication-extension">,
   HelpText<"Restrict code to those available for App Extensions">;
 def fno_application_extension : Flag<["-"], "fno-application-extension">,
   Group<f_Group>;
+def fsized_deallocation : Flag<["-"], "fsized-deallocation">, Flags<[CC1Option]>,
+  HelpText<"Enable C++14 sized global deallocation functions">, Group<f_Group>;
+def fno_sized_deallocation: Flag<["-"], "fno-sized-deallocation">, Group<f_Group>;
 
 def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Use GC exclusively for Objective-C related memory management">;
index e700cf8..3498772 100644 (file)
@@ -2513,39 +2513,6 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const {
   return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace();
 }
 
-FunctionDecl *
-FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const {
-  ASTContext &Ctx = getASTContext();
-  if (!Ctx.getLangOpts().SizedDeallocation)
-    return nullptr;
-
-  if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
-    return nullptr;
-  if (getDeclName().getCXXOverloadedOperator() != OO_Delete &&
-      getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
-    return nullptr;
-  if (isa<CXXRecordDecl>(getDeclContext()))
-    return nullptr;
-
-  if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
-    return nullptr;
-
-  if (getNumParams() != 2 || isVariadic() ||
-      !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getParamType(1),
-                       Ctx.getSizeType()))
-    return nullptr;
-
-  // This is a sized deallocation function. Find the corresponding unsized
-  // deallocation function.
-  lookup_result R = getDeclContext()->lookup(getDeclName());
-  for (lookup_result::iterator RI = R.begin(), RE = R.end(); RI != RE;
-       ++RI)
-    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*RI))
-      if (FD->getNumParams() == 1 && !FD->isVariadic())
-        return FD;
-  return nullptr;
-}
-
 LanguageLinkage FunctionDecl::getLanguageLinkage() const {
   return getDeclLanguageLinkage(*this);
 }
index dabec15..9e80f0a 100644 (file)
@@ -802,20 +802,6 @@ static void TryMarkNoThrow(llvm::Function *F) {
   F->setDoesNotThrow();
 }
 
-static void EmitSizedDeallocationFunction(CodeGenFunction &CGF,
-                                          const FunctionDecl *UnsizedDealloc) {
-  // This is a weak discardable definition of the sized deallocation function.
-  CGF.CurFn->setLinkage(llvm::Function::LinkOnceAnyLinkage);
-  if (CGF.CGM.supportsCOMDAT())
-    CGF.CurFn->setComdat(
-        CGF.CGM.getModule().getOrInsertComdat(CGF.CurFn->getName()));
-
-  // Call the unsized deallocation function and forward the first argument
-  // unchanged.
-  llvm::Constant *Unsized = CGF.CGM.GetAddrOfFunction(UnsizedDealloc);
-  CGF.Builder.CreateCall(Unsized, &*CGF.CurFn->arg_begin());
-}
-
 void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
                                    const CGFunctionInfo &FnInfo) {
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -891,14 +877,6 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
     emitImplicitAssignmentOperatorBody(Args);
   } else if (Stmt *Body = FD->getBody()) {
     EmitFunctionBody(Args, Body);
-  } else if (FunctionDecl *UnsizedDealloc =
-                 FD->getCorrespondingUnsizedGlobalDeallocationFunction()) {
-    // Global sized deallocation functions get an implicit weak definition if
-    // they don't have an explicit definition, if allowed.
-    assert(getLangOpts().DefineSizedDeallocation &&
-           "Can't emit unallowed definition.");
-    EmitSizedDeallocationFunction(*this, UnsizedDealloc);
-
   } else
     llvm_unreachable("no definition for emitted function");
 
index d1da069..f4ae684 100644 (file)
@@ -1620,16 +1620,6 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,
       // don't need it anymore).
       addDeferredDeclToEmit(F, DDI->second);
       DeferredDecls.erase(DDI);
-      
-      // Otherwise, if this is a sized deallocation function, emit a weak
-      // definition for it at the end of the translation unit (if allowed),
-      // unless the sized deallocation function is aliased.
-    } else if (D &&
-               cast<FunctionDecl>(D)
-                  ->getCorrespondingUnsizedGlobalDeallocationFunction() &&
-               getLangOpts().DefineSizedDeallocation &&
-               !D->hasAttr<AliasAttr>()) {
-      addDeferredDeclToEmit(F, GD);
 
       // Otherwise, there are cases we have to worry about where we're
       // using a declaration for which we must emit a definition but where
index 4ec8cae..94c71ac 100644 (file)
@@ -4250,6 +4250,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                     options::OPT_fno_assume_sane_operator_new))
     CmdArgs.push_back("-fno-assume-sane-operator-new");
 
+  // -fsized-deallocation is off by default, as it is an ABI-breaking change for
+  // most platforms.
+  if (Args.hasFlag(options::OPT_fsized_deallocation,
+                   options::OPT_fno_sized_deallocation, false))
+    CmdArgs.push_back("-fsized-deallocation");
+
   // -fconstant-cfstrings is default, and may be subject to argument translation
   // on Darwin.
   if (!Args.hasFlag(options::OPT_fconstant_cfstrings,
index b9869fd..42de57e 100644 (file)
@@ -1262,9 +1262,6 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
   Opts.CXXOperatorNames = Opts.CPlusPlus;
 
   Opts.DollarIdents = !Opts.AsmPreprocessor;
-
-  // C++14 onwards has sized global deallocation functions.
-  Opts.SizedDeallocation = Opts.CPlusPlus14;
 }
 
 /// Attempt to parse a visibility value out of the given argument.
@@ -1543,10 +1540,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
   Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin);
   Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
-  Opts.SizedDeallocation |= Args.hasArg(OPT_fsized_deallocation);
-  Opts.SizedDeallocation &= !Args.hasArg(OPT_fno_sized_deallocation);
-  Opts.DefineSizedDeallocation = Opts.SizedDeallocation &&
-      Args.hasArg(OPT_fdefine_sized_deallocation);
+  Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation);
   Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
   Opts.AccessControl = !Args.hasArg(OPT_fno_access_control);
   Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
index 97ee7bd..bdd92c0 100644 (file)
@@ -2168,15 +2168,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;
 
index 39cdd61..27bc7e5 100644 (file)
@@ -15,7 +15,7 @@ inline void* operator new(size_t) BAD_ALLOC; // expected-error {{cannot be decla
 inline void* operator new[](size_t) BAD_ALLOC; // expected-error {{cannot be declared 'inline'}}
 inline void operator delete(void*) NOEXCEPT; // expected-error {{cannot be declared 'inline'}}
 inline void operator delete[](void*) NOEXCEPT; // expected-error {{cannot be declared 'inline'}}
-#if __cplusplus >= 201402L
+#ifdef __cpp_sized_deallocation
 inline void operator delete(void*, size_t) NOEXCEPT; // expected-error {{cannot be declared 'inline'}}
 inline void operator delete[](void*, size_t) NOEXCEPT; // expected-error {{cannot be declared 'inline'}}
 #endif
index 1d021a7..78cc713 100644 (file)
@@ -1,22 +1,18 @@
-// 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 -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 -fdefine-sized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKDEF
+// Check that delete exprs call the sized deallocation function if
+// -fsized-deallocation is passed in both C++11 and C++14.
+// RUN: %clang_cc1 -std=c++11 -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s
+// RUN: %clang_cc1 -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 -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
+// RUN: %clang_cc1 -std=c++14 %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNSIZED
 
 // CHECK-UNSIZED-NOT: _ZdlPvm
 // CHECK-UNSIZED-NOT: _ZdaPvm
 
 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() {} };
@@ -60,9 +56,7 @@ D::D() {}
 // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4)
 // 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*
+// CHECK-LABEL: declare void @_ZdlPvm(i8*
 
 // CHECK-LABEL: define weak_odr void @_Z3delI1BEvv()
 // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 4)
@@ -82,9 +76,7 @@ D::D() {}
 // CHECK: add i64 %{{[^ ]*}}, 8
 // CHECK: call void @_ZdaPvm(i8* %{{[^ ]*}}, i64 %{{[^ ]*}})
 
-// CHECKDEF-LABEL: define linkonce void @_ZdaPvm(i8*, i64) #{{[0-9]+}} comdat
-// CHECKDEF: call void @_ZdaPv(i8* %0)
-// CHECKUND-LABEL: declare void @_ZdaPvm(i8*
+// CHECK-LABEL: declare void @_ZdaPvm(i8*
 
 // CHECK-LABEL: define weak_odr void @_Z3delI1DEvv()
 // CHECK: call void @_ZdlPvm(i8* %{{[^ ]*}}, i64 8)
diff --git a/clang/test/CodeGenCXX/implicit-allocation-functions.cpp b/clang/test/CodeGenCXX/implicit-allocation-functions.cpp
deleted file mode 100644 (file)
index d4e9841..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-// 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
-
-// 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 { };
-
-// CHECKDEF-DAG: define void @_Z3fooP1A(%struct.A* %is)
-// CHECKHID-DAG: define hidden void @_Z3fooP1A(%struct.A* %is)
-void foo(A* is) {
-
-  // CHECK11-DAG: call noalias i8* @_Znwm(i64 1)
-  // CHECK14-DAG: call noalias i8* @_Znwm(i64 1)
-  is = new A();
-
-  // CHECK11-DAG: call void @_ZdlPv(i8* %{{.+}})
-  // CHECK14-DAG: call void @_ZdlPvm(i8* %{{.+}}, i64 1)
-  delete is;
-}
-
-// CHECK11-DAG: declare noalias i8* @_Znwm(i64)
-// CHECK11-DAG: declare void @_ZdlPv(i8*)
-
-// CHECK14-DAG: declare noalias i8* @_Znwm(i64)
-// CHECK14UND-DAG: declare 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]+}} {
-// CHECK14DEFNOCOMDAT-DAG: declare void @_ZdlPv(i8*)
-
-// CHECK14-DAG: %struct.B = type { i8 }
-struct B { ~B() { }};
-
-// CHECKDEF-DAG: define void @_Z1fP1B(%struct.B* %p)
-// CHECKHID-DAG: define hidden void @_Z1fP1B(%struct.B* %p)
-void f(B *p) {
-
-  // CHECK11-DAG: call noalias i8* @_Znam(i64 13)
-  // CHECK14-DAG: call noalias i8* @_Znam(i64 13)
-  p = new B[5];
-
-  // CHECK11-DAG: call void @_ZdaPv(i8* %{{.+}})
-  // CHECK14-DAG: call void @_ZdaPvm(i8* %{{.+}}, i64 %{{.+}})
-  delete[] p;
-}
-
-// CHECK11-DAG: declare noalias i8* @_Znam(i64)
-// CHECK11-DAG: declare void @_ZdaPv(i8*)
-
-// CHECK14-DAG: declare noalias i8* @_Znam(i64)
-// CHECK14UND-DAG: declare 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]+}} {
-// CHECK14DEFNOCOMDAT-DAG: declare void @_ZdaPv(i8*)
diff --git a/clang/test/CodeGenCXX/pr21754.cpp b/clang/test/CodeGenCXX/pr21754.cpp
deleted file mode 100644 (file)
index 65ee765..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// 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
-
-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
index 670a105..d06090e 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -std=c++98 -verify %s
 // RUN: %clang_cc1 -std=c++11 -verify %s
-// RUN: %clang_cc1 -std=c++1y -verify %s
+// RUN: %clang_cc1 -std=c++1y -fsized-deallocation -verify %s
 
 // expected-no-diagnostics
 
index 4c767d1..5b53cba 100644 (file)
@@ -504,14 +504,14 @@ Clang version in which each feature became available.</p>
       <td class="full" align="center">Clang 3.4 <a href="#n3778">(6)</a></td>
     </tr>
 </table>
+
 <p>
-<span id="n3778">(6): In Clang SVN, using sized deallocation in C++14 mode requires linking either
-libc++ 3.7 or later, or libstdc++ 5 or later. Alternatively, you can use the
-<code>-Xclang -fdefine-sized-deallocation</code> compiler option to enable the implementation from
-Clang 3.4 through Clang 3.6, where weak definitions of sized deallocation functions are implicitly
-generated (by the compiler). You can also use the <code>-Xclang -fno-sized-deallocation</code> option 
-to disable sized deallocation. Note that both of these flags are temporary provisions and may go away
-soon.
+<span id="n3778">(6): In Clang 3.7 and later, sized deallocation is only enabled
+if the user passes the <code>-fsized-deallocation</code> 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. <code>libstdc++</code>
+added these functions in version 5.0, and <code>libc++</code> added them in
+version 3.7.
 </span>
 </p>