<div dir="ltr"><div>Richard: the msan bot printed this, maybe it helps relanding (<a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/17061/steps/check-clang%20msan/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/17061/steps/check-clang%20msan/logs/stdio</a>):</div><div>==23518==WARNING: MemorySanitizer: use-of-uninitialized-value</div><div>    #0 0x81d82d9 in getKind /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/AST/DeclBase.h:390:51</div><div>    #1 0x81d82d9 in getUnderlyingDecl /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/AST/Decl.h:389</div><div>    #2 0x81d82d9 in getUnderlyingDecl /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/AST/Decl.h:398</div><div>    #3 0x81d82d9 in operator() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Sema/SemaCUDA.cpp:168</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Oct 10, 2016 at 10:13 AM, Daniel Jasper via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: djasper<br>
Date: Mon Oct 10 09:13:55 2016<br>
New Revision: 283750<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=283750&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=283750&view=rev</a><br>
Log:<br>
Revert "P0035R4: Semantic analysis and code generation for C++17 overaligned allocation."<br>
<br>
This reverts commit r283722. Breaks:<br>
  <a href="http://Clang.SemaCUDA.device-var-init.cu" rel="noreferrer" target="_blank">Clang.SemaCUDA.device-var-<wbr>init.cu</a><br>
  <a href="http://Clang.CodeGenCUDA.device-var-init.cu" rel="noreferrer" target="_blank">Clang.CodeGenCUDA.device-var-<wbr>init.cu</a><br>
<br>
<a href="http://lab.llvm.org:8080/green/job/clang-stage1-cmake-RA-expensive/884/" rel="noreferrer" target="_blank">http://lab.llvm.org:8080/<wbr>green/job/clang-stage1-cmake-<wbr>RA-expensive/884/</a><br>
<br>
Removed:<br>
    cfe/trunk/test/CXX/basic/<wbr>basic.stc/basic.stc.dynamic/<wbr>basic.stc.dynamic.<wbr>deallocation/p2.cpp<br>
    cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.delete/p10.cpp<br>
    cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.new/p14.cpp<br>
    cfe/trunk/test/CodeGenCXX/<wbr>cxx1z-aligned-allocation.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/AST/<wbr>ASTContext.h<br>
    cfe/trunk/include/clang/AST/<wbr>ExprCXX.h<br>
    cfe/trunk/include/clang/AST/<wbr>Type.h<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
    cfe/trunk/include/clang/Sema/<wbr>Overload.h<br>
    cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
    cfe/trunk/lib/AST/ASTContext.<wbr>cpp<br>
    cfe/trunk/lib/AST/ASTImporter.<wbr>cpp<br>
    cfe/trunk/lib/AST/Decl.cpp<br>
    cfe/trunk/lib/AST/DeclCXX.cpp<br>
    cfe/trunk/lib/AST/ExprCXX.cpp<br>
    cfe/trunk/lib/AST/Type.cpp<br>
    cfe/trunk/lib/CodeGen/<wbr>CGExprCXX.cpp<br>
    cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h<br>
    cfe/trunk/lib/Sema/SemaCUDA.<wbr>cpp<br>
    cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
    cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp<br>
    cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
    cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp<br>
    cfe/trunk/lib/Serialization/<wbr>ASTReaderStmt.cpp<br>
    cfe/trunk/lib/Serialization/<wbr>ASTWriterStmt.cpp<br>
    cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.new/p20-0x.cpp<br>
    cfe/trunk/test/CXX/special/<wbr>class.dtor/p9.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/<wbr>ASTContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/ASTContext.h?rev=<wbr>283750&r1=283749&r2=283750&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/AST/<wbr>ASTContext.h (original)<br>
+++ cfe/trunk/include/clang/AST/<wbr>ASTContext.h Mon Oct 10 09:13:55 2016<br>
@@ -1881,11 +1881,6 @@ public:<br>
   unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; }<br>
   unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; }<br>
<br>
-  /// \brief Return the ABI-specified alignment of a type, in bits, or 0 if<br>
-  /// the type is incomplete and we cannot determine the alignment (for<br>
-  /// example, from alignment attributes).<br>
-  unsigned getTypeAlignIfKnown(QualType T) const;<br>
-<br>
   /// \brief Return the ABI-specified alignment of a (complete) type \p T, in<br>
   /// characters.<br>
   CharUnits getTypeAlignInChars(QualType T) const;<br>
<br>
Modified: cfe/trunk/include/clang/AST/<wbr>ExprCXX.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/ExprCXX.h?rev=<wbr>283750&r1=283749&r2=283750&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/AST/<wbr>ExprCXX.h (original)<br>
+++ cfe/trunk/include/clang/AST/<wbr>ExprCXX.h Mon Oct 10 09:13:55 2016<br>
@@ -1838,13 +1838,11 @@ class CXXNewExpr : public Expr {<br>
   unsigned GlobalNew : 1;<br>
   /// Do we allocate an array? If so, the first SubExpr is the size expression.<br>
   unsigned Array : 1;<br>
-  /// Should the alignment be passed to the allocation function?<br>
-  unsigned PassAlignment : 1;<br>
   /// If this is an array allocation, does the usual deallocation<br>
   /// function for the allocated type want to know the allocated size?<br>
   unsigned UsualArrayDeleteWantsSize : 1;<br>
   /// The number of placement new arguments.<br>
-  unsigned NumPlacementArgs : 26;<br>
+  unsigned NumPlacementArgs : 13;<br>
   /// What kind of initializer do we have? Could be none, parens, or braces.<br>
   /// In storage, we distinguish between "none, and no initializer expr", and<br>
   /// "none, but an implicit initializer expr".<br>
@@ -1860,8 +1858,8 @@ public:<br>
   };<br>
<br>
   CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew,<br>
-             FunctionDecl *operatorDelete, bool PassAlignment,<br>
-             bool usualArrayDeleteWantsSize, ArrayRef<Expr*> placementArgs,<br>
+             FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize,<br>
+             ArrayRef<Expr*> placementArgs,<br>
              SourceRange typeIdParens, Expr *arraySize,<br>
              InitializationStyle initializationStyle, Expr *initializer,<br>
              QualType ty, TypeSourceInfo *AllocatedTypeInfo,<br>
@@ -1949,16 +1947,10 @@ public:<br>
   }<br>
<br>
   /// \brief Returns the CXXConstructExpr from this new-expression, or null.<br>
-  const CXXConstructExpr *getConstructExpr() const {<br>
+  const CXXConstructExpr* getConstructExpr() const {<br>
     return dyn_cast_or_null<<wbr>CXXConstructExpr>(<wbr>getInitializer());<br>
   }<br>
<br>
-  /// Indicates whether the required alignment should be implicitly passed to<br>
-  /// the allocation function.<br>
-  bool passAlignment() const {<br>
-    return PassAlignment;<br>
-  }<br>
-<br>
   /// Answers whether the usual array deallocation function for the<br>
   /// allocated type expects the size of the allocation as a<br>
   /// parameter.<br>
<br>
Modified: cfe/trunk/include/clang/AST/<wbr>Type.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/Type.h?rev=283750&<wbr>r1=283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/AST/<wbr>Type.h (original)<br>
+++ cfe/trunk/include/clang/AST/<wbr>Type.h Mon Oct 10 09:13:55 2016<br>
@@ -1729,8 +1729,7 @@ public:<br>
   bool isObjCARCBridgableType() const;<br>
   bool isCARCBridgableType() const;<br>
   bool isTemplateTypeParmType() const;          // C++ template type parameter<br>
-  bool isNullPtrType() const;                   // C++11 std::nullptr_t<br>
-  bool isAlignValT() const;                     // C++17 std::align_val_t<br>
+  bool isNullPtrType() const;                   // C++0x nullptr_t<br>
   bool isAtomicType() const;                    // C11 _Atomic()<br>
<br>
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/<wbr>DiagnosticSemaKinds.td?rev=<wbr>283750&r1=283749&r2=283750&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td Mon Oct 10 09:13:55 2016<br>
@@ -6025,10 +6025,6 @@ def err_no_suitable_delete_member_<wbr>functi<br>
   "no suitable member %0 in %1">;<br>
 def err_ambiguous_suitable_delete_<wbr>member_function_found : Error<<br>
   "multiple suitable %0 functions in %1">;<br>
-def warn_ambiguous_suitable_<wbr>delete_function_found : Warning<<br>
-  "multiple suitable %0 functions for %1; no 'operator delete' function "<br>
-  "will be invoked if initialization throws an exception">,<br>
-  InGroup<DiagGroup<"ambiguous-<wbr>delete">>;<br>
 def note_member_declared_here : Note<<br>
   "member %0 declared here">;<br>
 def err_decrement_bool : Error<"cannot decrement expression of type bool">;<br>
<br>
Modified: cfe/trunk/include/clang/Sema/<wbr>Overload.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Overload.h?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Sema/Overload.h?rev=<wbr>283750&r1=283749&r2=283750&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Sema/<wbr>Overload.h (original)<br>
+++ cfe/trunk/include/clang/Sema/<wbr>Overload.h Mon Oct 10 09:13:55 2016<br>
@@ -795,9 +795,7 @@ namespace clang {<br>
                         OverloadCandidateDisplayKind OCD,<br>
                         ArrayRef<Expr *> Args,<br>
                         StringRef Opc = "",<br>
-                        SourceLocation Loc = SourceLocation(),<br>
-                        llvm::function_ref<bool(<wbr>OverloadCandidate&)> Filter =<br>
-                          [](OverloadCandidate&) { return true; });<br>
+                        SourceLocation Loc = SourceLocation());<br>
   };<br>
<br>
   bool isBetterOverloadCandidate(Sema &S,<br>
<br>
Modified: cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Sema/Sema.h?rev=283750&<wbr>r1=283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Sema/<wbr>Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/<wbr>Sema.h Mon Oct 10 09:13:55 2016<br>
@@ -4855,9 +4855,14 @@ public:<br>
                           SourceRange R);<br>
   bool FindAllocationFunctions(<wbr>SourceLocation StartLoc, SourceRange Range,<br>
                                bool UseGlobal, QualType AllocType, bool IsArray,<br>
-                               bool &PassAlignment, MultiExprArg PlaceArgs,<br>
+                               MultiExprArg PlaceArgs,<br>
                                FunctionDecl *&OperatorNew,<br>
                                FunctionDecl *&OperatorDelete);<br>
+  bool FindAllocationOverload(<wbr>SourceLocation StartLoc, SourceRange Range,<br>
+                              DeclarationName Name, MultiExprArg Args,<br>
+                              DeclContext *Ctx,<br>
+                              bool AllowMissing, FunctionDecl *&Operator,<br>
+                              bool Diagnose = true);<br>
   void DeclareGlobalNewDelete();<br>
   void DeclareGlobalAllocationFunctio<wbr>n(DeclarationName Name, QualType Return,<br>
                                        ArrayRef<QualType> Params);<br>
@@ -4867,10 +4872,7 @@ public:<br>
                                 bool Diagnose = true);<br>
   FunctionDecl *<wbr>FindUsualDeallocationFunction(<wbr>SourceLocation StartLoc,<br>
                                               bool CanProvideSize,<br>
-                                              bool Overaligned,<br>
                                               DeclarationName Name);<br>
-  FunctionDecl *<wbr>FindDeallocationFunctionForDes<wbr>tructor(SourceLocation StartLoc,<br>
-                                                      CXXRecordDecl *RD);<br>
<br>
   /// ActOnCXXDelete - Parsed a C++ 'delete' expression<br>
   ExprResult ActOnCXXDelete(SourceLocation StartLoc,<br>
@@ -9335,7 +9337,6 @@ public:<br>
   void EraseUnwantedCUDAMatches(<br>
       const FunctionDecl *Caller,<br>
       SmallVectorImpl<std::pair<<wbr>DeclAccessPair, FunctionDecl *>> &Matches);<br>
-  void EraseUnwantedCUDAMatches(const FunctionDecl *Caller, LookupResult &R);<br>
<br>
   /// Given a implicit special member, infer its CUDA target from the<br>
   /// calls it needs to make to underlying base/field special members.<br>
<br>
Modified: cfe/trunk/lib/AST/ASTContext.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ASTContext.cpp?rev=283750&r1=<wbr>283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/ASTContext.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTContext.<wbr>cpp Mon Oct 10 09:13:55 2016<br>
@@ -1572,30 +1572,6 @@ bool ASTContext::<wbr>isAlignmentRequired(Qua<br>
   return isAlignmentRequired(T.<wbr>getTypePtr());<br>
 }<br>
<br>
-unsigned ASTContext::<wbr>getTypeAlignIfKnown(QualType T) const {<br>
-  // An alignment on a typedef overrides anything else.<br>
-  if (auto *TT = T->getAs<TypedefType>())<br>
-    if (unsigned Align = TT->getDecl()-><wbr>getMaxAlignment())<br>
-      return Align;<br>
-<br>
-  // If we have an (array of) complete type, we're done.<br>
-  T = getBaseElementType(T);<br>
-  if (!T->isIncompleteType())<br>
-    return getTypeAlign(T);<br>
-<br>
-  // If we had an array type, its element type might be a typedef<br>
-  // type with an alignment attribute.<br>
-  if (auto *TT = T->getAs<TypedefType>())<br>
-    if (unsigned Align = TT->getDecl()-><wbr>getMaxAlignment())<br>
-      return Align;<br>
-<br>
-  // Otherwise, see if the declaration of the type had an attribute.<br>
-  if (auto *TT = T->getAs<TagType>())<br>
-    return TT->getDecl()-><wbr>getMaxAlignment();<br>
-<br>
-  return 0;<br>
-}<br>
-<br>
 TypeInfo ASTContext::getTypeInfo(const Type *T) const {<br>
   TypeInfoMap::iterator I = MemoizedTypeInfo.find(T);<br>
   if (I != MemoizedTypeInfo.end())<br>
<br>
Modified: cfe/trunk/lib/AST/ASTImporter.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ASTImporter.cpp?rev=283750&r1=<wbr>283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/ASTImporter.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTImporter.<wbr>cpp Mon Oct 10 09:13:55 2016<br>
@@ -6330,7 +6330,6 @@ Expr *ASTNodeImporter::<wbr>VisitCXXNewExpr(C<br>
         Importer.getToContext(),<br>
         CE->isGlobalNew(),<br>
         OperatorNewDecl, OperatorDeleteDecl,<br>
-        CE->passAlignment(),<br>
         CE-><wbr>doesUsualArrayDeleteWantSize()<wbr>,<br>
         PlacementArgs,<br>
         Importer.Import(CE-><wbr>getTypeIdParens()),<br>
<br>
Modified: cfe/trunk/lib/AST/Decl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>Decl.cpp?rev=283750&r1=283749&<wbr>r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/Decl.cpp (original)<br>
+++ cfe/trunk/lib/AST/Decl.cpp Mon Oct 10 09:13:55 2016<br>
@@ -2596,7 +2596,7 @@ bool FunctionDecl::<wbr>isReplaceableGlobalAl<br>
     return false;<br>
<br>
   const auto *FPT = getType()->castAs<<wbr>FunctionProtoType>();<br>
-  if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic())<br>
+  if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic())<br>
     return false;<br>
<br>
   // If this is a single-parameter function, it must be a replaceable global<br>
@@ -2604,42 +2604,20 @@ bool FunctionDecl::<wbr>isReplaceableGlobalAl<br>
   if (FPT->getNumParams() == 1)<br>
     return true;<br>
<br>
-  unsigned Params = 1;<br>
-  QualType Ty = FPT->getParamType(Params);<br>
+  // Otherwise, we're looking for a second parameter whose type is<br>
+  // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'.<br>
+  QualType Ty = FPT->getParamType(1);<br>
   ASTContext &Ctx = getASTContext();<br>
-<br>
-  auto Consume = [&] {<br>
-    ++Params;<br>
-    Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType();<br>
-  };<br>
-<br>
-  // In C++14, the next parameter can be a 'std::size_t' for sized delete.<br>
-  bool IsSizedDelete = false;<br>
   if (Ctx.getLangOpts().<wbr>SizedDeallocation &&<br>
-      (getDeclName().<wbr>getCXXOverloadedOperator() == OO_Delete ||<br>
-       getDeclName().<wbr>getCXXOverloadedOperator() == OO_Array_Delete) &&<br>
-      Ctx.hasSameType(Ty, Ctx.getSizeType())) {<br>
-    IsSizedDelete = true;<br>
-    Consume();<br>
-  }<br>
-<br>
-  // In C++17, the next parameter can be a 'std::align_val_t' for aligned<br>
-  // new/delete.<br>
-  if (Ctx.getLangOpts().<wbr>AlignedAllocation && !Ty.isNull() && Ty->isAlignValT())<br>
-    Consume();<br>
-<br>
-  // Finally, if this is not a sized delete, the final parameter can<br>
-  // be a 'const std::nothrow_t&'.<br>
-  if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) {<br>
-    Ty = Ty->getPointeeType();<br>
-    if (Ty.getCVRQualifiers() != Qualifiers::Const)<br>
-      return false;<br>
-    const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();<br>
-    if (RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace())<br>
-      Consume();<br>
-  }<br>
-<br>
-  return Params == FPT->getNumParams();<br>
+      Ctx.hasSameType(Ty, Ctx.getSizeType()))<br>
+    return true;<br>
+  if (!Ty->isReferenceType())<br>
+    return false;<br>
+  Ty = Ty->getPointeeType();<br>
+  if (Ty.getCVRQualifiers() != Qualifiers::Const)<br>
+    return false;<br>
+  const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();<br>
+  return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace();<br>
 }<br>
<br>
 LanguageLinkage FunctionDecl::<wbr>getLanguageLinkage() const {<br>
<br>
Modified: cfe/trunk/lib/AST/DeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>DeclCXX.cpp?rev=283750&r1=<wbr>283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Oct 10 09:13:55 2016<br>
@@ -1577,35 +1577,17 @@ bool CXXMethodDecl::<wbr>isUsualDeallocationF<br>
   //   deallocation function. [...]<br>
   if (getNumParams() == 1)<br>
     return true;<br>
-  unsigned UsualParams = 1;<br>
<br>
-  // C++ <=14 [basic.stc.dynamic.<wbr>deallocation]p2:<br>
+  // C++ [basic.stc.dynamic.<wbr>deallocation]p2:<br>
   //   [...] If class T does not declare such an operator delete but does<br>
   //   declare a member deallocation function named operator delete with<br>
   //   exactly two parameters, the second of which has type std::size_t (18.1),<br>
   //   then this function is a usual deallocation function.<br>
-  //<br>
-  // C++17 says a usual deallocation function is one with the signature<br>
-  //   (void* [, size_t] [, std::align_val_t] [, ...])<br>
-  // and all such functions are usual deallocation functions. It's not clear<br>
-  // that allowing varargs functions was intentional.<br>
   ASTContext &Context = getASTContext();<br>
-  if (UsualParams < getNumParams() &&<br>
-      Context.<wbr>hasSameUnqualifiedType(<wbr>getParamDecl(UsualParams)-><wbr>getType(),<br>
-                                     Context.getSizeType()))<br>
-    ++UsualParams;<br>
-<br>
-  if (UsualParams < getNumParams() &&<br>
-      getParamDecl(UsualParams)-><wbr>getType()->isAlignValT())<br>
-    ++UsualParams;<br>
-<br>
-  if (UsualParams != getNumParams())<br>
+  if (getNumParams() != 2 ||<br>
+      !Context.<wbr>hasSameUnqualifiedType(<wbr>getParamDecl(1)->getType(),<br>
+                                      Context.getSizeType()))<br>
     return false;<br>
-<br>
-  // In C++17 onwards, all potential usual deallocation functions are actual<br>
-  // usual deallocation functions.<br>
-  if (Context.getLangOpts().<wbr>AlignedAllocation)<br>
-    return true;<br>
<br>
   // This function is a usual deallocation function if there are no<br>
   // single-parameter deallocation functions of the same kind.<br>
<br>
Modified: cfe/trunk/lib/AST/ExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ExprCXX.cpp?rev=283750&r1=<wbr>283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Oct 10 09:13:55 2016<br>
@@ -62,7 +62,7 @@ SourceLocation CXXScalarValueInitExpr::g<br>
 // CXXNewExpr<br>
 CXXNewExpr::CXXNewExpr(const ASTContext &C, bool globalNew,<br>
                        FunctionDecl *operatorNew, FunctionDecl *operatorDelete,<br>
-                       bool PassAlignment, bool usualArrayDeleteWantsSize,<br>
+                       bool usualArrayDeleteWantsSize,<br>
                        ArrayRef<Expr*> placementArgs,<br>
                        SourceRange typeIdParens, Expr *arraySize,<br>
                        InitializationStyle initializationStyle,<br>
@@ -76,8 +76,7 @@ CXXNewExpr::CXXNewExpr(const ASTContext<br>
     SubExprs(nullptr), OperatorNew(operatorNew), OperatorDelete(operatorDelete)<wbr>,<br>
     AllocatedTypeInfo(<wbr>allocatedTypeInfo), TypeIdParens(typeIdParens),<br>
     Range(Range), DirectInitRange(<wbr>directInitRange),<br>
-    GlobalNew(globalNew), PassAlignment(PassAlignment),<br>
-    UsualArrayDeleteWantsSize(<wbr>usualArrayDeleteWantsSize) {<br>
+    GlobalNew(globalNew), UsualArrayDeleteWantsSize(<wbr>usualArrayDeleteWantsSize) {<br>
   assert((initializer != nullptr || initializationStyle == NoInit) &&<br>
          "Only NoInit can have no initializer.");<br>
   StoredInitializationStyle = initializer ? initializationStyle + 1 : 0;<br>
<br>
Modified: cfe/trunk/lib/AST/Type.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>Type.cpp?rev=283750&r1=283749&<wbr>r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/Type.cpp (original)<br>
+++ cfe/trunk/lib/AST/Type.cpp Mon Oct 10 09:13:55 2016<br>
@@ -2337,15 +2337,6 @@ bool QualType::isCXX11PODType(const ASTC<br>
   return false;<br>
 }<br>
<br>
-bool Type::isAlignValT() const {<br>
-  if (auto *ET = getAs<EnumType>()) {<br>
-    auto *II = ET->getDecl()->getIdentifier()<wbr>;<br>
-    if (II && II->isStr("align_val_t") && ET->getDecl()-><wbr>isInStdNamespace())<br>
-      return true;<br>
-  }<br>
-  return false;<br>
-}<br>
-<br>
 bool Type::isPromotableIntegerType(<wbr>) const {<br>
   if (const BuiltinType *BT = getAs<BuiltinType>())<br>
     switch (BT->getKind()) {<br>
<br>
Modified: cfe/trunk/lib/CodeGen/<wbr>CGExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGExprCXX.cpp?rev=283750&r1=<wbr>283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/<wbr>CGExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/<wbr>CGExprCXX.cpp Mon Oct 10 09:13:55 2016<br>
@@ -1219,116 +1219,111 @@ RValue CodeGenFunction::<wbr>EmitBuiltinNewDe<br>
   llvm_unreachable("predeclared global operator new/delete is missing");<br>
 }<br>
<br>
-static std::pair<bool, bool><br>
-<wbr>shouldPassSizeAndAlignToUsualD<wbr>elete(const FunctionProtoType *FPT) {<br>
-  auto AI = FPT->param_type_begin(), AE = FPT->param_type_end();<br>
+namespace {<br>
+  /// A cleanup to call the given 'operator delete' function upon<br>
+  /// abnormal exit from a new expression.<br>
+  class CallDeleteDuringNew final : public EHScopeStack::Cleanup {<br>
+    size_t NumPlacementArgs;<br>
+    const FunctionDecl *OperatorDelete;<br>
+    llvm::Value *Ptr;<br>
+    llvm::Value *AllocSize;<br>
<br>
-  // The first argument is always a void*.<br>
-  ++AI;<br>
+    RValue *getPlacementArgs() { return reinterpret_cast<RValue*>(<wbr>this+1); }<br>
<br>
-  // Figure out what other parameters we should be implicitly passing.<br>
-  bool PassSize = false;<br>
-  bool PassAlignment = false;<br>
+  public:<br>
+    static size_t getExtraSize(size_t NumPlacementArgs) {<br>
+      return NumPlacementArgs * sizeof(RValue);<br>
+    }<br>
<br>
-  if (AI != AE && (*AI)->isIntegerType()) {<br>
-    PassSize = true;<br>
-    ++AI;<br>
-  }<br>
+    CallDeleteDuringNew(size_t NumPlacementArgs,<br>
+                        const FunctionDecl *OperatorDelete,<br>
+                        llvm::Value *Ptr,<br>
+                        llvm::Value *AllocSize)<br>
+      : NumPlacementArgs(<wbr>NumPlacementArgs), OperatorDelete(OperatorDelete)<wbr>,<br>
+        Ptr(Ptr), AllocSize(AllocSize) {}<br>
<br>
-  if (AI != AE && (*AI)->isAlignValT()) {<br>
-    PassAlignment = true;<br>
-    ++AI;<br>
-  }<br>
+    void setPlacementArg(unsigned I, RValue Arg) {<br>
+      assert(I < NumPlacementArgs && "index out of range");<br>
+      getPlacementArgs()[I] = Arg;<br>
+    }<br>
<br>
-  assert(AI == AE && "unexpected usual deallocation function parameter");<br>
-  return {PassSize, PassAlignment};<br>
-}<br>
+    void Emit(CodeGenFunction &CGF, Flags flags) override {<br>
+      const FunctionProtoType *FPT<br>
+        = OperatorDelete->getType()-><wbr>getAs<FunctionProtoType>();<br>
+      assert(FPT->getNumParams() == NumPlacementArgs + 1 ||<br>
+             (FPT->getNumParams() == 2 && NumPlacementArgs == 0));<br>
<br>
-namespace {<br>
-  /// A cleanup to call the given 'operator delete' function upon abnormal<br>
-  /// exit from a new expression. Templated on a traits type that deals with<br>
-  /// ensuring that the arguments dominate the cleanup if necessary.<br>
-  template<typename Traits><br>
-  class CallDeleteDuringNew final : public EHScopeStack::Cleanup {<br>
-    /// Type used to hold llvm::Value*s.<br>
-    typedef typename Traits::ValueTy ValueTy;<br>
-    /// Type used to hold RValues.<br>
-    typedef typename Traits::RValueTy RValueTy;<br>
-    struct PlacementArg {<br>
-      RValueTy ArgValue;<br>
-      QualType ArgType;<br>
-    };<br>
+      CallArgList DeleteArgs;<br>
+<br>
+      // The first argument is always a void*.<br>
+      FunctionProtoType::param_type_<wbr>iterator AI = FPT->param_type_begin();<br>
+      DeleteArgs.add(RValue::get(<wbr>Ptr), *AI++);<br>
<br>
-    unsigned NumPlacementArgs : 31;<br>
-    unsigned PassAlignmentToPlacementDelete : 1;<br>
+      // A member 'operator delete' can take an extra 'size_t' argument.<br>
+      if (FPT->getNumParams() == NumPlacementArgs + 2)<br>
+        DeleteArgs.add(RValue::get(<wbr>AllocSize), *AI++);<br>
+<br>
+      // Pass the rest of the arguments, which must match exactly.<br>
+      for (unsigned I = 0; I != NumPlacementArgs; ++I)<br>
+        DeleteArgs.add(<wbr>getPlacementArgs()[I], *AI++);<br>
+<br>
+      // Call 'operator delete'.<br>
+      EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs);<br>
+    }<br>
+  };<br>
+<br>
+  /// A cleanup to call the given 'operator delete' function upon<br>
+  /// abnormal exit from a new expression when the new expression is<br>
+  /// conditional.<br>
+  class CallDeleteDuringConditionalNew final : public EHScopeStack::Cleanup {<br>
+    size_t NumPlacementArgs;<br>
     const FunctionDecl *OperatorDelete;<br>
-    ValueTy Ptr;<br>
-    ValueTy AllocSize;<br>
-    CharUnits AllocAlign;<br>
+    DominatingValue<RValue>::<wbr>saved_type Ptr;<br>
+    DominatingValue<RValue>::<wbr>saved_type AllocSize;<br>
<br>
-    PlacementArg *getPlacementArgs() {<br>
-      return reinterpret_cast<PlacementArg *>(this + 1);<br>
+    DominatingValue<RValue>::<wbr>saved_type *getPlacementArgs() {<br>
+      return reinterpret_cast<<wbr>DominatingValue<RValue>::<wbr>saved_type*>(this+1);<br>
     }<br>
<br>
   public:<br>
     static size_t getExtraSize(size_t NumPlacementArgs) {<br>
-      return NumPlacementArgs * sizeof(PlacementArg);<br>
+      return NumPlacementArgs * sizeof(DominatingValue<RValue><wbr>::saved_type);<br>
     }<br>
<br>
-    CallDeleteDuringNew(size_t NumPlacementArgs,<br>
-                        const FunctionDecl *OperatorDelete, ValueTy Ptr,<br>
-                        ValueTy AllocSize, bool PassAlignmentToPlacementDelete<wbr>,<br>
-                        CharUnits AllocAlign)<br>
-      : NumPlacementArgs(<wbr>NumPlacementArgs),<br>
-        PassAlignmentToPlacementDelete<wbr>(<wbr>PassAlignmentToPlacementDelete<wbr>),<br>
-        OperatorDelete(OperatorDelete)<wbr>, Ptr(Ptr), AllocSize(AllocSize),<br>
-        AllocAlign(AllocAlign) {}<br>
+    CallDeleteDuringConditionalNew<wbr>(size_t NumPlacementArgs,<br>
+                                   const FunctionDecl *OperatorDelete,<br>
+                                   DominatingValue<RValue>::<wbr>saved_type Ptr,<br>
+                              DominatingValue<RValue>::<wbr>saved_type AllocSize)<br>
+      : NumPlacementArgs(<wbr>NumPlacementArgs), OperatorDelete(OperatorDelete)<wbr>,<br>
+        Ptr(Ptr), AllocSize(AllocSize) {}<br>
<br>
-    void setPlacementArg(unsigned I, RValueTy Arg, QualType Type) {<br>
+    void setPlacementArg(unsigned I, DominatingValue<RValue>::<wbr>saved_type Arg) {<br>
       assert(I < NumPlacementArgs && "index out of range");<br>
-      getPlacementArgs()[I] = {Arg, Type};<br>
+      getPlacementArgs()[I] = Arg;<br>
     }<br>
<br>
     void Emit(CodeGenFunction &CGF, Flags flags) override {<br>
-      const FunctionProtoType *FPT =<br>
-          OperatorDelete->getType()-><wbr>getAs<FunctionProtoType>();<br>
+      const FunctionProtoType *FPT<br>
+        = OperatorDelete->getType()-><wbr>getAs<FunctionProtoType>();<br>
+      assert(FPT->getNumParams() == NumPlacementArgs + 1 ||<br>
+             (FPT->getNumParams() == 2 && NumPlacementArgs == 0));<br>
+<br>
       CallArgList DeleteArgs;<br>
<br>
       // The first argument is always a void*.<br>
-      DeleteArgs.add(Traits::get(<wbr>CGF, Ptr), FPT->getParamType(0));<br>
+      FunctionProtoType::param_type_<wbr>iterator AI = FPT->param_type_begin();<br>
+      DeleteArgs.add(Ptr.restore(<wbr>CGF), *AI++);<br>
<br>
-      // Figure out what other parameters we should be implicitly passing.<br>
-      bool PassSize = false;<br>
-      bool PassAlignment = false;<br>
-      if (NumPlacementArgs) {<br>
-        // A placement deallocation function is implicitly passed an alignment<br>
-        // if the placement allocation function was, but is never passed a size.<br>
-        PassAlignment = PassAlignmentToPlacementDelete<wbr>;<br>
-      } else {<br>
-        // For a non-placement new-expression, 'operator delete' can take a<br>
-        // size and/or an alignment if it has the right parameters.<br>
-        std::tie(PassSize, PassAlignment) =<br>
-            shouldPassSizeAndAlignToUsualD<wbr>elete(FPT);<br>
+      // A member 'operator delete' can take an extra 'size_t' argument.<br>
+      if (FPT->getNumParams() == NumPlacementArgs + 2) {<br>
+        RValue RV = AllocSize.restore(CGF);<br>
+        DeleteArgs.add(RV, *AI++);<br>
       }<br>
<br>
-      // The second argument can be a std::size_t (for non-placement delete).<br>
-      if (PassSize)<br>
-        DeleteArgs.add(Traits::get(<wbr>CGF, AllocSize),<br>
-                       CGF.getContext().getSizeType()<wbr>);<br>
-<br>
-      // The next (second or third) argument can be a std::align_val_t, which<br>
-      // is an enum whose underlying type is std::size_t.<br>
-      // FIXME: Use the right type as the parameter type. Note that in a call<br>
-      // to operator delete(size_t, ...), we may not have it available.<br>
-      if (PassAlignment)<br>
-        DeleteArgs.add(RValue::get(<wbr>llvm::ConstantInt::get(<br>
-                           CGF.SizeTy, AllocAlign.getQuantity())),<br>
-                       CGF.getContext().getSizeType()<wbr>);<br>
-<br>
       // Pass the rest of the arguments, which must match exactly.<br>
       for (unsigned I = 0; I != NumPlacementArgs; ++I) {<br>
-        auto Arg = getPlacementArgs()[I];<br>
-        DeleteArgs.add(Traits::get(<wbr>CGF, Arg.ArgValue), Arg.ArgType);<br>
+        RValue RV = getPlacementArgs()[I].restore(<wbr>CGF);<br>
+        DeleteArgs.add(RV, *AI++);<br>
       }<br>
<br>
       // Call 'operator delete'.<br>
@@ -1343,34 +1338,18 @@ static void EnterNewDeleteCleanup(CodeGe<br>
                                   const CXXNewExpr *E,<br>
                                   Address NewPtr,<br>
                                   llvm::Value *AllocSize,<br>
-                                  CharUnits AllocAlign,<br>
                                   const CallArgList &NewArgs) {<br>
-  unsigned NumNonPlacementArgs = E->passAlignment() ? 2 : 1;<br>
-<br>
   // If we're not inside a conditional branch, then the cleanup will<br>
   // dominate and we can do the easier (and more efficient) thing.<br>
   if (!CGF.isInConditionalBranch()) {<br>
-    struct DirectCleanupTraits {<br>
-      typedef llvm::Value *ValueTy;<br>
-      typedef RValue RValueTy;<br>
-      static RValue get(CodeGenFunction &, ValueTy V) { return RValue::get(V); }<br>
-      static RValue get(CodeGenFunction &, RValueTy V) { return V; }<br>
-    };<br>
-<br>
-    typedef CallDeleteDuringNew<<wbr>DirectCleanupTraits> DirectCleanup;<br>
-<br>
-    DirectCleanup *Cleanup = CGF.EHStack<br>
-      .pushCleanupWithExtra<<wbr>DirectCleanup>(EHCleanup,<br>
-                                           E->getNumPlacementArgs(),<br>
-                                           E->getOperatorDelete(),<br>
-                                           NewPtr.getPointer(),<br>
-                                           AllocSize,<br>
-                                           E->passAlignment(),<br>
-                                           AllocAlign);<br>
-    for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {<br>
-      auto &Arg = NewArgs[I + NumNonPlacementArgs];<br>
-      Cleanup->setPlacementArg(I, Arg.RV, Arg.Ty);<br>
-    }<br>
+    CallDeleteDuringNew *Cleanup = CGF.EHStack<br>
+      .pushCleanupWithExtra<<wbr>CallDeleteDuringNew>(<wbr>EHCleanup,<br>
+                                                 E->getNumPlacementArgs(),<br>
+                                                 E->getOperatorDelete(),<br>
+                                                 NewPtr.getPointer(),<br>
+                                                 AllocSize);<br>
+    for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)<br>
+      Cleanup->setPlacementArg(I, NewArgs[I+1].RV);<br>
<br>
     return;<br>
   }<br>
@@ -1381,28 +1360,15 @@ static void EnterNewDeleteCleanup(CodeGe<br>
   DominatingValue<RValue>::<wbr>saved_type SavedAllocSize =<br>
     DominatingValue<RValue>::save(<wbr>CGF, RValue::get(AllocSize));<br>
<br>
-  struct ConditionalCleanupTraits {<br>
-    typedef DominatingValue<RValue>::<wbr>saved_type ValueTy;<br>
-    typedef DominatingValue<RValue>::<wbr>saved_type RValueTy;<br>
-    static RValue get(CodeGenFunction &CGF, ValueTy V) {<br>
-      return V.restore(CGF);<br>
-    }<br>
-  };<br>
-  typedef CallDeleteDuringNew<<wbr>ConditionalCleanupTraits> ConditionalCleanup;<br>
-<br>
-  ConditionalCleanup *Cleanup = CGF.EHStack<br>
-    .pushCleanupWithExtra<<wbr>ConditionalCleanup>(EHCleanup,<br>
-                                              E->getNumPlacementArgs(),<br>
-                                              E->getOperatorDelete(),<br>
-                                              SavedNewPtr,<br>
-                                              SavedAllocSize,<br>
-                                              E->passAlignment(),<br>
-                                              AllocAlign);<br>
-  for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) {<br>
-    auto &Arg = NewArgs[I + NumNonPlacementArgs];<br>
-    Cleanup->setPlacementArg(I, DominatingValue<RValue>::save(<wbr>CGF, Arg.RV),<br>
-                             Arg.Ty);<br>
-  }<br>
+  CallDeleteDuringConditionalNew *Cleanup = CGF.EHStack<br>
+    .pushCleanupWithExtra<<wbr>CallDeleteDuringConditionalNew<wbr>>(EHCleanup,<br>
+                                                 E->getNumPlacementArgs(),<br>
+                                                 E->getOperatorDelete(),<br>
+                                                 SavedNewPtr,<br>
+                                                 SavedAllocSize);<br>
+  for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I)<br>
+    Cleanup->setPlacementArg(I,<br>
+                     DominatingValue<RValue>::save(<wbr>CGF, NewArgs[I+1].RV));<br>
<br>
   CGF.initFullExprCleanup();<br>
 }<br>
@@ -1431,7 +1397,6 @@ llvm::Value *CodeGenFunction::EmitCXXNew<br>
   llvm::Value *allocSize =<br>
     EmitCXXNewAllocSize(*this, E, minElements, numElements,<br>
                         allocSizeWithoutCookie);<br>
-  CharUnits allocAlign = getContext().<wbr>getTypeAlignInChars(allocType)<wbr>;<br>
<br>
   // Emit the allocation call.  If the allocator is a global placement<br>
   // operator, just "inline" it directly.<br>
@@ -1447,8 +1412,10 @@ llvm::Value *CodeGenFunction::EmitCXXNew<br>
     // The pointer expression will, in many cases, be an opaque void*.<br>
     // In these cases, discard the computed alignment and use the<br>
     // formal alignment of the allocated type.<br>
-    if (alignSource != AlignmentSource::Decl)<br>
-      allocation = Address(allocation.getPointer(<wbr>), allocAlign);<br>
+    if (alignSource != AlignmentSource::Decl) {<br>
+      allocation = Address(allocation.getPointer(<wbr>),<br>
+                           getContext().<wbr>getTypeAlignInChars(allocType)<wbr>);<br>
+    }<br>
<br>
     // Set up allocatorArgs for the call to operator delete if it's not<br>
     // the reserved global operator.<br>
@@ -1461,55 +1428,28 @@ llvm::Value *CodeGenFunction::EmitCXXNew<br>
   } else {<br>
     const FunctionProtoType *allocatorType =<br>
       allocator->getType()->castAs<<wbr>FunctionProtoType>();<br>
-    unsigned ParamsToSkip = 0;<br>
<br>
     // The allocation size is the first argument.<br>
     QualType sizeType = getContext().getSizeType();<br>
     allocatorArgs.add(RValue::get(<wbr>allocSize), sizeType);<br>
-    ++ParamsToSkip;<br>
<br>
-    if (allocSize != allocSizeWithoutCookie) {<br>
-      CharUnits cookieAlign = getSizeAlign(); // FIXME: Ask the ABI.<br>
-      allocAlign = std::max(allocAlign, cookieAlign);<br>
-    }<br>
-<br>
-    // The allocation alignment may be passed as the second argument.<br>
-    if (E->passAlignment()) {<br>
-      QualType AlignValT = sizeType;<br>
-      if (allocatorType->getNumParams() > 1) {<br>
-        AlignValT = allocatorType->getParamType(1)<wbr>;<br>
-        assert(getContext().<wbr>hasSameUnqualifiedType(<br>
-                   AlignValT->castAs<EnumType>()-<wbr>>getDecl()->getIntegerType(),<br>
-                   sizeType) &&<br>
-               "wrong type for alignment parameter");<br>
-        ++ParamsToSkip;<br>
-      } else {<br>
-        // Corner case, passing alignment to 'operator new(size_t, ...)'.<br>
-        assert(allocator->isVariadic() && "can't pass alignment to allocator");<br>
-      }<br>
-      allocatorArgs.add(<br>
-          RValue::get(llvm::ConstantInt:<wbr>:get(SizeTy, allocAlign.getQuantity())),<br>
-          AlignValT);<br>
-    }<br>
-<br>
-    // FIXME: Why do we not pass a CalleeDecl here?<br>
+    // We start at 1 here because the first argument (the allocation size)<br>
+    // has already been emitted.<br>
     EmitCallArgs(allocatorArgs, allocatorType, E->placement_arguments(),<br>
-                 /*CalleeDecl*/nullptr, /*ParamsToSkip*/ParamsToSkip);<br>
+                 /* CalleeDecl */ nullptr,<br>
+                 /*ParamsToSkip*/ 1);<br>
<br>
     RValue RV =<br>
       EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);<br>
<br>
-    // If this was a call to a global replaceable allocation function that does<br>
-    // not take an alignment argument, the allocator is known to produce<br>
-    // storage that's suitably aligned for any object that fits, up to a known<br>
-    // threshold. Otherwise assume it's suitably aligned for the allocated type.<br>
-    CharUnits allocationAlign = allocAlign;<br>
-    if (!E->passAlignment() &&<br>
-        allocator-><wbr>isReplaceableGlobalAllocationF<wbr>unction()) {<br>
-      unsigned AllocatorAlign = llvm::PowerOf2Floor(std::min<<wbr>uint64_t>(<br>
-          Target.getNewAlign(), getContext().getTypeSize(<wbr>allocType)));<br>
-      allocationAlign = std::max(<br>
-          allocationAlign, getContext().<wbr>toCharUnitsFromBits(<wbr>AllocatorAlign));<br>
+    // For now, only assume that the allocation function returns<br>
+    // something satisfactorily aligned for the element type, plus<br>
+    // the cookie if we have one.<br>
+    CharUnits allocationAlign =<br>
+      getContext().<wbr>getTypeAlignInChars(allocType)<wbr>;<br>
+    if (allocSize != allocSizeWithoutCookie) {<br>
+      CharUnits cookieAlign = getSizeAlign(); // FIXME?<br>
+      allocationAlign = std::max(allocationAlign, cookieAlign);<br>
     }<br>
<br>
     allocation = Address(RV.getScalarVal(), allocationAlign);<br>
@@ -1548,8 +1488,7 @@ llvm::Value *CodeGenFunction::EmitCXXNew<br>
   llvm::Instruction *cleanupDominator = nullptr;<br>
   if (E->getOperatorDelete() &&<br>
       !E->getOperatorDelete()-><wbr>isReservedGlobalPlacementOpera<wbr>tor()) {<br>
-    EnterNewDeleteCleanup(*this, E, allocation, allocSize, allocAlign,<br>
-                          allocatorArgs);<br>
+    EnterNewDeleteCleanup(*this, E, allocation, allocSize, allocatorArgs);<br>
     operatorDeleteCleanup = EHStack.stable_begin();<br>
     cleanupDominator = Builder.CreateUnreachable();<br>
   }<br>
@@ -1611,58 +1550,31 @@ llvm::Value *CodeGenFunction::EmitCXXNew<br>
 }<br>
<br>
 void CodeGenFunction::<wbr>EmitDeleteCall(const FunctionDecl *DeleteFD,<br>
-                                     llvm::Value *Ptr, QualType DeleteTy,<br>
-                                     llvm::Value *NumElements,<br>
-                                     CharUnits CookieSize) {<br>
-  assert((!NumElements && CookieSize.isZero()) ||<br>
-         DeleteFD-><wbr>getOverloadedOperator() == OO_Array_Delete);<br>
+                                     llvm::Value *Ptr,<br>
+                                     QualType DeleteTy) {<br>
+  assert(DeleteFD-><wbr>getOverloadedOperator() == OO_Delete);<br>
<br>
   const FunctionProtoType *DeleteFTy =<br>
     DeleteFD->getType()->getAs<<wbr>FunctionProtoType>();<br>
<br>
   CallArgList DeleteArgs;<br>
<br>
-  std::pair<bool, bool> PassSizeAndAlign =<br>
-      shouldPassSizeAndAlignToUsualD<wbr>elete(DeleteFTy);<br>
-<br>
-  auto ParamTypeIt = DeleteFTy->param_type_begin();<br>
-<br>
-  // Pass the pointer itself.<br>
-  QualType ArgTy = *ParamTypeIt++;<br>
-  llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));<br>
-  DeleteArgs.add(RValue::get(<wbr>DeletePtr), ArgTy);<br>
-<br>
-  // Pass the size if the delete function has a size_t parameter.<br>
-  if (PassSizeAndAlign.first) {<br>
-    QualType SizeType = *ParamTypeIt++;<br>
+  // Check if we need to pass the size to the delete operator.<br>
+  llvm::Value *Size = nullptr;<br>
+  QualType SizeTy;<br>
+  if (DeleteFTy->getNumParams() == 2) {<br>
+    SizeTy = DeleteFTy->getParamType(1);<br>
     CharUnits DeleteTypeSize = getContext().<wbr>getTypeSizeInChars(DeleteTy);<br>
-    llvm::Value *Size = llvm::ConstantInt::get(<wbr>ConvertType(SizeType),<br>
-                                               DeleteTypeSize.getQuantity());<br>
-<br>
-    // For array new, multiply by the number of elements.<br>
-    if (NumElements)<br>
-      Size = Builder.CreateMul(Size, NumElements);<br>
-<br>
-    // If there is a cookie, add the cookie size.<br>
-    if (!CookieSize.isZero())<br>
-      Size = Builder.CreateAdd(<br>
-          Size, llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity()));<br>
-<br>
-    DeleteArgs.add(RValue::get(<wbr>Size), SizeType);<br>
+    Size = llvm::ConstantInt::get(<wbr>ConvertType(SizeTy),<br>
+                                  DeleteTypeSize.getQuantity());<br>
   }<br>
<br>
-  // Pass the alignment if the delete function has an align_val_t parameter.<br>
-  if (PassSizeAndAlign.second) {<br>
-    QualType AlignValType = *ParamTypeIt++;<br>
-    CharUnits DeleteTypeAlign = getContext().<wbr>toCharUnitsFromBits(<br>
-        getContext().<wbr>getTypeAlignIfKnown(DeleteTy))<wbr>;<br>
-    llvm::Value *Align = llvm::ConstantInt::get(<wbr>ConvertType(AlignValType),<br>
-                                                DeleteTypeAlign.getQuantity())<wbr>;<br>
-    DeleteArgs.add(RValue::get(<wbr>Align), AlignValType);<br>
-  }<br>
+  QualType ArgTy = DeleteFTy->getParamType(0);<br>
+  llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));<br>
+  DeleteArgs.add(RValue::get(<wbr>DeletePtr), ArgTy);<br>
<br>
-  assert(ParamTypeIt == DeleteFTy->param_type_end() &&<br>
-         "unknown parameter to usual delete function");<br>
+  if (Size)<br>
+    DeleteArgs.add(RValue::get(<wbr>Size), SizeTy);<br>
<br>
   // Emit the call to delete.<br>
   EmitNewDeleteCall(*this, DeleteFD, DeleteFTy, DeleteArgs);<br>
@@ -1766,8 +1678,45 @@ namespace {<br>
         ElementType(ElementType), CookieSize(CookieSize) {}<br>
<br>
     void Emit(CodeGenFunction &CGF, Flags flags) override {<br>
-      CGF.EmitDeleteCall(<wbr>OperatorDelete, Ptr, ElementType, NumElements,<br>
-                         CookieSize);<br>
+      const FunctionProtoType *DeleteFTy =<br>
+        OperatorDelete->getType()-><wbr>getAs<FunctionProtoType>();<br>
+      assert(DeleteFTy-><wbr>getNumParams() == 1 || DeleteFTy->getNumParams() == 2);<br>
+<br>
+      CallArgList Args;<br>
+<br>
+      // Pass the pointer as the first argument.<br>
+      QualType VoidPtrTy = DeleteFTy->getParamType(0);<br>
+      llvm::Value *DeletePtr<br>
+        = CGF.Builder.CreateBitCast(Ptr, CGF.ConvertType(VoidPtrTy));<br>
+      Args.add(RValue::get(<wbr>DeletePtr), VoidPtrTy);<br>
+<br>
+      // Pass the original requested size as the second argument.<br>
+      if (DeleteFTy->getNumParams() == 2) {<br>
+        QualType size_t = DeleteFTy->getParamType(1);<br>
+        llvm::IntegerType *SizeTy<br>
+          = cast<llvm::IntegerType>(CGF.<wbr>ConvertType(size_t));<br>
+<br>
+        CharUnits ElementTypeSize =<br>
+          CGF.CGM.getContext().<wbr>getTypeSizeInChars(<wbr>ElementType);<br>
+<br>
+        // The size of an element, multiplied by the number of elements.<br>
+        llvm::Value *Size<br>
+          = llvm::ConstantInt::get(SizeTy, ElementTypeSize.getQuantity())<wbr>;<br>
+        if (NumElements)<br>
+          Size = CGF.Builder.CreateMul(Size, NumElements);<br>
+<br>
+        // Plus the size of the cookie if applicable.<br>
+        if (!CookieSize.isZero()) {<br>
+          llvm::Value *CookieSizeV<br>
+            = llvm::ConstantInt::get(SizeTy, CookieSize.getQuantity());<br>
+          Size = CGF.Builder.CreateAdd(Size, CookieSizeV);<br>
+        }<br>
+<br>
+        Args.add(RValue::get(Size), size_t);<br>
+      }<br>
+<br>
+      // Emit the call to delete.<br>
+      EmitNewDeleteCall(CGF, OperatorDelete, DeleteFTy, Args);<br>
     }<br>
   };<br>
 }<br>
<br>
Modified: cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h?rev=283750&<wbr>r1=283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h (original)<br>
+++ cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h Mon Oct 10 09:13:55 2016<br>
@@ -2033,8 +2033,7 @@ public:<br>
   void EmitCXXDeleteExpr(const CXXDeleteExpr *E);<br>
<br>
   void EmitDeleteCall(const FunctionDecl *DeleteFD, llvm::Value *Ptr,<br>
-                      QualType DeleteTy, llvm::Value *NumElements = nullptr,<br>
-                      CharUnits CookieSize = CharUnits());<br>
+                      QualType DeleteTy);<br>
<br>
   RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,<br>
                                   const Expr *Arg, bool IsDelete);<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaCUDA.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCUDA.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaCUDA.cpp?rev=283750&r1=<wbr>283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaCUDA.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaCUDA.<wbr>cpp Mon Oct 10 09:13:55 2016<br>
@@ -158,34 +158,6 @@ Sema::IdentifyCUDAPreference(<wbr>const Funct<br>
   llvm_unreachable("All cases should've been handled by now.");<br>
 }<br>
<br>
-void Sema::<wbr>EraseUnwantedCUDAMatches(const FunctionDecl *Caller,<br>
-                                    LookupResult &R) {<br>
-  if (R.isSingleResult())<br>
-    return;<br>
-<br>
-  // Gets the CUDA function preference for a call from Caller to Match.<br>
-  auto GetCFP = [&](const NamedDecl *D) {<br>
-    if (auto *Callee = dyn_cast<FunctionDecl>(D-><wbr>getUnderlyingDecl()))<br>
-      return IdentifyCUDAPreference(Caller, Callee);<br>
-    return CFP_Never;<br>
-  };<br>
-<br>
-  // Find the best call preference among the functions in R.<br>
-  CUDAFunctionPreference BestCFP = GetCFP(*std::max_element(<br>
-      R.begin(), R.end(), [&](const NamedDecl *D1, const NamedDecl *D2) {<br>
-        return GetCFP(D1) < GetCFP(D2);<br>
-      }));<br>
-<br>
-  // Erase all functions with lower priority.<br>
-  auto Filter = R.makeFilter();<br>
-  while (Filter.hasNext()) {<br>
-    auto *Callee = dyn_cast<FunctionDecl>(Filter.<wbr>next()->getUnderlyingDecl());<br>
-    if (Callee && GetCFP(Callee) < BestCFP)<br>
-      Filter.erase();<br>
-  }<br>
-  Filter.done();<br>
-}<br>
-<br>
 template <typename T><br>
 static void EraseUnwantedCUDAMatchesImpl(<br>
     Sema &S, const FunctionDecl *Caller, llvm::SmallVectorImpl<T> &Matches,<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDecl.cpp?rev=283750&r1=<wbr>283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp Mon Oct 10 09:13:55 2016<br>
@@ -14368,14 +14368,6 @@ void Sema::ActOnFields(Scope *S, SourceL<br>
     if (!Completed)<br>
       Record->completeDefinition();<br>
<br>
-    // We may have deferred checking for a deleted destructor. Check now.<br>
-    if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(<wbr>Record)) {<br>
-      auto *Dtor = CXXRecord->getDestructor();<br>
-      if (Dtor && Dtor->isImplicit() &&<br>
-          ShouldDeleteSpecialMember(<wbr>Dtor, CXXDestructor))<br>
-        SetDeclDeleted(Dtor, CXXRecord->getLocation());<br>
-    }<br>
-<br>
     if (Record->hasAttrs()) {<br>
       CheckAlignasUnderalignment(<wbr>Record);<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp?rev=283750&r1=<wbr>283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp Mon Oct 10 09:13:55 2016<br>
@@ -6755,7 +6755,7 @@ bool Sema::<wbr>ShouldDeleteSpecialMember(CXX<br>
     DeclarationName Name =<br>
       Context.DeclarationNames.<wbr>getCXXOperatorName(OO_Delete);<br>
     if (FindDeallocationFunction(MD-><wbr>getLocation(), MD->getParent(), Name,<br>
-                                 OperatorDelete, /*Diagnose*/false)) {<br>
+                                 OperatorDelete, false)) {<br>
       if (Diagnose)<br>
         Diag(RD->getLocation(), diag::note_deleted_dtor_no_<wbr>operator_delete);<br>
       return true;<br>
@@ -7695,11 +7695,19 @@ bool Sema::CheckDestructor(<wbr>CXXDestructor<br>
       Loc = RD->getLocation();<br>
<br>
     // If we have a virtual destructor, look up the deallocation function<br>
-    if (FunctionDecl *OperatorDelete =<br>
-            FindDeallocationFunctionForDes<wbr>tructor(Loc, RD)) {<br>
-      MarkFunctionReferenced(Loc, OperatorDelete);<br>
-      Destructor->setOperatorDelete(<wbr>OperatorDelete);<br>
-    }<br>
+    FunctionDecl *OperatorDelete = nullptr;<br>
+    DeclarationName Name =<br>
+    Context.DeclarationNames.<wbr>getCXXOperatorName(OO_Delete);<br>
+    if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))<br>
+      return true;<br>
+    // If there's no class-specific operator delete, look up the global<br>
+    // non-array delete.<br>
+    if (!OperatorDelete)<br>
+      OperatorDelete = FindUsualDeallocationFunction(<wbr>Loc, true, Name);<br>
+<br>
+    MarkFunctionReferenced(Loc, OperatorDelete);<br>
+<br>
+    Destructor->setOperatorDelete(<wbr>OperatorDelete);<br>
   }<br>
<br>
   return false;<br>
@@ -10272,11 +10280,7 @@ CXXDestructorDecl *Sema::DeclareImplicit<br>
   Scope *S = getScopeForContext(ClassDecl);<br>
   CheckImplicitSpecialMemberDecl<wbr>aration(S, Destructor);<br>
<br>
-  // We can't check whether an implicit destructor is deleted before we complete<br>
-  // the definition of the class, because its validity depends on the alignment<br>
-  // of the class. We'll check this from ActOnFields once the class is complete.<br>
-  if (ClassDecl-><wbr>isCompleteDefinition() &&<br>
-      ShouldDeleteSpecialMember(<wbr>Destructor, CXXDestructor))<br>
+  if (ShouldDeleteSpecialMember(<wbr>Destructor, CXXDestructor))<br>
     SetDeclDeleted(Destructor, ClassLoc);<br>
<br>
   // Introduce this destructor into its scope.<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp?rev=283750&r1=<wbr>283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp Mon Oct 10 09:13:55 2016<br>
@@ -1321,126 +1321,8 @@ Sema::<wbr>BuildCXXTypeConstructExpr(<wbr>TypeSour<br>
   return Result;<br>
 }<br>
<br>
-/// \brief Determine whether the given function is a non-placement<br>
-/// deallocation function.<br>
-static bool isNonPlacementDeallocationFunc<wbr>tion(Sema &S, FunctionDecl *FD) {<br>
-  if (FD->isInvalidDecl())<br>
-    return false;<br>
-<br>
-  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))<br>
-    return Method-><wbr>isUsualDeallocationFunction();<br>
-<br>
-  if (FD->getOverloadedOperator() != OO_Delete &&<br>
-      FD->getOverloadedOperator() != OO_Array_Delete)<br>
-    return false;<br>
-<br>
-  unsigned UsualParams = 1;<br>
-<br>
-  if (S.getLangOpts().<wbr>SizedDeallocation && UsualParams < FD->getNumParams() &&<br>
-      S.Context.<wbr>hasSameUnqualifiedType(<br>
-          FD->getParamDecl(UsualParams)-<wbr>>getType(),<br>
-          S.Context.getSizeType()))<br>
-    ++UsualParams;<br>
-<br>
-  if (S.getLangOpts().<wbr>AlignedAllocation && UsualParams < FD->getNumParams() &&<br>
-      S.Context.<wbr>hasSameUnqualifiedType(<br>
-          FD->getParamDecl(UsualParams)-<wbr>>getType(),<br>
-          S.Context.getTypeDeclType(S.<wbr>getStdAlignValT())))<br>
-    ++UsualParams;<br>
-<br>
-  return UsualParams == FD->getNumParams();<br>
-}<br>
-<br>
-namespace {<br>
-  struct UsualDeallocFnInfo {<br>
-    UsualDeallocFnInfo() : Found(), FD(nullptr) {}<br>
-    UsualDeallocFnInfo(<wbr>DeclAccessPair Found)<br>
-        : Found(Found), FD(dyn_cast<FunctionDecl>(<wbr>Found->getUnderlyingDecl())),<br>
-          HasSizeT(false), HasAlignValT(false) {<br>
-      // A function template declaration is never a usual deallocation function.<br>
-      if (!FD)<br>
-        return;<br>
-      if (FD->getNumParams() == 3)<br>
-        HasAlignValT = HasSizeT = true;<br>
-      else if (FD->getNumParams() == 2) {<br>
-        HasSizeT = FD->getParamDecl(1)->getType()<wbr>->isIntegerType();<br>
-        HasAlignValT = !HasSizeT;<br>
-      }<br>
-    }<br>
-<br>
-    operator bool() const { return FD; }<br>
-<br>
-    DeclAccessPair Found;<br>
-    FunctionDecl *FD;<br>
-    bool HasSizeT, HasAlignValT;<br>
-  };<br>
-}<br>
-<br>
-/// Determine whether a type has new-extended alignment. This may be called when<br>
-/// the type is incomplete (for a delete-expression with an incomplete pointee<br>
-/// type), in which case it will conservatively return false if the alignment is<br>
-/// not known.<br>
-static bool hasNewExtendedAlignment(Sema &S, QualType AllocType) {<br>
-  return S.getLangOpts().<wbr>AlignedAllocation &&<br>
-         S.getASTContext().<wbr>getTypeAlignIfKnown(AllocType) ><br>
-             S.getASTContext().<wbr>getTargetInfo().getNewAlign();<br>
-}<br>
-<br>
-/// Select the correct "usual" deallocation function to use from a selection of<br>
-/// deallocation functions (either global or class-scope).<br>
-static UsualDeallocFnInfo resolveDeallocationOverload(<br>
-    Sema &S, LookupResult &R, bool WantSize, bool WantAlign,<br>
-    llvm::SmallVectorImpl<<wbr>UsualDeallocFnInfo> *BestFns = nullptr) {<br>
-  UsualDeallocFnInfo Best;<br>
-<br>
-  // For CUDA, rank callability above anything else when ordering usual<br>
-  // deallocation functions.<br>
-  // FIXME: We should probably instead rank this between alignment (which<br>
-  // affects correctness) and size (which is just an optimization).<br>
-  if (S.getLangOpts().CUDA)<br>
-    S.EraseUnwantedCUDAMatches(<wbr>dyn_cast<FunctionDecl>(S.<wbr>CurContext), R);<br>
-<br>
-  for (auto I = R.begin(), E = R.end(); I != E; ++I) {<br>
-    UsualDeallocFnInfo Info(I.getPair());<br>
-    if (!Info || !<wbr>isNonPlacementDeallocationFunc<wbr>tion(S, Info.FD))<br>
-      continue;<br>
-<br>
-    if (!Best) {<br>
-      Best = Info;<br>
-      if (BestFns)<br>
-        BestFns->push_back(Info);<br>
-      continue;<br>
-    }<br>
-<br>
-    // C++17 [expr.delete]p10:<br>
-    //   If the type has new-extended alignment, a function with a parameter of<br>
-    //   type std::align_val_t is preferred; otherwise a function without such a<br>
-    //   parameter is preferred<br>
-    if (Best.HasAlignValT == WantAlign && Info.HasAlignValT != WantAlign)<br>
-      continue;<br>
-<br>
-    if (Best.HasAlignValT == Info.HasAlignValT &&<br>
-        Best.HasSizeT == WantSize && Info.HasSizeT != WantSize)<br>
-      continue;<br>
-<br>
-    //   If more than one preferred function is found, all non-preferred<br>
-    //   functions are eliminated from further consideration.<br>
-    if (BestFns && (Best.HasAlignValT != Info.HasAlignValT ||<br>
-        Best.HasSizeT != Info.HasSizeT))<br>
-      BestFns->clear();<br>
-<br>
-    Best = Info;<br>
-    if (BestFns)<br>
-      BestFns->push_back(Info);<br>
-  }<br>
-<br>
-  return Best;<br>
-}<br>
-<br>
-/// Determine whether a given type is a class for which 'delete[]' would call<br>
-/// a member 'operator delete[]' with a 'size_t' parameter. This implies that<br>
-/// we need to store the array size (even if the type is<br>
-/// trivially-destructible).<br>
+/// doesUsualArrayDeleteWantSize - Answers whether the usual<br>
+/// operator delete[] for the given type has a size_t parameter.<br>
 static bool doesUsualArrayDeleteWantSize(<wbr>Sema &S, SourceLocation loc,<br>
                                          QualType allocType) {<br>
   const RecordType *record =<br>
@@ -1464,13 +1346,35 @@ static bool doesUsualArrayDeleteWantSize<br>
   // on this thing, so it doesn't matter if we allocate extra space or not.<br>
   if (ops.isAmbiguous()) return false;<br>
<br>
-  // C++17 [expr.delete]p10:<br>
-  //   If the deallocation functions have class scope, the one without a<br>
-  //   parameter of type std::size_t is selected.<br>
-  auto Best = resolveDeallocationOverload(<br>
-      S, ops, /*WantSize*/false,<br>
-      /*WantAlign*/<wbr>hasNewExtendedAlignment(S, allocType));<br>
-  return Best && Best.HasSizeT;<br>
+  LookupResult::Filter filter = ops.makeFilter();<br>
+  while (filter.hasNext()) {<br>
+    NamedDecl *del = filter.next()-><wbr>getUnderlyingDecl();<br>
+<br>
+    // C++0x [basic.stc.dynamic.<wbr>deallocation]p2:<br>
+    //   A template instance is never a usual deallocation function,<br>
+    //   regardless of its signature.<br>
+    if (isa<FunctionTemplateDecl>(<wbr>del)) {<br>
+      filter.erase();<br>
+      continue;<br>
+    }<br>
+<br>
+    // C++0x [basic.stc.dynamic.<wbr>deallocation]p2:<br>
+    //   If class T does not declare [an operator delete[] with one<br>
+    //   parameter] but does declare a member deallocation function<br>
+    //   named operator delete[] with exactly two parameters, the<br>
+    //   second of which has type std::size_t, then this function<br>
+    //   is a usual deallocation function.<br>
+    if (!cast<CXXMethodDecl>(del)-><wbr>isUsualDeallocationFunction()) {<br>
+      filter.erase();<br>
+      continue;<br>
+    }<br>
+  }<br>
+  filter.done();<br>
+<br>
+  if (!ops.isSingleResult()) return false;<br>
+<br>
+  const FunctionDecl *del = cast<FunctionDecl>(ops.<wbr>getFoundDecl());<br>
+  return (del->getNumParams() == 2);<br>
 }<br>
<br>
 /// \brief Parsed a C++ 'new' expression (C++ 5.3.4).<br>
@@ -1826,26 +1730,21 @@ Sema::BuildCXXNew(SourceRange Range, boo<br>
<br>
   FunctionDecl *OperatorNew = nullptr;<br>
   FunctionDecl *OperatorDelete = nullptr;<br>
-  unsigned Alignment =<br>
-      AllocType->isDependentType() ? 0 : Context.getTypeAlign(<wbr>AllocType);<br>
-  unsigned NewAlignment = Context.getTargetInfo().<wbr>getNewAlign();<br>
-  bool PassAlignment = getLangOpts().<wbr>AlignedAllocation &&<br>
-                       Alignment > NewAlignment;<br>
<br>
   if (!AllocType->isDependentType() &&<br>
       !Expr::<wbr>hasAnyTypeDependentArguments(<wbr>PlacementArgs) &&<br>
       FindAllocationFunctions(<wbr>StartLoc,<br>
                               SourceRange(PlacementLParen, PlacementRParen),<br>
-                              UseGlobal, AllocType, ArraySize, PassAlignment,<br>
-                              PlacementArgs, OperatorNew, OperatorDelete))<br>
+                              UseGlobal, AllocType, ArraySize, PlacementArgs,<br>
+                              OperatorNew, OperatorDelete))<br>
     return ExprError();<br>
<br>
   // If this is an array allocation, compute whether the usual array<br>
   // deallocation function for the type has a size_t parameter.<br>
   bool UsualArrayDeleteWantsSize = false;<br>
   if (ArraySize && !AllocType->isDependentType())<br>
-    UsualArrayDeleteWantsSize =<br>
-        doesUsualArrayDeleteWantSize(*<wbr>this, StartLoc, AllocType);<br>
+    UsualArrayDeleteWantsSize<br>
+      = doesUsualArrayDeleteWantSize(*<wbr>this, StartLoc, AllocType);<br>
<br>
   SmallVector<Expr *, 8> AllPlaceArgs;<br>
   if (OperatorNew) {<br>
@@ -1856,11 +1755,9 @@ Sema::BuildCXXNew(SourceRange Range, boo<br>
<br>
     // We've already converted the placement args, just fill in any default<br>
     // arguments. Skip the first parameter because we don't have a corresponding<br>
-    // argument. Skip the second parameter too if we're passing in the<br>
-    // alignment; we've already filled it in.<br>
-    if (GatherArgumentsForCall(<wbr>PlacementLParen, OperatorNew, Proto,<br>
-                               PassAlignment ? 2 : 1, PlacementArgs,<br>
-                               AllPlaceArgs, CallType))<br>
+    // argument.<br>
+    if (GatherArgumentsForCall(<wbr>PlacementLParen, OperatorNew, Proto, 1,<br>
+                               PlacementArgs, AllPlaceArgs, CallType))<br>
       return ExprError();<br>
<br>
     if (!AllPlaceArgs.empty())<br>
@@ -1870,18 +1767,21 @@ Sema::BuildCXXNew(SourceRange Range, boo<br>
     DiagnoseSentinelCalls(<wbr>OperatorNew, PlacementLParen, PlacementArgs);<br>
<br>
     // FIXME: Missing call to CheckFunctionCall or equivalent<br>
+  }<br>
<br>
-    // Warn if the type is over-aligned and is being allocated by (unaligned)<br>
-    // global operator new.<br>
-    if (PlacementArgs.empty() && !PassAlignment &&<br>
-        (OperatorNew->isImplicit() ||<br>
-         (OperatorNew->getLocStart().<wbr>isValid() &&<br>
-          getSourceManager().<wbr>isInSystemHeader(OperatorNew-><wbr>getLocStart())))) {<br>
-      if (Alignment > NewAlignment)<br>
+  // Warn if the type is over-aligned and is being allocated by global operator<br>
+  // new.<br>
+  if (PlacementArgs.empty() && OperatorNew &&<br>
+      (OperatorNew->isImplicit() ||<br>
+       (OperatorNew->getLocStart().<wbr>isValid() &&<br>
+        getSourceManager().<wbr>isInSystemHeader(OperatorNew-><wbr>getLocStart())))) {<br>
+    if (unsigned Align = Context.getPreferredTypeAlign(<wbr>AllocType.getTypePtr())){<br>
+      unsigned SuitableAlign = Context.getTargetInfo().<wbr>getSuitableAlign();<br>
+      if (Align > SuitableAlign)<br>
         Diag(StartLoc, diag::warn_overaligned_type)<br>
             << AllocType<br>
-            << unsigned(Alignment / Context.getCharWidth())<br>
-            << unsigned(NewAlignment / Context.getCharWidth());<br>
+            << unsigned(Align / Context.getCharWidth())<br>
+            << unsigned(SuitableAlign / Context.getCharWidth());<br>
     }<br>
   }<br>
<br>
@@ -1980,7 +1880,7 @@ Sema::BuildCXXNew(SourceRange Range, boo<br>
   }<br>
<br>
   return new (Context)<br>
-      CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete, PassAlignment,<br>
+      CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete,<br>
                  UsualArrayDeleteWantsSize, PlacementArgs, TypeIdParens,<br>
                  ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo,<br>
                  Range, DirectInitRange);<br>
@@ -2023,128 +1923,32 @@ bool Sema::CheckAllocatedType(<wbr>QualType A<br>
   return false;<br>
 }<br>
<br>
-static bool<br>
-resolveAllocationOverload(<wbr>Sema &S, LookupResult &R, SourceRange Range,<br>
-                          SmallVectorImpl<Expr *> &Args, bool &PassAlignment,<br>
-                          FunctionDecl *&Operator,<br>
-                          OverloadCandidateSet *AlignedCandidates = nullptr,<br>
-                          Expr *AlignArg = nullptr) {<br>
-  OverloadCandidateSet Candidates(R.getNameLoc(),<br>
-                                  OverloadCandidateSet::CSK_<wbr>Normal);<br>
-  for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();<br>
-       Alloc != AllocEnd; ++Alloc) {<br>
-    // Even member operator new/delete are implicitly treated as<br>
-    // static, so don't use AddMemberCandidate.<br>
-    NamedDecl *D = (*Alloc)->getUnderlyingDecl();<br>
-<br>
-    if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl><wbr>(D)) {<br>
-      S.<wbr>AddTemplateOverloadCandidate(<wbr>FnTemplate, Alloc.getPair(),<br>
-                                     /*ExplicitTemplateArgs=*/<wbr>nullptr, Args,<br>
-                                     Candidates,<br>
-                                     /*SuppressUserConversions=*/<wbr>false);<br>
-      continue;<br>
-    }<br>
-<br>
-    FunctionDecl *Fn = cast<FunctionDecl>(D);<br>
-    S.AddOverloadCandidate(Fn, Alloc.getPair(), Args, Candidates,<br>
-                           /*SuppressUserConversions=*/<wbr>false);<br>
-  }<br>
+/// \brief Determine whether the given function is a non-placement<br>
+/// deallocation function.<br>
+static bool isNonPlacementDeallocationFunc<wbr>tion(Sema &S, FunctionDecl *FD) {<br>
+  if (FD->isInvalidDecl())<br>
+    return false;<br>
<br>
-  // Do the resolution.<br>
-  OverloadCandidateSet::iterator Best;<br>
-  switch (Candidates.<wbr>BestViableFunction(S, R.getNameLoc(), Best)) {<br>
-  case OR_Success: {<br>
-    // Got one!<br>
-    FunctionDecl *FnDecl = Best->Function;<br>
-    if (S.CheckAllocationAccess(R.<wbr>getNameLoc(), Range, R.getNamingClass(),<br>
-                                Best->FoundDecl) == Sema::AR_inaccessible)<br>
-      return true;<br>
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD))<br>
+    return Method-><wbr>isUsualDeallocationFunction();<br>
<br>
-    Operator = FnDecl;<br>
+  if (FD->getOverloadedOperator() != OO_Delete &&<br>
+      FD->getOverloadedOperator() != OO_Array_Delete)<br>
     return false;<br>
-  }<br>
<br>
-  case OR_No_Viable_Function:<br>
-    // C++17 [expr.new]p13:<br>
-    //   If no matching function is found and the allocated object type has<br>
-    //   new-extended alignment, the alignment argument is removed from the<br>
-    //   argument list, and overload resolution is performed again.<br>
-    if (PassAlignment) {<br>
-      PassAlignment = false;<br>
-      AlignArg = Args[1];<br>
-      Args.erase(Args.begin() + 1);<br>
-      return resolveAllocationOverload(S, R, Range, Args, PassAlignment,<br>
-                                       Operator, &Candidates, AlignArg);<br>
-    }<br>
-<br>
-    // MSVC will fall back on trying to find a matching global operator new<br>
-    // if operator new[] cannot be found.  Also, MSVC will leak by not<br>
-    // generating a call to operator delete or operator delete[], but we<br>
-    // will not replicate that bug.<br>
-    // FIXME: Find out how this interacts with the std::align_val_t fallback<br>
-    // once MSVC implements it.<br>
-    if (R.getLookupName().<wbr>getCXXOverloadedOperator() == OO_Array_New &&<br>
-        S.Context.getLangOpts().<wbr>MSVCCompat) {<br>
-      R.clear();<br>
-      R.setLookupName(S.Context.<wbr>DeclarationNames.<wbr>getCXXOperatorName(OO_New));<br>
-      S.LookupQualifiedName(R, S.Context.<wbr>getTranslationUnitDecl());<br>
-      // FIXME: This will give bad diagnostics pointing at the wrong functions.<br>
-      return resolveAllocationOverload(S, R, Range, Args, PassAlignment,<br>
-                                       Operator, nullptr);<br>
-    }<br>
-<br>
-    S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_<wbr>function_in_call)<br>
-      << R.getLookupName() << Range;<br>
-<br>
-    // If we have aligned candidates, only note the align_val_t candidates<br>
-    // from AlignedCandidates and the non-align_val_t candidates from<br>
-    // Candidates.<br>
-    if (AlignedCandidates) {<br>
-      auto IsAligned = [](OverloadCandidate &C) {<br>
-        return C.Function->getNumParams() > 1 &&<br>
-               C.Function->getParamDecl(1)-><wbr>getType()->isAlignValT();<br>
-      };<br>
-      auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); };<br>
-<br>
-      // This was an overaligned allocation, so list the aligned candidates<br>
-      // first.<br>
-      Args.insert(Args.begin() + 1, AlignArg);<br>
-      AlignedCandidates-><wbr>NoteCandidates(S, OCD_AllCandidates, Args, "",<br>
-                                        R.getNameLoc(), IsAligned);<br>
-      Args.erase(Args.begin() + 1);<br>
-      Candidates.NoteCandidates(S, OCD_AllCandidates, Args, "", R.getNameLoc(),<br>
-                                IsUnaligned);<br>
-    } else {<br>
-      Candidates.NoteCandidates(S, OCD_AllCandidates, Args);<br>
-    }<br>
+  if (FD->getNumParams() == 1)<br>
     return true;<br>
<br>
-  case OR_Ambiguous:<br>
-    S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call)<br>
-      << R.getLookupName() << Range;<br>
-    Candidates.NoteCandidates(S, OCD_ViableCandidates, Args);<br>
-    return true;<br>
-<br>
-  case OR_Deleted: {<br>
-    S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call)<br>
-      << Best->Function->isDeleted()<br>
-      << R.getLookupName()<br>
-      << S.<wbr>getDeletedOrUnavailableSuffix(<wbr>Best->Function)<br>
-      << Range;<br>
-    Candidates.NoteCandidates(S, OCD_AllCandidates, Args);<br>
-    return true;<br>
-  }<br>
-  }<br>
-  llvm_unreachable("Unreachable, bad result from BestViableFunction");<br>
+  return S.getLangOpts().<wbr>SizedDeallocation && FD->getNumParams() == 2 &&<br>
+         S.Context.<wbr>hasSameUnqualifiedType(FD-><wbr>getParamDecl(1)->getType(),<br>
+                                          S.Context.getSizeType());<br>
 }<br>
<br>
-<br>
 /// FindAllocationFunctions - Finds the overloads of operator new and delete<br>
 /// that are appropriate for the allocation.<br>
 bool Sema::FindAllocationFunctions(<wbr>SourceLocation StartLoc, SourceRange Range,<br>
                                    bool UseGlobal, QualType AllocType,<br>
-                                   bool IsArray, bool &PassAlignment,<br>
-                                   MultiExprArg PlaceArgs,<br>
+                                   bool IsArray, MultiExprArg PlaceArgs,<br>
                                    FunctionDecl *&OperatorNew,<br>
                                    FunctionDecl *&OperatorDelete) {<br>
   // --- Choosing an allocation function ---<br>
@@ -2156,29 +1960,16 @@ bool Sema::FindAllocationFunctions(<wbr>Sourc<br>
   // 3) The first argument is always size_t. Append the arguments from the<br>
   //   placement form.<br>
<br>
-  SmallVector<Expr*, 8> AllocArgs;<br>
-  AllocArgs.reserve((<wbr>PassAlignment ? 2 : 1) + PlaceArgs.size());<br>
-<br>
-  // We don't care about the actual value of these arguments.<br>
+  SmallVector<Expr*, 8> AllocArgs(1 + PlaceArgs.size());<br>
+  // We don't care about the actual value of this argument.<br>
   // FIXME: Should the Sema create the expression and embed it in the syntax<br>
   // tree? Or should the consumer just recalculate the value?<br>
-  // FIXME: Using a dummy value will interact poorly with attribute enable_if.<br>
   IntegerLiteral Size(Context, llvm::APInt::getNullValue(<br>
                       Context.getTargetInfo().<wbr>getPointerWidth(0)),<br>
                       Context.getSizeType(),<br>
                       SourceLocation());<br>
-  AllocArgs.push_back(&Size);<br>
-<br>
-  QualType AlignValT = Context.VoidTy;<br>
-  if (PassAlignment) {<br>
-    DeclareGlobalNewDelete();<br>
-    AlignValT = Context.getTypeDeclType(<wbr>getStdAlignValT());<br>
-  }<br>
-  CXXScalarValueInitExpr Align(AlignValT, nullptr, SourceLocation());<br>
-  if (PassAlignment)<br>
-    AllocArgs.push_back(&Align);<br>
-<br>
-  AllocArgs.insert(AllocArgs.<wbr>end(), PlaceArgs.begin(), PlaceArgs.end());<br>
+  AllocArgs[0] = &Size;<br>
+  std::copy(PlaceArgs.begin(), PlaceArgs.end(), AllocArgs.begin() + 1);<br>
<br>
   // C++ [expr.new]p8:<br>
   //   If the allocated type is a non-array type, the allocation<br>
@@ -2187,57 +1978,50 @@ bool Sema::FindAllocationFunctions(<wbr>Sourc<br>
   //   type, the allocation function's name is operator new[] and the<br>
   //   deallocation function's name is operator delete[].<br>
   DeclarationName NewName = Context.DeclarationNames.<wbr>getCXXOperatorName(<br>
-      IsArray ? OO_Array_New : OO_New);<br>
+                                        IsArray ? OO_Array_New : OO_New);<br>
+  DeclarationName DeleteName = Context.DeclarationNames.<wbr>getCXXOperatorName(<br>
+                                        IsArray ? OO_Array_Delete : OO_Delete);<br>
<br>
   QualType AllocElemType = Context.getBaseElementType(<wbr>AllocType);<br>
<br>
-  // Find the allocation function.<br>
-  {<br>
-    LookupResult R(*this, NewName, StartLoc, LookupOrdinaryName);<br>
-<br>
-    // C++1z [expr.new]p9:<br>
-    //   If the new-expression begins with a unary :: operator, the allocation<br>
-    //   function's name is looked up in the global scope. Otherwise, if the<br>
-    //   allocated type is a class type T or array thereof, the allocation<br>
-    //   function's name is looked up in the scope of T.<br>
-    if (AllocElemType->isRecordType() && !UseGlobal)<br>
-      LookupQualifiedName(R, AllocElemType-><wbr>getAsCXXRecordDecl());<br>
-<br>
-    // We can see ambiguity here if the allocation function is found in<br>
-    // multiple base classes.<br>
-    if (R.isAmbiguous())<br>
+  if (AllocElemType->isRecordType() && !UseGlobal) {<br>
+    CXXRecordDecl *Record<br>
+      = cast<CXXRecordDecl>(<wbr>AllocElemType->getAs<<wbr>RecordType>()->getDecl());<br>
+    if (FindAllocationOverload(<wbr>StartLoc, Range, NewName, AllocArgs, Record,<br>
+                               /*AllowMissing=*/true, OperatorNew))<br>
       return true;<br>
+  }<br>
<br>
-    //   If this lookup fails to find the name, or if the allocated type is not<br>
-    //   a class type, the allocation function's name is looked up in the<br>
-    //   global scope.<br>
-    if (R.empty())<br>
-      LookupQualifiedName(R, Context.<wbr>getTranslationUnitDecl());<br>
-<br>
-    assert(!R.empty() && "implicitly declared allocation functions not found");<br>
-    assert(!R.isAmbiguous() && "global allocation functions are ambiguous");<br>
-<br>
-    // We do our own custom access checks below.<br>
-    R.suppressDiagnostics();<br>
-<br>
-    if (resolveAllocationOverload(*<wbr>this, R, Range, AllocArgs, PassAlignment,<br>
-                                  OperatorNew))<br>
+  if (!OperatorNew) {<br>
+    // Didn't find a member overload. Look for a global one.<br>
+    DeclareGlobalNewDelete();<br>
+    DeclContext *TUDecl = Context.<wbr>getTranslationUnitDecl();<br>
+    bool FallbackEnabled = IsArray && Context.getLangOpts().<wbr>MSVCCompat;<br>
+    if (FindAllocationOverload(<wbr>StartLoc, Range, NewName, AllocArgs, TUDecl,<br>
+                               /*AllowMissing=*/<wbr>FallbackEnabled, OperatorNew,<br>
+                               /*Diagnose=*/!FallbackEnabled)<wbr>) {<br>
+      if (!FallbackEnabled)<br>
+        return true;<br>
+<br>
+      // MSVC will fall back on trying to find a matching global operator new<br>
+      // if operator new[] cannot be found.  Also, MSVC will leak by not<br>
+      // generating a call to operator delete or operator delete[], but we<br>
+      // will not replicate that bug.<br>
+      NewName = Context.DeclarationNames.<wbr>getCXXOperatorName(OO_New);<br>
+      DeleteName = Context.DeclarationNames.<wbr>getCXXOperatorName(OO_Delete);<br>
+      if (FindAllocationOverload(<wbr>StartLoc, Range, NewName, AllocArgs, TUDecl,<br>
+                               /*AllowMissing=*/false, OperatorNew))<br>
       return true;<br>
+    }<br>
   }<br>
<br>
-  // We don't need an operator delete if we're running under -fno-exceptions.<br>
+  // We don't need an operator delete if we're running under<br>
+  // -fno-exceptions.<br>
   if (!getLangOpts().Exceptions) {<br>
     OperatorDelete = nullptr;<br>
     return false;<br>
   }<br>
<br>
-  // Note, the name of OperatorNew might have been changed from array to<br>
-  // non-array by resolveAllocationOverload.<br>
-  DeclarationName DeleteName = Context.DeclarationNames.<wbr>getCXXOperatorName(<br>
-      OperatorNew->getDeclName().<wbr>getCXXOverloadedOperator() == OO_Array_New<br>
-          ? OO_Array_Delete<br>
-          : OO_Delete);<br>
-<br>
   // C++ [expr.new]p19:<br>
   //<br>
   //   If the new-expression begins with a unary :: operator, the<br>
@@ -2256,7 +2040,6 @@ bool Sema::FindAllocationFunctions(<wbr>Sourc<br>
   if (FoundDelete.isAmbiguous())<br>
     return true; // FIXME: clean up expressions?<br>
<br>
-  bool FoundGlobalDelete = FoundDelete.empty();<br>
   if (FoundDelete.empty()) {<br>
     DeclareGlobalNewDelete();<br>
     LookupQualifiedName(<wbr>FoundDelete, Context.<wbr>getTranslationUnitDecl());<br>
@@ -2271,16 +2054,7 @@ bool Sema::FindAllocationFunctions(<wbr>Sourc<br>
   // we had explicit placement arguments.  This matters for things like<br>
   //   struct A { void *operator new(size_t, int = 0); ... };<br>
   //   A *a = new A()<br>
-  //<br>
-  // We don't have any definition for what a "placement allocation function"<br>
-  // is, but we assume it's any allocation function whose<br>
-  // parameter-declaration-clause is anything other than (size_t).<br>
-  //<br>
-  // FIXME: Should (size_t, std::align_val_t) also be considered non-placement?<br>
-  // This affects whether an exception from the constructor of an overaligned<br>
-  // type uses the sized or non-sized form of aligned operator delete.<br>
-  bool isPlacementNew = !PlaceArgs.empty() || OperatorNew->param_size() != 1 ||<br>
-                        OperatorNew->isVariadic();<br>
+  bool isPlacementNew = (!PlaceArgs.empty() || OperatorNew->param_size() != 1);<br>
<br>
   if (isPlacementNew) {<br>
     // C++ [expr.new]p20:<br>
@@ -2306,9 +2080,7 @@ bool Sema::FindAllocationFunctions(<wbr>Sourc<br>
         ArgTypes.push_back(Proto-><wbr>getParamType(I));<br>
<br>
       FunctionProtoType::<wbr>ExtProtoInfo EPI;<br>
-      // FIXME: This is not part of the standard's rule.<br>
       EPI.Variadic = Proto->isVariadic();<br>
-      EPI.ExceptionSpec.Type = EST_BasicNoexcept;<br>
<br>
       ExpectedFunctionType<br>
         = Context.getFunctionType(<wbr>Context.VoidTy, ArgTypes, EPI);<br>
@@ -2332,29 +2104,35 @@ bool Sema::FindAllocationFunctions(<wbr>Sourc<br>
       if (Context.hasSameType(Fn-><wbr>getType(), ExpectedFunctionType))<br>
         Matches.push_back(std::make_<wbr>pair(D.getPair(), Fn));<br>
     }<br>
-<br>
-    if (getLangOpts().CUDA)<br>
-      EraseUnwantedCUDAMatches(dyn_<wbr>cast<FunctionDecl>(CurContext)<wbr>, Matches);<br>
   } else {<br>
+    // C++ [expr.new]p20:<br>
+    //   [...] Any non-placement deallocation function matches a<br>
+    //   non-placement allocation function. [...]<br>
+    for (LookupResult::iterator D = FoundDelete.begin(),<br>
+                             DEnd = FoundDelete.end();<br>
+         D != DEnd; ++D) {<br>
+      if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)-><wbr>getUnderlyingDecl()))<br>
+        if (<wbr>isNonPlacementDeallocationFunc<wbr>tion(*this, Fn))<br>
+          Matches.push_back(std::make_<wbr>pair(D.getPair(), Fn));<br>
+    }<br>
+<br>
     // C++1y [expr.new]p22:<br>
     //   For a non-placement allocation function, the normal deallocation<br>
     //   function lookup is used<br>
-    //<br>
-    // Per [expr.delete]p10, this lookup prefers a member operator delete<br>
-    // without a size_t argument, but prefers a non-member operator delete<br>
-    // with a size_t where possible (which it always is in this case).<br>
-    llvm::SmallVector<<wbr>UsualDeallocFnInfo, 4> BestDeallocFns;<br>
-    UsualDeallocFnInfo Selected = resolveDeallocationOverload(<br>
-        *this, FoundDelete, /*WantSize*/ FoundGlobalDelete,<br>
-        /*WantAlign*/ hasNewExtendedAlignment(*this, AllocElemType),<br>
-        &BestDeallocFns);<br>
-    if (Selected)<br>
-      Matches.push_back(std::make_<wbr>pair(Selected.Found, Selected.FD));<br>
-    else {<br>
-      // If we failed to select an operator, all remaining functions are viable<br>
-      // but ambiguous.<br>
-      for (auto Fn : BestDeallocFns)<br>
-        Matches.push_back(std::make_<wbr>pair(Fn.Found, Fn.FD));<br>
+    // C++1y [expr.delete]p?:<br>
+    //   If [...] deallocation function lookup finds both a usual deallocation<br>
+    //   function with only a pointer parameter and a usual deallocation<br>
+    //   function with both a pointer parameter and a size parameter, then the<br>
+    //   selected deallocation function shall be the one with two parameters.<br>
+    //   Otherwise, the selected deallocation function shall be the function<br>
+    //   with one parameter.<br>
+    if (getLangOpts().<wbr>SizedDeallocation && Matches.size() == 2) {<br>
+      if (Matches[0].second-><wbr>getNumParams() == 1)<br>
+        Matches.erase(Matches.begin())<wbr>;<br>
+      else<br>
+        Matches.erase(Matches.begin() + 1);<br>
+      assert(Matches[0].second-><wbr>getNumParams() == 2 &&<br>
+             "found an unexpected usual deallocation function");<br>
     }<br>
   }<br>
<br>
@@ -2365,58 +2143,130 @@ bool Sema::FindAllocationFunctions(<wbr>Sourc<br>
   if (Matches.size() == 1) {<br>
     OperatorDelete = Matches[0].second;<br>
<br>
-    // C++1z [expr.new]p23:<br>
-    //   If the lookup finds a usual deallocation function (3.7.4.2)<br>
-    //   with a parameter of type std::size_t and that function, considered<br>
+    // C++0x [expr.new]p20:<br>
+    //   If the lookup finds the two-parameter form of a usual<br>
+    //   deallocation function (3.7.4.2) and that function, considered<br>
     //   as a placement deallocation function, would have been<br>
     //   selected as a match for the allocation function, the program<br>
     //   is ill-formed.<br>
-    if (getLangOpts().CPlusPlus11 && isPlacementNew &&<br>
+    if (!PlaceArgs.empty() && getLangOpts().CPlusPlus11 &&<br>
         isNonPlacementDeallocationFunc<wbr>tion(*this, OperatorDelete)) {<br>
-      UsualDeallocFnInfo Info(DeclAccessPair::make(<wbr>OperatorDelete, AS_public));<br>
-      // Core issue, per mail to core reflector, 2016-10-09:<br>
-      //   If this is a member operator delete, and there is a corresponding<br>
-      //   non-sized member operator delete, this isn't /really/ a sized<br>
-      //   deallocation function, it just happens to have a size_t parameter.<br>
-      bool IsSizedDelete = Info.HasSizeT;<br>
-      if (IsSizedDelete && !FoundGlobalDelete) {<br>
-        auto NonSizedDelete =<br>
-            resolveDeallocationOverload(*<wbr>this, FoundDelete, /*WantSize*/false,<br>
-                                        /*WantAlign*/Info.<wbr>HasAlignValT);<br>
-        if (NonSizedDelete && !NonSizedDelete.HasSizeT &&<br>
-            NonSizedDelete.HasAlignValT == Info.HasAlignValT)<br>
-          IsSizedDelete = false;<br>
-      }<br>
+      Diag(StartLoc, diag::err_placement_new_non_<wbr>placement_delete)<br>
+        << SourceRange(PlaceArgs.front()-<wbr>>getLocStart(),<br>
+                       PlaceArgs.back()->getLocEnd())<wbr>;<br>
+      if (!OperatorDelete->isImplicit()<wbr>)<br>
+        Diag(OperatorDelete-><wbr>getLocation(), diag::note_previous_decl)<br>
+          << DeleteName;<br>
+    } else {<br>
+      CheckAllocationAccess(<wbr>StartLoc, Range, FoundDelete.getNamingClass(),<br>
+                            Matches[0].first);<br>
+    }<br>
+  }<br>
<br>
-      if (IsSizedDelete) {<br>
-        SourceRange R = PlaceArgs.empty()<br>
-                            ? SourceRange()<br>
-                            : SourceRange(PlaceArgs.front()-<wbr>>getLocStart(),<br>
-                                          PlaceArgs.back()->getLocEnd())<wbr>;<br>
-        Diag(StartLoc, diag::err_placement_new_non_<wbr>placement_delete) << R;<br>
-        if (!OperatorDelete->isImplicit()<wbr>)<br>
-          Diag(OperatorDelete-><wbr>getLocation(), diag::note_previous_decl)<br>
-              << DeleteName;<br>
-      }<br>
+  return false;<br>
+}<br>
+<br>
+/// \brief Find an fitting overload for the allocation function<br>
+/// in the specified scope.<br>
+///<br>
+/// \param StartLoc The location of the 'new' token.<br>
+/// \param Range The range of the placement arguments.<br>
+/// \param Name The name of the function ('operator new' or 'operator new[]').<br>
+/// \param Args The placement arguments specified.<br>
+/// \param Ctx The scope in which we should search; either a class scope or the<br>
+///        translation unit.<br>
+/// \param AllowMissing If \c true, report an error if we can't find any<br>
+///        allocation functions. Otherwise, succeed but don't fill in \p<br>
+///        Operator.<br>
+/// \param Operator Filled in with the found allocation function. Unchanged if<br>
+///        no allocation function was found.<br>
+/// \param Diagnose If \c true, issue errors if the allocation function is not<br>
+///        usable.<br>
+bool Sema::FindAllocationOverload(<wbr>SourceLocation StartLoc, SourceRange Range,<br>
+                                  DeclarationName Name, MultiExprArg Args,<br>
+                                  DeclContext *Ctx,<br>
+                                  bool AllowMissing, FunctionDecl *&Operator,<br>
+                                  bool Diagnose) {<br>
+  LookupResult R(*this, Name, StartLoc, LookupOrdinaryName);<br>
+  LookupQualifiedName(R, Ctx);<br>
+  if (R.empty()) {<br>
+    if (AllowMissing || !Diagnose)<br>
+      return false;<br>
+    return Diag(StartLoc, diag::err_ovl_no_viable_<wbr>function_in_call)<br>
+      << Name << Range;<br>
+  }<br>
+<br>
+  if (R.isAmbiguous())<br>
+    return true;<br>
+<br>
+  R.suppressDiagnostics();<br>
+<br>
+  OverloadCandidateSet Candidates(StartLoc, OverloadCandidateSet::CSK_<wbr>Normal);<br>
+  for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end();<br>
+       Alloc != AllocEnd; ++Alloc) {<br>
+    // Even member operator new/delete are implicitly treated as<br>
+    // static, so don't use AddMemberCandidate.<br>
+    NamedDecl *D = (*Alloc)->getUnderlyingDecl();<br>
+<br>
+    if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl><wbr>(D)) {<br>
+      AddTemplateOverloadCandidate(<wbr>FnTemplate, Alloc.getPair(),<br>
+                                   /*ExplicitTemplateArgs=*/<wbr>nullptr,<br>
+                                   Args, Candidates,<br>
+                                   /*SuppressUserConversions=*/<wbr>false);<br>
+      continue;<br>
     }<br>
<br>
-    CheckAllocationAccess(<wbr>StartLoc, Range, FoundDelete.getNamingClass(),<br>
-                          Matches[0].first);<br>
-  } else if (!Matches.empty()) {<br>
-    // We found multiple suitable operators. Per [expr.new]p20, that means we<br>
-    // call no 'operator delete' function, but we should at least warn the user.<br>
-    // FIXME: Suppress this warning if the construction cannot throw.<br>
-    Diag(StartLoc, diag::warn_ambiguous_suitable_<wbr>delete_function_found)<br>
-      << DeleteName << AllocElemType;<br>
-<br>
-    for (auto &Match : Matches)<br>
-      Diag(Match.second-><wbr>getLocation(),<br>
-           diag::note_member_declared_<wbr>here) << DeleteName;<br>
+    FunctionDecl *Fn = cast<FunctionDecl>(D);<br>
+    AddOverloadCandidate(Fn, Alloc.getPair(), Args, Candidates,<br>
+                         /*SuppressUserConversions=*/<wbr>false);<br>
   }<br>
<br>
-  return false;<br>
+  // Do the resolution.<br>
+  OverloadCandidateSet::iterator Best;<br>
+  switch (Candidates.<wbr>BestViableFunction(*this, StartLoc, Best)) {<br>
+  case OR_Success: {<br>
+    // Got one!<br>
+    FunctionDecl *FnDecl = Best->Function;<br>
+    if (CheckAllocationAccess(<wbr>StartLoc, Range, R.getNamingClass(),<br>
+                              Best->FoundDecl, Diagnose) == AR_inaccessible)<br>
+      return true;<br>
+<br>
+    Operator = FnDecl;<br>
+    return false;<br>
+  }<br>
+<br>
+  case OR_No_Viable_Function:<br>
+    if (Diagnose) {<br>
+      Diag(StartLoc, diag::err_ovl_no_viable_<wbr>function_in_call)<br>
+        << Name << Range;<br>
+      Candidates.NoteCandidates(*<wbr>this, OCD_AllCandidates, Args);<br>
+    }<br>
+    return true;<br>
+<br>
+  case OR_Ambiguous:<br>
+    if (Diagnose) {<br>
+      Diag(StartLoc, diag::err_ovl_ambiguous_call)<br>
+        << Name << Range;<br>
+      Candidates.NoteCandidates(*<wbr>this, OCD_ViableCandidates, Args);<br>
+    }<br>
+    return true;<br>
+<br>
+  case OR_Deleted: {<br>
+    if (Diagnose) {<br>
+      Diag(StartLoc, diag::err_ovl_deleted_call)<br>
+        << Best->Function->isDeleted()<br>
+        << Name<br>
+        << getDeletedOrUnavailableSuffix(<wbr>Best->Function)<br>
+        << Range;<br>
+      Candidates.NoteCandidates(*<wbr>this, OCD_AllCandidates, Args);<br>
+    }<br>
+    return true;<br>
+  }<br>
+  }<br>
+  llvm_unreachable("Unreachable, bad result from BestViableFunction");<br>
 }<br>
<br>
+<br>
 /// DeclareGlobalNewDelete - Declare the global forms of operator new and<br>
 /// delete. These are:<br>
 /// @code<br>
@@ -2610,43 +2460,52 @@ void Sema::<wbr>DeclareGlobalAllocationFuncti<br>
<br>
 FunctionDecl *Sema::<wbr>FindUsualDeallocationFunction(<wbr>SourceLocation StartLoc,<br>
                                                   bool CanProvideSize,<br>
-                                                  bool Overaligned,<br>
                                                   DeclarationName Name) {<br>
   DeclareGlobalNewDelete();<br>
<br>
   LookupResult FoundDelete(*this, Name, StartLoc, LookupOrdinaryName);<br>
   LookupQualifiedName(<wbr>FoundDelete, Context.<wbr>getTranslationUnitDecl());<br>
<br>
-  // FIXME: It's possible for this to result in ambiguity, through a<br>
-  // user-declared variadic operator delete or the enable_if attribute. We<br>
-  // should probably not consider those cases to be usual deallocation<br>
-  // functions. But for now we just make an arbitrary choice in that case.<br>
-  auto Result = resolveDeallocationOverload(*<wbr>this, FoundDelete, CanProvideSize,<br>
-                                            Overaligned);<br>
-  assert(Result.FD && "operator delete missing from global scope?");<br>
-  return Result.FD;<br>
-}<br>
+  // C++ [expr.new]p20:<br>
+  //   [...] Any non-placement deallocation function matches a<br>
+  //   non-placement allocation function. [...]<br>
+  llvm::SmallVector<<wbr>FunctionDecl*, 2> Matches;<br>
+  for (LookupResult::iterator D = FoundDelete.begin(),<br>
+                           DEnd = FoundDelete.end();<br>
+       D != DEnd; ++D) {<br>
+    if (FunctionDecl *Fn = dyn_cast<FunctionDecl>(*D))<br>
+      if (<wbr>isNonPlacementDeallocationFunc<wbr>tion(*this, Fn))<br>
+        Matches.push_back(Fn);<br>
+  }<br>
+<br>
+  // C++1y [expr.delete]p?:<br>
+  //   If the type is complete and deallocation function lookup finds both a<br>
+  //   usual deallocation function with only a pointer parameter and a usual<br>
+  //   deallocation function with both a pointer parameter and a size<br>
+  //   parameter, then the selected deallocation function shall be the one<br>
+  //   with two parameters.  Otherwise, the selected deallocation function<br>
+  //   shall be the function with one parameter.<br>
+  if (getLangOpts().<wbr>SizedDeallocation && Matches.size() == 2) {<br>
+    unsigned NumArgs = CanProvideSize ? 2 : 1;<br>
+    if (Matches[0]->getNumParams() != NumArgs)<br>
+      Matches.erase(Matches.begin())<wbr>;<br>
+    else<br>
+      Matches.erase(Matches.begin() + 1);<br>
+    assert(Matches[0]-><wbr>getNumParams() == NumArgs &&<br>
+           "found an unexpected usual deallocation function");<br>
+  }<br>
<br>
-FunctionDecl *Sema::<wbr>FindDeallocationFunctionForDes<wbr>tructor(SourceLocation Loc,<br>
-                                                          CXXRecordDecl *RD) {<br>
-  DeclarationName Name = Context.DeclarationNames.<wbr>getCXXOperatorName(OO_Delete);<br>
+  if (getLangOpts().CUDA)<br>
+    EraseUnwantedCUDAMatches(dyn_<wbr>cast<FunctionDecl>(CurContext)<wbr>, Matches);<br>
<br>
-  FunctionDecl *OperatorDelete = nullptr;<br>
-  if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))<br>
-    return nullptr;<br>
-  if (OperatorDelete)<br>
-    return OperatorDelete;<br>
-<br>
-  // If there's no class-specific operator delete, look up the global<br>
-  // non-array delete.<br>
-  return FindUsualDeallocationFunction(<br>
-      Loc, true, hasNewExtendedAlignment(*this, Context.getRecordType(RD)),<br>
-      Name);<br>
+  assert(Matches.size() == 1 &&<br>
+         "unexpectedly have multiple usual deallocation functions");<br>
+  return Matches.front();<br>
 }<br>
<br>
 bool Sema::<wbr>FindDeallocationFunction(<wbr>SourceLocation StartLoc, CXXRecordDecl *RD,<br>
                                     DeclarationName Name,<br>
-                                    FunctionDecl *&Operator, bool Diagnose) {<br>
+                                    FunctionDecl* &Operator, bool Diagnose) {<br>
   LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);<br>
   // Try to find operator delete/operator delete[] in class scope.<br>
   LookupQualifiedName(Found, RD);<br>
@@ -2656,20 +2515,27 @@ bool Sema::<wbr>FindDeallocationFunction(Sour<br>
<br>
   Found.suppressDiagnostics();<br>
<br>
-  bool Overaligned = hasNewExtendedAlignment(*this, Context.getRecordType(RD));<br>
+  SmallVector<DeclAccessPair,4> Matches;<br>
+  for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();<br>
+       F != FEnd; ++F) {<br>
+    NamedDecl *ND = (*F)->getUnderlyingDecl();<br>
+<br>
+    // Ignore template operator delete members from the check for a usual<br>
+    // deallocation function.<br>
+    if (isa<FunctionTemplateDecl>(ND)<wbr>)<br>
+      continue;<br>
+<br>
+    if (cast<CXXMethodDecl>(ND)-><wbr>isUsualDeallocationFunction())<br>
+      Matches.push_back(F.getPair())<wbr>;<br>
+  }<br>
<br>
-  // C++17 [expr.delete]p10:<br>
-  //   If the deallocation functions have class scope, the one without a<br>
-  //   parameter of type std::size_t is selected.<br>
-  llvm::SmallVector<<wbr>UsualDeallocFnInfo, 4> Matches;<br>
-  resolveDeallocationOverload(*<wbr>this, Found, /*WantSize*/ false,<br>
-                              /*WantAlign*/ Overaligned, &Matches);<br>
+  if (getLangOpts().CUDA)<br>
+    EraseUnwantedCUDAMatches(dyn_<wbr>cast<FunctionDecl>(CurContext)<wbr>, Matches);<br>
<br>
-  // If we could find an overload, use it.<br>
+  // There's exactly one suitable operator;  pick it.<br>
   if (Matches.size() == 1) {<br>
-    Operator = cast<CXXMethodDecl>(Matches[0]<wbr>.FD);<br>
+    Operator = cast<CXXMethodDecl>(Matches[0]<wbr>->getUnderlyingDecl());<br>
<br>
-    // FIXME: DiagnoseUseOfDecl?<br>
     if (Operator->isDeleted()) {<br>
       if (Diagnose) {<br>
         Diag(StartLoc, diag::err_deleted_function_<wbr>use);<br>
@@ -2679,21 +2545,21 @@ bool Sema::<wbr>FindDeallocationFunction(Sour<br>
     }<br>
<br>
     if (CheckAllocationAccess(<wbr>StartLoc, SourceRange(), Found.getNamingClass(),<br>
-                              Matches[0].Found, Diagnose) == AR_inaccessible)<br>
+                              Matches[0], Diagnose) == AR_inaccessible)<br>
       return true;<br>
<br>
     return false;<br>
-  }<br>
<br>
-  // We found multiple suitable operators; complain about the ambiguity.<br>
-  // FIXME: The standard doesn't say to do this; it appears that the intent<br>
-  // is that this should never happen.<br>
-  if (!Matches.empty()) {<br>
+  // We found multiple suitable operators;  complain about the ambiguity.<br>
+  } else if (!Matches.empty()) {<br>
     if (Diagnose) {<br>
       Diag(StartLoc, diag::err_ambiguous_suitable_<wbr>delete_member_function_found)<br>
         << Name << RD;<br>
-      for (auto &Match : Matches)<br>
-        Diag(Match.FD->getLocation(), diag::note_member_declared_<wbr>here) << Name;<br>
+<br>
+      for (SmallVectorImpl<<wbr>DeclAccessPair>::iterator<br>
+             F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F)<br>
+        Diag((*F)->getUnderlyingDecl()<wbr>->getLocation(),<br>
+             diag::note_member_declared_<wbr>here) << Name;<br>
     }<br>
     return true;<br>
   }<br>
@@ -2705,8 +2571,9 @@ bool Sema::<wbr>FindDeallocationFunction(Sour<br>
       Diag(StartLoc, diag::err_no_suitable_delete_<wbr>member_function_found)<br>
         << Name << RD;<br>
<br>
-      for (NamedDecl *D : Found)<br>
-        Diag(D->getUnderlyingDecl()-><wbr>getLocation(),<br>
+      for (LookupResult::iterator F = Found.begin(), FEnd = Found.end();<br>
+           F != FEnd; ++F)<br>
+        Diag((*F)->getUnderlyingDecl()<wbr>->getLocation(),<br>
              diag::note_member_declared_<wbr>here) << Name;<br>
     }<br>
     return true;<br>
@@ -3117,10 +2984,7 @@ Sema::ActOnCXXDelete(<wbr>SourceLocation Star<br>
         // Otherwise, the usual operator delete[] should be the<br>
         // function we just found.<br>
         else if (OperatorDelete && isa<CXXMethodDecl>(<wbr>OperatorDelete))<br>
-          UsualArrayDeleteWantsSize =<br>
-              UsualDeallocFnInfo(<br>
-                  DeclAccessPair::make(<wbr>OperatorDelete, AS_public))<br>
-                  .HasSizeT;<br>
+          UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams(<wbr>) == 2);<br>
       }<br>
<br>
       if (!PointeeRD-><wbr>hasIrrelevantDestructor())<br>
@@ -3137,17 +3001,13 @@ Sema::ActOnCXXDelete(<wbr>SourceLocation Star<br>
                            SourceLocation());<br>
     }<br>
<br>
-    if (!OperatorDelete) {<br>
-      bool IsComplete = isCompleteType(StartLoc, Pointee);<br>
-      bool CanProvideSize =<br>
-          IsComplete && (!ArrayForm || UsualArrayDeleteWantsSize ||<br>
-                         Pointee.isDestructedType());<br>
-      bool Overaligned = hasNewExtendedAlignment(*this, Pointee);<br>
-<br>
+    if (!OperatorDelete)<br>
       // Look for a global declaration.<br>
-      OperatorDelete = FindUsualDeallocationFunction(<wbr>StartLoc, CanProvideSize,<br>
-                                                     Overaligned, DeleteName);<br>
-    }<br>
+      OperatorDelete = FindUsualDeallocationFunction(<br>
+          StartLoc, isCompleteType(StartLoc, Pointee) &&<br>
+                    (!ArrayForm || UsualArrayDeleteWantsSize ||<br>
+                     Pointee.isDestructedType()),<br>
+          DeleteName);<br>
<br>
     MarkFunctionReferenced(<wbr>StartLoc, OperatorDelete);<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp?rev=283750&<wbr>r1=283749&r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaOverload.cpp Mon Oct 10 09:13:55 2016<br>
@@ -10142,17 +10142,16 @@ static void CompleteNonViableCandidate(S<br>
 /// PrintOverloadCandidates - When overload resolution fails, prints<br>
 /// diagnostic messages containing the candidates in the candidate<br>
 /// set.<br>
-void OverloadCandidateSet::<wbr>NoteCandidates(<br>
-    Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args,<br>
-    StringRef Opc, SourceLocation OpLoc,<br>
-    llvm::function_ref<bool(<wbr>OverloadCandidate &)> Filter) {<br>
+void OverloadCandidateSet::<wbr>NoteCandidates(Sema &S,<br>
+                                          OverloadCandidateDisplayKind OCD,<br>
+                                          ArrayRef<Expr *> Args,<br>
+                                          StringRef Opc,<br>
+                                          SourceLocation OpLoc) {<br>
   // Sort the candidates by viability and position.  Sorting directly would<br>
   // be prohibitive, so we make a set of pointers and sort those.<br>
   SmallVector<OverloadCandidate*<wbr>, 32> Cands;<br>
   if (OCD == OCD_AllCandidates) Cands.reserve(size());<br>
   for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {<br>
-    if (!Filter(*Cand))<br>
-      continue;<br>
     if (Cand->Viable)<br>
       Cands.push_back(Cand);<br>
     else if (OCD == OCD_AllCandidates) {<br>
<br>
Modified: cfe/trunk/lib/Serialization/<wbr>ASTReaderStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTReaderStmt.<wbr>cpp?rev=283750&r1=283749&r2=<wbr>283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/<wbr>ASTReaderStmt.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<wbr>ASTReaderStmt.cpp Mon Oct 10 09:13:55 2016<br>
@@ -1410,7 +1410,6 @@ void ASTStmtReader::<wbr>VisitCXXNewExpr(CXXN<br>
   VisitExpr(E);<br>
   E->GlobalNew = Record[Idx++];<br>
   bool isArray = Record[Idx++];<br>
-  E->PassAlignment = Record[Idx++];<br>
   E->UsualArrayDeleteWantsSize = Record[Idx++];<br>
   unsigned NumPlacementArgs = Record[Idx++];<br>
   E->StoredInitializationStyle = Record[Idx++];<br>
<br>
Modified: cfe/trunk/lib/Serialization/<wbr>ASTWriterStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTWriterStmt.<wbr>cpp?rev=283750&r1=283749&r2=<wbr>283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/<wbr>ASTWriterStmt.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<wbr>ASTWriterStmt.cpp Mon Oct 10 09:13:55 2016<br>
@@ -1392,7 +1392,6 @@ void ASTStmtWriter::<wbr>VisitCXXNewExpr(CXXN<br>
   VisitExpr(E);<br>
   Record.push_back(E-><wbr>isGlobalNew());<br>
   Record.push_back(E->isArray())<wbr>;<br>
-  Record.push_back(E-><wbr>passAlignment());<br>
   Record.push_back(E-><wbr>doesUsualArrayDeleteWantSize()<wbr>);<br>
   Record.push_back(E-><wbr>getNumPlacementArgs());<br>
   Record.push_back(E-><wbr>StoredInitializationStyle);<br>
<br>
Removed: cfe/trunk/test/CXX/basic/<wbr>basic.stc/basic.stc.dynamic/<wbr>basic.stc.dynamic.<wbr>deallocation/p2.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.stc/basic.stc.dynamic/basic.stc.dynamic.deallocation/p2.cpp?rev=283749&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>basic/basic.stc/basic.stc.<wbr>dynamic/basic.stc.dynamic.<wbr>deallocation/p2.cpp?rev=<wbr>283749&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/basic/<wbr>basic.stc/basic.stc.dynamic/<wbr>basic.stc.dynamic.<wbr>deallocation/p2.cpp (original)<br>
+++ cfe/trunk/test/CXX/basic/<wbr>basic.stc/basic.stc.dynamic/<wbr>basic.stc.dynamic.<wbr>deallocation/p2.cpp (removed)<br>
@@ -1,19 +0,0 @@<br>
-// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fexceptions -verify %s<br>
-<br>
-using size_t = decltype(sizeof(0));<br>
-<br>
-namespace std { enum class align_val_t : size_t {}; }<br>
-<br>
-// p2 says "A template instance is never a usual deallocation function,<br>
-// regardless of its signature." We (and every other implementation) assume<br>
-// this means "A function template specialization [...]"<br>
-template<typename...Ts> struct A {<br>
-  void *operator new(size_t);<br>
-  void operator delete(void*, Ts...) = delete; // expected-note 4{{deleted}}<br>
-};<br>
-<br>
-auto *a1 = new A<>; // expected-error {{deleted}}<br>
-auto *a2 = new A<size_t>; // expected-error {{deleted}}<br>
-auto *a3 = new A<std::align_val_t>; // expected-error {{deleted}}<br>
-auto *a4 = new A<size_t, std::align_val_t>; // expected-error {{deleted}}<br>
-auto *a5 = new A<std::align_val_t, size_t>; // ok, not usual<br>
<br>
Removed: cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.delete/p10.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.delete/p10.cpp?rev=283749&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>expr/expr.unary/expr.delete/<wbr>p10.cpp?rev=283749&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.delete/p10.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.delete/p10.cpp (removed)<br>
@@ -1,25 +0,0 @@<br>
-// RUN: %clang_cc1 -std=c++1z -verify %s<br>
-<br>
-using size_t = decltype(sizeof(0));<br>
-namespace std { enum class align_val_t : size_t {}; }<br>
-<br>
-// Aligned version is preferred over unaligned version,<br>
-// unsized version is preferred over sized version.<br>
-template<unsigned Align><br>
-struct alignas(Align) A {<br>
-  void operator delete(void*);<br>
-  void operator delete(void*, std::align_val_t) = delete; // expected-note {{here}}<br>
-<br>
-  void operator delete(void*, size_t) = delete;<br>
-  void operator delete(void*, size_t, std::align_val_t) = delete;<br>
-};<br>
-void f(A<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__> *p) { delete p; }<br>
-void f(A<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2> *p) { delete p; } // expected-error {{deleted}}<br>
-<br>
-template<unsigned Align><br>
-struct alignas(Align) B {<br>
-  void operator delete(void*, size_t);<br>
-  void operator delete(void*, size_t, std::align_val_t) = delete; // expected-note {{here}}<br>
-};<br>
-void f(B<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__> *p) { delete p; }<br>
-void f(B<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2> *p) { delete p; } // expected-error {{deleted}}<br>
<br>
Removed: cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.new/p14.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.new/p14.cpp?rev=283749&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>expr/expr.unary/expr.new/p14.<wbr>cpp?rev=283749&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.new/p14.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.new/p14.cpp (removed)<br>
@@ -1,69 +0,0 @@<br>
-// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fexceptions %s -verify<br>
-<br>
-using size_t = decltype(sizeof(0));<br>
-namespace std { enum class align_val_t : size_t {}; }<br>
-<br>
-struct Arg {} arg;<br>
-<br>
-// If the type is aligned, first try with an alignment argument and then<br>
-// without. If not, never consider supplying an alignment.<br>
-<br>
-template<unsigned Align, typename ...Ts><br>
-struct alignas(Align) Unaligned {<br>
-  void *operator new(size_t, Ts...) = delete; // expected-note 4{{deleted}}<br>
-};<br>
-auto *ua = new Unaligned<__STDCPP_DEFAULT_<wbr>NEW_ALIGNMENT__>; // expected-error {{deleted}}<br>
-auto *ub = new Unaligned<__STDCPP_DEFAULT_<wbr>NEW_ALIGNMENT__ * 2>; // expected-error {{deleted}}<br>
-auto *uap = new (arg) Unaligned<__STDCPP_DEFAULT_<wbr>NEW_ALIGNMENT__, Arg>; // expected-error {{deleted}}<br>
-auto *ubp = new (arg) Unaligned<__STDCPP_DEFAULT_<wbr>NEW_ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}}<br>
-<br>
-template<unsigned Align, typename ...Ts><br>
-struct alignas(Align) Aligned {<br>
-  void *operator new(size_t, std::align_val_t, Ts...) = delete; // expected-note 2{{deleted}} expected-note 2{{not viable}}<br>
-};<br>
-auto *aa = new Aligned<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__>; // expected-error {{no matching}}<br>
-auto *ab = new Aligned<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2>; // expected-error {{deleted}}<br>
-auto *aap = new (arg) Aligned<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__, Arg>; // expected-error {{no matching}}<br>
-auto *abp = new (arg) Aligned<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}}<br>
-<br>
-// If both are available, we prefer the aligned version for an overaligned<br>
-// type, and only use the unaligned version for a non-overaligned type.<br>
-<br>
-template<unsigned Align, typename ...Ts><br>
-struct alignas(Align) Both1 {<br>
-  void *operator new(size_t, Ts...); // expected-note 2{{not viable}}<br>
-  void *operator new(size_t, std::align_val_t, Ts...) = delete; // expected-note 2{{deleted}}<br>
-};<br>
-template<unsigned Align, typename ...Ts><br>
-struct alignas(Align) Both2 {<br>
-  void *operator new(size_t, Ts...) = delete; // expected-note 2{{deleted}}<br>
-  void *operator new(size_t, std::align_val_t, Ts...); // expected-note 2{{not viable}}<br>
-};<br>
-auto *b1a = new Both1<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__>;<br>
-auto *b1b = new Both1<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2>; // expected-error {{deleted}}<br>
-auto *b2a = new Both2<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__>; // expected-error {{deleted}}<br>
-auto *b2b = new Both2<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2>;<br>
-auto *b1ap = new (arg) Both1<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__, Arg>;<br>
-auto *b1bp = new (arg) Both1<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2, Arg>; // expected-error {{deleted}}<br>
-auto *b2ap = new (arg) Both2<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__, Arg>; // expected-error {{deleted}}<br>
-auto *b2bp = new (arg) Both2<__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2, Arg>;<br>
-<br>
-// Note that the aligned form can select a function with a parameter different<br>
-// from std::align_val_t.<br>
-<br>
-struct alignas(__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2) WeirdAlignedAlloc1 {<br>
-  void *operator new(size_t, ...) = delete; // expected-note 2{{deleted}}<br>
-};<br>
-auto *waa1 = new WeirdAlignedAlloc1; // expected-error {{deleted}}<br>
-auto *waa1p = new (arg) WeirdAlignedAlloc1; // expected-error {{deleted}}<br>
-<br>
-struct alignas(__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2) WeirdAlignedAlloc2 {<br>
-  template<typename ...T><br>
-  void *operator new(size_t, T...) {<br>
-    using U = void(T...); // expected-note 2{{previous}}<br>
-    using U = void; // expected-error {{different types ('void' vs 'void (std::align_val_t)')}} \<br>
-                       expected-error {{different types ('void' vs 'void (std::align_val_t, Arg)')}}<br>
-  }<br>
-};<br>
-auto *waa2 = new WeirdAlignedAlloc2; // expected-note {{instantiation of}}<br>
-auto *waa2p = new (arg) WeirdAlignedAlloc2; // expected-note {{instantiation of}}<br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.new/p20-0x.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>expr/expr.unary/expr.new/p20-<wbr>0x.cpp?rev=283750&r1=283749&<wbr>r2=283750&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.new/p20-0x.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.<wbr>unary/expr.new/p20-0x.cpp Mon Oct 10 09:13:55 2016<br>
@@ -1,10 +1,6 @@<br>
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -fexceptions %s<br>
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -fexceptions %s<br>
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z -fexceptions %s<br>
 typedef __SIZE_TYPE__ size_t;<br>
<br>
-namespace std { enum class align_val_t : size_t {}; }<br>
-<br>
 struct S {<br>
   // Placement allocation function:<br>
   static void* operator new(size_t, size_t);<br>
@@ -13,56 +9,5 @@ struct S {<br>
 };<br>
<br>
 void testS() {<br>
-  S* p = new (0) S; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}}<br>
-}<br>
-<br>
-struct T {<br>
-  // Placement allocation function:<br>
-  static void* operator new(size_t, size_t);<br>
-  // Usual (non-placement) deallocation function:<br>
-  static void operator delete(void*);<br>
-  // Placement deallocation function:<br>
-  static void operator delete(void*, size_t);<br>
-};<br>
-<br>
-void testT() {<br>
-  T* p = new (0) T; // ok<br>
-}<br>
-<br>
-#if __cplusplus > 201402L<br>
-struct U {<br>
-  // Placement allocation function:<br>
-  static void* operator new(size_t, size_t, std::align_val_t);<br>
-  // Placement deallocation function:<br>
-  static void operator delete(void*, size_t, std::align_val_t); // expected-note{{declared here}}<br>
-};<br>
-<br>
-void testU() {<br>
-  U* p = new (0, std::align_val_t(0)) U; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}}<br>
-}<br>
-<br>
-struct V {<br>
-  // Placement allocation function:<br>
-  static void* operator new(size_t, size_t, std::align_val_t);<br>
-  // Usual (non-placement) deallocation function:<br>
-  static void operator delete(void*, std::align_val_t);<br>
-  // Placement deallocation function:<br>
-  static void operator delete(void*, size_t, std::align_val_t);<br>
-};<br>
-<br>
-void testV() {<br>
-  V* p = new (0, std::align_val_t(0)) V;<br>
-}<br>
-<br>
-struct W {<br>
-  // Placement allocation function:<br>
-  static void* operator new(size_t, size_t, std::align_val_t);<br>
-  // Usual (non-placement) deallocation functions:<br>
-  static void operator delete(void*);<br>
-  static void operator delete(void*, size_t, std::align_val_t); // expected-note {{declared here}}<br>
-};<br>
-<br>
-void testW() {<br>
-  W* p = new (0, std::align_val_t(0)) W; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}}<br>
+  S* p = new (0) S;    // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}}<br>
 }<br>
-#endif<br>
<br>
Modified: cfe/trunk/test/CXX/special/<wbr>class.dtor/p9.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.dtor/p9.cpp?rev=283750&r1=283749&r2=283750&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/CXX/<wbr>special/class.dtor/p9.cpp?rev=<wbr>283750&r1=283749&r2=283750&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CXX/special/<wbr>class.dtor/p9.cpp (original)<br>
+++ cfe/trunk/test/CXX/special/<wbr>class.dtor/p9.cpp Mon Oct 10 09:13:55 2016<br>
@@ -31,13 +31,13 @@ namespace test0 {<br>
 namespace test1 {<br>
   class A {<br>
   public:<br>
-    static void operator delete(void *p) {};<br>
+    static void operator delete(void *p) {}; // expected-note {{member 'operator delete' declared here}}<br>
     virtual ~A();<br>
   };<br>
<br>
   class B : protected A {<br>
   public:<br>
-    static void operator delete(void *, size_t) {};<br>
+    static void operator delete(void *, size_t) {}; // expected-note {{member 'operator delete' declared here}}<br>
     ~B();<br>
   };<br>
<br>
@@ -49,20 +49,7 @@ namespace test1 {<br>
     ~C();<br>
   };<br>
<br>
-  // We assume that the intent is to treat C::operator delete(void*, size_t) as<br>
-  // /not/ being a usual deallocation function, as it would be if it were<br>
-  // declared with in C directly.<br>
-  C::~C() {}<br>
-<br>
-  struct D {<br>
-    void operator delete(void*); // expected-note {{member 'operator delete' declared here}}<br>
-    void operator delete(void*, ...); // expected-note {{member 'operator delete' declared here}}<br>
-    virtual ~D();<br>
-  };<br>
-  // FIXME: The standard doesn't say this is ill-formed, but presumably either<br>
-  // it should be or the variadic operator delete should not be a usual<br>
-  // deallocation function.<br>
-  D::~D() {} // expected-error {{multiple suitable 'operator delete' functions in 'D'}}<br>
+  C::~C() {} // expected-error {{multiple suitable 'operator delete' functions in 'C'}}<br>
 }<br>
<br>
 // ...at the point of definition of a virtual destructor...<br>
<br>
Removed: cfe/trunk/test/CodeGenCXX/<wbr>cxx1z-aligned-allocation.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx1z-aligned-allocation.cpp?rev=283749&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenCXX/cxx1z-aligned-<wbr>allocation.cpp?rev=283749&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenCXX/<wbr>cxx1z-aligned-allocation.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/<wbr>cxx1z-aligned-allocation.cpp (removed)<br>
@@ -1,206 +0,0 @@<br>
-// Check that delete exprs call aligned (de)allocation functions if<br>
-// -faligned-allocation is passed in both C++11 and C++14.<br>
-// RUN: %clang_cc1 -std=c++11 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s<br>
-// RUN: %clang_cc1 -std=c++14 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s<br>
-// RUN: %clang_cc1 -std=c++1z -fexceptions -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s<br>
-<br>
-// Check that we don't used aligned (de)allocation without -faligned-allocation or C++1z.<br>
-// RUN: %clang_cc1 -std=c++14 -DUNALIGNED -fexceptions %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED<br>
-// RUN: %clang_cc1 -std=c++1z -DUNALIGNED -fexceptions -fno-aligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED<br>
-<br>
-// CHECK-UNALIGNED-NOT: _Znwm_St11align_val_t<br>
-// CHECK-UNALIGNED-NOT: _Znam_St11align_val_t<br>
-// CHECK-UNALIGNED-NOT: _ZdlPv_St11align_val_t<br>
-// CHECK-UNALIGNED-NOT: _ZdaPv_St11align_val_t<br>
-// CHECK-UNALIGNED-NOT: _ZdlPvm_St11align_val_t<br>
-// CHECK-UNALIGNED-NOT: _ZdaPvm_St11align_val_t<br>
-<br>
-typedef decltype(sizeof(0)) size_t;<br>
-namespace std { enum class align_val_t : size_t {}; }<br>
-<br>
-#define OVERALIGNED alignas(__STDCPP_DEFAULT_NEW_<wbr>ALIGNMENT__ * 2)<br>
-<br>
-// Global new and delete.<br>
-// ======================<br>
-struct OVERALIGNED A { A(); int n[128]; };<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2a0v()<br>
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 32)<br>
-// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 32)<br>
-void *a0() { return new A; }<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2a1l(<br>
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32)<br>
-// No array cookie.<br>
-// CHECK-NOT: store<br>
-// CHECK: invoke void @_ZN1AC1Ev(<br>
-// CHECK: call void @_ZdaPvSt11align_val_t(i8* %[[ALLOC]], i64 32)<br>
-void *a1(long n) { return new A[n]; }<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2a2P1A(<br>
-// CHECK: call void @_ZdlPvmSt11align_val_t(i8* %{{.*}}, i64 512, i64 32) #9<br>
-void a2(A *p) { delete p; }<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2a3P1A(<br>
-// CHECK: call void @_ZdaPvSt11align_val_t(i8* %{{.*}}, i64 32) #9<br>
-void a3(A *p) { delete[] p; }<br>
-<br>
-<br>
-// Class-specific usual new and delete.<br>
-// ==============================<wbr>======<br>
-struct OVERALIGNED B {<br>
-  B();<br>
-  // These are just a distraction. We should ignore them.<br>
-  void *operator new(size_t);<br>
-  void operator delete(void*, size_t);<br>
-  void operator delete[](void*, size_t);<br>
-<br>
-  void *operator new(size_t, std::align_val_t);<br>
-  void operator delete(void*, std::align_val_t);<br>
-  void operator delete[](void*, std::align_val_t);<br>
-<br>
-  int n[128];<br>
-};<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2b0v()<br>
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 32)<br>
-// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 32)<br>
-void *b0() { return new B; }<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2b1l(<br>
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32)<br>
-// No array cookie.<br>
-// CHECK-NOT: store<br>
-// CHECK: invoke void @_ZN1BC1Ev(<br>
-// CHECK: call void @_ZN1BdaEPvSt11align_val_t(i8* %[[ALLOC]], i64 32)<br>
-void *b1(long n) { return new B[n]; }<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2b2P1B(<br>
-// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %{{.*}}, i64 32)<br>
-void b2(B *p) { delete p; }<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2b3P1B(<br>
-// CHECK: call void @_ZN1BdaEPvSt11align_val_t(i8* %{{.*}}, i64 32)<br>
-void b3(B *p) { delete[] p; }<br>
-<br>
-struct OVERALIGNED C {<br>
-  C();<br>
-  void *operator new[](size_t, std::align_val_t);<br>
-  void operator delete[](void*, size_t, std::align_val_t);<br>
-<br>
-  // It doesn't matter that we have an unaligned operator delete[] that doesn't<br>
-  // want the size. What matters is that the aligned one does.<br>
-  void operator delete[](void*);<br>
-};<br>
-<br>
-// This one has an array cookie.<br>
-// CHECK-LABEL: define {{.*}} @_Z2b4l(<br>
-// CHECK: call {{.*}} @llvm.umul.with.overflow{{.*}}<wbr>i64 32<br>
-// CHECK: call {{.*}} @llvm.uadd.with.overflow{{.*}}<wbr>i64 32<br>
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1CnaEmSt11align_val_t(i64 %{{.*}}, i64 32)<br>
-// CHECK: store<br>
-// CHECK: call void @_ZN1CC1Ev(<br>
-//<br>
-// Note, we're still calling a placement allocation function, and there is no<br>
-// matching placement operator delete. =(<br>
-// FIXME: This seems broken.<br>
-// CHECK-NOT: call void @_ZN1CdaEPvmSt11align_val_t(<br>
-#ifndef UNALIGNED<br>
-void *b4(long n) { return new C[n]; }<br>
-#endif<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2b5P1C(<br>
-// CHECK: mul i64{{.*}} 32<br>
-// CHECK: add i64{{.*}} 32<br>
-// CHECK: call void @_ZN1CdaEPvmSt11align_val_t(<br>
-void b5(C *p) { delete[] p; }<br>
-<br>
-<br>
-// Global placement new.<br>
-// =====================<br>
-<br>
-struct Q { int n; } q;<br>
-void *operator new(size_t, Q);<br>
-void *operator new(size_t, std::align_val_t, Q);<br>
-void operator delete(void*, Q);<br>
-void operator delete(void*, std::align_val_t, Q);<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2c0v(<br>
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t1Q(i64 512, i64 32, i32 %<br>
-// CHECK: call void @_ZdlPvSt11align_val_t1Q(i8* %[[ALLOC]], i64 32, i32 %<br>
-void *c0() { return new (q) A; }<br>
-<br>
-<br>
-// Class-specific placement new.<br>
-// =============================<br>
-<br>
-struct OVERALIGNED D {<br>
-  D();<br>
-  void *operator new(size_t, Q);<br>
-  void *operator new(size_t, std::align_val_t, Q);<br>
-  void operator delete(void*, Q);<br>
-  void operator delete(void*, std::align_val_t, Q);<br>
-};<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2d0v(<br>
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1DnwEmSt11align_val_t1Q(<wbr>i64 32, i64 32, i32 %<br>
-// CHECK: call void @_ZN1DdlEPvSt11align_val_t1Q(<wbr>i8* %[[ALLOC]], i64 32, i32 %<br>
-void *d0() { return new (q) D; }<br>
-<br>
-<br>
-// Calling aligned new with placement syntax.<br>
-// ==============================<wbr>============<br>
-<br>
-#ifndef UNALIGNED<br>
-// CHECK-LABEL: define {{.*}} @_Z2e0v(<br>
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 5)<br>
-// CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 5)<br>
-void *e0() { return new (std::align_val_t(5)) A; }<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2e1v(<br>
-// CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 5)<br>
-// CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 5)<br>
-void *e1() { return new (std::align_val_t(5)) B; }<br>
-#endif<br>
-<br>
-// Variadic placement/non-placement allocation functions.<br>
-// ==============================<wbr>========================<br>
-<br>
-struct OVERALIGNED F {<br>
-  F();<br>
-  void *operator new(size_t, ...);<br>
-  void operator delete(void*, ...);<br>
-  int n[128];<br>
-};<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2f0v(<br>
-// CHECK: %[[ALLOC:.*]] = call i8* (i64, ...) @_ZN1FnwEmz(i64 512, i64 32)<br>
-// Non-placement allocation function, uses normal deallocation lookup which<br>
-// cares about whether a parameter has type std::align_val_t.<br>
-// CHECK: call void (i8*, ...) @_ZN1FdlEPvz(i8* %[[ALLOC]])<br>
-void *f0() { return new F; }<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2f1v(<br>
-// CHECK: %[[ALLOC:.*]] = call i8* (i64, ...) @_ZN1FnwEmz(i64 512, i64 32, i32 %<br>
-// Placement allocation function, uses placement deallocation matching, which<br>
-// passes same arguments and therefore includes alignment.<br>
-// CHECK: call void (i8*, ...) @_ZN1FdlEPvz(i8* %[[ALLOC]], i64 32, i32 %<br>
-void *f1() { return new (q) F; }<br>
-<br>
-struct OVERALIGNED G {<br>
-  G();<br>
-  void *operator new(size_t, std::align_val_t, ...);<br>
-  void operator delete(void*, std::align_val_t, ...);<br>
-  int n[128];<br>
-};<br>
-#ifndef UNALIGNED<br>
-// CHECK-LABEL: define {{.*}} @_Z2g0v<br>
-// CHECK: %[[ALLOC:.*]] = call i8* (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 512, i64 32)<br>
-// CHECK: call void (i8*, i64, ...) @_ZN1GdlEPvSt11align_val_tz(<wbr>i8* %[[ALLOC]], i64 32)<br>
-void *g0() { return new G; }<br>
-<br>
-// CHECK-LABEL: define {{.*}} @_Z2g1v<br>
-// CHECK: %[[ALLOC:.*]] = call i8* (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 512, i64 32, i32 %<br>
-// CHECK: call void (i8*, i64, ...) @_ZN1GdlEPvSt11align_val_tz(<wbr>i8* %[[ALLOC]], i64 32, i32 %<br>
-void *g1() { return new (q) G; }<br>
-#endif<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>