Sorry, I didn't see the failure yesterday. I'll get on it or revert it.
On Thu, Mar 22, 2018 at 11:51 AM, Galina Kistanova <gkistan...@gmail.com> wrote: > Hello Eric, > > One of added tests fails on the next builder: > http://lab.llvm.org:8011/builders/llvm-clang-x86_64- > expensive-checks-win/builds/8624 > > . . . > Failing Tests: > . . . > Clang :: SemaCXX/builtin-operator-new-delete.cpp > > Please have a look? > > It is not good idea to keep the bot red for too long. This hides new > problem which later hard to track down. > > Thanks > > Galina > > > On Wed, Mar 21, 2018 at 12:19 PM, Eric Fiselier via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> Author: ericwf >> Date: Wed Mar 21 12:19:48 2018 >> New Revision: 328134 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=328134&view=rev >> Log: >> [Builtins] Overload __builtin_operator_new/delete to allow forwarding to >> usual allocation/deallocation functions. >> >> Summary: >> Libc++'s default allocator uses `__builtin_operator_new` and >> `__builtin_operator_delete` in order to allow the calls to new/delete to be >> ellided. However, libc++ now needs to support over-aligned types in the >> default allocator. In order to support this without disabling the existing >> optimization Clang needs to support calling the aligned new overloads from >> the builtins. >> >> See llvm.org/PR22634 for more information about the libc++ bug. >> >> This patch changes `__builtin_operator_new`/`__builtin_operator_delete` >> to call any usual `operator new`/`operator delete` function. It does this >> by performing overload resolution with the arguments passed to the builtin >> to determine which allocation function to call. If the selected function is >> not a usual allocation function a diagnostic is issued. >> >> One open issue is if the `align_val_t` overloads should be considered >> "usual" when `LangOpts::AlignedAllocation` is disabled. >> >> >> In order to allow libc++ to detect this new behavior the value for >> `__has_builtin(__builtin_operator_new)` has been updated to `201802`. >> >> Reviewers: rsmith, majnemer, aaron.ballman, erik.pilkington, bogner, >> ahatanak >> >> Reviewed By: rsmith >> >> Subscribers: cfe-commits >> >> Differential Revision: https://reviews.llvm.org/D43047 >> >> Added: >> cfe/trunk/test/CodeGenCXX/builtin-operator-new-delete.cpp >> cfe/trunk/test/SemaCXX/builtin-operator-new-delete.cpp >> Modified: >> cfe/trunk/include/clang/Basic/Builtins.def >> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> cfe/trunk/include/clang/Sema/Sema.h >> cfe/trunk/lib/CodeGen/CGBuiltin.cpp >> cfe/trunk/lib/CodeGen/CGExprCXX.cpp >> cfe/trunk/lib/CodeGen/CodeGenFunction.h >> cfe/trunk/lib/Lex/PPMacroExpansion.cpp >> cfe/trunk/lib/Sema/SemaChecking.cpp >> cfe/trunk/lib/Sema/SemaExprCXX.cpp >> >> Modified: cfe/trunk/include/clang/Basic/Builtins.def >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ >> Basic/Builtins.def?rev=328134&r1=328133&r2=328134&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/include/clang/Basic/Builtins.def (original) >> +++ cfe/trunk/include/clang/Basic/Builtins.def Wed Mar 21 12:19:48 2018 >> @@ -1371,8 +1371,8 @@ BUILTIN(__builtin_smulll_overflow, "bSLL >> >> // Clang builtins (not available in GCC). >> BUILTIN(__builtin_addressof, "v*v&", "nct") >> -BUILTIN(__builtin_operator_new, "v*z", "c") >> -BUILTIN(__builtin_operator_delete, "vv*", "n") >> +BUILTIN(__builtin_operator_new, "v*z", "tc") >> +BUILTIN(__builtin_operator_delete, "vv*", "tn") >> BUILTIN(__builtin_char_memchr, "c*cC*iz", "n") >> >> // Safestack builtins >> >> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ >> Basic/DiagnosticSemaKinds.td?rev=328134&r1=328133&r2=328134&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) >> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Mar 21 >> 12:19:48 2018 >> @@ -7627,6 +7627,11 @@ def err_destroying_operator_delete_not_u >> "alignment parameter">; >> def note_implicit_delete_this_in_destructor_here : Note< >> "while checking implicit 'delete this' for virtual destructor">; >> +def err_builtin_operator_new_delete_not_usual : Error< >> + "call to '%select{__builtin_operator_new|__builtin_operator_delete}0' >> " >> + "selects non-usual %select{allocation|deallocation}0 function">; >> +def note_non_usual_function_declared_here : Note< >> + "non-usual %0 declared here">; >> >> // C++ literal operators >> def err_literal_operator_outside_namespace : Error< >> >> Modified: cfe/trunk/include/clang/Sema/Sema.h >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ >> Sema/Sema.h?rev=328134&r1=328133&r2=328134&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/include/clang/Sema/Sema.h (original) >> +++ cfe/trunk/include/clang/Sema/Sema.h Wed Mar 21 12:19:48 2018 >> @@ -10376,6 +10376,8 @@ private: >> ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult); >> ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult, >> AtomicExpr::AtomicOp Op); >> + ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult >> TheCallResult, >> + bool IsDelete); >> bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, >> llvm::APSInt &Result); >> bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, >> >> Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CG >> Builtin.cpp?rev=328134&r1=328133&r2=328134&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Wed Mar 21 12:19:48 2018 >> @@ -2611,11 +2611,12 @@ RValue CodeGenFunction::EmitBuiltinExpr( >> case Builtin::BI__builtin_addressof: >> return RValue::get(EmitLValue(E->getArg(0)).getPointer()); >> case Builtin::BI__builtin_operator_new: >> - return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProto >> Type>(), >> - E->getArg(0), false); >> + return EmitBuiltinNewDeleteCall( >> + E->getCallee()->getType()->castAs<FunctionProtoType>(), E, >> false); >> case Builtin::BI__builtin_operator_delete: >> - return EmitBuiltinNewDeleteCall(FD->getType()->castAs<FunctionProto >> Type>(), >> - E->getArg(0), true); >> + return EmitBuiltinNewDeleteCall( >> + E->getCallee()->getType()->castAs<FunctionProtoType>(), E, >> true); >> + >> case Builtin::BI__noop: >> // __noop always evaluates to an integer literal zero. >> return RValue::get(ConstantInt::get(IntTy, 0)); >> >> Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CG >> ExprCXX.cpp?rev=328134&r1=328133&r2=328134&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original) >> +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Mar 21 12:19:48 2018 >> @@ -1307,19 +1307,19 @@ static RValue EmitNewDeleteCall(CodeGenF >> } >> >> RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const >> FunctionProtoType *Type, >> - const Expr *Arg, >> + const CallExpr *TheCall, >> bool IsDelete) { >> CallArgList Args; >> - const Stmt *ArgS = Arg; >> - EmitCallArgs(Args, *Type->param_type_begin(), >> llvm::makeArrayRef(ArgS)); >> + EmitCallArgs(Args, Type->getParamTypes(), TheCall->arguments()); >> // Find the allocation or deallocation function that we're calling. >> ASTContext &Ctx = getContext(); >> DeclarationName Name = Ctx.DeclarationNames >> .getCXXOperatorName(IsDelete ? OO_Delete : OO_New); >> + >> for (auto *Decl : Ctx.getTranslationUnitDecl()->lookup(Name)) >> if (auto *FD = dyn_cast<FunctionDecl>(Decl)) >> if (Ctx.hasSameType(FD->getType(), QualType(Type, 0))) >> - return EmitNewDeleteCall(*this, cast<FunctionDecl>(Decl), Type, >> Args); >> + return EmitNewDeleteCall(*this, FD, Type, Args); >> llvm_unreachable("predeclared global operator new/delete is missing"); >> } >> >> >> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Co >> deGenFunction.h?rev=328134&r1=328133&r2=328134&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original) >> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Mar 21 12:19:48 2018 >> @@ -2356,7 +2356,7 @@ public: >> CharUnits CookieSize = CharUnits()); >> >> RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type, >> - const Expr *Arg, bool IsDelete); >> + const CallExpr *TheCallExpr, bool >> IsDelete); >> >> llvm::Value *EmitCXXTypeidExpr(const CXXTypeidExpr *E); >> llvm::Value *EmitDynamicCast(Address V, const CXXDynamicCastExpr *DCE); >> >> Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacr >> oExpansion.cpp?rev=328134&r1=328133&r2=328134&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original) >> +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Wed Mar 21 12:19:48 2018 >> @@ -1801,12 +1801,21 @@ void Preprocessor::ExpandBuiltinMacro(To >> [this](Token &Tok, bool &HasLexedNextToken) -> int { >> IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this, >> diag::err_feature_check_malfor >> med); >> + const LangOptions &LangOpts = getLangOpts(); >> if (!II) >> return false; >> - else if (II->getBuiltinID() != 0) >> + else if (II->getBuiltinID() != 0) { >> + switch (II->getBuiltinID()) { >> + case Builtin::BI__builtin_operator_new: >> + case Builtin::BI__builtin_operator_delete: >> + // denotes date of behavior change to support calling >> arbitrary >> + // usual allocation and deallocation functions. Required by >> libc++ >> + return 201802; >> + default: >> + return true; >> + } >> return true; >> - else { >> - const LangOptions &LangOpts = getLangOpts(); >> + } else { >> return llvm::StringSwitch<bool>(II->getName()) >> .Case("__make_integer_seq", LangOpts.CPlusPlus) >> .Case("__type_pack_element", LangOpts.CPlusPlus) >> >> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaC >> hecking.cpp?rev=328134&r1=328133&r2=328134&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Mar 21 12:19:48 2018 >> @@ -1097,20 +1097,14 @@ Sema::CheckBuiltinFunctionCall(FunctionD >> return ExprError(); >> break; >> case Builtin::BI__builtin_operator_new: >> - case Builtin::BI__builtin_operator_delete: >> - if (!getLangOpts().CPlusPlus) { >> - Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language) >> - << (BuiltinID == Builtin::BI__builtin_operator_new >> - ? "__builtin_operator_new" >> - : "__builtin_operator_delete") >> - << "C++"; >> - return ExprError(); >> - } >> - // CodeGen assumes it can find the global new and delete to call, >> - // so ensure that they are declared. >> - DeclareGlobalNewDelete(); >> - break; >> - >> + case Builtin::BI__builtin_operator_delete: { >> + bool IsDelete = BuiltinID == Builtin::BI__builtin_operator_delete; >> + ExprResult Res = >> + SemaBuiltinOperatorNewDeleteOverloaded(TheCallResult, IsDelete); >> + if (Res.isInvalid()) >> + CorrectDelayedTyposInExpr(TheCallResult.get()); >> + return Res; >> + } >> // check secure string manipulation functions where overflows >> // are detectable at compile time >> case Builtin::BI__builtin___memcpy_chk: >> >> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaE >> xprCXX.cpp?rev=328134&r1=328133&r2=328134&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Mar 21 12:19:48 2018 >> @@ -1443,7 +1443,7 @@ namespace { >> CUDAPref = S.IdentifyCUDAPreference(Caller, FD); >> } >> >> - operator bool() const { return FD; } >> + explicit operator bool() const { return FD; } >> >> bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize, >> bool WantAlign) const { >> @@ -2271,7 +2271,6 @@ static bool resolveAllocationOverload( >> llvm_unreachable("Unreachable, bad result from BestViableFunction"); >> } >> >> - >> /// FindAllocationFunctions - Finds the overloads of operator new and >> delete >> /// that are appropriate for the allocation. >> bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange >> Range, >> @@ -3343,6 +3342,128 @@ Sema::ActOnCXXDelete(SourceLocation Star >> return Result; >> } >> >> +static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall, >> + bool IsDelete, >> + FunctionDecl *&Operator) { >> + >> + DeclarationName NewName = S.Context.DeclarationNames.get >> CXXOperatorName( >> + IsDelete ? OO_Delete : OO_New); >> + >> + LookupResult R(S, NewName, TheCall->getLocStart(), >> Sema::LookupOrdinaryName); >> + S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl()); >> + assert(!R.empty() && "implicitly declared allocation functions not >> found"); >> + assert(!R.isAmbiguous() && "global allocation functions are >> ambiguous"); >> + >> + // We do our own custom access checks below. >> + R.suppressDiagnostics(); >> + >> + SmallVector<Expr *, 8> Args(TheCall->arg_begin(), TheCall->arg_end()); >> + OverloadCandidateSet Candidates(R.getNameLoc(), >> + OverloadCandidateSet::CSK_Normal); >> + for (LookupResult::iterator FnOvl = R.begin(), FnOvlEnd = R.end(); >> + FnOvl != FnOvlEnd; ++FnOvl) { >> + // Even member operator new/delete are implicitly treated as >> + // static, so don't use AddMemberCandidate. >> + NamedDecl *D = (*FnOvl)->getUnderlyingDecl(); >> + >> + if (FunctionTemplateDecl *FnTemplate = >> dyn_cast<FunctionTemplateDecl>(D)) >> { >> + S.AddTemplateOverloadCandidate(FnTemplate, FnOvl.getPair(), >> + /*ExplicitTemplateArgs=*/nullptr, >> Args, >> + Candidates, >> + /*SuppressUserConversions=*/false); >> + continue; >> + } >> + >> + FunctionDecl *Fn = cast<FunctionDecl>(D); >> + S.AddOverloadCandidate(Fn, FnOvl.getPair(), Args, Candidates, >> + /*SuppressUserConversions=*/false); >> + } >> + >> + SourceRange Range = TheCall->getSourceRange(); >> + >> + // Do the resolution. >> + OverloadCandidateSet::iterator Best; >> + switch (Candidates.BestViableFunction(S, R.getNameLoc(), Best)) { >> + case OR_Success: { >> + // Got one! >> + FunctionDecl *FnDecl = Best->Function; >> + assert(R.getNamingClass() == nullptr && >> + "class members should not be considered"); >> + >> + if (!FnDecl->isReplaceableGlobalAllocationFunction()) { >> + S.Diag(R.getNameLoc(), diag::err_builtin_operator_new >> _delete_not_usual) >> + << (IsDelete ? 1 : 0) << Range; >> + S.Diag(FnDecl->getLocation(), diag::note_non_usual_function_ >> declared_here) >> + << R.getLookupName() << FnDecl->getSourceRange(); >> + return true; >> + } >> + >> + Operator = FnDecl; >> + return false; >> + } >> + >> + case OR_No_Viable_Function: >> + S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call) >> + << R.getLookupName() << Range; >> + Candidates.NoteCandidates(S, OCD_AllCandidates, Args); >> + return true; >> + >> + case OR_Ambiguous: >> + S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) >> + << R.getLookupName() << Range; >> + Candidates.NoteCandidates(S, OCD_ViableCandidates, Args); >> + return true; >> + >> + case OR_Deleted: { >> + S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call) >> + << Best->Function->isDeleted() << R.getLookupName() >> + << S.getDeletedOrUnavailableSuffix(Best->Function) << Range; >> + Candidates.NoteCandidates(S, OCD_AllCandidates, Args); >> + return true; >> + } >> + } >> + llvm_unreachable("Unreachable, bad result from BestViableFunction"); >> +} >> + >> +ExprResult >> +Sema::SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult, >> + bool IsDelete) { >> + CallExpr *TheCall = cast<CallExpr>(TheCallResult.get()); >> + if (!getLangOpts().CPlusPlus) { >> + Diag(TheCall->getExprLoc(), diag::err_builtin_requires_language) >> + << (IsDelete ? "__builtin_operator_delete" : >> "__builtin_operator_new") >> + << "C++"; >> + return ExprError(); >> + } >> + // CodeGen assumes it can find the global new and delete to call, >> + // so ensure that they are declared. >> + DeclareGlobalNewDelete(); >> + >> + FunctionDecl *OperatorNewOrDelete = nullptr; >> + if (resolveBuiltinNewDeleteOverload(*this, TheCall, IsDelete, >> + OperatorNewOrDelete)) >> + return ExprError(); >> + assert(OperatorNewOrDelete && "should be found"); >> + >> + TheCall->setType(OperatorNewOrDelete->getReturnType()); >> + for (unsigned i = 0; i != TheCall->getNumArgs(); ++i) { >> + QualType ParamTy = OperatorNewOrDelete->getParamDecl(i)->getType(); >> + InitializedEntity Entity = >> + InitializedEntity::InitializeParameter(Context, ParamTy, false); >> + ExprResult Arg = PerformCopyInitialization( >> + Entity, TheCall->getArg(i)->getLocStart(), TheCall->getArg(i)); >> + if (Arg.isInvalid()) >> + return ExprError(); >> + TheCall->setArg(i, Arg.get()); >> + } >> + auto Callee = dyn_cast<ImplicitCastExpr>(TheCall->getCallee()); >> + assert(Callee && Callee->getCastKind() == CK_BuiltinFnToFnPtr && >> + "Callee expected to be implicit cast to a builtin function >> pointer"); >> + Callee->setType(OperatorNewOrDelete->getType()); >> + >> + return TheCallResult; >> +} >> + >> void Sema::CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation >> Loc, >> bool IsDelete, bool CallCanBeVirtual, >> bool WarnOnNonAbstractTypes, >> >> Added: cfe/trunk/test/CodeGenCXX/builtin-operator-new-delete.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCX >> X/builtin-operator-new-delete.cpp?rev=328134&view=auto >> ============================================================ >> ================== >> --- cfe/trunk/test/CodeGenCXX/builtin-operator-new-delete.cpp (added) >> +++ cfe/trunk/test/CodeGenCXX/builtin-operator-new-delete.cpp Wed Mar 21 >> 12:19:48 2018 >> @@ -0,0 +1,71 @@ >> +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s \ >> +// RUN: -faligned-allocation -fsized-deallocation -emit-llvm -o - \ >> +// RUN: | FileCheck %s >> + >> +typedef __SIZE_TYPE__ size_t; >> + >> +// Declare an 'operator new' template to tickle a bug in >> __builtin_operator_new. >> +template<typename T> void *operator new(size_t, int (*)(T)); >> + >> +// Ensure that this declaration doesn't cause operator new to lose its >> +// 'noalias' attribute. >> +void *operator new(size_t); >> + >> +namespace std { >> + struct nothrow_t {}; >> + enum class align_val_t : size_t { __zero = 0, >> + __max = (size_t)-1 }; >> +} >> +std::nothrow_t nothrow; >> + >> +// Declare the reserved placement operators. >> +void *operator new(size_t, void*) throw(); >> +void operator delete(void*, void*) throw(); >> +void *operator new[](size_t, void*) throw(); >> +void operator delete[](void*, void*) throw(); >> + >> +// Declare the replaceable global allocation operators. >> +void *operator new(size_t, const std::nothrow_t &) throw(); >> +void *operator new[](size_t, const std::nothrow_t &) throw(); >> +void operator delete(void *, const std::nothrow_t &) throw(); >> +void operator delete[](void *, const std::nothrow_t &) throw(); >> + >> +// Declare some other placement operators. >> +void *operator new(size_t, void*, bool) throw(); >> +void *operator new[](size_t, void*, bool) throw(); >> + >> + >> +// CHECK-LABEL: define void @test_basic( >> +extern "C" void test_basic() { >> + // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] >> + // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]] >> + // CHECK: ret void >> + __builtin_operator_delete(__builtin_operator_new(4)); >> +} >> +// CHECK: declare noalias i8* @_Znwm(i64) [[ATTR_NOBUILTIN:#[^ ]*]] >> +// CHECK: declare void @_ZdlPv(i8*) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] >> + >> +// CHECK-LABEL: define void @test_aligned_alloc( >> +extern "C" void test_aligned_alloc() { >> + // CHECK: call i8* @_ZnwmSt11align_val_t(i64 4, i64 4) >> [[ATTR_BUILTIN_NEW:#[^ ]*]] >> + // CHECK: call void @_ZdlPvSt11align_val_t({{.*}}, i64 4) >> [[ATTR_BUILTIN_DELETE:#[^ ]*]] >> + __builtin_operator_delete(__builtin_operator_new(4, >> std::align_val_t(4)), std::align_val_t(4)); >> +} >> +// CHECK: declare noalias i8* @_ZnwmSt11align_val_t(i64, i64) >> [[ATTR_NOBUILTIN:#[^ ]*]] >> +// CHECK: declare void @_ZdlPvSt11align_val_t(i8*, i64) >> [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] >> + >> + >> +// CHECK-LABEL: define void @test_sized_delete( >> +extern "C" void test_sized_delete() { >> + // CHECK: call i8* @_Znwm(i64 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] >> + // CHECK: call void @_ZdlPvm({{.*}}, i64 4) [[ATTR_BUILTIN_DELETE:#[^ >> ]*]] >> + __builtin_operator_delete(__builtin_operator_new(4), 4); >> +} >> +// CHECK: declare void @_ZdlPvm(i8*, i64) [[ATTR_NOBUILTIN_UNWIND:#[^ >> ]*]] >> + >> + >> +// CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin >> {{.*[}]}} >> +// CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} >> nobuiltin nounwind {{.*[}]}} >> + >> +// CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin >> {{.*[}]}} >> +// CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin >> {{.*[}]}} >> >> Added: cfe/trunk/test/SemaCXX/builtin-operator-new-delete.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ >> builtin-operator-new-delete.cpp?rev=328134&view=auto >> ============================================================ >> ================== >> --- cfe/trunk/test/SemaCXX/builtin-operator-new-delete.cpp (added) >> +++ cfe/trunk/test/SemaCXX/builtin-operator-new-delete.cpp Wed Mar 21 >> 12:19:48 2018 >> @@ -0,0 +1,153 @@ >> +// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s >> +// RUN: %clang_cc1 -std=c++03 -fsyntax-only -verify %s >> +// RUN: %clang_cc1 -std=c++03 -faligned-allocation -fsyntax-only -verify >> %s >> +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s >> +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fsized-deallocation >> %s >> + >> +#if !__has_builtin(__builtin_operator_new) || >> !__has_builtin(__builtin_operator_delete) >> +#error builtins should always be available >> +#endif >> + >> +#if __has_builtin(__builtin_operator_new) != 201802L || \ >> + __has_builtin(__builtin_operator_delete) != 201802L >> +#error builtin should report updated value >> +#endif >> + >> +typedef __SIZE_TYPE__ size_t; >> +namespace std { >> + struct nothrow_t {}; >> +#if __cplusplus >= 201103L >> +enum class align_val_t : size_t {}; >> +#else >> + enum align_val_t { __zero = 0, >> + __max = (size_t)-1 }; >> +#endif >> +} >> +std::nothrow_t nothrow; >> + >> +void *operator new(size_t); // expected-note 1+ {{candidate function}} >> +void operator delete(void *); // expected-note 1+ {{candidate function}} >> + >> +// Declare the reserved placement operators. >> +void *operator new(size_t, void*) throw(); // expected-note 1+ >> {{candidate function}} >> +void operator delete(void *, void *)throw(); // expected-note 1+ >> {{candidate function}} >> +void *operator new[](size_t, void*) throw(); >> +void operator delete[](void*, void*) throw(); >> + >> +// Declare the replaceable global allocation operators. >> +void *operator new(size_t, const std::nothrow_t &) throw(); // >> expected-note 1+ {{candidate function}} >> +void *operator new[](size_t, const std::nothrow_t &) throw(); >> +void operator delete(void *, const std::nothrow_t &)throw(); // >> expected-note 1+ {{candidate function}} >> +void operator delete[](void *, const std::nothrow_t &) throw(); >> + >> +// aligned allocation and deallocation functions. >> +void* operator new ( size_t count, std::align_val_t al); // >> expected-note 1+ {{candidate function}} >> +void operator delete(void *, std::align_val_t); // expected-note 1+ >> {{candidate}} >> +#ifndef __cpp_aligned_new >> +// expected-note@-3 1+ {{non-usual 'operator new' declared here}} >> +// expected-note@-3 1+ {{non-usual 'operator delete' declared here}} >> +#endif >> +void *operator new[](size_t count, std::align_val_t al); >> +void operator delete[](void*, std::align_val_t); >> + >> +void operator delete(void *, size_t); // expected-note 1+ {{candidate}} >> +#ifndef __cpp_sized_deallocation >> +// expected-note@-2 1+ {{non-usual 'operator delete' declared here}} >> +#endif >> +void operator delete[](void*, size_t); >> + >> +// Declare some other placemenet operators. >> +void *operator new(size_t, void*, bool) throw(); // expected-note 1+ >> {{candidate function}} >> +void *operator new[](size_t, void*, bool) throw(); >> + >> +void *NP = 0; >> + >> +void test_typo_in_args() { >> + __builtin_operator_new(DNE); // expected-error {{undeclared >> identifier 'DNE'}} >> + __builtin_operator_new(DNE, DNE2); // expected-error {{undeclared >> identifier 'DNE'}} expected-error {{'DNE2'}} >> + __builtin_operator_delete(DNE); // expected-error {{'DNE'}} >> + __builtin_operator_delete(DNE, DNE2); // expected-error {{'DNE'}} >> expected-error {{'DNE2'}} >> +} >> + >> +void test_arg_types() { >> + __builtin_operator_new(NP); // expected-error >> {{no matching function for call to 'operator new'}} >> + __builtin_operator_new(NP, std::align_val_t(0)); // expected-error >> {{no matching function for call to 'operator new'}}} >> +} >> +void test_return_type() { >> + int w = __builtin_operator_new(42); // expected-error {{cannot >> initialize a variable of type 'int' with an rvalue of type 'void *'}} >> + int y = __builtin_operator_delete(NP); // expected-error {{cannot >> initialize a variable of type 'int' with an rvalue of type 'void'}} >> +} >> + >> +void test_aligned_new() { >> +#ifdef __cpp_aligned_new >> + void *p = __builtin_operator_new(42, std::align_val_t(2)); >> + __builtin_operator_delete(p, std::align_val_t(2)); >> +#else >> + // FIXME: We've manually declared the aligned new/delete overloads, >> + // but LangOpts::AlignedAllocation is false. Should our overloads be >> considered >> + // usual allocation/deallocation functions? >> + void *p = __builtin_operator_new(42, std::align_val_t(2)); // >> expected-error {{call to '__builtin_operator_new' selects non-usual >> allocation function}} >> + __builtin_operator_delete(p, std::align_val_t(2)); // >> expected-error {{call to '__builtin_operator_delete' selects non-usual >> deallocation function}} >> +#endif >> +} >> + >> +void test_sized_delete() { >> +#ifdef __cpp_sized_deallocation >> + __builtin_operator_delete(NP, 4); >> +#else >> + __builtin_operator_delete(NP, 4); // expected-error {{call to >> '__builtin_operator_delete' selects non-usual deallocation function}} >> +#endif >> +} >> + >> +void *operator new(size_t, bool); // expected-note 1+ {{candidate}} >> +// expected-note@-1 {{non-usual 'operator new' declared here}} >> +void operator delete(void *, bool); // expected-note 1+ {{candidate}} >> +// expected-note@-1 {{non-usual 'operator delete' declared here}} >> + >> +void test_non_usual() { >> + __builtin_operator_new(42, true); // expected-error {{call to >> '__builtin_operator_new' selects non-usual allocation function}} >> + __builtin_operator_delete(NP, false); // expected-error {{call to >> '__builtin_operator_delete' selects non-usual deallocation function}} >> +} >> + >> +template <int ID> >> +struct Tag {}; >> +struct ConvertsToTypes { >> + operator std::align_val_t() const; >> + operator Tag<0>() const; >> +}; >> + >> +void *operator new(size_t, Tag<0>); // expected-note 0+ {{candidate}} >> +void operator delete(void *, Tag<0>); // expected-note 0+ {{candidate}} >> + >> +void test_ambiguous() { >> +#ifdef __cpp_aligned_new >> + ConvertsToTypes cvt; >> + __builtin_operator_new(42, cvt); // expected-error {{call to >> 'operator new' is ambiguous}} >> + __builtin_operator_delete(NP, cvt); // expected-error {{call to >> 'operator delete' is ambiguous}} >> +#endif >> +} >> + >> +void test_no_args() { >> + __builtin_operator_new(); // expected-error {{no matching function >> for call to 'operator new'}} >> + __builtin_operator_delete(); // expected-error {{no matching function >> for call to 'operator delete'}} >> +} >> + >> +void test_no_matching_fn() { >> + Tag<1> tag; >> + __builtin_operator_new(42, tag); // expected-error {{no matching >> function for call to 'operator new'}} >> + __builtin_operator_delete(NP, tag); // expected-error {{no matching >> function for call to 'operator delete'}} >> +} >> + >> +template <class Tp, class Up, class RetT> >> +void test_dependent_call(Tp new_arg, Up delete_arg, RetT) { >> + RetT ret = __builtin_operator_new(new_arg); >> + __builtin_operator_delete(delete_arg); >> +} >> +template void test_dependent_call(int, int*, void*); >> + >> +void test_const_attribute() { >> + __builtin_operator_new(42); // expected-warning {{ignoring return >> value of function declared with const attribute}} >> +#ifdef __cpp_aligned_new >> + __builtin_operator_new(42, std::align_val_t(8)); // expected-warning >> {{ignoring return value of function declared with const attribute}} >> +#endif >> +} >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> > >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits