aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-04-07 17:47:10 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-04-07 17:47:10 -0400
commit2b8497cd7aef2697b00b7e57ae3ea787f7cbe251 (patch)
tree283bd508dcdce7684a9caf0e7849659f2fbe008e /gcc
parent6cdb14286db4ace59759757ce2b1fab2d03a04c2 (diff)
downloadgcc-2b8497cd7aef2697b00b7e57ae3ea787f7cbe251.zip
gcc-2b8497cd7aef2697b00b7e57ae3ea787f7cbe251.tar.gz
gcc-2b8497cd7aef2697b00b7e57ae3ea787f7cbe251.tar.bz2
re PR c++/48449 ([C++0x][SFINAE] Hard errors during value-initialization expressions)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/init.c8
-rw-r--r--gcc/cp/typeck2.c26
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/sfinae8.C14
6 files changed, 51 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e194e33..7e0a596 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 06b0b3e..94bd3ce 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index e1961c8..2e9eb680 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 82218f0..f2046f7 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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]
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9d5f63d..7aace9f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..7f3012f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae8.C
@@ -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");