@@ -1095,12 +1095,40 @@ static TypeSourceInfo *getTypeSourceInfoForStdAlignValT(Sema &S,
10951095 return S.Context .getTrivialTypeSourceInfo (StdAlignValDecl);
10961096}
10971097
1098+ // When searching for custom allocators on the PromiseType we want to
1099+ // warn that we will ignore type aware allocators.
1100+ static bool DiagnoseTypeAwareAllocatorsIfNecessary (Sema &S, SourceLocation Loc,
1101+ unsigned DiagnosticID,
1102+ DeclarationName Name,
1103+ QualType PromiseType) {
1104+ if (!S.getLangOpts ().TypeAwareAllocators )
1105+ return false ;
1106+ if (!PromiseType->isRecordType ())
1107+ return false ;
1108+ LookupResult R (S, Name, Loc, Sema::LookupOrdinaryName);
1109+ S.LookupQualifiedName (R, PromiseType->getAsCXXRecordDecl ());
1110+ bool HaveIssuedWarning = false ;
1111+ for (auto Decl : R) {
1112+ if (S.isTypeAwareOperatorNewOrDelete (Decl)) {
1113+ if (!HaveIssuedWarning) {
1114+ S.Diag (Loc, DiagnosticID) << Name;
1115+ HaveIssuedWarning = true ;
1116+ }
1117+ S.Diag (Decl->getLocation (), diag::note_type_aware_operator_declared)
1118+ << 0 << Decl;
1119+ }
1120+ }
1121+ return HaveIssuedWarning;
1122+ }
1123+
10981124// Find an appropriate delete for the promise.
10991125static bool findDeleteForPromise (Sema &S, SourceLocation Loc, QualType PromiseType,
11001126 FunctionDecl *&OperatorDelete) {
11011127 DeclarationName DeleteName =
11021128 S.Context .DeclarationNames .getCXXOperatorName (OO_Delete);
1103-
1129+ DiagnoseTypeAwareAllocatorsIfNecessary (
1130+ S, Loc, diag::warn_coroutine_type_aware_allocator_ignored, DeleteName,
1131+ PromiseType);
11041132 auto *PointeeRD = PromiseType->getAsCXXRecordDecl ();
11051133 assert (PointeeRD && " PromiseType must be a CxxRecordDecl type" );
11061134
@@ -1111,7 +1139,7 @@ static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseTy
11111139 // scope of the promise type. If nothing is found, a search is performed in
11121140 // the global scope.
11131141 ImplicitDeallocationParameters IDP = {
1114- typeAwareAllocationModeFromBool (S. getLangOpts (). TypeAwareAllocators ) ,
1142+ S. Context . VoidTy , TypeAwareAllocationMode::No ,
11151143 alignedAllocationModeFromBool (Overaligned), SizedDeallocationMode::Yes};
11161144 if (S.FindDeallocationFunction (Loc, PointeeRD, DeleteName, OperatorDelete,
11171145 PromiseType, IDP, /* Diagnose*/ true ))
@@ -1407,10 +1435,10 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
14071435
14081436 FunctionDecl *OperatorNew = nullptr ;
14091437 SmallVector<Expr *, 1 > PlacementArgs;
1438+ DeclarationName NewName =
1439+ S.getASTContext ().DeclarationNames .getCXXOperatorName (OO_New);
14101440
1411- const bool PromiseContainsNew = [this , &PromiseType]() -> bool {
1412- DeclarationName NewName =
1413- S.getASTContext ().DeclarationNames .getCXXOperatorName (OO_New);
1441+ const bool PromiseContainsNew = [this , &PromiseType, NewName]() -> bool {
14141442 LookupResult R (S, NewName, Loc, Sema::LookupOrdinaryName);
14151443
14161444 if (PromiseType->isRecordType ())
@@ -1422,36 +1450,36 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
14221450 // Helper function to indicate whether the last lookup found the aligned
14231451 // allocation function.
14241452 ImplicitAllocationParameters IAP = {
1425- typeAwareAllocationModeFromBool (S. getLangOpts (). TypeAwareAllocators ) ,
1453+ S. Context . VoidTy , TypeAwareAllocationMode::No ,
14261454 alignedAllocationModeFromBool (S.getLangOpts ().CoroAlignedAllocation )};
1427- auto LookupAllocationFunction = [&](Sema::AllocationFunctionScope NewScope =
1428- Sema::AFS_Both,
1429- bool WithoutPlacementArgs = false ,
1430- bool ForceNonAligned = false ) {
1431- // [dcl.fct.def.coroutine]p9
1432- // The allocation function's name is looked up by searching for it in
1433- // the
1434- // scope of the promise type .
1435- // - If any declarations are found, ...
1436- // - If no declarations are found in the scope of the promise type, a
1437- // search is performed in the global scope.
1438- if ( NewScope == Sema::AFS_Both)
1439- NewScope = PromiseContainsNew ? Sema::AFS_Class : Sema::AFS_Global;
1440-
1441- bool ShouldUseAlignedAlloc =
1442- !ForceNonAligned && S. getLangOpts (). CoroAlignedAllocation ;
1443- IAP = { typeAwareAllocationModeFromBool (S. getLangOpts (). TypeAwareAllocators ),
1444- alignedAllocationModeFromBool (ShouldUseAlignedAlloc)};
1445-
1446- FunctionDecl *UnusedResult = nullptr ;
1447-
1448- S. FindAllocationFunctions ( Loc, SourceRange (), NewScope,
1449- /* DeleteScope*/ Sema::AFS_Both, PromiseType,
1450- /* isArray*/ false , IAP,
1451- WithoutPlacementArgs ? MultiExprArg{}
1452- : PlacementArgs,
1453- OperatorNew, UnusedResult, /* Diagnose */ false );
1454- };
1455+ auto LookupAllocationFunction =
1456+ [&](Sema::AllocationFunctionScope NewScope = Sema::AFS_Both,
1457+ bool WithoutPlacementArgs = false , bool ForceNonAligned = false ) {
1458+ // [dcl.fct.def.coroutine]p9
1459+ // The allocation function's name is looked up by searching for it in
1460+ // the
1461+ // scope of the promise type.
1462+ // - If any declarations are found, .. .
1463+ // - If no declarations are found in the scope of the promise type, a
1464+ // search is performed in the global scope.
1465+ if (NewScope == Sema::AFS_Both)
1466+ NewScope = PromiseContainsNew ? Sema::AFS_Class : Sema::AFS_Global;
1467+
1468+ bool ShouldUseAlignedAlloc =
1469+ !ForceNonAligned && S. getLangOpts (). CoroAlignedAllocation ;
1470+ IAP = {S. Context . VoidTy , TypeAwareAllocationMode::No,
1471+ alignedAllocationModeFromBool (ShouldUseAlignedAlloc)};
1472+
1473+ FunctionDecl *UnusedResult = nullptr ;
1474+
1475+ S. FindAllocationFunctions (
1476+ Loc, SourceRange (), NewScope,
1477+ /* DeleteScope*/ Sema::AFS_Both, PromiseType,
1478+ /* isArray*/ false , IAP,
1479+ WithoutPlacementArgs ? MultiExprArg{} : PlacementArgs, OperatorNew,
1480+ UnusedResult, /* Diagnose */ false );
1481+ assert (! OperatorNew || !OperatorNew-> isTypeAwareOperatorNewOrDelete () );
1482+ };
14551483
14561484 // We don't expect to call to global operator new with (size, p0, …, pn).
14571485 // So if we choose to lookup the allocation function in global scope, we
@@ -1537,15 +1565,22 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
15371565 }
15381566
15391567 if (!OperatorNew) {
1540- if (PromiseContainsNew)
1568+ if (PromiseContainsNew) {
15411569 S.Diag (Loc, diag::err_coroutine_unusable_new) << PromiseType << &FD;
1542- else if (RequiresNoThrowAlloc)
1570+ DiagnoseTypeAwareAllocatorsIfNecessary (
1571+ S, Loc, diag::note_coroutine_unusable_type_aware_allocators, NewName,
1572+ PromiseType);
1573+ } else if (RequiresNoThrowAlloc)
15431574 S.Diag (Loc, diag::err_coroutine_unfound_nothrow_new)
15441575 << &FD << S.getLangOpts ().CoroAlignedAllocation ;
15451576
15461577 return false ;
15471578 }
15481579
1580+ DiagnoseTypeAwareAllocatorsIfNecessary (
1581+ S, Loc, diag::warn_coroutine_type_aware_allocator_ignored, NewName,
1582+ PromiseType);
1583+
15491584 if (RequiresNoThrowAlloc) {
15501585 const auto *FT = OperatorNew->getType ()->castAs <FunctionProtoType>();
15511586 if (!FT->isNothrow (/* ResultIfDependent*/ false )) {
0 commit comments