Check for overflow and signedness problems with template
arguments. Eliminates a FIXME.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66993 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 142cc45..fd1eaf0 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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)));
     }