PR c++/79092 - non-type args of different types are different
authorJason Merrill <jason@redhat.com>
Thu, 16 Nov 2017 20:13:48 +0000 (15:13 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 16 Nov 2017 20:13:48 +0000 (15:13 -0500)
* tree.c (cp_tree_equal): Check the type of constants.
* pt.c (unify) [TEMPLATE_PARM_INDEX]: Handle UNIFY_ALLOW_INTEGER
when comparing to previously deduced argument.
(maybe_convert_nontype_argument): New.
(convert_nontype_argument): Call it.
(tsubst_copy_and_build): Handle partial instantiation of
IMPLICIT_CONV_EXPR.
(unify): Ignore type when deducing from array bound.
(dependent_type_p_r): Handle DEFERRED_NOEXCEPT.
(value_dependent_expression_p): Any type-dependent expression is
value-dependent.  Handle IMPLICIT_CONV_EXPR.
* cp-tree.h (IMPLICIT_CONV_EXPR_NONTYPE_ARG): New.
* mangle.c (write_template_arg): Strip IMPLICIT_CONV_EXPR.

From-SVN: r254843

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/cpp1z/nontype-auto12.C [new file with mode: 0644]

index 9ceff2f397e759b735b4da18fd32b0163b1f336b..e0bb1b1ddd43c4538f83e53ffa6bf8aeadeace30 100644 (file)
@@ -1,3 +1,20 @@
+2017-11-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/79092 - non-type args of different types are different
+       * tree.c (cp_tree_equal): Check the type of constants.
+       * pt.c (unify) [TEMPLATE_PARM_INDEX]: Handle UNIFY_ALLOW_INTEGER
+       when comparing to previously deduced argument.
+       (maybe_convert_nontype_argument): New.
+       (convert_nontype_argument): Call it.
+       (tsubst_copy_and_build): Handle partial instantiation of
+       IMPLICIT_CONV_EXPR.
+       (unify): Ignore type when deducing from array bound.
+       (dependent_type_p_r): Handle DEFERRED_NOEXCEPT.
+       (value_dependent_expression_p): Any type-dependent expression is
+       value-dependent.  Handle IMPLICIT_CONV_EXPR.
+       * cp-tree.h (IMPLICIT_CONV_EXPR_NONTYPE_ARG): New.
+       * mangle.c (write_template_arg): Strip IMPLICIT_CONV_EXPR.
+
 2017-11-16  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/82836
index c6554162078d514ba4241ebab747d63ad749e3db..1c19c3d31f82a847a7141a2e750b5a3a162bad7f 100644 (file)
@@ -382,6 +382,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       TINFO_USED_TEMPLATE_ID (in TEMPLATE_INFO)
       PACK_EXPANSION_SIZEOF_P (in *_PACK_EXPANSION)
       OVL_USING_P (in OVERLOAD)
+      IMPLICIT_CONV_EXPR_NONTYPE_ARG (in IMPLICIT_CONV_EXPR)
    2: IDENTIFIER_KIND_BIT_2 (in IDENTIFIER_NODE)
       ICS_THIS_FLAG (in _CONV)
       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
@@ -4126,6 +4127,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \
   (TREE_LANG_FLAG_0 (IMPLICIT_CONV_EXPR_CHECK (NODE)))
 
+/* True if NODE represents a dependent conversion of a non-type template
+   argument.  Set by maybe_convert_nontype_argument.  */
+#define IMPLICIT_CONV_EXPR_NONTYPE_ARG(NODE) \
+  (TREE_LANG_FLAG_1 (IMPLICIT_CONV_EXPR_CHECK (NODE)))
+
 /* Nonzero means that an object of this type can not be initialized using
    an initializer list.  */
 #define CLASSTYPE_NON_AGGREGATE(NODE) \
index 050055bd26cec0c0f5d5f5f82b01f0b9007a0191..6d4e59101ee3bdb26bd17c787140ff99b2d59cff 100644 (file)
@@ -2836,7 +2836,7 @@ write_expression (tree expr)
   while (CONVERT_EXPR_CODE_P (code)
         /* Parentheses aren't mangled.  */
         || code == PAREN_EXPR
-        || TREE_CODE (expr) == NON_LVALUE_EXPR)
+        || code == NON_LVALUE_EXPR)
     {
       expr = TREE_OPERAND (expr, 0);
       code = TREE_CODE (expr);
@@ -3407,6 +3407,9 @@ write_template_arg (tree node)
        }
     }
 
+  /* Strip a conversion added by convert_nontype_argument.  */
+  if (TREE_CODE (node) == IMPLICIT_CONV_EXPR)
+    node = TREE_OPERAND (node, 0);
   if (REFERENCE_REF_P (node))
     node = TREE_OPERAND (node, 0);
   if (TREE_CODE (node) == NOP_EXPR
index 562b9272596195d35376d9f8475e6f75f57bea7c..2b70969999e00e38516e18bdeb7650a428973a0c 100644 (file)
@@ -7519,6 +7519,31 @@ convert_wildcard_argument (tree parm, tree arg)
   return arg;
 }
 
+/* We can't fully resolve ARG given as a non-type template argument to TYPE,
+   because one of them is dependent.  But we need to represent the
+   conversion for the benefit of cp_tree_equal.  */
+
+static tree
+maybe_convert_nontype_argument (tree type, tree arg)
+{
+  /* Auto parms get no conversion.  */
+  if (type_uses_auto (type))
+    return arg;
+  /* We don't need or want to add this conversion now if we're going to use the
+     argument for deduction.  */
+  if (value_dependent_expression_p (arg))
+    return arg;
+
+  type = cv_unqualified (type);
+  tree argtype = TREE_TYPE (arg);
+  if (same_type_p (type, argtype))
+    return arg;
+
+  arg = build1 (IMPLICIT_CONV_EXPR, type, arg);
+  IMPLICIT_CONV_EXPR_NONTYPE_ARG (arg) = true;
+  return arg;
+}
+
 /* Convert the indicated template ARG as necessary to match the
    indicated template PARM.  Returns the converted ARG, or
    error_mark_node if the conversion was unsuccessful.  Error and
@@ -7774,7 +7799,11 @@ convert_template_argument (tree parm,
           argument specification is valid.  */
        val = convert_nontype_argument (t, orig_arg, complain);
       else
-       val = canonicalize_expr_argument (orig_arg, complain);
+       {
+         val = canonicalize_expr_argument (orig_arg, complain);
+         val = maybe_convert_nontype_argument (t, val);
+       }
+
 
       if (val == NULL_TREE)
        val = error_mark_node;
@@ -17097,6 +17126,17 @@ tsubst_copy_and_build (tree t,
       {
        tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
        tree expr = RECUR (TREE_OPERAND (t, 0));
+       if (dependent_type_p (type) || type_dependent_expression_p (expr))
+         {
+           retval = copy_node (t);
+           TREE_TYPE (retval) = type;
+           TREE_OPERAND (retval, 0) = expr;
+           RETURN (retval);
+         }
+       if (IMPLICIT_CONV_EXPR_NONTYPE_ARG (t))
+         /* We'll pass this to convert_nontype_argument again, we don't need
+            to actually perform any conversion here.  */
+         RETURN (expr);
        int flags = LOOKUP_IMPLICIT;
        if (IMPLICIT_CONV_EXPR_DIRECT_INIT (t))
          flags = LOOKUP_NORMAL;
@@ -20886,6 +20926,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 
       if (targ)
        {
+         if ((strict & UNIFY_ALLOW_INTEGER)
+             && TREE_TYPE (targ) && TREE_TYPE (arg)
+             && CP_INTEGRAL_TYPE_P (TREE_TYPE (targ)))
+           /* We're deducing from an array bound, the type doesn't matter.  */
+           arg = fold_convert (TREE_TYPE (targ), arg);
          int x = !cp_tree_equal (targ, arg);
          if (x)
            unify_inconsistency (explain_p, parm, targ, arg);
@@ -23704,13 +23749,15 @@ dependent_type_p_r (tree type)
        if (dependent_type_p (TREE_VALUE (arg_type)))
          return true;
       if (cxx_dialect >= cxx17)
-       {
-         /* A value-dependent noexcept-specifier makes the type dependent.  */
-         tree spec = TYPE_RAISES_EXCEPTIONS (type);
-         if (spec && TREE_PURPOSE (spec)
-             && value_dependent_expression_p (TREE_PURPOSE (spec)))
-           return true;
-       }
+       /* A value-dependent noexcept-specifier makes the type dependent.  */
+       if (tree spec = TYPE_RAISES_EXCEPTIONS (type))
+         if (tree noex = TREE_PURPOSE (spec))
+           /* Treat DEFERRED_NOEXCEPT as non-dependent, since it doesn't
+              affect overload resolution and treating it as dependent breaks
+              things.  */
+           if (TREE_CODE (noex) != DEFERRED_NOEXCEPT
+               && value_dependent_expression_p (noex))
+             return true;
       return false;
     }
   /* -- an array type constructed from any dependent type or whose
@@ -23875,8 +23922,8 @@ value_dependent_expression_p (tree expression)
   if (!processing_template_decl || expression == NULL_TREE)
     return false;
 
-  /* A name declared with a dependent type.  */
-  if (DECL_P (expression) && type_dependent_expression_p (expression))
+  /* A type-dependent expression is also value-dependent.  */
+  if (type_dependent_expression_p (expression))
     return true;
 
   switch (TREE_CODE (expression))
@@ -23918,13 +23965,12 @@ value_dependent_expression_p (tree expression)
          && (TREE_CODE (DECL_INITIAL (expression)) == TREE_LIST
              /* cp_finish_decl doesn't fold reference initializers.  */
              || TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE
-             || type_dependent_expression_p (DECL_INITIAL (expression))
              || value_dependent_expression_p (DECL_INITIAL (expression))))
        return true;
       if (DECL_HAS_VALUE_EXPR_P (expression))
        {
          tree value_expr = DECL_VALUE_EXPR (expression);
-         if (type_dependent_expression_p (value_expr))
+         if (value_dependent_expression_p (value_expr))
            return true;
        }
       return false;
@@ -23934,6 +23980,7 @@ value_dependent_expression_p (tree expression)
     case CONST_CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
     case CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
       /* These expressions are value-dependent if the type to which
         the cast occurs is dependent or the expression being casted
         is value-dependent.  */
@@ -24078,10 +24125,7 @@ value_dependent_expression_p (tree expression)
       }
 
     case TEMPLATE_ID_EXPR:
-      /* If a TEMPLATE_ID_EXPR involves a dependent name, it will be
-        type-dependent.  */
-      return type_dependent_expression_p (expression)
-       || variable_concept_p (TREE_OPERAND (expression, 0));
+      return variable_concept_p (TREE_OPERAND (expression, 0));
 
     case CONSTRUCTOR:
       {
index c60d54ab01fb498d1b030a0f2fd5a51db01c3598..245657866dfd9b3c3cecfd284f3c5e366cf62bc5 100644 (file)
@@ -3494,6 +3494,10 @@ cp_tree_equal (tree t1, tree t2)
   if (code1 != code2)
     return false;
 
+  if (CONSTANT_CLASS_P (t1)
+      && !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+    return false;
+
   switch (code1)
     {
     case VOID_CST:
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype-auto12.C b/gcc/testsuite/g++.dg/cpp1z/nontype-auto12.C
new file mode 100644 (file)
index 0000000..7bff75c
--- /dev/null
@@ -0,0 +1,6 @@
+// PR c++/79092
+// { dg-options -std=c++17 }
+
+template<auto V> struct val {};
+
+struct type : val<0>, val<0u> {};