re PR c++/62115 (ICE with invalid default argument)
authorJason Merrill <jason@redhat.com>
Sun, 12 Oct 2014 01:42:31 +0000 (21:42 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 12 Oct 2014 01:42:31 +0000 (21:42 -0400)
PR c++/62115
* class.c (build_base_path): Preserve rvalueness.
* call.c (convert_like_real) [ck_base]: Let convert_to_base handle &/*.
* rtti.c (build_dynamic_cast_1): Call convert_to_reference later.

From-SVN: r216124

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/rtti.c
gcc/testsuite/g++.dg/expr/cond6.C
gcc/testsuite/g++.dg/overload/defarg9.C [new file with mode: 0644]

index acdb354816c39476c97721f5193e51a073f2efb5..ebb62d277f173d8543cfa4fc1289f1ff97de97b2 100644 (file)
@@ -1,5 +1,10 @@
 2014-10-10  Jason Merrill  <jason@redhat.com>
 
+       PR c++/62115
+       * class.c (build_base_path): Preserve rvalueness.
+       * call.c (convert_like_real) [ck_base]: Let convert_to_base handle &/*.
+       * rtti.c (build_dynamic_cast_1): Call convert_to_reference later.
+
        PR c++/63194
        * method.c (defaulted_late_check): Call maybe_instantiate_noexcept.
 
index 76d8eabf33f1e94b56040d6261222b28cc26809d..8a89aadeaf9c1ab70756feefe2f725d9695d5d46 100644 (file)
@@ -6341,10 +6341,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
          /* We are going to bind a reference directly to a base-class
             subobject of EXPR.  */
          /* Build an expression for `*((base*) &expr)'.  */
-         expr = cp_build_addr_expr (expr, complain);
-         expr = convert_to_base (expr, build_pointer_type (totype),
+         expr = convert_to_base (expr, totype,
                                  !c_cast_p, /*nonnull=*/true, complain);
-         expr = cp_build_indirect_ref (expr, RO_IMPLICIT_CONVERSION, complain);
          return expr;
        }
 
index b6611870a23dff0fb2ca5f36a64053f19df3935e..99bfa957f6374e8ad8d557b1ff9c39271b877805 100644 (file)
@@ -251,6 +251,7 @@ build_base_path (enum tree_code code,
   int want_pointer = TYPE_PTR_P (TREE_TYPE (expr));
   bool has_empty = false;
   bool virtual_access;
+  bool rvalue = false;
 
   if (expr == error_mark_node || binfo == error_mark_node || !binfo)
     return error_mark_node;
@@ -324,8 +325,11 @@ build_base_path (enum tree_code code,
     }
 
   if (!want_pointer)
-    /* This must happen before the call to save_expr.  */
-    expr = cp_build_addr_expr (expr, complain);
+    {
+      rvalue = !real_lvalue_p (expr);
+      /* This must happen before the call to save_expr.  */
+      expr = cp_build_addr_expr (expr, complain);
+    }
   else
     expr = mark_rvalue_use (expr);
 
@@ -351,9 +355,7 @@ build_base_path (enum tree_code code,
       || in_template_function ())
     {
       expr = build_nop (ptr_target_type, expr);
-      if (!want_pointer)
-       expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
-      return expr;
+      goto indout;
     }
 
   /* If we're in an NSDMI, we don't have the full constructor context yet
@@ -364,9 +366,7 @@ build_base_path (enum tree_code code,
     {
       expr = build1 (CONVERT_EXPR, ptr_target_type, expr);
       CONVERT_EXPR_VBASE_PATH (expr) = true;
-      if (!want_pointer)
-       expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
-      return expr;
+      goto indout;
     }
 
   /* Do we need to check for a null pointer?  */
@@ -402,6 +402,8 @@ build_base_path (enum tree_code code,
     {
       expr = cp_build_indirect_ref (expr, RO_NULL, complain);
       expr = build_simple_base_path (expr, binfo);
+      if (rvalue)
+       expr = move (expr);
       if (want_pointer)
        expr = build_address (expr);
       target_type = TREE_TYPE (expr);
@@ -478,8 +480,13 @@ build_base_path (enum tree_code code,
   else
     null_test = NULL;
 
+ indout:
   if (!want_pointer)
-    expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+    {
+      expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+      if (rvalue)
+       expr = move (expr);
+    }
 
  out:
   if (null_test)
index 10cc168faf6ab405ed053b6d14036cd60e08c98a..762953b38a015793cf1635f117ed957f2d7304c7 100644 (file)
@@ -608,10 +608,6 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
          errstr = _("source is of incomplete class type");
          goto fail;
        }
-
-      /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
-      expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
-                                  LOOKUP_NORMAL, NULL_TREE, complain);
     }
 
   /* The dynamic_cast operator shall not cast away constness.  */
@@ -631,6 +627,11 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
       return build_static_cast (type, expr, complain);
   }
 
+  /* Apply trivial conversion T -> T& for dereferenced ptrs.  */
+  if (tc == REFERENCE_TYPE)
+    expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
+                                LOOKUP_NORMAL, NULL_TREE, complain);
+
   /* Otherwise *exprtype must be a polymorphic class (have a vtbl).  */
   if (TYPE_POLYMORPHIC_P (TREE_TYPE (exprtype)))
     {
index 943aa85a9632b05b701aae0649545d205650a4fe..8f7f084ce5425d6c1781ce9e43c7148d9ac50222 100644 (file)
@@ -1,10 +1,11 @@
 // { dg-do run }
 
 extern "C" void abort ();
+bool ok = false;
 
 struct B {
   B() {}
-  B(const B& b) { abort (); }
+  B(const B& b) { ok = true; }
 };
 
 struct D : public B {
@@ -21,4 +22,5 @@ D f() {
 
 int main () {
   b = (true ? f() : b);
+  return !ok;
 }
diff --git a/gcc/testsuite/g++.dg/overload/defarg9.C b/gcc/testsuite/g++.dg/overload/defarg9.C
new file mode 100644 (file)
index 0000000..401fe0e
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/62115
+
+struct A {};
+struct B : A {};
+
+struct C
+{
+  C(A& a = B()) {}             // { dg-error "rvalue" }
+};
+
+C c;                           // { dg-error "" }