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.

////////////////////////////
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;

Reply via email to