@@ -16422,8 +16422,8 @@ enum class AllocationOperatorKind { New, Delete };
1642216422static inline bool CheckOperatorNewDeleteTypes(
1642316423 Sema &SemaRef, const FunctionDecl *FnDecl,
1642416424 AllocationOperatorKind OperatorKind, CanQualType ExpectedResultType,
16425- CanQualType ExpectedFirstParamType , unsigned DependentParamTypeDiag,
16426- unsigned InvalidParamTypeDiag, unsigned *MinimumNonDefaultArgs ) {
16425+ CanQualType ExpectedSizeOrAddressParamType , unsigned DependentParamTypeDiag,
16426+ unsigned InvalidParamTypeDiag) {
1642716427 auto NormalizeType = [&SemaRef](QualType T) {
1642816428 if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
1642916429 // The operator is valid on any address space for OpenCL.
@@ -16467,18 +16467,26 @@ static inline bool CheckOperatorNewDeleteTypes(
1646716467 ++MinimumMandatoryArgumentCount;
1646816468 ++SizeParameterIndex;
1646916469 }
16470- *MinimumNonDefaultArgs = MinimumMandatoryArgumentCount;
1647116470
1647216471 if (FnDecl->getNumParams() < MinimumMandatoryArgumentCount)
1647316472 return SemaRef.Diag(FnDecl->getLocation(),
1647416473 diag::err_operator_new_delete_too_few_parameters)
1647516474 << IsPotentiallyTypeAware << IsDestroyingDelete
1647616475 << FnDecl->getDeclName() << MinimumMandatoryArgumentCount;
1647716476
16477+ for (unsigned Idx = 0; Idx < MinimumMandatoryArgumentCount; ++Idx) {
16478+ const ParmVarDecl *ParamDecl = FnDecl->getParamDecl(Idx);
16479+ if (ParamDecl->hasDefaultArg())
16480+ return SemaRef.Diag(FnDecl->getLocation(),
16481+ diag::err_operator_new_default_arg)
16482+ << FnDecl->getDeclName() << Idx << ParamDecl->getDefaultArgRange();
16483+ }
16484+
1647816485 auto *FnType = FnDecl->getType()->castAs<FunctionType>();
1647916486 QualType CanResultType = NormalizeType(FnType->getReturnType());
1648016487 QualType CanExpectedResultType = NormalizeType(ExpectedResultType);
16481- QualType CanExpectedFirstParamType = NormalizeType(ExpectedFirstParamType);
16488+ QualType CanExpectedSizeOrAddressParamType =
16489+ NormalizeType(ExpectedSizeOrAddressParamType);
1648216490
1648316491 // Check that the result type is what we expect.
1648416492 if (CanResultType != CanExpectedResultType) {
@@ -16520,12 +16528,11 @@ static inline bool CheckOperatorNewDeleteTypes(
1652016528 };
1652116529
1652216530 // Check that the first parameter type is what we expect.
16523- if (CheckType(FirstNonTypeParam, CanExpectedFirstParamType , "size_t"))
16531+ if (CheckType(FirstNonTypeParam, CanExpectedSizeOrAddressParamType , "size_t"))
1652416532 return true;
1652516533
16526- // If the first parameter type is a type_identity specialization
16527- // we need to ensure the remaining mandatory parameters are present
16528- // and have the correct type
16534+ // If the first parameter type is not a type-identity we're done, otherwise
16535+ // we need to ensure the size and alignment parameters have the correct type
1652916536 if (!IsPotentiallyTypeAware)
1653016537 return false;
1653116538
@@ -16554,24 +16561,10 @@ CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
1655416561 // C++ [basic.stc.dynamic.allocation]p1:
1655516562 // The return type shall be void*. The first parameter shall have type
1655616563 // std::size_t.
16557- if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, AllocationOperatorKind::New,
16558- SemaRef.Context.VoidPtrTy, SizeTy,
16559- diag::err_operator_new_dependent_param_type,
16560- diag::err_operator_new_param_type,
16561- &MinimumNonDefaultArgs))
16562- return true;
16563- assert(MinimumNonDefaultArgs > 0 && MinimumNonDefaultArgs <= 4);
16564- // C++ [basic.stc.dynamic.allocation]p1:
16565- // The first parameter shall not have an associated default argument.
16566- for (unsigned Idx = 0; Idx < MinimumNonDefaultArgs; ++Idx) {
16567- const ParmVarDecl *ParamDecl = FnDecl->getParamDecl(Idx);
16568- if (ParamDecl->hasDefaultArg()) {
16569- return SemaRef.Diag(FnDecl->getLocation(),
16570- diag::err_operator_new_default_arg)
16571- << FnDecl->getDeclName() << Idx << ParamDecl->getDefaultArgRange();
16572- }
16573- }
16574- return false;
16564+ return CheckOperatorNewDeleteTypes(
16565+ SemaRef, FnDecl, AllocationOperatorKind::New, SemaRef.Context.VoidPtrTy,
16566+ SizeTy, diag::err_operator_new_dependent_param_type,
16567+ diag::err_operator_new_param_type);
1657516568}
1657616569
1657716570static bool
@@ -16590,20 +16583,12 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
1659016583 SemaRef.Context.getRecordType(MD->getParent())));
1659116584 };
1659216585
16593- // C++ P0722:
16594- // Within a class C, the first parameter of a destroying operator delete
16595- // shall be of type C *. The first parameter of any other deallocation
16596- // function shall be of type void *.
16597- CanQualType ExpectedFirstParamType =
16598- MD && MD->isDestroyingOperatorDelete()
16599- ? SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType(
16600- SemaRef.Context.getRecordType(MD->getParent())))
16601- : SemaRef.Context.VoidPtrTy;
16602-
1660316586 // C++ P2719: A destroying operator delete cannot be type aware
1660416587 // so as a QoL we actually check for this explicitly
16605- bool IsTypeAwareClassMethod = MD && MD->isTypeAwareOperatorNewOrDelete();
16606- if (IsTypeAwareClassMethod && MD->getNumParams() > 1) {
16588+ bool IsPotentiallyTypeAwareClassMethod =
16589+ MD && MD->getNumParams() > 0 &&
16590+ MD->getParamDecl(0)->getType()->isTypeIdentitySpecialization();
16591+ if (IsPotentiallyTypeAwareClassMethod) {
1660716592 QualType AddressParamType =
1660816593 SemaRef.Context.getCanonicalType(MD->getParamDecl(1)->getType());
1660916594 if (AddressParamType != SemaRef.Context.VoidPtrTy &&
@@ -16626,19 +16611,25 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
1662616611 }
1662716612 }
1662816613
16629- unsigned MinimumNonDefaultArgs = 0;
16614+ // C++ P0722:
16615+ // Within a class C, the first parameter of a destroying operator delete
16616+ // shall be of type C *. The first parameter of any other deallocation
16617+ // function shall be of type void *.
16618+ CanQualType ExpectedAddressParamType =
16619+ MD && MD->isDestroyingOperatorDelete()
16620+ ? SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType(
16621+ SemaRef.Context.getRecordType(MD->getParent())))
16622+ : SemaRef.Context.VoidPtrTy;
16623+
1663016624 // C++ [basic.stc.dynamic.deallocation]p2:
1663116625 // Each deallocation function shall return void
1663216626 if (CheckOperatorNewDeleteTypes(
1663316627 SemaRef, FnDecl, AllocationOperatorKind::Delete,
16634- SemaRef.Context.VoidTy, ExpectedFirstParamType ,
16628+ SemaRef.Context.VoidTy, ExpectedAddressParamType ,
1663516629 diag::err_operator_delete_dependent_param_type,
16636- diag::err_operator_delete_param_type, &MinimumNonDefaultArgs ))
16630+ diag::err_operator_delete_param_type))
1663716631 return true;
1663816632
16639- assert(MinimumNonDefaultArgs > 0 &&
16640- MinimumNonDefaultArgs <=
16641- FunctionDecl::RequiredTypeAwareDeleteParameterCount);
1664216633 // C++ P0722:
1664316634 // A destroying operator delete shall be a usual deallocation function.
1664416635 if (MD && !MD->getParent()->isDependentContext() &&
@@ -16649,14 +16640,6 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
1664916640 return true;
1665016641 }
1665116642 }
16652- for (unsigned Idx = 0; Idx < MinimumNonDefaultArgs; ++Idx) {
16653- const ParmVarDecl *ParamDecl = FnDecl->getParamDecl(Idx);
16654- if (ParamDecl->hasDefaultArg()) {
16655- return SemaRef.Diag(FnDecl->getLocation(),
16656- diag::err_operator_new_default_arg)
16657- << FnDecl->getDeclName() << ParamDecl->getDefaultArgRange();
16658- }
16659- }
1666016643
1666116644 return false;
1666216645}
0 commit comments