Skip to content

Commit 08fcf03

Browse files
committed
Start addressing r4 changes following EWG approval
1 parent b1e665d commit 08fcf03

File tree

2 files changed

+62
-34
lines changed

2 files changed

+62
-34
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9768,25 +9768,25 @@ def err_operator_new_delete_invalid_result_type : Error<
97689768
def err_operator_new_delete_dependent_result_type : Error<
97699769
"%0 cannot have a dependent return type; use %1 instead">;
97709770
def err_operator_new_delete_too_few_parameters : Error<
9771-
"%0 must have at least one parameter">;
9771+
"%select{|type aware }0%1 must have at least %select{|one|two|three|four}2 parameter%s2">;
97729772
def err_operator_new_delete_template_too_few_parameters : Error<
97739773
"%0 template must have at least two parameters">;
97749774
def warn_operator_new_returns_null : Warning<
97759775
"%0 should not return a null pointer unless it is declared 'throw()'"
97769776
"%select{| or 'noexcept'}1">, InGroup<OperatorNewReturnsNull>;
97779777

97789778
def err_operator_new_dependent_param_type : Error<
9779-
"%select{|type aware}1 %0 cannot take a dependent type as %select{first|second}1 parameter; "
9780-
"use size_t (%2) instead">;
9779+
"%select{|type aware }0%1 cannot take a dependent type as %select{first|second|third|fourth}2 parameter; "
9780+
"use %4 (%3) instead">;
97819781
def err_operator_new_param_type : Error<
9782-
"%select{|type aware}1 %0 takes type size_t (%2) as %select{first|second}1 parameter">;
9782+
"%select{|type aware }0%1 takes type %4 (%3) as %select{first|second|third|fourth}2 parameter">;
97839783
def err_operator_new_default_arg: Error<
97849784
"parameter of %0 cannot have a default argument">;
97859785
def err_operator_delete_dependent_param_type : Error<
9786-
"%select{|type aware}1 %0 cannot take a dependent type as %select{first|second}1 parameter; "
9787-
"use %2 instead">;
9786+
"%select{|type aware }0%1 cannot take a dependent type as %select{first|second|third|fourth}2 parameter; "
9787+
"use %3 instead">;
97889788
def err_operator_delete_param_type : Error<
9789-
"%select{first|second}1 parameter of%select{|type aware}1 %0 must have type %2">;
9789+
"%select{first|second|third|fourth}2 parameter of%select{| type aware}0 %1 must have type %3">;
97909790
def err_destroying_operator_delete_not_usual : Error<
97919791
"destroying operator delete can have only an optional size and optional "
97929792
"alignment parameter">;

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
1635416360
static 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

1642516453
static 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

Comments
 (0)