diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-03-25 22:21:04 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-03-25 22:21:04 +0000 |
commit | 684d096c204c5eef29c10777bce890400d235d8c (patch) | |
tree | a7e3f7f7e3f10eecec39df906746c0aa8368e140 /lib/Sema/SemaTemplate.cpp | |
parent | eab5d1eaaa662c849f1f9920dc8c6a31d7c32d47 (diff) |
Warn when the conversion of an integral non-type template argument to
the type of its corresponding non-type template parameter changes the
value. Previously, we were diagnosing this as an error, which was
wrong. We give reasonably nice warnings like:
test/SemaTemplate/temp_arg_nontype.cpp:100:10: warning: non-type template
argument value '256' truncated to '0' for template parameter of type
'unsigned char'
Overflow<256> *overflow3; // expected-warning{{non-type template ...
^~~
test/SemaTemplate/temp_arg_nontype.cpp:96:24: note: template parameter is
declared here
template<unsigned char C> struct Overflow;
^
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99561 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 39 |
1 files changed, 20 insertions, 19 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5a1bec927c..0102aefa7e 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2554,38 +2554,39 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType()); if (!Arg->isValueDependent()) { - // Check that an unsigned parameter does not receive a negative - // value. + llvm::APSInt OldValue = Value; + + // Coerce the template argument's value to the value it will have + // based on the template parameter's type. + unsigned AllowedBits = Context.getTypeSize(IntegerType); + Value.setIsSigned(IntegerType->isSignedIntegerType()); + if (Value.getBitWidth() != AllowedBits) + Value.extOrTrunc(AllowedBits); + + // Complain if an unsigned parameter received a negative value. if (IntegerType->isUnsignedIntegerType() - && (Value.isSigned() && Value.isNegative())) { - Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_negative) - << Value.toString(10) << Param->getType() + && (OldValue.isSigned() && OldValue.isNegative())) { + Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative) + << OldValue.toString(10) << 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); + // Complain if we overflowed the template parameter's type. unsigned RequiredBits; if (IntegerType->isUnsignedIntegerType()) - RequiredBits = Value.getActiveBits(); - else if (Value.isUnsigned()) - RequiredBits = Value.getActiveBits() + 1; + RequiredBits = OldValue.getActiveBits(); + else if (OldValue.isUnsigned()) + RequiredBits = OldValue.getActiveBits() + 1; else - RequiredBits = Value.getMinSignedBits(); + RequiredBits = OldValue.getMinSignedBits(); if (RequiredBits > AllowedBits) { Diag(Arg->getSourceRange().getBegin(), - diag::err_template_arg_too_large) - << Value.toString(10) << Param->getType() + diag::warn_template_arg_too_large) + << OldValue.toString(10) << 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()); } // Add the value of this argument to the list of converted |