pt.c (fold_non_dependent_expr_sfinae): Split out from...
authorJason Merrill <jason@redhat.com>
Mon, 6 Sep 2010 04:49:16 +0000 (00:49 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 6 Sep 2010 04:49:16 +0000 (00:49 -0400)
* pt.c (fold_non_dependent_expr_sfinae): Split out from...
(fold_non_dependent_expr): ...here.
(convert_nontype_argument): Use it.  Take complain parm.
Use perform_implicit_conversion instead of ocp_convert.
Allow cv-qual changes.
(convert_template_argument): Pass complain down.
(tsubst_template_arg): Suppress constant expression warnings.
Don't fold here.

From-SVN: r163895

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/char1.C
gcc/testsuite/g++.dg/template/nontype10.C
gcc/testsuite/g++.dg/template/sfinae25.C [new file with mode: 0644]

index 357464f9c67c8c11e9462af126519599e993d25a..9fe9ef0db897cf9751e0acca841824fa700afb0d 100644 (file)
@@ -1,5 +1,14 @@
 2010-09-06  Jason Merrill  <jason@redhat.com>
 
+       * pt.c (fold_non_dependent_expr_sfinae): Split out from...
+       (fold_non_dependent_expr): ...here.
+       (convert_nontype_argument): Use it.  Take complain parm.
+       Use perform_implicit_conversion instead of ocp_convert.
+       Allow cv-qual changes.
+       (convert_template_argument): Pass complain down.
+       (tsubst_template_arg): Suppress constant expression warnings.
+       Don't fold here.
+
        * method.c (synthesized_method_walk): In constructors, also check
        subobject destructors.
 
index 759e22f66791971ce31bf867900e58714a98a59f..eb47ac41600af981620ff35b640b6ea7fe3f5a09 100644 (file)
@@ -131,7 +131,7 @@ static int type_unification_real (tree, tree, tree, const tree *,
                                  unsigned int, int, unification_kind_t, int);
 static void note_template_header (int);
 static tree convert_nontype_argument_function (tree, tree);
-static tree convert_nontype_argument (tree, tree);
+static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
 static tree convert_template_argument (tree, tree, tree,
                                       tsubst_flags_t, int, tree);
 static int for_each_template_parm (tree, tree_fn_t, void*,
@@ -4800,8 +4800,8 @@ redeclare_class_template (tree type, tree parms)
 /* Simplify EXPR if it is a non-dependent expression.  Returns the
    (possibly simplified) expression.  */
 
-tree
-fold_non_dependent_expr (tree expr)
+static tree
+fold_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
 {
   if (expr == NULL_TREE)
     return NULL_TREE;
@@ -4823,7 +4823,7 @@ fold_non_dependent_expr (tree expr)
       processing_template_decl = 0;
       expr = tsubst_copy_and_build (expr,
                                    /*args=*/NULL_TREE,
-                                   tf_error,
+                                   complain,
                                    /*in_decl=*/NULL_TREE,
                                    /*function_p=*/false,
                                    /*integral_constant_expression_p=*/true);
@@ -4832,6 +4832,12 @@ fold_non_dependent_expr (tree expr)
   return expr;
 }
 
+tree
+fold_non_dependent_expr (tree expr)
+{
+  return fold_non_dependent_expr_sfinae (expr, tf_error);
+}
+
 /* EXPR is an expression which is used in a constant-expression context.
    For instance, it could be a VAR_DECL with a constant initializer.
    Extract the innermost constant expression.
@@ -4960,7 +4966,7 @@ has_value_dependent_address (tree op)
    hacks can go away after we fix the double coercion problem.  */
 
 static tree
-convert_nontype_argument (tree type, tree expr)
+convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 {
   tree expr_type;
 
@@ -4969,11 +4975,13 @@ convert_nontype_argument (tree type, tree expr)
      catch this later), but only to provide better diagnostic for this
      common user mistake. As suggested by DR 100, we do not mention
      linkage issues in the diagnostic as this is not the point.  */
+  /* FIXME we're making this OK.  */
   if (TREE_CODE (expr) == STRING_CST)
     {
-      error ("%qE is not a valid template argument for type %qT "
-            "because string literals can never be used in this context",
-            expr, type);
+      if (complain & tf_error)
+       error ("%qE is not a valid template argument for type %qT "
+              "because string literals can never be used in this context",
+              expr, type);
       return NULL_TREE;
     }
 
@@ -4992,8 +5000,8 @@ convert_nontype_argument (tree type, tree expr)
   if (TYPE_REF_OBJ_P (type)
       && has_value_dependent_address (expr))
     /* If we want the address and it's value-dependent, don't fold.  */;
-  else
-    expr = fold_non_dependent_expr (expr);
+  else if (!type_unknown_p (expr))
+    expr = fold_non_dependent_expr_sfinae (expr, complain);
   if (error_operand_p (expr))
     return error_mark_node;
   expr_type = TREE_TYPE (expr);
@@ -5061,15 +5069,16 @@ convert_nontype_argument (tree type, tree expr)
         do not fold into integer constants.  */
       if (TREE_CODE (expr) != INTEGER_CST)
        {
-         error ("%qE is not a valid template argument for type %qT "
-                "because it is a non-constant expression", expr, type);
+         if (complain & tf_error)
+           error ("%qE is not a valid template argument for type %qT "
+                  "because it is a non-constant expression", expr, type);
          return NULL_TREE;
        }
 
       /* At this point, an implicit conversion does what we want,
         because we already know that the expression is of integral
         type.  */
-      expr = ocp_convert (type, expr, CONV_IMPLICIT, LOOKUP_PROTECT);
+      expr = perform_implicit_conversion (type, expr, complain);
       if (expr == error_mark_node)
        return error_mark_node;
 
@@ -5319,7 +5328,8 @@ convert_nontype_argument (tree type, tree expr)
 
   /* Sanity check: did we actually convert the argument to the
      right type?  */
-  gcc_assert (same_type_p (type, TREE_TYPE (expr)));
+  gcc_assert (same_type_ignoring_top_level_qualifiers_p
+             (type, TREE_TYPE (expr)));
   return expr;
 }
 
@@ -5784,7 +5794,7 @@ convert_template_argument (tree parm,
           conversions can occur is part of determining which
           function template to call, or whether a given explicit
           argument specification is valid.  */
-       val = convert_nontype_argument (t, orig_arg);
+       val = convert_nontype_argument (t, orig_arg, complain);
       else
        val = orig_arg;
 
@@ -8270,9 +8280,12 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     r = tsubst (t, args, complain, in_decl);
   else
     {
+      if (!(complain & tf_warning))
+       ++c_inhibit_evaluation_warnings;
       r = tsubst_expr (t, args, complain, in_decl,
                       /*integral_constant_expression_p=*/true);
-      r = fold_non_dependent_expr (r);
+      if (!(complain & tf_warning))
+       --c_inhibit_evaluation_warnings;
     }
   return r;
 }
index e723af418ba9837eadf41a90e3ede2419ee7e8fc..8cfc06e06a3d552d4c947f301662e596cb0734d0 100644 (file)
@@ -1,5 +1,9 @@
 2010-09-06  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/template/sfinae25.C: New.
+       * g++.dg/template/char1.C: Expect warning.
+       * g++.dg/template/nontype10.C: Likewise.
+
        * g++.dg/cpp0x/implicit9.C: New.
 
        * g++.dg/cpp0x/initlist43.C: New.
index 64ffda8fd367985136cd34c46bf4dcd5c2910a35..c440577e808625bfd4e28465a9489df6ae5a979d 100644 (file)
@@ -1,4 +1,4 @@
 template <class CharType, CharType line_terminator = 0>
 class String {};
 
-String<char, 255> s;
+String<char, 255> s;           // { dg-warning "overflow" }
index cd3a3aabd7f8ae173c13c94407ef275a0c291f9c..83ac8e3026f3c421fa62950a2f8d0e246f8d9e6e 100644 (file)
@@ -5,6 +5,6 @@
 template <int  T> struct A {};
 template <void* T> struct B {};
 
-A<NULL> a;
+A<NULL> a;                     // { dg-warning "NULL" }
 B<NULL> b;  // { dg-error "" }
 
diff --git a/gcc/testsuite/g++.dg/template/sfinae25.C b/gcc/testsuite/g++.dg/template/sfinae25.C
new file mode 100644 (file)
index 0000000..e9ee83e
--- /dev/null
@@ -0,0 +1,14 @@
+template <int I>
+struct A { };
+
+template <int J>
+void f(A<1/J>);
+
+template <int J>
+void f(...) { }
+
+int main()
+{
+  f<0>();
+}
+