re PR c++/48449 ([C++0x][SFINAE] Hard errors during value-initialization expressions)
authorJason Merrill <jason@redhat.com>
Thu, 7 Apr 2011 21:47:10 +0000 (17:47 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 7 Apr 2011 21:47:10 +0000 (17:47 -0400)
PR c++/48449
* typeck2.c (build_functional_cast): Check complain consistently.
Use build_value_init and abstract_virtuals_error_sfinae.
(abstract_virtuals_error_sfinae): Split out.
* cp-tree.h: Declare it.
* init.c (build_new_1): Use it.
(build_value_init_noctor): Handle FUNCTION_TYPE.

From-SVN: r172141

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/sfinae8.C [new file with mode: 0644]

index e194e33a7cd53f6f80e8bfe3f39282101c3a4ffe..7e0a596884afa848e57a8354de61d47be5a30829 100644 (file)
@@ -1,5 +1,13 @@
 2011-04-07  Jason Merrill  <jason@redhat.com>
 
+       PR c++/48449
+       * typeck2.c (build_functional_cast): Check complain consistently.
+       Use build_value_init and abstract_virtuals_error_sfinae.
+       (abstract_virtuals_error_sfinae): Split out.
+       * cp-tree.h: Declare it.
+       * init.c (build_new_1): Use it.
+       (build_value_init_noctor): Handle FUNCTION_TYPE.
+
        * semantics.c (finish_decltype_type): Simplify handling of unknown
        type.
 
index 06b0b3e89903c3d395f9c46da86bceab0faaa936..94bd3cee016cf35de68c4b5225665e31ceee56e3 100644 (file)
@@ -5596,6 +5596,7 @@ extern tree binfo_or_else                 (tree, tree);
 extern void cxx_readonly_error                 (tree, enum lvalue_use);
 extern void complete_type_check_abstract       (tree);
 extern int abstract_virtuals_error             (tree, tree);
+extern int abstract_virtuals_error_sfinae      (tree, tree, tsubst_flags_t);
 
 extern tree store_init_value                   (tree, tree, int);
 extern void check_narrowing                    (tree, tree);
index e1961c8ee77429ecd1c3d2c3357977c820c4a4cc..2e9eb68079948d40c5b64358023a5aaf87deebcf 100644 (file)
@@ -458,6 +458,12 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
       /* Build a constructor to contain the initializations.  */
       return build_constructor (type, v);
     }
+  else if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      if (complain & tf_error)
+       error ("value-initialization of function type %qT", type);
+      return error_mark_node;
+    }
 
   return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
 }
@@ -2030,7 +2036,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
       return error_mark_node;
     }
 
-  if (abstract_virtuals_error (NULL_TREE, elt_type))
+  if (abstract_virtuals_error_sfinae (NULL_TREE, elt_type, complain))
     return error_mark_node;
 
   is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
index 82218f0b806ccb330e07e47de9236259e8094526..f2046f7e221bf855dcb82af7f09ea1f37611c9c1 100644 (file)
@@ -250,7 +250,7 @@ complete_type_check_abstract (tree type)
    occurred; zero if all was well.  */
 
 int
-abstract_virtuals_error (tree decl, tree type)
+abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
 {
   VEC(tree,gc) *pure;
 
@@ -301,11 +301,14 @@ abstract_virtuals_error (tree decl, tree type)
   if (!pure)
     return 0;
 
+  if (decl && TREE_CODE (decl) == RESULT_DECL)
+    return 0;
+
+  if (!(complain & tf_error))
+    return 1;
+
   if (decl)
     {
-      if (TREE_CODE (decl) == RESULT_DECL)
-       return 0;
-
       if (TREE_CODE (decl) == VAR_DECL)
        error ("cannot declare variable %q+D to be of abstract "
               "type %qT", decl, type);
@@ -354,6 +357,14 @@ abstract_virtuals_error (tree decl, tree type)
   return 1;
 }
 
+/* Wrapper for the above function in the common case of wanting errors.  */
+
+int
+abstract_virtuals_error (tree decl, tree type)
+{
+  return abstract_virtuals_error_sfinae (decl, type, tf_warning_or_error);
+}
+
 /* Print an error message for invalid use of an incomplete type.
    VALUE is the expression that was used (or 0 if that isn't known)
    and TYPE is the type that was invalid.  DIAG_KIND indicates the
@@ -1527,7 +1538,8 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
 
   if (TREE_CODE (type) == REFERENCE_TYPE && !parms)
     {
-      error ("invalid value-initialization of reference type");
+      if (complain & tf_error)
+       error ("invalid value-initialization of reference type");
       return error_mark_node;
     }
 
@@ -1542,7 +1554,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
   if (! MAYBE_CLASS_TYPE_P (type))
     {
       if (parms == NULL_TREE)
-       return cp_convert (type, integer_zero_node);
+       return build_value_init (type, complain);
 
       /* This must build a C cast.  */
       parms = build_x_compound_expr_from_list (parms, ELK_FUNC_CAST, complain);
@@ -1558,7 +1570,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
 
   if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
     return error_mark_node;
-  if (abstract_virtuals_error (NULL_TREE, type))
+  if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
     return error_mark_node;
 
   /* [expr.type.conv]
index 9d5f63d1a179adad7942d7078bf5a209707061d6..7aace9fd007292a638383b5b01dd7bd9d8db1c16 100644 (file)
@@ -1,5 +1,7 @@
 2011-04-07  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/sfinae8.C: New.
+
        * g++.dg/cpp0x/sfinae7.C: New.
 
        * g++.dg/cpp0x/enum9.C: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae8.C b/gcc/testsuite/g++.dg/cpp0x/sfinae8.C
new file mode 100644 (file)
index 0000000..7f3012f
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/48449
+// { dg-options -std=c++0x }
+
+template<class T, class = decltype(T())>
+char f(int);
+
+template<class>
+char (&f(...))[2];
+
+struct A { virtual ~A() = 0; };
+
+static_assert(sizeof(f<int&>(0)) != 1, "Error");
+static_assert(sizeof(f<void()>(0)) != 1, "Error");
+static_assert(sizeof(f<A>(0)) != 1, "Error");