aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-03-26 02:38:37 +0000
committerDouglas Gregor <dgregor@apple.com>2010-03-26 02:38:37 +0000
commit1a6e03457ebafd6ac523cdcf5d6b6f411ea08772 (patch)
tree6823501bcfb35b2b780491276302e560d4ec6641
parentd7e29e114d20da5b83e0cb7bc29ec717a7458cb1 (diff)
Reinstate change to non-type template arguments of integral type, so
that we extend/truncate then correct the sign to convert the non-type template argument to the template parameter's type. Previously, we reported an error when the non-type template argument was out of range; now we just warn. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99600 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td14
-rw-r--r--lib/Sema/SemaTemplate.cpp39
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp6
-rw-r--r--test/SemaTemplate/temp_arg_nontype.cpp10
4 files changed, 38 insertions, 31 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 4b14595892..c6f20247fa 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1207,12 +1207,12 @@ def err_template_arg_not_ice : Error<
def err_template_arg_not_convertible : Error<
"non-type template argument of type %0 cannot be converted to a value "
"of type %1">;
-def err_template_arg_negative : Error<
- "non-type template argument provides negative value '%0' for unsigned "
- "template parameter of type %1">;
-def err_template_arg_too_large : Error<
- "non-type template argument value '%0' is too large for template "
- "parameter of type %1">;
+def warn_template_arg_negative : Warning<
+ "non-type template argument with value '%0' converted to '%1' for unsigned "
+ "template parameter of type %2">;
+def warn_template_arg_too_large : Warning<
+ "non-type template argument value '%0' truncated to '%1' for "
+ "template parameter of type %2">;
def err_template_arg_no_ref_bind : Error<
"non-type template parameter of reference type %0 cannot bind to template "
"argument of type %1">;
@@ -1379,7 +1379,7 @@ def note_default_function_arg_instantiation_here : Note<
"for '%0' required here">;
def note_explicit_template_arg_substitution_here : Note<
"while substituting explicitly-specified template arguments into function "
- "template %f, here">;
+ "template %0, here">;
def note_function_template_deduction_instantiation_here : Note<
"while substituting deduced template arguments into function template %0, "
"here">;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 5a1bec927c..ba9e3c7df9 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);
+ if (Value.getBitWidth() != AllowedBits)
+ Value.extOrTrunc(AllowedBits);
+ Value.setIsSigned(IntegerType->isSignedIntegerType());
+
+ // 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
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp
new file mode 100644
index 0000000000..634da7d1c2
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template <int> int f(int); // expected-note 2{{candidate}}
+template <signed char> int f(int); // expected-note 2{{candidate}}
+int i1 = f<1>(0); // expected-error{{ambiguous}}
+int i2 = f<1000>(0); // expected-error{{ambiguous}}
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
index 9c20f2a0eb..d077a35930 100644
--- a/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -97,21 +97,21 @@ template<unsigned char C> struct Overflow; // expected-note{{template parameter
Overflow<5> *overflow1; // okay
Overflow<255> *overflow2; // okay
-Overflow<256> *overflow3; // expected-error{{non-type template argument value '256' is too large for template parameter of type 'unsigned char'}}
+Overflow<256> *overflow3; // expected-warning{{non-type template argument value '256' truncated to '0' 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'}}
+Signedness<-10> *signedness2; // expected-warning{{non-type template argument with value '-10' converted to '4294967286' for unsigned template parameter of type 'unsigned int'}}
template<signed char C> struct SignedOverflow; // expected-note 3 {{template parameter is declared here}}
SignedOverflow<1> *signedoverflow1;
SignedOverflow<-1> *signedoverflow2;
SignedOverflow<-128> *signedoverflow3;
-SignedOverflow<-129> *signedoverflow4; // expected-error{{non-type template argument value '-129' is too large for template parameter of type 'signed char'}}
+SignedOverflow<-129> *signedoverflow4; // expected-warning{{non-type template argument value '-129' truncated to '127' for template parameter of type 'signed char'}}
SignedOverflow<127> *signedoverflow5;
-SignedOverflow<128> *signedoverflow6; // expected-error{{non-type template argument value '128' is too large for template parameter of type 'signed char'}}
-SignedOverflow<(unsigned char)128> *signedoverflow7; // expected-error{{non-type template argument value '128' is too large for template parameter of type 'signed char'}}
+SignedOverflow<128> *signedoverflow6; // expected-warning{{non-type template argument value '128' truncated to '-128' for template parameter of type 'signed char'}}
+SignedOverflow<(unsigned char)128> *signedoverflow7; // expected-warning{{non-type template argument value '128' truncated to '-128' for template parameter of type 'signed char'}}
// Check canonicalization of template arguments.
template<int (*)(int, int)> struct FuncPtr0;