forked from OSchip/llvm-project
Semantic checking for template arguments that correspond to non-type
template parameters that have reference type. Effectively, we're doing a very limited form of reference binding here. llvm-svn: 64270
This commit is contained in:
parent
081e354f11
commit
a9faa44162
|
@ -531,6 +531,11 @@ DIAG(err_template_arg_not_ice, ERROR,
|
|||
"non-type template argument of type %0 is not an integral constant expression")
|
||||
DIAG(err_template_arg_not_convertible, ERROR,
|
||||
"non-type template argument of type %0 cannot be converted to a value of type %1")
|
||||
DIAG(err_template_arg_no_ref_bind, ERROR,
|
||||
"non-type template parameter of reference type %0 cannot bind to template argument of type %1")
|
||||
DIAG(err_template_arg_ref_bind_ignores_quals, ERROR,
|
||||
"reference binding of non-type template parameter of type %0 to template argument of type %1 ignores qualifiers")
|
||||
|
||||
|
||||
DIAG(err_unexpected_typedef, ERROR,
|
||||
"unexpected type name %0: expected expression")
|
||||
|
|
|
@ -897,10 +897,10 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
}
|
||||
|
||||
if (const PointerType *ParamPtrType = ParamType->getAsPointerType()) {
|
||||
// -- for a non-type template-parameter of type pointer to
|
||||
// object, qualification conversions (4.4) and the
|
||||
// array-to-pointer conversion (4.2) are applied.
|
||||
if (ParamPtrType->getPointeeType()->isObjectType()) {
|
||||
// -- for a non-type template-parameter of type pointer to
|
||||
// object, qualification conversions (4.4) and the
|
||||
// array-to-pointer conversion (4.2) are applied.
|
||||
if (ArgType->isArrayType()) {
|
||||
ArgType = Context.getArrayDecayedType(ArgType);
|
||||
ImpCastExprToType(Arg, ArgType);
|
||||
|
@ -960,6 +960,43 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (const ReferenceType *ParamRefType = ParamType->getAsReferenceType()) {
|
||||
if (ParamRefType->getPointeeType()->isObjectType()) {
|
||||
// -- For a non-type template-parameter of type reference to
|
||||
// object, no conversions apply. The type referred to by the
|
||||
// reference may be more cv-qualified than the (otherwise
|
||||
// identical) type of the template-argument. The
|
||||
// template-parameter is bound directly to the
|
||||
// template-argument, which must be an lvalue.
|
||||
if (!hasSameUnqualifiedType(ParamRefType->getPointeeType(), ArgType)) {
|
||||
Diag(Arg->getSourceRange().getBegin(),
|
||||
diag::err_template_arg_no_ref_bind)
|
||||
<< Param->getType() << Arg->getType()
|
||||
<< Arg->getSourceRange();
|
||||
Diag(Param->getLocation(), diag::note_template_param_here);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned ParamQuals
|
||||
= Context.getCanonicalType(ParamType).getCVRQualifiers();
|
||||
unsigned ArgQuals = Context.getCanonicalType(ArgType).getCVRQualifiers();
|
||||
|
||||
if ((ParamQuals | ArgQuals) != ParamQuals) {
|
||||
Diag(Arg->getSourceRange().getBegin(),
|
||||
diag::err_template_arg_ref_bind_ignores_quals)
|
||||
<< Param->getType() << Arg->getType()
|
||||
<< Arg->getSourceRange();
|
||||
Diag(Param->getLocation(), diag::note_template_param_here);
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: Check the restrictions in p1!
|
||||
// CheckAddressConstantExpression(Lvalue) can be modified to do
|
||||
// this.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: p5 has a lot more checks to perform!
|
||||
|
||||
return false;
|
||||
|
|
|
@ -67,3 +67,15 @@ A3<g> *a14_7; // expected-error{{non-type template argument of type '<overloaded
|
|||
// FIXME: expected-error{{expected unqualified-id}}
|
||||
// FIXME: the first error includes the string <overloaded function
|
||||
// type>, which makes Doug slightly unhappy.
|
||||
|
||||
|
||||
struct Y { } y;
|
||||
|
||||
volatile X * X_volatile_ptr;
|
||||
template<X const &AnX> struct A4; // expected-note 2{{template parameter is declared here}}
|
||||
A4<*X_ptr> *a15_1; // okay
|
||||
A4<*X_volatile_ptr> *a15_2; // expected-error{{reference binding of non-type template parameter of type 'class X const &' to template argument of type 'class X volatile' ignores qualifiers}} \
|
||||
// FIXME: expected-error{{expected unqualified-id}}
|
||||
A4<y> *15_3; // expected-error{{non-type template parameter of reference type 'class X const &' cannot bind to template argument of type 'struct Y'}}\
|
||||
// FIXME: expected-error{{expected unqualified-id}}
|
||||
|
||||
|
|
Loading…
Reference in New Issue