================ @@ -16327,79 +16531,181 @@ static CanQualType RemoveAddressSpaceFromPtr(Sema &SemaRef, PtrTy->getPointeeType().getUnqualifiedType(), PtrQuals))); } -static inline bool -CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, - CanQualType ExpectedResultType, - CanQualType ExpectedFirstParamType, - unsigned DependentParamTypeDiag, - unsigned InvalidParamTypeDiag) { - QualType ResultType = - FnDecl->getType()->castAs<FunctionType>()->getReturnType(); +enum class AllocationOperatorKind { New, Delete }; + +static bool IsPotentiallyTypeAwareOperatorNewOrDelete(Sema &SemaRef, + const FunctionDecl *FD, + bool *WasMalformed) { + const Decl *MalformedDecl = nullptr; + if (FD->getNumParams() > 0 && + SemaRef.isStdTypeIdentity(FD->getParamDecl(0)->getType(), + /*TypeArgument=*/nullptr, &MalformedDecl)) + return true; - if (SemaRef.getLangOpts().OpenCLCPlusPlus) { - // The operator is valid on any address space for OpenCL. - // Drop address space from actual and expected result types. - if (const auto *PtrTy = ResultType->getAs<PointerType>()) - ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); + if (!MalformedDecl) + return false; + + if (WasMalformed) + *WasMalformed = true; + + // SemaRef.Diag(MalformedDecl->getLocation(), + // diag::err_malformed_std_class_template) << "type_identity"; + return true; +} + +static bool isDestroyingDeleteT(QualType Type) { + auto *RD = Type->getAsCXXRecordDecl(); + return RD && RD->isInStdNamespace() && RD->getIdentifier() && + RD->getIdentifier()->isStr("destroying_delete_t"); +} + +static bool IsPotentiallyDestroyingOperatorDelete(Sema &SemaRef, + const FunctionDecl *FD) { + // C++ P0722: + // Within a class C, a single object deallocation function with signature + // (T, std::destroying_delete_t, <more params>) + // is a destroying operator delete. + bool IsPotentiallyTypeAware = IsPotentiallyTypeAwareOperatorNewOrDelete( + SemaRef, FD, /*WasMalformed=*/nullptr); + unsigned DestroyingDeleteIdx = IsPotentiallyTypeAware + /* address */ 1; + return isa<CXXMethodDecl>(FD) && FD->getOverloadedOperator() == OO_Delete && + FD->getNumParams() > DestroyingDeleteIdx && + isDestroyingDeleteT(FD->getParamDecl(DestroyingDeleteIdx)->getType()); +} + +static inline bool CheckOperatorNewDeleteTypes( + Sema &SemaRef, FunctionDecl *FnDecl, AllocationOperatorKind OperatorKind, + CanQualType ExpectedResultType, CanQualType ExpectedSizeOrAddressParamType, + unsigned DependentParamTypeDiag, unsigned InvalidParamTypeDiag) { + auto NormalizeType = [&SemaRef](QualType T) { + if (SemaRef.getLangOpts().OpenCLCPlusPlus) { + // The operator is valid on any address space for OpenCL. + // Drop address space from actual and expected result types. + if (const auto PtrTy = T->template getAs<PointerType>()) + T = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); + } + return SemaRef.Context.getCanonicalType(T); + }; - if (auto ExpectedPtrTy = ExpectedResultType->getAs<PointerType>()) - ExpectedResultType = RemoveAddressSpaceFromPtr(SemaRef, ExpectedPtrTy); + const unsigned NumParams = FnDecl->getNumParams(); + unsigned FirstNonTypeParam = 0; + bool MalformedTypeIdentity = false; + bool IsPotentiallyTypeAware = IsPotentiallyTypeAwareOperatorNewOrDelete( + SemaRef, FnDecl, &MalformedTypeIdentity); + unsigned MinimumMandatoryArgumentCount = 1; + unsigned SizeParameterIndex = 0; + if (IsPotentiallyTypeAware) { + if (!FnDecl->isTemplateInstantiation()) { + unsigned DiagID = SemaRef.getLangOpts().CPlusPlus26 + ? diag::warn_cxx26_type_aware_allocators + : diag::ext_cxx26_type_aware_allocators; + SemaRef.Diag(FnDecl->getLocation(), DiagID); + } + + if (OperatorKind == AllocationOperatorKind::New) { + SizeParameterIndex = 1; + MinimumMandatoryArgumentCount = + FunctionDecl::RequiredTypeAwareNewParameterCount; + } else { + SizeParameterIndex = 2; + MinimumMandatoryArgumentCount = + FunctionDecl::RequiredTypeAwareDeleteParameterCount; + } + FirstNonTypeParam = 1; } + bool IsPotentiallyDestroyingDelete = + IsPotentiallyDestroyingOperatorDelete(SemaRef, FnDecl); + + if (IsPotentiallyDestroyingDelete) { + ++MinimumMandatoryArgumentCount; + ++SizeParameterIndex; + } + + if (NumParams < MinimumMandatoryArgumentCount) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_too_few_parameters) + << IsPotentiallyTypeAware << IsPotentiallyDestroyingDelete + << FnDecl->getDeclName() << MinimumMandatoryArgumentCount; + + for (unsigned Idx = 0; Idx < MinimumMandatoryArgumentCount; ++Idx) { + const ParmVarDecl *ParamDecl = FnDecl->getParamDecl(Idx); + if (ParamDecl->hasDefaultArg()) + return SemaRef.Diag(FnDecl->getLocation(), ---------------- mizvekov wrote:
Ditto. https://github.com/llvm/llvm-project/pull/113510 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits