[cfe-commits] r99561 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp test/SemaTemplate/temp_arg_nontype.cpp

Douglas Gregor dgregor at apple.com
Thu Mar 25 15:21:04 PDT 2010


Author: dgregor
Date: Thu Mar 25 17:21:04 2010
New Revision: 99561

URL: http://llvm.org/viewvc/llvm-project?rev=99561&view=rev
Log:
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;
                       ^


Added:
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=99561&r1=99560&r2=99561&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Mar 25 17:21:04 2010
@@ -1207,12 +1207,12 @@
 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 @@
   "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">;

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=99561&r1=99560&r2=99561&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Mar 25 17:21:04 2010
@@ -2554,38 +2554,39 @@
       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

Added: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp?rev=99561&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/p9.cpp Thu Mar 25 17:21:04 2010
@@ -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}}

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=99561&r1=99560&r2=99561&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Thu Mar 25 17:21:04 2010
@@ -97,21 +97,21 @@
 
 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;





More information about the cfe-commits mailing list