@@ -16351,10 +16351,17 @@ static CanQualType RemoveAddressSpaceFromPtr(Sema &SemaRef,
1635116351 PtrTy->getPointeeType().getUnqualifiedType(), PtrQuals)));
1635216352}
1635316353
16354+
16355+ enum class AllocationOperatorKind {
16356+ New,
16357+ Delete
16358+ };
16359+
1635416360static inline bool CheckOperatorNewDeleteTypes(
16355- Sema &SemaRef, const FunctionDecl *FnDecl, CanQualType ExpectedResultType,
16356- CanQualType ExpectedFirstParamType, unsigned DependentParamTypeDiag,
16357- unsigned InvalidParamTypeDiag, unsigned *MinimumNonDefaultArgs) {
16361+ Sema &SemaRef, const FunctionDecl *FnDecl, AllocationOperatorKind OperatorKind,
16362+ CanQualType ExpectedResultType, CanQualType ExpectedFirstParamType,
16363+ unsigned DependentParamTypeDiag, unsigned InvalidParamTypeDiag,
16364+ unsigned *MinimumNonDefaultArgs) {
1635816365 auto NormalizeType = [&SemaRef](QualType T) {
1635916366 if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
1636016367 // The operator is valid on any address space for OpenCL.
@@ -16366,13 +16373,22 @@ static inline bool CheckOperatorNewDeleteTypes(
1636616373 };
1636716374
1636816375 unsigned FirstNonTypeParam = 0;
16369- if (FnDecl->isTypeAwareOperatorNewOrDelete()) {
16376+ bool IsTypeAware = FnDecl->isTypeAwareOperatorNewOrDelete();
16377+ unsigned MinimumMandatoryArgumentCount = 1;
16378+ unsigned SizeParameterIndex = 0;
16379+ if (IsTypeAware) {
1637016380 if (!SemaRef.getLangOpts().TypeAwareAllocators) {
1637116381 return SemaRef.Diag(FnDecl->getLocation(),
1637216382 diag::err_unsupported_type_aware_allocator);
1637316383 }
16384+ if (OperatorKind == AllocationOperatorKind::New)
16385+ SizeParameterIndex = 1;
16386+ else
16387+ SizeParameterIndex = 2;
1637416388 ++FirstNonTypeParam;
16389+ MinimumMandatoryArgumentCount = SizeParameterIndex + 2;
1637516390 }
16391+ *MinimumNonDefaultArgs = MinimumMandatoryArgumentCount;
1637616392
1637716393 auto *FnType = FnDecl->getType()->castAs<FunctionType>();
1637816394 QualType CanResultType = NormalizeType(FnType->getReturnType());
@@ -16397,29 +16413,41 @@ static inline bool CheckOperatorNewDeleteTypes(
1639716413 diag::err_operator_new_delete_template_too_few_parameters)
1639816414 << FnDecl->getDeclName();
1639916415
16400- // The function decl must have at least 1 parameter.
16401- if (FnDecl->getNumParams() <= FirstNonTypeParam)
16416+ if (FnDecl->getNumParams() < MinimumMandatoryArgumentCount)
1640216417 return SemaRef.Diag(FnDecl->getLocation(),
1640316418 diag::err_operator_new_delete_too_few_parameters)
16404- << FnDecl->getDeclName();
16405-
16406- QualType FirstParamType =
16407- NormalizeType(FnDecl->getParamDecl(FirstNonTypeParam)->getType());
16419+ << IsTypeAware << FnDecl->getDeclName() << MinimumMandatoryArgumentCount;
16420+
16421+ auto CheckType = [&](unsigned ParamIdx, QualType ExpectedType, auto FallbackType) -> bool {
16422+ if (ExpectedType.isNull()) {
16423+ return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
16424+ << IsTypeAware << FnDecl->getDeclName() << ParamIdx << FallbackType;
16425+ }
16426+ CanQualType CanExpectedTy =
16427+ NormalizeType(SemaRef.Context.getCanonicalType(ExpectedType));
16428+ auto ActualParamType =
16429+ NormalizeType(FnDecl->getParamDecl(ParamIdx)->getType().getUnqualifiedType());
16430+ if (ActualParamType == CanExpectedTy)
16431+ return false;
16432+ unsigned Diagnostic =
16433+ ActualParamType->isDependentType() ? DependentParamTypeDiag : InvalidParamTypeDiag;
16434+ return SemaRef.Diag(FnDecl->getLocation(), Diagnostic)
16435+ << IsTypeAware << FnDecl->getDeclName() << ParamIdx << ExpectedType << FallbackType;
16436+ };
1640816437
1640916438 // Check that the first parameter type is what we expect.
16410- if (FirstParamType.getUnqualifiedType() != CanExpectedFirstParamType) {
16411- // The first parameter type is not allowed to be dependent. As a tentative
16412- // DR resolution, we allow a dependent parameter type if it is the right
16413- // type anyway, to allow destroying operator delete in class templates.
16414- return SemaRef.Diag(FnDecl->getLocation(), FirstParamType->isDependentType()
16415- ? DependentParamTypeDiag
16416- : InvalidParamTypeDiag)
16417- << FnDecl->getDeclName() << FirstNonTypeParam
16418- << ExpectedFirstParamType;
16419- }
16420-
16421- *MinimumNonDefaultArgs = FirstNonTypeParam + 1;
16422- return false;
16439+ if (CheckType(FirstNonTypeParam, CanExpectedFirstParamType, "size_t"))
16440+ return true;
16441+
16442+ if (!IsTypeAware)
16443+ return false;
16444+
16445+ if (CheckType(SizeParameterIndex, SemaRef.Context.getSizeType(), "size_t"))
16446+ return true;
16447+ TypeDecl *StdAlignValTDecl = SemaRef.getStdAlignValT();
16448+ QualType StdAlignValT = StdAlignValTDecl ?
16449+ SemaRef.Context.getTypeDeclType(StdAlignValTDecl) : QualType();
16450+ return CheckType(SizeParameterIndex + 1, StdAlignValT, "std::align_val_t");
1642316451}
1642416452
1642516453static bool
@@ -16439,11 +16467,11 @@ CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
1643916467 // The return type shall be void*. The first parameter shall have type
1644016468 // std::size_t.
1644116469 if (CheckOperatorNewDeleteTypes(
16442- SemaRef, FnDecl, SemaRef.Context.VoidPtrTy, SizeTy,
16470+ SemaRef, FnDecl, AllocationOperatorKind::New, SemaRef.Context.VoidPtrTy, SizeTy,
1644316471 diag::err_operator_new_dependent_param_type,
1644416472 diag::err_operator_new_param_type, &MinimumNonDefaultArgs))
1644516473 return true;
16446- assert(MinimumNonDefaultArgs > 0 && MinimumNonDefaultArgs <= 2 );
16474+ assert(MinimumNonDefaultArgs > 0 && MinimumNonDefaultArgs <= 4 );
1644716475 // C++ [basic.stc.dynamic.allocation]p1:
1644816476 // The first parameter shall not have an associated default argument.
1644916477 for (unsigned Idx = 0; Idx < MinimumNonDefaultArgs; ++Idx) {
@@ -16482,12 +16510,12 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
1648216510 // C++ [basic.stc.dynamic.deallocation]p2:
1648316511 // Each deallocation function shall return void
1648416512 if (CheckOperatorNewDeleteTypes(
16485- SemaRef, FnDecl, SemaRef.Context.VoidTy, ExpectedFirstParamType,
16513+ SemaRef, FnDecl, AllocationOperatorKind::Delete, SemaRef.Context.VoidTy, ExpectedFirstParamType,
1648616514 diag::err_operator_delete_dependent_param_type,
1648716515 diag::err_operator_delete_param_type, &MinimumNonDefaultArgs))
1648816516 return true;
1648916517
16490- assert(MinimumNonDefaultArgs > 0 && MinimumNonDefaultArgs <= 2 );
16518+ assert(MinimumNonDefaultArgs > 0 && MinimumNonDefaultArgs <= 4 );
1649116519 // C++ P0722:
1649216520 // A destroying operator delete shall be a usual deallocation function.
1649316521 if (MD && !MD->getParent()->isDependentContext() &&
0 commit comments