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