forked from OSchip/llvm-project
PR31081: ignore exception specifications when deducing function template
arguments from a declaration; despite what the standard says, this form of deduction should not be considering exception specifications. llvm-svn: 288301
This commit is contained in:
parent
b66cb88c2e
commit
baa4783d31
|
@ -6515,7 +6515,12 @@ public:
|
||||||
// C++ Template Argument Deduction (C++ [temp.deduct])
|
// C++ Template Argument Deduction (C++ [temp.deduct])
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
|
||||||
QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType);
|
/// Adjust the type \p ArgFunctionType to match the calling convention,
|
||||||
|
/// noreturn, and optionally the exception specification of \p FunctionType.
|
||||||
|
/// Deduction often wants to ignore these properties when matching function
|
||||||
|
/// types.
|
||||||
|
QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType,
|
||||||
|
bool AdjustExceptionSpec = false);
|
||||||
|
|
||||||
/// \brief Describes the result of template argument deduction.
|
/// \brief Describes the result of template argument deduction.
|
||||||
///
|
///
|
||||||
|
@ -6624,7 +6629,7 @@ public:
|
||||||
QualType ArgFunctionType,
|
QualType ArgFunctionType,
|
||||||
FunctionDecl *&Specialization,
|
FunctionDecl *&Specialization,
|
||||||
sema::TemplateDeductionInfo &Info,
|
sema::TemplateDeductionInfo &Info,
|
||||||
bool InOverloadResolution = false);
|
bool IsAddressOfFunction = false);
|
||||||
|
|
||||||
TemplateDeductionResult
|
TemplateDeductionResult
|
||||||
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
|
@ -6637,7 +6642,7 @@ public:
|
||||||
TemplateArgumentListInfo *ExplicitTemplateArgs,
|
TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||||
FunctionDecl *&Specialization,
|
FunctionDecl *&Specialization,
|
||||||
sema::TemplateDeductionInfo &Info,
|
sema::TemplateDeductionInfo &Info,
|
||||||
bool InOverloadResolution = false);
|
bool IsAddressOfFunction = false);
|
||||||
|
|
||||||
/// \brief Substitute Replacement for \p auto in \p TypeWithAuto
|
/// \brief Substitute Replacement for \p auto in \p TypeWithAuto
|
||||||
QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
|
QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
|
||||||
|
|
|
@ -2319,8 +2319,6 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
||||||
// To perform this comparison, we compute the function type that
|
// To perform this comparison, we compute the function type that
|
||||||
// the deallocation function should have, and use that type both
|
// the deallocation function should have, and use that type both
|
||||||
// for template argument deduction and for comparison purposes.
|
// for template argument deduction and for comparison purposes.
|
||||||
//
|
|
||||||
// FIXME: this comparison should ignore CC and the like.
|
|
||||||
QualType ExpectedFunctionType;
|
QualType ExpectedFunctionType;
|
||||||
{
|
{
|
||||||
const FunctionProtoType *Proto
|
const FunctionProtoType *Proto
|
||||||
|
@ -2334,7 +2332,6 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
||||||
FunctionProtoType::ExtProtoInfo EPI;
|
FunctionProtoType::ExtProtoInfo EPI;
|
||||||
// FIXME: This is not part of the standard's rule.
|
// FIXME: This is not part of the standard's rule.
|
||||||
EPI.Variadic = Proto->isVariadic();
|
EPI.Variadic = Proto->isVariadic();
|
||||||
EPI.ExceptionSpec.Type = EST_BasicNoexcept;
|
|
||||||
|
|
||||||
ExpectedFunctionType
|
ExpectedFunctionType
|
||||||
= Context.getFunctionType(Context.VoidTy, ArgTypes, EPI);
|
= Context.getFunctionType(Context.VoidTy, ArgTypes, EPI);
|
||||||
|
@ -2344,8 +2341,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
||||||
DEnd = FoundDelete.end();
|
DEnd = FoundDelete.end();
|
||||||
D != DEnd; ++D) {
|
D != DEnd; ++D) {
|
||||||
FunctionDecl *Fn = nullptr;
|
FunctionDecl *Fn = nullptr;
|
||||||
if (FunctionTemplateDecl *FnTmpl
|
if (FunctionTemplateDecl *FnTmpl =
|
||||||
= dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
|
dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) {
|
||||||
// Perform template argument deduction to try to match the
|
// Perform template argument deduction to try to match the
|
||||||
// expected function type.
|
// expected function type.
|
||||||
TemplateDeductionInfo Info(StartLoc);
|
TemplateDeductionInfo Info(StartLoc);
|
||||||
|
@ -2355,7 +2352,10 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
|
||||||
} else
|
} else
|
||||||
Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
|
Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
|
||||||
|
|
||||||
if (Context.hasSameType(Fn->getType(), ExpectedFunctionType))
|
if (Context.hasSameType(adjustCCAndNoReturn(Fn->getType(),
|
||||||
|
ExpectedFunctionType,
|
||||||
|
/*AdjustExcpetionSpec*/true),
|
||||||
|
ExpectedFunctionType))
|
||||||
Matches.push_back(std::make_pair(D.getPair(), Fn));
|
Matches.push_back(std::make_pair(D.getPair(), Fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10572,7 +10572,7 @@ private:
|
||||||
= S.DeduceTemplateArguments(FunctionTemplate,
|
= S.DeduceTemplateArguments(FunctionTemplate,
|
||||||
&OvlExplicitTemplateArgs,
|
&OvlExplicitTemplateArgs,
|
||||||
TargetFunctionType, Specialization,
|
TargetFunctionType, Specialization,
|
||||||
Info, /*InOverloadResolution=*/true)) {
|
Info, /*IsAddressOfFunction*/true)) {
|
||||||
// Make a note of the failed deduction for diagnostics.
|
// Make a note of the failed deduction for diagnostics.
|
||||||
FailedCandidates.addCandidate()
|
FailedCandidates.addCandidate()
|
||||||
.set(CurAccessFunPair, FunctionTemplate->getTemplatedDecl(),
|
.set(CurAccessFunPair, FunctionTemplate->getTemplatedDecl(),
|
||||||
|
@ -10975,7 +10975,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
|
||||||
if (TemplateDeductionResult Result
|
if (TemplateDeductionResult Result
|
||||||
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
|
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
|
||||||
Specialization, Info,
|
Specialization, Info,
|
||||||
/*InOverloadResolution=*/true)) {
|
/*IsAddressOfFunction*/true)) {
|
||||||
// Make a note of the failed deduction for diagnostics.
|
// Make a note of the failed deduction for diagnostics.
|
||||||
// TODO: Actually use the failed-deduction info?
|
// TODO: Actually use the failed-deduction info?
|
||||||
FailedCandidates.addCandidate()
|
FailedCandidates.addCandidate()
|
||||||
|
|
|
@ -8075,7 +8075,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
||||||
NamedDecl *Prev = *P;
|
NamedDecl *Prev = *P;
|
||||||
if (!HasExplicitTemplateArgs) {
|
if (!HasExplicitTemplateArgs) {
|
||||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
|
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) {
|
||||||
QualType Adjusted = adjustCCAndNoReturn(R, Method->getType());
|
QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(),
|
||||||
|
/*AdjustExceptionSpec*/true);
|
||||||
if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
|
if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
|
||||||
Matches.clear();
|
Matches.clear();
|
||||||
|
|
||||||
|
|
|
@ -3571,25 +3571,42 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
|
||||||
}
|
}
|
||||||
|
|
||||||
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
|
QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
|
||||||
QualType FunctionType) {
|
QualType FunctionType,
|
||||||
|
bool AdjustExceptionSpec) {
|
||||||
if (ArgFunctionType.isNull())
|
if (ArgFunctionType.isNull())
|
||||||
return ArgFunctionType;
|
return ArgFunctionType;
|
||||||
|
|
||||||
const FunctionProtoType *FunctionTypeP =
|
const FunctionProtoType *FunctionTypeP =
|
||||||
FunctionType->castAs<FunctionProtoType>();
|
FunctionType->castAs<FunctionProtoType>();
|
||||||
CallingConv CC = FunctionTypeP->getCallConv();
|
|
||||||
bool NoReturn = FunctionTypeP->getNoReturnAttr();
|
|
||||||
const FunctionProtoType *ArgFunctionTypeP =
|
const FunctionProtoType *ArgFunctionTypeP =
|
||||||
ArgFunctionType->getAs<FunctionProtoType>();
|
ArgFunctionType->getAs<FunctionProtoType>();
|
||||||
if (ArgFunctionTypeP->getCallConv() == CC &&
|
|
||||||
ArgFunctionTypeP->getNoReturnAttr() == NoReturn)
|
FunctionProtoType::ExtProtoInfo EPI = ArgFunctionTypeP->getExtProtoInfo();
|
||||||
|
bool Rebuild = false;
|
||||||
|
|
||||||
|
CallingConv CC = FunctionTypeP->getCallConv();
|
||||||
|
if (EPI.ExtInfo.getCC() != CC) {
|
||||||
|
EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC);
|
||||||
|
Rebuild = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NoReturn = FunctionTypeP->getNoReturnAttr();
|
||||||
|
if (EPI.ExtInfo.getNoReturn() != NoReturn) {
|
||||||
|
EPI.ExtInfo = EPI.ExtInfo.withNoReturn(NoReturn);
|
||||||
|
Rebuild = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AdjustExceptionSpec && (FunctionTypeP->hasExceptionSpec() ||
|
||||||
|
ArgFunctionTypeP->hasExceptionSpec())) {
|
||||||
|
EPI.ExceptionSpec = FunctionTypeP->getExtProtoInfo().ExceptionSpec;
|
||||||
|
Rebuild = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Rebuild)
|
||||||
return ArgFunctionType;
|
return ArgFunctionType;
|
||||||
|
|
||||||
FunctionType::ExtInfo EI = ArgFunctionTypeP->getExtInfo().withCallingConv(CC);
|
return Context.getFunctionType(ArgFunctionTypeP->getReturnType(),
|
||||||
EI = EI.withNoReturn(NoReturn);
|
ArgFunctionTypeP->getParamTypes(), EPI);
|
||||||
ArgFunctionTypeP =
|
|
||||||
cast<FunctionProtoType>(Context.adjustFunctionType(ArgFunctionTypeP, EI));
|
|
||||||
return QualType(ArgFunctionTypeP, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Deduce template arguments when taking the address of a function
|
/// \brief Deduce template arguments when taking the address of a function
|
||||||
|
@ -3614,14 +3631,17 @@ QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType,
|
||||||
/// \param Info the argument will be updated to provide additional information
|
/// \param Info the argument will be updated to provide additional information
|
||||||
/// about template argument deduction.
|
/// about template argument deduction.
|
||||||
///
|
///
|
||||||
|
/// \param IsAddressOfFunction If \c true, we are deducing as part of taking
|
||||||
|
/// the address of a function template per [temp.deduct.funcaddr] and
|
||||||
|
/// [over.over]. If \c false, we are looking up a function template
|
||||||
|
/// specialization based on its signature, per [temp.deduct.decl].
|
||||||
|
///
|
||||||
/// \returns the result of template argument deduction.
|
/// \returns the result of template argument deduction.
|
||||||
Sema::TemplateDeductionResult
|
Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
|
||||||
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
FunctionTemplateDecl *FunctionTemplate,
|
||||||
TemplateArgumentListInfo *ExplicitTemplateArgs,
|
TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType,
|
||||||
QualType ArgFunctionType,
|
FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
|
||||||
FunctionDecl *&Specialization,
|
bool IsAddressOfFunction) {
|
||||||
TemplateDeductionInfo &Info,
|
|
||||||
bool InOverloadResolution) {
|
|
||||||
if (FunctionTemplate->isInvalidDecl())
|
if (FunctionTemplate->isInvalidDecl())
|
||||||
return TDK_Invalid;
|
return TDK_Invalid;
|
||||||
|
|
||||||
|
@ -3629,8 +3649,13 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
TemplateParameterList *TemplateParams
|
TemplateParameterList *TemplateParams
|
||||||
= FunctionTemplate->getTemplateParameters();
|
= FunctionTemplate->getTemplateParameters();
|
||||||
QualType FunctionType = Function->getType();
|
QualType FunctionType = Function->getType();
|
||||||
if (!InOverloadResolution)
|
|
||||||
ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType);
|
// When taking the address of a function, we require convertibility of
|
||||||
|
// the resulting function type. Otherwise, we allow arbitrary mismatches
|
||||||
|
// of calling convention, noreturn, and noexcept.
|
||||||
|
if (!IsAddressOfFunction)
|
||||||
|
ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, FunctionType,
|
||||||
|
/*AdjustExceptionSpec*/true);
|
||||||
|
|
||||||
// Substitute any explicit template arguments.
|
// Substitute any explicit template arguments.
|
||||||
LocalInstantiationScope InstScope(*this);
|
LocalInstantiationScope InstScope(*this);
|
||||||
|
@ -3655,9 +3680,11 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
Deduced.resize(TemplateParams->size());
|
Deduced.resize(TemplateParams->size());
|
||||||
|
|
||||||
// If the function has a deduced return type, substitute it for a dependent
|
// If the function has a deduced return type, substitute it for a dependent
|
||||||
// type so that we treat it as a non-deduced context in what follows.
|
// type so that we treat it as a non-deduced context in what follows. If we
|
||||||
|
// are looking up by signature, the signature type should also have a deduced
|
||||||
|
// return type, which we instead expect to exactly match.
|
||||||
bool HasDeducedReturnType = false;
|
bool HasDeducedReturnType = false;
|
||||||
if (getLangOpts().CPlusPlus14 && InOverloadResolution &&
|
if (getLangOpts().CPlusPlus14 && IsAddressOfFunction &&
|
||||||
Function->getReturnType()->getContainedAutoType()) {
|
Function->getReturnType()->getContainedAutoType()) {
|
||||||
FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
|
FunctionType = SubstAutoType(FunctionType, Context.DependentTy);
|
||||||
HasDeducedReturnType = true;
|
HasDeducedReturnType = true;
|
||||||
|
@ -3665,7 +3692,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
|
|
||||||
if (!ArgFunctionType.isNull()) {
|
if (!ArgFunctionType.isNull()) {
|
||||||
unsigned TDF = TDF_TopLevelParameterTypeList;
|
unsigned TDF = TDF_TopLevelParameterTypeList;
|
||||||
if (InOverloadResolution) TDF |= TDF_InOverloadResolution;
|
if (IsAddressOfFunction)
|
||||||
|
TDF |= TDF_InOverloadResolution;
|
||||||
// Deduce template arguments from the function type.
|
// Deduce template arguments from the function type.
|
||||||
if (TemplateDeductionResult Result
|
if (TemplateDeductionResult Result
|
||||||
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
|
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
|
||||||
|
@ -3696,16 +3724,27 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
!ResolveExceptionSpec(Info.getLocation(), SpecializationFPT))
|
!ResolveExceptionSpec(Info.getLocation(), SpecializationFPT))
|
||||||
return TDK_MiscellaneousDeductionFailure;
|
return TDK_MiscellaneousDeductionFailure;
|
||||||
|
|
||||||
|
// Adjust the exception specification of the argument again to match the
|
||||||
|
// substituted and resolved type we just formed. (Calling convention and
|
||||||
|
// noreturn can't be dependent, so we don't actually need this for them
|
||||||
|
// right now.)
|
||||||
|
QualType SpecializationType = Specialization->getType();
|
||||||
|
if (!IsAddressOfFunction)
|
||||||
|
ArgFunctionType = adjustCCAndNoReturn(ArgFunctionType, SpecializationType,
|
||||||
|
/*AdjustExceptionSpec*/true);
|
||||||
|
|
||||||
// If the requested function type does not match the actual type of the
|
// If the requested function type does not match the actual type of the
|
||||||
// specialization with respect to arguments of compatible pointer to function
|
// specialization with respect to arguments of compatible pointer to function
|
||||||
// types, template argument deduction fails.
|
// types, template argument deduction fails.
|
||||||
if (!ArgFunctionType.isNull()) {
|
if (!ArgFunctionType.isNull()) {
|
||||||
if (InOverloadResolution && !isSameOrCompatibleFunctionType(
|
if (IsAddressOfFunction &&
|
||||||
Context.getCanonicalType(Specialization->getType()),
|
!isSameOrCompatibleFunctionType(
|
||||||
Context.getCanonicalType(ArgFunctionType)))
|
Context.getCanonicalType(SpecializationType),
|
||||||
|
Context.getCanonicalType(ArgFunctionType)))
|
||||||
return TDK_MiscellaneousDeductionFailure;
|
return TDK_MiscellaneousDeductionFailure;
|
||||||
else if(!InOverloadResolution &&
|
|
||||||
!Context.hasSameType(Specialization->getType(), ArgFunctionType))
|
if (!IsAddressOfFunction &&
|
||||||
|
!Context.hasSameType(SpecializationType, ArgFunctionType))
|
||||||
return TDK_MiscellaneousDeductionFailure;
|
return TDK_MiscellaneousDeductionFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3977,16 +4016,22 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *ConversionTemplate,
|
||||||
/// \param Info the argument will be updated to provide additional information
|
/// \param Info the argument will be updated to provide additional information
|
||||||
/// about template argument deduction.
|
/// about template argument deduction.
|
||||||
///
|
///
|
||||||
|
/// \param IsAddressOfFunction If \c true, we are deducing as part of taking
|
||||||
|
/// the address of a function template in a context where we do not have a
|
||||||
|
/// target type, per [over.over]. If \c false, we are looking up a function
|
||||||
|
/// template specialization based on its signature, which only happens when
|
||||||
|
/// deducing a function parameter type from an argument that is a template-id
|
||||||
|
/// naming a function template specialization.
|
||||||
|
///
|
||||||
/// \returns the result of template argument deduction.
|
/// \returns the result of template argument deduction.
|
||||||
Sema::TemplateDeductionResult
|
Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(
|
||||||
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
FunctionTemplateDecl *FunctionTemplate,
|
||||||
TemplateArgumentListInfo *ExplicitTemplateArgs,
|
TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||||
FunctionDecl *&Specialization,
|
FunctionDecl *&Specialization, TemplateDeductionInfo &Info,
|
||||||
TemplateDeductionInfo &Info,
|
bool IsAddressOfFunction) {
|
||||||
bool InOverloadResolution) {
|
|
||||||
return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
|
return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
|
||||||
QualType(), Specialization, Info,
|
QualType(), Specialization, Info,
|
||||||
InOverloadResolution);
|
IsAddressOfFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// RUN: %clang_cc1 -std=c++14 -verify %s
|
// RUN: %clang_cc1 -std=c++14 -verify -fexceptions -fcxx-exceptions %s
|
||||||
// RUN: %clang_cc1 -std=c++1z -verify %s
|
// RUN: %clang_cc1 -std=c++1z -verify -fexceptions -fcxx-exceptions %s
|
||||||
|
|
||||||
#if __cplusplus > 201402L
|
#if __cplusplus > 201402L
|
||||||
|
|
||||||
|
@ -106,3 +106,47 @@ namespace Builtins {
|
||||||
typedef int arr[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)];
|
typedef int arr[strcmp("bar", "foo") + 4 * strncmp("foo", "bar", 4)];
|
||||||
typedef int arr[3];
|
typedef int arr[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ExplicitInstantiation {
|
||||||
|
template<typename T> void f() noexcept {}
|
||||||
|
template<typename T> struct X { void f() noexcept {} };
|
||||||
|
template void f<int>();
|
||||||
|
template void X<int>::f();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ConversionFunction {
|
||||||
|
struct A { template<typename T> operator T() noexcept; };
|
||||||
|
int a = A().operator int();
|
||||||
|
}
|
||||||
|
|
||||||
|
using size_t = decltype(sizeof(0));
|
||||||
|
|
||||||
|
namespace OperatorDelete {
|
||||||
|
struct W {};
|
||||||
|
struct X {};
|
||||||
|
struct Y {};
|
||||||
|
struct Z {};
|
||||||
|
template<bool N, bool D> struct T {};
|
||||||
|
}
|
||||||
|
void *operator new(size_t, OperatorDelete::W) noexcept(false);
|
||||||
|
void operator delete(void*, OperatorDelete::W) noexcept(false) = delete; // expected-note {{here}}
|
||||||
|
void *operator new(size_t, OperatorDelete::X) noexcept(false);
|
||||||
|
void operator delete(void*, OperatorDelete::X) noexcept(true) = delete; // expected-note {{here}}
|
||||||
|
void *operator new(size_t, OperatorDelete::Y) noexcept(true);
|
||||||
|
void operator delete(void*, OperatorDelete::Y) noexcept(false) = delete; // expected-note {{here}}
|
||||||
|
void *operator new(size_t, OperatorDelete::Z) noexcept(true);
|
||||||
|
void operator delete(void*, OperatorDelete::Z) noexcept(true) = delete; // expected-note {{here}}
|
||||||
|
template<bool N, bool D> void *operator new(size_t, OperatorDelete::T<N, D>) noexcept(N);
|
||||||
|
template<bool N, bool D> void operator delete(void*, OperatorDelete::T<N, D>) noexcept(D) = delete; // expected-note 4{{here}}
|
||||||
|
namespace OperatorDelete {
|
||||||
|
struct A { A(); };
|
||||||
|
A *w = new (W{}) A; // expected-error {{deleted function}}
|
||||||
|
A *x = new (X{}) A; // expected-error {{deleted function}}
|
||||||
|
A *y = new (Y{}) A; // expected-error {{deleted function}}
|
||||||
|
A *z = new (Z{}) A; // expected-error {{deleted function}}
|
||||||
|
|
||||||
|
A *t00 = new (T<false, false>{}) A; // expected-error {{deleted function}}
|
||||||
|
A *t01 = new (T<false, true>{}) A; // expected-error {{deleted function}}
|
||||||
|
A *t10 = new (T<true, false>{}) A; // expected-error {{deleted function}}
|
||||||
|
A *t11 = new (T<true, true>{}) A; // expected-error {{deleted function}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue