r283750 - Revert "P0035R4: Semantic analysis and code generation for C++17 overaligned allocation."

Nico Weber via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 10 08:08:25 PDT 2016


Richard: the msan bot printed this, maybe it helps relanding (
http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/17061/steps/check-clang%20msan/logs/stdio
):
==23518==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x81d82d9 in getKind
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/AST/DeclBase.h:390:51
    #1 0x81d82d9 in getUnderlyingDecl
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/AST/Decl.h:389
    #2 0x81d82d9 in getUnderlyingDecl
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/AST/Decl.h:398
    #3 0x81d82d9 in operator()
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Sema/SemaCUDA.cpp:168

On Mon, Oct 10, 2016 at 10:13 AM, Daniel Jasper via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

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


More information about the cfe-commits mailing list