Patchwork [C++] PR 51424

login
register
mail settings
Submitter Paolo Carlini
Date Aug. 30, 2013, 11:24 a.m.
Message ID <522080E4.3050703@oracle.com>
Download mbox | patch
Permalink /patch/271236/
State New
Headers show

Comments

Paolo Carlini - Aug. 30, 2013, 11:24 a.m.
Hi again,

On 08/30/2013 11:06 AM, Paolo Carlini wrote:
> I could, for example pass down a separate bit, instead of playing 
> again with the LOOKUP_* bits. At some point yesterday I even had that 
> version tested ;)
In practice, something like the attached.

By the way, as regards this comment in cp-tree.h:

/* These are uses as bits in flags passed to various functions to
    control their behavior.  Despite the LOOKUP_ prefix, many of these
    do not control name lookup.  ??? Functions using these flags should
    probably be modified to accept explicit boolean flags for the
    behaviors relevant to them.  */

I think I could rather easily remove LOOKUP_ALREADY_DIGESTED, because 
it's only used between check_initializer and store_init_value.

Thanks!
Paolo.

////////////////////////////

Patch

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 202101)
+++ cp/cp-tree.h	(working copy)
@@ -5359,7 +5359,7 @@  extern tree do_friend				(tree, tree, tree, tree,
 /* in init.c */
 extern tree expand_member_init			(tree);
 extern void emit_mem_initializers		(tree);
-extern tree build_aggr_init			(tree, tree, int,
+extern tree build_aggr_init			(tree, tree, int, bool,
                                                  tsubst_flags_t);
 extern int is_class_type			(tree, int);
 extern tree get_type_value			(tree);
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 202101)
+++ cp/decl.c	(working copy)
@@ -5539,7 +5539,8 @@  build_aggr_init_full_exprs (tree decl, tree init,
      
 {
   gcc_assert (stmts_are_full_exprs_p ());
-  return build_aggr_init (decl, init, flags, tf_warning_or_error);
+  return build_aggr_init (decl, init, flags, /*delegating_cons_p=*/false,
+			  tf_warning_or_error);
 }
 
 /* Verify INIT (the initializer for DECL), and record the
Index: cp/init.c
===================================================================
--- cp/init.c	(revision 202101)
+++ cp/init.c	(working copy)
@@ -32,8 +32,10 @@  along with GCC; see the file COPYING3.  If not see
 static bool begin_init_stmts (tree *, tree *);
 static tree finish_init_stmts (bool, tree, tree);
 static void construct_virtual_base (tree, tree);
-static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t);
-static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t);
+static void expand_aggr_init_1 (tree, tree, tree, tree, int, bool,
+				tsubst_flags_t);
+static void expand_default_init (tree, tree, tree, tree, int, bool,
+				 tsubst_flags_t);
 static void perform_member_init (tree, tree);
 static tree build_builtin_delete_call (tree);
 static int member_init_ok_or_else (tree, tree, tree);
@@ -501,7 +503,8 @@  perform_target_ctor (tree init)
   tree type = current_class_type;
 
   finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL,
-                                     tf_warning_or_error));
+				     /*delegating_cons_p=*/true,
+				     tf_warning_or_error));
   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
     {
       tree expr = build_delete (type, decl, sfk_complete_destructor,
@@ -693,6 +696,7 @@  perform_member_init (tree member, tree init)
 		       "uninitialized member %qD with %<const%> type %qT",
 		       member, type);
 	  finish_expr_stmt (build_aggr_init (decl, init, flags,
+					     /*delegating_cons_p=*/false,
 					     tf_warning_or_error));
 	}
     }
@@ -1076,6 +1080,7 @@  emit_mem_initializers (tree mem_inits)
                                                      tf_warning_or_error),
 			      arguments,
 			      flags,
+			      /*delegating_cons_p=*/false,
                               tf_warning_or_error);
 	  expand_cleanup_for_base (subobject, NULL_TREE);
 	}
@@ -1242,7 +1247,7 @@  construct_virtual_base (tree vbase, tree arguments
   exp = convert_to_base_statically (current_class_ref, vbase);
 
   expand_aggr_init_1 (vbase, current_class_ref, exp, arguments,
-		      0, tf_warning_or_error);
+		      0, /*delegating_cons_p=*/false, tf_warning_or_error);
   finish_then_clause (inner_if_stmt);
   finish_if_stmt (inner_if_stmt);
 
@@ -1448,7 +1453,8 @@  expand_member_init (tree name)
    perform the initialization, but not both, as it would be ambiguous.  */
 
 tree
-build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
+build_aggr_init (tree exp, tree init, int flags, bool delegating_cons_p,
+		 tsubst_flags_t complain)
 {
   tree stmt_expr;
   tree compound_stmt;
@@ -1513,7 +1519,7 @@  tree
   destroy_temps = stmts_are_full_exprs_p ();
   current_stmt_tree ()->stmts_are_full_exprs_p = 0;
   expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
-		      init, LOOKUP_NORMAL|flags, complain);
+		      init, LOOKUP_NORMAL|flags, delegating_cons_p, complain);
   stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
   current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
   TREE_READONLY (exp) = was_const;
@@ -1524,7 +1530,7 @@  tree
 
 static void
 expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
-                     tsubst_flags_t complain)
+                     bool delegating_cons_p, tsubst_flags_t complain)
 {
   tree type = TREE_TYPE (exp);
   tree ctor_name;
@@ -1641,6 +1647,14 @@  expand_default_init (tree binfo, tree true_exp, tr
       complete = build_special_member_call (exp, complete_ctor_identifier,
 					    &parms2, binfo, flags,
 					    complain);
+
+      if ((complain & tf_error)
+	  && delegating_cons_p
+	  && TREE_CODE (complete) == CALL_EXPR
+	  && (DECL_ABSTRACT_ORIGIN (TREE_OPERAND (CALL_EXPR_FN (complete), 0))
+	      == current_function_decl))
+	error ("constructor delegates to itself");
+
       complete = fold_build_cleanup_point_expr (void_type_node, complete);
       release_tree_vector (parms2);
 
@@ -1662,8 +1676,16 @@  expand_default_init (tree binfo, tree true_exp, tr
 	ctor_name = base_ctor_identifier;
       rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags,
 					complain);
-  }
 
+      if ((complain & tf_error)
+	  && delegating_cons_p
+	  && ctor_name == complete_ctor_identifier
+	  && TREE_CODE (rval) == CALL_EXPR
+	  && (DECL_ABSTRACT_ORIGIN (TREE_OPERAND (CALL_EXPR_FN (rval), 0))
+	      == current_function_decl))
+	error ("constructor delegates to itself");
+    }
+
   if (parms != NULL)
     release_tree_vector (parms);
 
@@ -1705,7 +1727,7 @@  expand_default_init (tree binfo, tree true_exp, tr
 
 static void
 expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
-                    tsubst_flags_t complain)
+                    bool delegating_cons_p, tsubst_flags_t complain)
 {
   tree type = TREE_TYPE (exp);
 
@@ -1762,7 +1784,8 @@  expand_aggr_init_1 (tree binfo, tree true_exp, tre
 
   /* We know that expand_default_init can handle everything we want
      at this point.  */
-  expand_default_init (binfo, true_exp, exp, init, flags, complain);
+  expand_default_init (binfo, true_exp, exp, init, flags, delegating_cons_p,
+		       complain);
 }
 
 /* Report an error if TYPE is not a user-defined, class type.  If
@@ -3497,7 +3520,9 @@  build_vec_init (tree base, tree maxindex, tree ini
 	  if (digested)
 	    one_init = build2 (INIT_EXPR, type, baseref, elt);
 	  else if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
-	    one_init = build_aggr_init (baseref, elt, 0, complain);
+	    one_init = build_aggr_init (baseref, elt, 0,
+					/*delegating_cons_p=*/false,
+					complain);
 	  else
 	    one_init = cp_build_modify_expr (baseref, NOP_EXPR,
 					     elt, complain);
@@ -3632,7 +3657,9 @@  build_vec_init (tree base, tree maxindex, tree ini
 	    elt_init = cp_build_modify_expr (to, NOP_EXPR, from, 
 					     complain);
 	  else if (type_build_ctor_call (type))
-	    elt_init = build_aggr_init (to, from, 0, complain);
+	    elt_init = build_aggr_init (to, from, 0,
+					/*delegating_cons_p=*/false,
+					complain);
 	  else if (from)
 	    elt_init = cp_build_modify_expr (to, NOP_EXPR, from,
 					     complain);
@@ -3659,7 +3686,9 @@  build_vec_init (tree base, tree maxindex, tree ini
 	{
 	  gcc_assert (type_build_ctor_call (type) || init);
 	  if (CLASS_TYPE_P (type))
-	    elt_init = build_aggr_init (to, init, 0, complain);
+	    elt_init = build_aggr_init (to, init, 0,
+					/*delegating_cons_p=*/false,
+					complain);
 	  else
 	    {
 	      if (TREE_CODE (init) == TREE_LIST)
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 202101)
+++ cp/semantics.c	(working copy)
@@ -3777,6 +3777,7 @@  simplify_aggr_init_expr (tree *tp)
       push_deferring_access_checks (dk_no_check);
       call_expr = build_aggr_init (slot, call_expr,
 				   DIRECT_BIND | LOOKUP_ONLYCONVERTING,
+				   /*delegating_cons_p=*/false,
                                    tf_warning_or_error);
       pop_deferring_access_checks ();
       call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot);
Index: testsuite/g++.dg/cpp0x/dc8.C
===================================================================
--- testsuite/g++.dg/cpp0x/dc8.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/dc8.C	(working copy)
@@ -0,0 +1,66 @@ 
+// PR c++/51424
+// { dg-do compile { target c++11 } }
+
+template <class T >
+struct S
+{
+  S() : S() {}          // { dg-error "delegates to itself" }
+  S(int x) : S(x) {}    // { dg-error "delegates to itself" }
+};
+
+struct B1
+{
+  B1() : B1() {}        // { dg-error "delegates to itself" }
+  B1(int y) : B1(y) {}  // { dg-error "delegates to itself" }
+};
+
+struct V1 : virtual B1
+{
+  V1() : B1() {}
+  V1(int x) : B1(x) {}
+};
+
+struct B2
+{
+  B2() : B2() {}        // { dg-error "delegates to itself" }
+  B2(int y) : B2(y) {}  // { dg-error "delegates to itself" }
+};
+
+struct V2 : virtual B2
+{
+  V2() : V2() {}        // { dg-error "delegates to itself" }
+  V2(int x) : V2(x) {}  // { dg-error "delegates to itself" }
+};
+
+struct B3
+{
+  B3() {}
+  B3(int y) {}
+};
+
+struct V3 : virtual B3
+{
+  V3() : V3() {}        // { dg-error "delegates to itself" }
+  V3(int x) : V3(x) {}  // { dg-error "delegates to itself" }
+};
+
+struct CE1
+{
+  constexpr CE1() : CE1() {}        // { dg-error "delegates to itself" }
+  constexpr CE1(int x) : CE1(x) {}  // { dg-error "delegates to itself" }
+};
+
+struct CEB2
+{
+  constexpr CEB2() : CEB2() {}        // { dg-error "delegates to itself" }
+  constexpr CEB2(int x) : CEB2(x) {}  // { dg-error "delegates to itself" }
+};
+
+struct CE2 : CEB2
+{
+  constexpr CE2() : CEB2() {}
+  constexpr CE2(int x) : CEB2(x) {}
+};
+
+S<int> s1;
+S<int> s2(1);
Index: testsuite/g++.dg/template/meminit1.C
===================================================================
--- testsuite/g++.dg/template/meminit1.C	(revision 202101)
+++ testsuite/g++.dg/template/meminit1.C	(working copy)
@@ -3,6 +3,6 @@  template <class T >
 struct S
 {
   S() : S() {} // { dg-message "delegating constructors" }
-};
+}; // { dg-error "delegates to itself" "" { target *-*-* } 5 }
 
 S<int> s;