forked from OSchip/llvm-project
Check for overflow and signedness problems with template
arguments. Eliminates a FIXME. llvm-svn: 66993
This commit is contained in:
parent
9a46804ca8
commit
52aba87df7
|
@ -604,6 +604,12 @@ 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_negative, ERROR,
|
||||
"non-type template argument provides negative value '%0' for unsigned "
|
||||
"template parameter of type %1")
|
||||
DIAG(err_template_arg_too_large, ERROR,
|
||||
"non-type template argument value '%0' is too large for template "
|
||||
"parameter 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,
|
||||
|
|
|
@ -1266,16 +1266,42 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
return true;
|
||||
}
|
||||
|
||||
// FIXME: Check overflow of template arguments?
|
||||
QualType IntegerType = Context.getCanonicalType(ParamType);
|
||||
if (const EnumType *Enum = IntegerType->getAsEnumType())
|
||||
IntegerType = Enum->getDecl()->getIntegerType();
|
||||
|
||||
if (!Arg->isValueDependent()) {
|
||||
// Check that an unsigned parameter does not receive a negative
|
||||
// value.
|
||||
if (IntegerType->isUnsignedIntegerType()
|
||||
&& (Value.isSigned() && Value.isNegative())) {
|
||||
Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_negative)
|
||||
<< Value.toString(10) << Param->getType()
|
||||
<< Arg->getSourceRange();
|
||||
Diag(Param->getLocation(), diag::note_template_param_here);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check that we don't overflow the template parameter type.
|
||||
unsigned AllowedBits = Context.getTypeSize(IntegerType);
|
||||
if (Value.getActiveBits() > AllowedBits) {
|
||||
Diag(Arg->getSourceRange().getBegin(),
|
||||
diag::err_template_arg_too_large)
|
||||
<< Value.toString(10) << Param->getType()
|
||||
<< Arg->getSourceRange();
|
||||
Diag(Param->getLocation(), diag::note_template_param_here);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Value.getBitWidth() != AllowedBits)
|
||||
Value.extOrTrunc(AllowedBits);
|
||||
Value.setIsSigned(IntegerType->isSignedIntegerType());
|
||||
}
|
||||
|
||||
if (Converted) {
|
||||
// Add the value of this argument to the list of converted
|
||||
// arguments. We use the bitwidth and signedness of the template
|
||||
// parameter.
|
||||
QualType IntegerType = Context.getCanonicalType(ParamType);
|
||||
if (const EnumType *Enum = IntegerType->getAsEnumType())
|
||||
IntegerType = Enum->getDecl()->getIntegerType();
|
||||
|
||||
if (Arg->isValueDependent()) {
|
||||
// The argument is value-dependent. Create a new
|
||||
// TemplateArgument with the converted expression.
|
||||
|
@ -1283,11 +1309,6 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
return false;
|
||||
}
|
||||
|
||||
unsigned ExpectedBits = Context.getTypeSize(IntegerType);
|
||||
if (Value.getBitWidth() != ExpectedBits)
|
||||
Value.extOrTrunc(ExpectedBits);
|
||||
Value.setIsSigned(IntegerType->isSignedIntegerType());
|
||||
|
||||
Converted->push_back(TemplateArgument(StartLoc, Value,
|
||||
Context.getCanonicalType(IntegerType)));
|
||||
}
|
||||
|
|
|
@ -102,3 +102,13 @@ A7<&Z::int_member> *a18_1;
|
|||
A7c<&Z::int_member> *a18_2;
|
||||
A7<&Z::float_member> *a18_3; // expected-error{{non-type template argument of type 'float struct Z::*' cannot be converted to a value of type 'int struct Z::*'}}
|
||||
A7c<(&Z::int_member)> *a18_3; // expected-error{{non-type template argument cannot be surrounded by parentheses}}
|
||||
|
||||
template<unsigned char C> struct Overflow; // expected-note{{template parameter is declared here}}
|
||||
|
||||
Overflow<5> *overflow1; // okay
|
||||
Overflow<256> *overflow2; // expected-error{{non-type template argument value '256' is too large for template parameter of type 'unsigned char'}}
|
||||
|
||||
|
||||
template<unsigned> struct Signedness; // expected-note{{template parameter is declared here}}
|
||||
Signedness<10> *signedness1; // okay
|
||||
Signedness<-10> *signedness2; // expected-error{{non-type template argument provides negative value '-10' for unsigned template parameter of type 'unsigned int'}}
|
||||
|
|
Loading…
Reference in New Issue