Fix the overflow calculation in Sema::CheckTemplateArgument to be a bit more
accurate.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92018 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index e6bd77d..3dd0243 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2488,7 +2488,14 @@
 
       // Check that we don't overflow the template parameter type.
       unsigned AllowedBits = Context.getTypeSize(IntegerType);
-      if (Value.getActiveBits() > AllowedBits) {
+      unsigned RequiredBits;
+      if (IntegerType->isUnsignedIntegerType())
+        RequiredBits = Value.getActiveBits();
+      else if (Value.isUnsigned())
+        RequiredBits = Value.getActiveBits() + 1;
+      else
+        RequiredBits = Value.getMinSignedBits();
+      if (RequiredBits > AllowedBits) {
         Diag(Arg->getSourceRange().getBegin(),
              diag::err_template_arg_too_large)
           << Value.toString(10) << Param->getType()
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
index 98e0b5d..133b8db 100644
--- a/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -105,13 +105,23 @@
 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'}}
+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'}}
 
 
 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'}}
 
+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<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'}}
+
 // Check canonicalization of template arguments.
 template<int (*)(int, int)> struct FuncPtr0;
 int func0(int, int);