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

Daniel Jasper via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 10 07:13:55 PDT 2016


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




More information about the cfe-commits mailing list