re PR c++/44267 (SFINAE does not handle down static_cast over virtual inheritance)
[gcc.git] / gcc / cp / typeck.c
index 4d0c0d7b06befc2dbc9f5dc4db61ff32a1d4e7f2..955e37a28893d596c9e05defa8b252ac3ab7234a 100644 (file)
@@ -516,7 +516,8 @@ composite_pointer_type_r (tree t1, tree t2,
     {
       if (complain & tf_error)
        composite_pointer_error (DK_PERMERROR, t1, t2, operation);
-
+      else
+       return error_mark_node;
       result_type = void_type_node;
     }
   result_type = cp_build_qualified_type (result_type,
@@ -527,9 +528,13 @@ composite_pointer_type_r (tree t1, tree t2,
   if (TYPE_PTR_TO_MEMBER_P (t1))
     {
       if (!same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1),
-                       TYPE_PTRMEM_CLASS_TYPE (t2))
-         && (complain & tf_error))
-       composite_pointer_error (DK_PERMERROR, t1, t2, operation);
+                       TYPE_PTRMEM_CLASS_TYPE (t2)))
+       {
+         if (complain & tf_error)
+           composite_pointer_error (DK_PERMERROR, t1, t2, operation);
+         else
+           return error_mark_node;
+       }
       result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1),
                                       result_type);
     }
@@ -825,7 +830,8 @@ merge_types (tree t1, tree t2)
        gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2));
        rval = apply_memfn_quals (rval, type_memfn_quals (t1));
        raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1),
-                                            TYPE_RAISES_EXCEPTIONS (t2));
+                                            TYPE_RAISES_EXCEPTIONS (t2),
+                                            NULL_TREE);
        t1 = build_exception_variant (rval, raises);
        break;
       }
@@ -836,7 +842,8 @@ merge_types (tree t1, tree t2)
           is just the main variant of this.  */
        tree basetype = class_of_this_parm (t2);
        tree raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1),
-                                                 TYPE_RAISES_EXCEPTIONS (t2));
+                                                 TYPE_RAISES_EXCEPTIONS (t2),
+                                                 NULL_TREE);
        tree t3;
 
        /* If this was a member function type, get back to the
@@ -986,14 +993,14 @@ comp_except_specs (const_tree t1, const_tree t2, int exact)
   /* First handle noexcept.  */
   if (exact < ce_exact)
     {
-      /* noexcept(false) is compatible with any throwing dynamic-exc-spec
+      /* noexcept(false) is compatible with no exception-specification,
         and stricter than any spec.  */
       if (t1 == noexcept_false_spec)
-       return !nothrow_spec_p (t2) || exact == ce_derived;
-      /* Even a derived noexcept(false) is compatible with a throwing
-        dynamic spec.  */
+       return t2 == NULL_TREE || exact == ce_derived;
+      /* Even a derived noexcept(false) is compatible with no
+        exception-specification.  */
       if (t2 == noexcept_false_spec)
-       return !nothrow_spec_p (t1);
+       return t1 == NULL_TREE;
 
       /* Otherwise, if we aren't looking for an exact match, noexcept is
         equivalent to throw().  */
@@ -1324,8 +1331,8 @@ structural_comptypes (tree t1, tree t2, int strict)
           != DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t2)
          || (DECLTYPE_FOR_LAMBDA_CAPTURE (t1)
              != DECLTYPE_FOR_LAMBDA_CAPTURE (t2))
-         || (DECLTYPE_FOR_LAMBDA_RETURN (t1)
-             != DECLTYPE_FOR_LAMBDA_RETURN (t2))
+         || (DECLTYPE_FOR_LAMBDA_PROXY (t1)
+             != DECLTYPE_FOR_LAMBDA_PROXY (t2))
           || !cp_tree_equal (DECLTYPE_TYPE_EXPR (t1), 
                              DECLTYPE_TYPE_EXPR (t2)))
         return false;
@@ -1948,6 +1955,9 @@ perform_integral_promotions (tree expr)
   if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
     type = TREE_TYPE (expr);
   gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+  /* Scoped enums don't promote.  */
+  if (SCOPED_ENUM_P (type))
+    return expr;
   promoted_type = type_promotes_to (type);
   if (type != promoted_type)
     expr = cp_convert (promoted_type, expr);
@@ -2027,7 +2037,7 @@ rationalize_conditional_expr (enum tree_code code, tree t,
                                                    ? LE_EXPR : GE_EXPR),
                                                   op0, TREE_CODE (op0),
                                                   op1, TREE_CODE (op1),
-                                                  /*overloaded_p=*/NULL,
+                                                  /*overload=*/NULL,
                                                   complain),
                                 cp_build_unary_op (code, op0, 0, complain),
                                 cp_build_unary_op (code, op1, 0, complain),
@@ -2211,7 +2221,7 @@ build_class_member_access_expr (tree object, tree member,
 
          /* Convert to the base.  */
          object = build_base_path (PLUS_EXPR, object, binfo,
-                                   /*nonnull=*/1);
+                                   /*nonnull=*/1, complain);
          /* If we found the base successfully then we should be able
             to convert to it successfully.  */
          gcc_assert (object != error_mark_node);
@@ -2671,8 +2681,7 @@ build_x_indirect_ref (tree expr, ref_operator errorstring,
 
   if (processing_template_decl)
     {
-      /* Retain the type if we know the operand is a pointer so that
-        describable_type doesn't make auto deduction break.  */
+      /* Retain the type if we know the operand is a pointer.  */
       if (TREE_TYPE (expr) && POINTER_TYPE_P (TREE_TYPE (expr)))
        return build_min (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);
       if (type_dependent_expression_p (expr))
@@ -2681,7 +2690,7 @@ build_x_indirect_ref (tree expr, ref_operator errorstring,
     }
 
   rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE,
-                      NULL_TREE, /*overloaded_p=*/NULL, complain);
+                      NULL_TREE, /*overload=*/NULL, complain);
   if (!rval)
     rval = cp_build_indirect_ref (expr, errorstring, complain);
 
@@ -3064,13 +3073,12 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
          basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
                                  basetype, ba_check, NULL);
          instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
-                                         1);
+                                         1, tf_warning_or_error);
          if (instance_ptr == error_mark_node)
            return error_mark_node;
        }
       /* ...and then the delta in the PMF.  */
-      instance_ptr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (instance_ptr),
-                            instance_ptr, fold_convert (sizetype, delta));
+      instance_ptr = fold_build_pointer_plus (instance_ptr, delta);
 
       /* Hand back the adjusted 'this' argument to our caller.  */
       *instance_ptrptr = instance_ptr;
@@ -3085,9 +3093,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
       TREE_NO_WARNING (vtbl) = 1;
 
       /* Finally, extract the function pointer from the vtable.  */
-      e2 = fold_build2_loc (input_location,
-                       POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
-                       fold_convert (sizetype, idx));
+      e2 = fold_build_pointer_plus_loc (input_location, vtbl, idx);
       e2 = cp_build_indirect_ref (e2, RO_NULL, tf_warning_or_error);
       TREE_CONSTANT (e2) = 1;
 
@@ -3266,8 +3272,7 @@ cp_build_function_call_vec (tree function, VEC(tree,gc) **params,
 
   /* Check for errors in format strings and inappropriately
      null parameters.  */
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
-                           parm_types);
+  check_function_arguments (fntype, nargs, argarray);
 
   ret = build_cxx_call (function, nargs, argarray);
 
@@ -3490,7 +3495,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
 
 tree
 build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code,
-                  tree arg2, enum tree_code arg2_code, bool *overloaded_p,
+                  tree arg2, enum tree_code arg2_code, tree *overload,
                   tsubst_flags_t complain)
 {
   tree orig_arg1;
@@ -3513,7 +3518,7 @@ build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code,
     expr = build_m_component_ref (arg1, arg2);
   else
     expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
-                        overloaded_p, complain);
+                        overload, complain);
 
   /* Check for cases such as x+y<<z which users are likely to
      misinterpret.  But don't warn about obj << x + y, since that is a
@@ -3553,7 +3558,7 @@ build_x_array_ref (tree arg1, tree arg2, tsubst_flags_t complain)
     }
 
   expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
-                      /*overloaded_p=*/NULL, complain);
+                      /*overload=*/NULL, complain);
 
   if (processing_template_decl && expr != error_mark_node)
     return build_min_non_dep (ARRAY_REF, expr, orig_arg1, orig_arg2,
@@ -4330,6 +4335,7 @@ cp_build_binary_op (location_t location,
                {
                case MULT_EXPR:
                case TRUNC_DIV_EXPR:
+                 op1 = save_expr (op1);
                  imag = build2 (resultcode, real_type, imag, op1);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -4348,6 +4354,7 @@ cp_build_binary_op (location_t location,
              switch (code)
                {
                case MULT_EXPR:
+                 op0 = save_expr (op0);
                  imag = build2 (resultcode, real_type, op0, imag);
                  /* Fall through.  */
                case PLUS_EXPR:
@@ -4551,7 +4558,7 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain)
     /* Don't look for a function.  */;
   else
     exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE,
-                       /*overloaded_p=*/NULL, complain);
+                       /*overload=*/NULL, complain);
   if (!exp && code == ADDR_EXPR)
     {
       if (is_overloaded_fn (xarg))
@@ -4831,8 +4838,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
     {
       tree type = build_pointer_type (argtype);
       tree op0 = fold_convert (type, TREE_OPERAND (val, 0));
-      tree op1 = fold_convert (sizetype, fold_offsetof (arg, val));
-      return fold_build2 (POINTER_PLUS_EXPR, type, op0, op1);
+      tree op1 = fold_offsetof (arg, val);
+      return fold_build_pointer_plus (op0, op1);
     }
 
   /* Handle complex lvalues (when permitted)
@@ -5213,6 +5220,9 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
              }
            val = boolean_increment (code, arg);
          }
+       else if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
+         /* An rvalue has no cv-qualifiers.  */
+         val = build2 (code, cv_unqualified (TREE_TYPE (arg)), arg, inc);
        else
          val = build2 (code, TREE_TYPE (arg), arg, inc);
 
@@ -5460,6 +5470,16 @@ build_x_compound_expr_from_list (tree list, expr_list_kind exp,
 {
   tree expr = TREE_VALUE (list);
 
+  if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+      && !CONSTRUCTOR_IS_DIRECT_INIT (expr))
+    {
+      if (complain & tf_error)
+       pedwarn (EXPR_LOC_OR_HERE (expr), 0, "list-initializer for "
+                "non-class type must not be parenthesized");
+      else
+       return error_mark_node;
+    }
+
   if (TREE_CHAIN (list))
     {
       if (complain & tf_error)
@@ -5538,7 +5558,7 @@ build_x_compound_expr (tree op1, tree op2, tsubst_flags_t complain)
     }
 
   result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE,
-                        /*overloaded_p=*/NULL, complain);
+                        /*overload=*/NULL, complain);
   if (!result)
     result = cp_build_compound_expr (op1, op2, complain);
 
@@ -5752,7 +5772,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       /* Convert from "B*" to "D*".  This function will check that "B"
         is not a virtual base of "D".  */
       expr = build_base_path (MINUS_EXPR, build_address (expr),
-                             base, /*nonnull=*/false);
+                             base, /*nonnull=*/false, complain);
       /* Convert the pointer to a reference -- but then remember that
         there are no expressions with reference type in C++.
 
@@ -5764,11 +5784,11 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       return convert_from_reference (rvalue (cp_fold_convert (type, expr)));
     }
 
-  /* "Alvalue of type cv1 T1 can be cast to type rvalue reference to
+  /* "A glvalue of type cv1 T1 can be cast to type rvalue reference to
      cv2 T2 if cv2 T2 is reference-compatible with cv1 T1 (8.5.3)."  */
   if (TREE_CODE (type) == REFERENCE_TYPE
       && TYPE_REF_IS_RVALUE (type)
-      && real_lvalue_p (expr)
+      && lvalue_or_rvalue_with_address_p (expr)
       && reference_related_p (TREE_TYPE (type), intype)
       && (c_cast_p || at_least_as_qualified_p (TREE_TYPE (type), intype)))
     {
@@ -5854,7 +5874,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
                          c_cast_p ? ba_unique : ba_check,
                          NULL);
-      expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
+      expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false,
+                             complain);
       return cp_fold_convert(type, expr);
     }
 
@@ -6237,14 +6258,29 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
 
   /* [expr.const.cast]
 
-     An lvalue of type T1 can be explicitly converted to an lvalue of
-     type T2 using the cast const_cast<T2&> (where T1 and T2 are object
-     types) if a pointer to T1 can be explicitly converted to the type
-     pointer to T2 using a const_cast.  */
+     For two object types T1 and T2, if a pointer to T1 can be explicitly
+     converted to the type "pointer to T2" using a const_cast, then the
+     following conversions can also be made:
+
+     -- an lvalue of type T1 can be explicitly converted to an lvalue of
+     type T2 using the cast const_cast<T2&>;
+
+     -- a glvalue of type T1 can be explicitly converted to an xvalue of
+     type T2 using the cast const_cast<T2&&>; and
+
+     -- if T1 is a class type, a prvalue of type T1 can be explicitly
+     converted to an xvalue of type T2 using the cast const_cast<T2&&>.  */
+
   if (TREE_CODE (dst_type) == REFERENCE_TYPE)
     {
       reference_type = dst_type;
-      if (! real_lvalue_p (expr))
+      if (!TYPE_REF_IS_RVALUE (dst_type)
+         ? real_lvalue_p (expr)
+         : (CLASS_TYPE_P (TREE_TYPE (dst_type))
+            ? lvalue_p (expr)
+            : lvalue_or_rvalue_with_address_p (expr)))
+       /* OK.  */;
+      else
        {
          if (complain & tf_error)
            error ("invalid const_cast of an rvalue of type %qT to type %qT",
@@ -6429,7 +6465,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
       if (!CLASS_TYPE_P (type))
        type = TYPE_MAIN_VARIANT (type);
       result_type = TREE_TYPE (result);
-      if (!CLASS_TYPE_P (result_type))
+      if (!CLASS_TYPE_P (result_type) && TREE_CODE (type) != REFERENCE_TYPE)
        result_type = TYPE_MAIN_VARIANT (result_type);
       /* If the type of RESULT does not match TYPE, perform a
         const_cast to make it match.  If the static_cast or
@@ -6628,7 +6664,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
            {
              result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
                                     lhs, rhs, make_node (NOP_EXPR),
-                                    /*overloaded_p=*/NULL, 
+                                    /*overload=*/NULL,
                                     complain);
              if (result == NULL_TREE)
                return error_mark_node;
@@ -6638,6 +6674,8 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
        }
       else
        {
+         tree init = NULL_TREE;
+
          /* A binary op has been requested.  Combine the old LHS
             value with the RHS producing the value we should actually
             store into the LHS.  */
@@ -6645,7 +6683,19 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
                         && MAYBE_CLASS_TYPE_P (TREE_TYPE (lhstype)))
                        || MAYBE_CLASS_TYPE_P (lhstype)));
 
+         /* Preevaluate the RHS to make sure its evaluation is complete
+            before the lvalue-to-rvalue conversion of the LHS:
+
+            [expr.ass] With respect to an indeterminately-sequenced
+            function call, the operation of a compound assignment is a
+            single evaluation. [ Note: Therefore, a function call shall
+            not intervene between the lvalue-to-rvalue conversion and the
+            side effect associated with any single compound assignment
+            operator. -- end note ]  */
          lhs = stabilize_reference (lhs);
+         if (TREE_SIDE_EFFECTS (rhs))
+           rhs = mark_rvalue_use (rhs);
+         rhs = stabilize_expr (rhs, &init);
          newrhs = cp_build_binary_op (input_location,
                                       modifycode, lhs, rhs,
                                       complain);
@@ -6657,6 +6707,9 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
              return error_mark_node;
            }
 
+         if (init)
+           newrhs = build2 (COMPOUND_EXPR, TREE_TYPE (newrhs), init, newrhs);
+
          /* Now it looks like a plain assignment.  */
          modifycode = NOP_EXPR;
          if (c_dialect_objc ())
@@ -6715,7 +6768,9 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
            }
          if (check_array_initializer (lhs, lhstype, newrhs))
            return error_mark_node;
-         newrhs = digest_init (lhstype, newrhs);
+         newrhs = digest_init (lhstype, newrhs, complain);
+         if (newrhs == error_mark_node)
+           return error_mark_node;
        }
 
       else if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
@@ -6729,7 +6784,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
 
       /* Allow array assignment in compiler-generated code.  */
       else if (!current_function_decl
-              || !DECL_ARTIFICIAL (current_function_decl))
+              || !DECL_DEFAULTED_FN (current_function_decl))
        {
           /* This routine is used for both initialization and assignment.
              Make sure the diagnostic message differentiates the context.  */
@@ -6811,7 +6866,7 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
     {
       tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
                                make_node (modifycode),
-                               /*overloaded_p=*/NULL,
+                               /*overload=*/NULL,
                                complain);
       if (rval)
        {
@@ -7456,7 +7511,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
       if (fndecl)
        savew = warningcount, savee = errorcount;
       rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE,
-                                 /*cleanup=*/NULL, complain);
+                                 /*cleanup=*/NULL, flags, complain);
       if (fndecl)
        {
          if (warningcount > savew)
@@ -7603,15 +7658,14 @@ check_return_expr (tree retval, bool *no_warning)
          tree type = lambda_return_type (retval);
          tree oldtype = LAMBDA_EXPR_RETURN_TYPE (lambda);
 
-         if (VOID_TYPE_P (type))
-           { /* Nothing.  */ }
-         else if (oldtype == NULL_TREE)
-           {
-             pedwarn (input_location, OPT_pedantic, "lambda return type "
-                      "can only be deduced when the return statement is "
-                      "the only statement in the function body");
-             apply_lambda_return_type (lambda, type);
-           }
+         if (oldtype == NULL_TREE)
+           apply_lambda_return_type (lambda, type);
+         /* If one of the answers is type-dependent, we can't do any
+            better until instantiation time.  */
+         else if (oldtype == dependent_lambda_return_type_node)
+           /* Leave it.  */;
+         else if (type == dependent_lambda_return_type_node)
+           apply_lambda_return_type (lambda, type);
          else if (!same_type_p (type, oldtype))
            error ("inconsistent types %qT and %qT deduced for "
                   "lambda return type", type, oldtype);
@@ -8102,15 +8156,13 @@ cp_apply_type_quals_to_decl (int type_quals, tree decl)
                && type_quals != TYPE_UNQUALIFIED));
 
   /* Avoid setting TREE_READONLY incorrectly.  */
-  if (/* If the object has a constructor, the constructor may modify
-        the object.  */
-      TYPE_NEEDS_CONSTRUCTING (type)
-      /* If the type isn't complete, we don't know yet if it will need
-        constructing.  */
-      || !COMPLETE_TYPE_P (type)
-      /* If the type has a mutable component, that component might be
-        modified.  */
-      || TYPE_HAS_MUTABLE_P (type))
+  /* We used to check TYPE_NEEDS_CONSTRUCTING here, but now a constexpr
+     constructor can produce constant init, so rely on cp_finish_decl to
+     clear TREE_READONLY if the variable has non-constant init.  */
+
+  /* If the type has a mutable component, that component might be
+     modified.  */
+  if (TYPE_HAS_MUTABLE_P (type))
     type_quals &= ~TYPE_QUAL_CONST;
 
   c_apply_type_quals_to_decl (type_quals, decl);