]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/cvt.c
Wrap option names in gcc internal messages with %< and %>.
[thirdparty/gcc.git] / gcc / cp / cvt.c
index 631ff49673f0d659c704343ec6f1285641f3d338..c10db92bd6f31ecf2aabf38025502bf62682fcbc 100644 (file)
@@ -1,5 +1,5 @@
 /* Language-level data type conversion for GNU C++.
-   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   Copyright (C) 1987-2019 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -33,6 +33,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "intl.h"
 #include "convert.h"
+#include "stringpool.h"
+#include "attribs.h"
 
 static tree convert_to_pointer_force (tree, tree, tsubst_flags_t);
 static tree build_type_conversion (tree, tree);
@@ -75,7 +77,7 @@ cp_convert_to_pointer (tree type, tree expr, bool dofold,
   tree intype = TREE_TYPE (expr);
   enum tree_code form;
   tree rval;
-  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+  location_t loc = cp_expr_loc_or_loc (expr, input_location);
 
   if (intype == error_mark_node)
     return error_mark_node;
@@ -120,7 +122,7 @@ cp_convert_to_pointer (tree type, tree expr, bool dofold,
 
   form = TREE_CODE (intype);
 
-  if (POINTER_TYPE_P (intype))
+  if (INDIRECT_TYPE_P (intype))
     {
       intype = TYPE_MAIN_VARIANT (intype);
 
@@ -234,8 +236,13 @@ cp_convert_to_pointer (tree type, tree expr, bool dofold,
       /* Modes may be different but sizes should be the same.  There
         is supposed to be some integral type that is the same width
         as a pointer.  */
-      gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
-                 == GET_MODE_SIZE (TYPE_MODE (type)));
+      gcc_assert (GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (expr)))
+                 == GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (type)));
+
+      /* FIXME needed because convert_to_pointer_maybe_fold still folds
+        conversion of constants.  */
+      if (!dofold)
+       return build1 (CONVERT_EXPR, type, expr);
 
       return convert_to_pointer_maybe_fold (type, expr, dofold);
     }
@@ -315,7 +322,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl,
   tree argtype = TREE_TYPE (arg);
   tree target_type = TREE_TYPE (type);
 
-  gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
+  gcc_assert (TYPE_REF_P (type));
 
   if ((flags & DIRECT_BIND) && ! lvalue_p (arg))
     {
@@ -374,7 +381,8 @@ diagnose_ref_binding (location_t loc, tree reftype, tree intype, tree decl)
 {
   tree ttl = TREE_TYPE (reftype);
 
-  if (!CP_TYPE_CONST_NON_VOLATILE_P (ttl))
+  if (!TYPE_REF_IS_RVALUE (reftype)
+      && !CP_TYPE_CONST_NON_VOLATILE_P (ttl))
     {
       const char *msg;
 
@@ -411,7 +419,7 @@ convert_to_reference (tree reftype, tree expr, int convtype,
   tree rval = NULL_TREE;
   tree rval_as_conversion = NULL_TREE;
   bool can_convert_intype_to_type;
-  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+  location_t loc = cp_expr_loc_or_loc (expr, input_location);
 
   if (TREE_CODE (type) == FUNCTION_TYPE
       && TREE_TYPE (expr) == unknown_type_node)
@@ -422,8 +430,8 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
   intype = TREE_TYPE (expr);
 
-  gcc_assert (TREE_CODE (intype) != REFERENCE_TYPE);
-  gcc_assert (TREE_CODE (reftype) == REFERENCE_TYPE);
+  gcc_assert (!TYPE_REF_P (intype));
+  gcc_assert (TYPE_REF_P (reftype));
 
   intype = TYPE_MAIN_VARIANT (intype);
 
@@ -526,7 +534,7 @@ tree
 convert_from_reference (tree val)
 {
   if (TREE_TYPE (val)
-      && TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
+      && TYPE_REF_P (TREE_TYPE (val)))
     {
       tree t = TREE_TYPE (TREE_TYPE (val));
       tree ref = build1 (INDIRECT_REF, t, val);
@@ -574,15 +582,20 @@ force_rvalue (tree expr, tsubst_flags_t complain)
 static tree
 ignore_overflows (tree expr, tree orig)
 {
-  if (TREE_CODE (expr) == INTEGER_CST
-      && TREE_CODE (orig) == INTEGER_CST
-      && TREE_OVERFLOW (expr) != TREE_OVERFLOW (orig))
+  tree stripped_expr = tree_strip_any_location_wrapper (expr);
+  tree stripped_orig = tree_strip_any_location_wrapper (orig);
+
+  if (TREE_CODE (stripped_expr) == INTEGER_CST
+      && TREE_CODE (stripped_orig) == INTEGER_CST
+      && TREE_OVERFLOW (stripped_expr) != TREE_OVERFLOW (stripped_orig))
     {
-      gcc_assert (!TREE_OVERFLOW (orig));
+      gcc_assert (!TREE_OVERFLOW (stripped_orig));
       /* Ensure constant sharing.  */
-      expr = wide_int_to_tree (TREE_TYPE (expr), expr);
+      stripped_expr = wide_int_to_tree (TREE_TYPE (stripped_expr),
+                                       wi::to_wide (stripped_expr));
     }
-  return expr;
+
+  return preserve_any_location_wrapper (stripped_expr, expr);
 }
 
 /* Fold away simple conversions, but make sure TREE_OVERFLOW is set
@@ -594,12 +607,20 @@ cp_fold_convert (tree type, tree expr)
   tree conv;
   if (TREE_TYPE (expr) == type)
     conv = expr;
-  else if (TREE_CODE (expr) == PTRMEM_CST)
+  else if (TREE_CODE (expr) == PTRMEM_CST
+          && same_type_p (TYPE_PTRMEM_CLASS_TYPE (type),
+                          PTRMEM_CST_CLASS (expr)))
     {
       /* Avoid wrapping a PTRMEM_CST in NOP_EXPR.  */
       conv = copy_node (expr);
       TREE_TYPE (conv) = type;
     }
+  else if (TYPE_PTRMEM_P (type))
+    {
+      conv = convert_ptrmem (type, expr, true, false,
+                            tf_warning_or_error);
+      conv = cp_fully_fold (conv);
+    }
   else
     {
       conv = fold_convert (type, expr);
@@ -651,7 +672,7 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
       folded_result = fold_simple (folded_result);
       if (!TREE_OVERFLOW_P (folded)
          && folded_result != error_mark_node)
-       warnings_for_convert_and_check (EXPR_LOC_OR_LOC (expr, input_location),
+       warnings_for_convert_and_check (cp_expr_loc_or_loc (expr, input_location),
                                        type, folded, folded_result);
     }
 
@@ -670,7 +691,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
   enum tree_code code = TREE_CODE (type);
   const char *invalid_conv_diag;
   tree e1;
-  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+  location_t loc = cp_expr_loc_or_loc (expr, input_location);
   bool dofold = (convtype & CONV_FOLD);
 
   if (error_operand_p (e) || type == error_mark_node)
@@ -689,15 +710,28 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 
   /* FIXME remove when moving to c_fully_fold model.  */
   if (!CLASS_TYPE_P (type))
-    e = scalar_constant_value (e);
+    {
+      e = mark_rvalue_use (e);
+      e = scalar_constant_value (e);
+    }
   if (error_operand_p (e))
     return error_mark_node;
 
+  if (NULLPTR_TYPE_P (type) && null_ptr_cst_p (e))
+    {
+      if (complain & tf_warning)
+       maybe_warn_zero_as_null_pointer_constant (e, loc);
+
+      if (!TREE_SIDE_EFFECTS (e))
+       return nullptr_node;
+    }
+
   if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP))
     /* We need a new temporary; don't take this shortcut.  */;
   else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
     {
-      if (same_type_p (type, TREE_TYPE (e)))
+      tree etype = TREE_TYPE (e);
+      if (same_type_p (type, etype))
        /* The call to fold will not always remove the NOP_EXPR as
           might be expected, since if one of the types is a typedef;
           the comparison in fold is just equality of pointers, not a
@@ -715,9 +749,16 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
        {
          /* Don't build a NOP_EXPR of class type.  Instead, change the
             type of the temporary.  */
+         gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, etype));
          TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
          return e;
        }
+      else if (TREE_CODE (e) == CONSTRUCTOR)
+       {
+         gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, etype));
+         TREE_TYPE (e) = type;
+         return e;
+       }
       else
        {
          /* We shouldn't be treating objects of ADDRESSABLE type as
@@ -764,10 +805,11 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
             the original value is within the range of the enumeration
             values. Otherwise, the resulting enumeration value is
             unspecified.  */
+         tree val = fold_for_warn (e);
          if ((complain & tf_warning)
-             && TREE_CODE (e) == INTEGER_CST
+             && TREE_CODE (val) == INTEGER_CST
              && ENUM_UNDERLYING_TYPE (type)
-             && !int_fits_type_p (e, ENUM_UNDERLYING_TYPE (type)))
+             && !int_fits_type_p (val, ENUM_UNDERLYING_TYPE (type)))
            warning_at (loc, OPT_Wconversion, 
                        "the result of the conversion is unspecified because "
                        "%qE is outside the range of type %qT",
@@ -814,13 +856,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       /* Ignore any integer overflow caused by the conversion.  */
       return ignore_overflows (converted, e);
     }
-  if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e))
-    {
-      if (complain & tf_warning)
-       maybe_warn_zero_as_null_pointer_constant (e, loc);
-      return nullptr_node;
-    }
-  if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type))
+  if (INDIRECT_TYPE_P (type) || TYPE_PTRMEM_P (type))
     return cp_convert_to_pointer (type, e, dofold, complain);
   if (code == VECTOR_TYPE)
     {
@@ -931,7 +967,7 @@ cp_get_callee (tree call)
    if we can.  */
 
 tree
-cp_get_fndecl_from_callee (tree fn)
+cp_get_fndecl_from_callee (tree fn, bool fold /* = true */)
 {
   if (fn == NULL_TREE)
     return fn;
@@ -940,8 +976,9 @@ cp_get_fndecl_from_callee (tree fn)
   tree type = TREE_TYPE (fn);
   if (type == unknown_type_node)
     return NULL_TREE;
-  gcc_assert (POINTER_TYPE_P (type));
-  fn = maybe_constant_init (fn);
+  gcc_assert (INDIRECT_TYPE_P (type));
+  if (fold)
+    fn = maybe_constant_init (fn);
   STRIP_NOPS (fn);
   if (TREE_CODE (fn) == ADDR_EXPR)
     {
@@ -961,6 +998,14 @@ cp_get_callee_fndecl (tree call)
   return cp_get_fndecl_from_callee (cp_get_callee (call));
 }
 
+/* As above, but not using the constexpr machinery.  */
+
+tree
+cp_get_callee_fndecl_nofold (tree call)
+{
+  return cp_get_fndecl_from_callee (cp_get_callee (call), false);
+}
+
 /* Subroutine of convert_to_void.  Warn if we're discarding something with
    attribute [[nodiscard]].  */
 
@@ -970,7 +1015,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
   tree call = expr;
   if (TREE_CODE (expr) == TARGET_EXPR)
     call = TARGET_EXPR_INITIAL (expr);
-  location_t loc = EXPR_LOC_OR_LOC (call, input_location);
+  location_t loc = cp_expr_loc_or_loc (call, input_location);
   tree callee = cp_get_callee (call);
   if (!callee)
     return;
@@ -978,7 +1023,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
   tree type = TREE_TYPE (callee);
   if (TYPE_PTRMEMFUNC_P (type))
     type = TYPE_PTRMEMFUNC_FN_TYPE (type);
-  if (POINTER_TYPE_P (type))
+  if (INDIRECT_TYPE_P (type))
     type = TREE_TYPE (type);
 
   tree rettype = TREE_TYPE (type);
@@ -986,6 +1031,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
   if (implicit != ICV_CAST && fn
       && lookup_attribute ("nodiscard", DECL_ATTRIBUTES (fn)))
     {
+      auto_diagnostic_group d;
       if (warning_at (loc, OPT_Wunused_result,
                      "ignoring return value of %qD, "
                      "declared with attribute nodiscard", fn))
@@ -994,6 +1040,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
   else if (implicit != ICV_CAST
           && lookup_attribute ("nodiscard", TYPE_ATTRIBUTES (rettype)))
     {
+      auto_diagnostic_group d;
       if (warning_at (loc, OPT_Wunused_result,
                      "ignoring returned value of type %qT, "
                      "declared with attribute nodiscard", rettype))
@@ -1012,6 +1059,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
         result is used, so handle that case here.  */
       if (fn)
        {
+         auto_diagnostic_group d;
          if (warning_at (loc, OPT_Wunused_result,
                          "ignoring return value of %qD, "
                          "declared with attribute warn_unused_result",
@@ -1047,30 +1095,18 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit)
 tree
 convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
 {
-  location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+  location_t loc = cp_expr_loc_or_loc (expr, input_location);
 
   if (expr == error_mark_node
       || TREE_TYPE (expr) == error_mark_node)
     return error_mark_node;
 
+  expr = maybe_undo_parenthesized_ref (expr);
+
+  expr = mark_discarded_use (expr);
   if (implicit == ICV_CAST)
+    /* An explicit cast to void avoids all -Wunused-but-set* warnings.  */
     mark_exp_read (expr);
-  else
-    {
-      tree exprv = expr;
-
-      while (TREE_CODE (exprv) == COMPOUND_EXPR)
-       exprv = TREE_OPERAND (exprv, 1);
-      if (DECL_P (exprv)
-         || handled_component_p (exprv)
-         || INDIRECT_REF_P (exprv))
-       /* Expr is not being 'used' here, otherwise we whould have
-          called mark_{rl}value_use use here, which would have in turn
-          called mark_exp_read.  Rather, we call mark_exp_read directly
-          to avoid some warnings when
-          -Wunused-but-set-{variable,parameter} is in effect.  */
-       mark_exp_read (exprv);
-    }
 
   if (!TREE_TYPE (expr))
     return expr;
@@ -1139,14 +1175,23 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
       break;
 
     case CALL_EXPR:   /* We have a special meaning for volatile void fn().  */
+      /* cdtors may return this or void, depending on
+        targetm.cxx.cdtor_returns_this, but this shouldn't affect our
+        decisions here: neither nodiscard warnings (nodiscard cdtors
+        are nonsensical), nor should any constexpr or template
+        instantiations be affected by an ABI property that is, or at
+        least ought to be transparent to the language.  */
+      if (tree fn = cp_get_callee_fndecl_nofold (expr))
+       if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn))
+         return expr;
+
       maybe_warn_nodiscard (expr, implicit);
       break;
 
     case INDIRECT_REF:
       {
        tree type = TREE_TYPE (expr);
-       int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
-                          == REFERENCE_TYPE;
+       int is_reference = TYPE_REF_P (TREE_TYPE (TREE_OPERAND (expr, 0)));
        int is_volatile = TYPE_VOLATILE (type);
        int is_complete = COMPLETE_TYPE_P (complete_type (type));
 
@@ -1584,7 +1629,7 @@ convert (tree type, tree expr)
 
   intype = TREE_TYPE (expr);
 
-  if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
+  if (INDIRECT_TYPE_P (type) && INDIRECT_TYPE_P (intype))
     return build_nop (type, expr);
 
   return ocp_convert (type, expr, CONV_BACKEND_CONVERT,
@@ -1654,11 +1699,11 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
   tree conv = NULL_TREE;
   tree winner = NULL_TREE;
 
-  if (expr == null_node
+  if (null_node_p (expr)
       && (desires & WANT_INT)
       && !(desires & WANT_NULL))
     {
-      source_location loc =
+      location_t loc =
        expansion_point_location_if_in_system_header (input_location);
 
       warning_at (loc, OPT_Wconversion_null,
@@ -1842,16 +1887,32 @@ type_promotes_to (tree type)
      wider.  Scoped enums don't promote, but pretend they do for backward
      ABI bug compatibility wrt varargs.  */
   else if (TREE_CODE (type) == ENUMERAL_TYPE
+          || type == char8_type_node
           || type == char16_type_node
           || type == char32_type_node
           || type == wchar_type_node)
     {
+      tree prom = type;
+
+      if (TREE_CODE (type) == ENUMERAL_TYPE)
+       {
+         prom = ENUM_UNDERLYING_TYPE (prom);
+         if (!ENUM_IS_SCOPED (type)
+             && ENUM_FIXED_UNDERLYING_TYPE_P (type))
+           {
+             /* ISO C++17, 7.6/4.  A prvalue of an unscoped enumeration type
+                whose underlying type is fixed (10.2) can be converted to a
+                prvalue of its underlying type. Moreover, if integral promotion
+                can be applied to its underlying type, a prvalue of an unscoped
+                enumeration type whose underlying type is fixed can also be 
+                converted to a prvalue of the promoted underlying type.  */
+             return type_promotes_to (prom);
+           }
+       }
+
       int precision = MAX (TYPE_PRECISION (type),
                           TYPE_PRECISION (integer_type_node));
       tree totype = c_common_type_for_size (precision, 0);
-      tree prom = type;
-      if (TREE_CODE (prom) == ENUMERAL_TYPE)
-       prom = ENUM_UNDERLYING_TYPE (prom);
       if (TYPE_UNSIGNED (prom)
          && ! int_fits_type_p (TYPE_MAX_VALUE (prom), totype))
        prom = c_common_type_for_size (precision, 1);
@@ -1862,7 +1923,7 @@ type_promotes_to (tree type)
          if (abi_version_crosses (6)
              && TYPE_MODE (prom) != TYPE_MODE (type))
            warning (OPT_Wabi, "scoped enum %qT passed through ... as "
-                    "%qT before -fabi-version=6, %qT after",
+                    "%qT before %<-fabi-version=6%>, %qT after",
                     type, prom, ENUM_UNDERLYING_TYPE (type));
          if (!abi_version_at_least (6))
            type = prom;
@@ -1912,7 +1973,8 @@ can_convert_qual (tree type, tree expr)
 
 /* Attempt to perform qualification conversions on EXPR to convert it
    to TYPE.  Return the resulting expression, or error_mark_node if
-   the conversion was impossible.  */
+   the conversion was impossible.  Since this is only used by
+   convert_nontype_argument, we fold the conversion.  */
 
 tree
 perform_qualification_conversions (tree type, tree expr)
@@ -1924,7 +1986,7 @@ perform_qualification_conversions (tree type, tree expr)
   if (same_type_p (type, expr_type))
     return expr;
   else if (can_convert_qual (type, expr))
-    return build_nop (type, expr);
+    return cp_fold_convert (type, expr);
   else
     return error_mark_node;
 }
@@ -1978,8 +2040,8 @@ noexcept_conv_p (tree to, tree from)
       t = TYPE_PTRMEMFUNC_FN_TYPE (t);
       f = TYPE_PTRMEMFUNC_FN_TYPE (f);
     }
-  if (TREE_CODE (t) == POINTER_TYPE
-      && TREE_CODE (f) == POINTER_TYPE)
+  if (TYPE_PTR_P (t)
+      && TYPE_PTR_P (f))
     {
       t = TREE_TYPE (t);
       f = TREE_TYPE (f);
@@ -2009,8 +2071,8 @@ fnptr_conv_p (tree to, tree from)
       t = TYPE_PTRMEMFUNC_FN_TYPE (t);
       f = TYPE_PTRMEMFUNC_FN_TYPE (f);
     }
-  if (TREE_CODE (t) == POINTER_TYPE
-      && TREE_CODE (f) == POINTER_TYPE)
+  if (TYPE_PTR_P (t)
+      && TYPE_PTR_P (f))
     {
       t = TREE_TYPE (t);
       f = TREE_TYPE (f);