re PR c++/16174 (deducing top-level consts)
authorNathan Sidwell <nathan@codesourcery.com>
Mon, 28 Jun 2004 11:07:23 +0000 (11:07 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 28 Jun 2004 11:07:23 +0000 (11:07 +0000)
cp:
PR C++/16174
* call.c (build_temp): Declare.
(check_constructor_callable): New.
(reference_binding): Only set CHECK_COPY_CONSTRUCTOR if not for
CONSTRUCTOR_CALLABLE.
(convert_like_real, initialize_reference): Use
check_constructor_callable.
* cp-tree.h (LOOKUP_CONSTRUCTOR_CALLABLE): New.
(LOOKUP_*): Renumber.
testsuite:
* PR C++/16174
* g++.dg/template/ctor4.C: New.

From-SVN: r83775

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/ctor4.C [new file with mode: 0644]

index 500567b88967c1886cf72d57cd852e133cbca617..74d845710ac46e02118ef903b473f0ba16e596d2 100644 (file)
@@ -1,5 +1,15 @@
 2004-06-28  Nathan Sidwell  <nathan@codesourcery.com>
 
+       PR C++/16174
+       * call.c (build_temp): Declare.
+       (check_constructor_callable): New.
+       (reference_binding): Only set CHECK_COPY_CONSTRUCTOR if not for
+       CONSTRUCTOR_CALLABLE.
+       (convert_like_real, initialize_reference): Use
+       check_constructor_callable.
+       * cp-tree.h (LOOKUP_CONSTRUCTOR_CALLABLE): New.
+       (LOOKUP_*): Renumber.
+
        * friend.c (add_friend): Only perform access checks when context
        is a class.
        * lex.c (cxx_make_type): Only create a binfo for aggregate types.
index 5cbf808d8ece9b4bb32fd7321a2c8dd17d13439f..207d7585f8806f568b88068c43209732c6dbfcbc 100644 (file)
@@ -188,6 +188,8 @@ static void add_candidates (tree, tree, tree, bool, tree, tree,
                            int, struct z_candidate **);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
 static bool magic_varargs_p (tree);
+static tree build_temp (tree, tree, int, void (**)(const char *, ...));
+static void check_constructor_callable (tree, tree);
 
 tree
 build_vfield_ref (tree datum, tree type)
@@ -1190,7 +1192,8 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
     {
       conv = build_identity_conv (from, expr);
       conv = direct_reference_binding (rto, conv);
-      conv->u.next->check_copy_constructor_p = true;
+      if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE))
+       conv->u.next->check_copy_constructor_p = true;
       return conv;
     }
 
@@ -4063,6 +4066,20 @@ enforce_access (tree basetype_path, tree decl)
   return true;
 }
 
+/* Check that a callable constructor to initialize a temporary of
+   TYPE from an EXPR exists.  */
+
+static void
+check_constructor_callable (tree type, tree expr)
+{
+  build_special_member_call (NULL_TREE,
+                            complete_ctor_identifier,
+                            build_tree_list (NULL_TREE, expr), 
+                            TYPE_BINFO (type),
+                            LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING
+                            | LOOKUP_CONSTRUCTOR_CALLABLE);
+}
+
 /* Initialize a temporary of type TYPE with EXPR.  The FLAGS are a
    bitwise or of LOOKUP_* values.  If any errors are warnings are
    generated, set *DIAGNOSTIC_FN to "error" or "warning",
@@ -4074,9 +4091,9 @@ build_temp (tree expr, tree type, int flags,
            void (**diagnostic_fn)(const char *, ...))
 {
   int savew, savee;
-
+  
   savew = warningcount, savee = errorcount;
-  expr = build_special_member_call (NULL_TREE, 
+  expr = build_special_member_call (NULL_TREE,
                                    complete_ctor_identifier,
                                    build_tree_list (NULL_TREE, expr), 
                                    TYPE_BINFO (type),
@@ -4209,12 +4226,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
          && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
        expr = decl_constant_value (expr);
       if (convs->check_copy_constructor_p)
-       /* Generate a temporary copy purely to generate the required
-          diagnostics.  */
-       build_temp
-         (build_dummy_object
-          (build_qualified_type (totype, TYPE_QUAL_CONST)),
-          totype, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING, &diagnostic_fn);
+       check_constructor_callable (totype, expr);
        return expr;
     case ck_ambig:
       /* Call build_user_type_conversion again for the error.  */
@@ -4243,12 +4255,7 @@ 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.  */
          if (convs->check_copy_constructor_p)
-           /* Generate a temporary copy purely to generate the required
-              diagnostics.  */
-           build_temp (build_dummy_object (TREE_TYPE (expr)),
-                       TREE_TYPE (expr),
-                       LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
-                       &diagnostic_fn);
+           check_constructor_callable (TREE_TYPE (expr), expr);
          /* Build an expression for `*((base*) &expr)'.  */
          expr = build_unary_op (ADDR_EXPR, expr, 0);
          expr = perform_implicit_conversion (build_pointer_type (totype), 
@@ -6426,14 +6433,8 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
         remember that the conversion was required.  */
       if (conv->kind == ck_base && conv->need_temporary_p)
        {
-         void (*diagnostic_fn) (const char *, ...);
          if (conv->check_copy_constructor_p)
-           /* Generate a temporary copy purely to generate the required
-              diagnostics.  */
-           build_temp (build_dummy_object (TREE_TYPE (expr)),
-                       TREE_TYPE (expr),
-                       LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
-                       &diagnostic_fn);
+           check_constructor_callable (TREE_TYPE (expr), expr);
          base_conv_type = conv->type;
          conv = conv->u.next;
        }
index c2a943e9066c8ef6c3347374df7e704a1cd7907d..23e660e0a4d4ee4183979595a0f785e6e6047b23 100644 (file)
@@ -3330,19 +3330,20 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
    LOOKUP_PREFER_NAMESPACES means not to accept objects, and possibly types.
    LOOKUP_PREFER_BOTH means class-or-namespace-name.  */
 
-#define LOOKUP_PROTECT (1)
-#define LOOKUP_COMPLAIN (2)
-#define LOOKUP_NORMAL (3)
-#define LOOKUP_NONVIRTUAL (8)
-#define LOOKUP_GLOBAL (16)
-#define LOOKUP_ONLYCONVERTING (128)
-#define DIRECT_BIND (256)
-#define LOOKUP_NO_CONVERSION (512)
-#define LOOKUP_DESTRUCTOR (512)
-#define LOOKUP_NO_TEMP_BIND (1024)
-#define LOOKUP_PREFER_TYPES (2048)
-#define LOOKUP_PREFER_NAMESPACES (4096)
-#define LOOKUP_PREFER_BOTH (6144)
+#define LOOKUP_PROTECT (1 << 0)
+#define LOOKUP_COMPLAIN (1 << 1)
+#define LOOKUP_NORMAL (LOOKUP_PROTECT | LOOKUP_COMPLAIN)
+#define LOOKUP_NONVIRTUAL (1 << 2)
+#define LOOKUP_GLOBAL (1 << 3)
+#define LOOKUP_ONLYCONVERTING (1 << 4)
+#define DIRECT_BIND (1 << 5)
+#define LOOKUP_NO_CONVERSION (1 << 6)
+#define LOOKUP_DESTRUCTOR (1 << 7)
+#define LOOKUP_NO_TEMP_BIND (1 << 8)
+#define LOOKUP_PREFER_TYPES (1 << 9)
+#define LOOKUP_PREFER_NAMESPACES (1 << 10)
+#define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES)
+#define LOOKUP_CONSTRUCTOR_CALLABLE (1 << 11)
 
 #define LOOKUP_NAMESPACES_ONLY(F)  \
   (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
index e655ebf42141f18b423d309e1e921a80be163326..2f8653e100916dca4ae87500aac65abb9bc98a17 100644 (file)
@@ -1,3 +1,8 @@
+2004-06-28  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * PR C++/16174
+       * g++.dg/template/ctor4.C: New.
+
 2004-06-27  Andrew Pinski  <pinskia@physics.uc.edu>
 
        PR c++/16205
diff --git a/gcc/testsuite/g++.dg/template/ctor4.C b/gcc/testsuite/g++.dg/template/ctor4.C
new file mode 100644 (file)
index 0000000..18ed628
--- /dev/null
@@ -0,0 +1,39 @@
+// { dg-do compile }
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 24 Jun 2004 <nathan@codesourcery.com>
+
+// Origin Rani Sharoni via giovannibajo@libero.it
+// Bug 16174, SFINAE failure.
+
+template <class T> struct K 
+{
+  K();
+
+  K(K<T> & rhs);
+  K(K<T> const& rhs);
+  template <class U> K(K<U> const& rhs);
+
+private:
+  template <class U> struct A;
+  template <class U> struct A< K<U> const>
+  {  typedef typename K<U>::compile_time_error type; };
+
+  // This is used to reject calls to the copy constructor
+  //  with objects which are top-level const. If they are
+  //  const, the specialization of A is instantiated and
+  //  causes a compile time error. Otherwise, the general
+  //  template is picked up, it misses definition, so this
+  //  ctor declaration is rejected by SFINAE and everybody
+  //  is happy.
+  // GCC 3.4.1pre and 3.5.0 always matches A's specialization
+  //  when instantiating from foo(), and this causes the error.
+  template <class U>
+  K(U& rhs, typename A<U>::type = 0);
+};
+
+
+K<int> foo(void)
+{
+  return K<int>();
+}