[cfe-commits] r66993 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/SemaTemplate.cpp test/SemaTemplate/temp_arg_nontype.cpp
Douglas Gregor
dgregor at apple.com
Fri Mar 13 17:20:21 PDT 2009
Author: dgregor
Date: Fri Mar 13 19:20:21 2009
New Revision: 66993
URL: http://llvm.org/viewvc/llvm-project?rev=66993&view=rev
Log:
Check for overflow and signedness problems with template
arguments. Eliminates a FIXME.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=66993&r1=66992&r2=66993&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Fri Mar 13 19:20:21 2009
@@ -604,6 +604,12 @@
"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,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=66993&r1=66992&r2=66993&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Mar 13 19:20:21 2009
@@ -1266,16 +1266,42 @@
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 @@
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)));
}
Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp?rev=66993&r1=66992&r2=66993&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Fri Mar 13 19:20:21 2009
@@ -102,3 +102,13 @@
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'}}
More information about the cfe-commits
mailing list