* Many C++ PATCHes for SFINAE fixes
@ 2011-04-07 21:33 Jason Merrill
2011-04-09 14:00 ` H.J. Lu
0 siblings, 1 reply; 2+ messages in thread
From: Jason Merrill @ 2011-04-07 21:33 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 320 bytes --]
People have been finding other places where we haven't been handling
SFINAE properly. In many cases, there are two patches for each fix; the
first one fixes the bug conservatively (for possible application to
4.6), and the second one reorganizes things to be cleaner.
Tested x86_64-pc-linux-gnu, applying to trunk.
[-- Attachment #2: sfinae-decltype.patch --]
[-- Type: text/plain, Size: 4443 bytes --]
commit 441f2c6d80756bed9c72aba05a315c34f2db2343
Author: Jason Merrill <jason@redhat.com>
Date: Sun Apr 3 11:42:47 2011 -0400
* semantics.c (finish_decltype_type): Add complain parm.
* cp-tree.h: Adjust.
* parser.c (cp_parser_decltype): Adjust.
* pt.c (tsubst): Adjust.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6ef6e6e..06b0b3e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5346,7 +5346,7 @@ extern tree baselink_for_fns (tree);
extern void finish_static_assert (tree, tree, location_t,
bool);
extern tree describable_type (tree);
-extern tree finish_decltype_type (tree, bool);
+extern tree finish_decltype_type (tree, bool, tsubst_flags_t);
extern tree finish_trait_expr (enum cp_trait_kind, tree, tree);
extern tree build_lambda_expr (void);
extern tree build_lambda_object (tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9ed3a1f..607e9b8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10197,7 +10197,8 @@ cp_parser_decltype (cp_parser *parser)
return error_mark_node;
}
- return finish_decltype_type (expr, id_expression_or_member_access_p);
+ return finish_decltype_type (expr, id_expression_or_member_access_p,
+ tf_warning_or_error);
}
/* Special member functions [gram.special] */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5960e46..66db880 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11025,7 +11025,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
type = lambda_return_type (type);
else
type = finish_decltype_type
- (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
+ (type, DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t), complain);
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index a15740a..80ec028 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4785,7 +4785,8 @@ describable_type (tree expr)
a full expression. */
tree
-finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
+finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
+ tsubst_flags_t complain)
{
tree orig_expr = expr;
tree type = NULL_TREE;
@@ -4798,7 +4799,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
|| (TREE_CODE (expr) == BIT_NOT_EXPR
&& TYPE_P (TREE_OPERAND (expr, 0))))
{
- error ("argument to decltype must be an expression");
+ if (complain & tf_error)
+ error ("argument to decltype must be an expression");
return error_mark_node;
}
@@ -4864,7 +4866,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
if (OVL_CHAIN (expr)
|| TREE_CODE (OVL_FUNCTION (expr)) == TEMPLATE_DECL)
{
- error ("%qE refers to a set of overloaded functions", orig_expr);
+ if (complain & tf_error)
+ error ("%qE refers to a set of overloaded functions",
+ orig_expr);
return error_mark_node;
}
else
@@ -4916,7 +4920,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
default:
gcc_assert (TYPE_P (expr) || DECL_P (expr)
|| TREE_CODE (expr) == SCOPE_REF);
- error ("argument to decltype must be an expression");
+ if (complain & tf_error)
+ error ("argument to decltype must be an expression");
return error_mark_node;
}
}
@@ -4954,7 +4959,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
if (!type || type == unknown_type_node)
{
- error ("type of %qE is unknown", expr);
+ if (complain & tf_error)
+ error ("type of %qE is unknown", expr);
return error_mark_node;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae7.C b/gcc/testsuite/g++.dg/cpp0x/sfinae7.C
new file mode 100644
index 0000000..0a95a96
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae7.C
@@ -0,0 +1,20 @@
+// { dg-options -std=c++0x }
+
+struct A
+{
+ void f();
+ void f(int);
+ typedef int g;
+};
+
+template <class T> decltype (T::f) f();
+template <class T> void f();
+
+template <class T> decltype (T::g) g();
+template <class T> void g();
+
+int main()
+{
+ f<A>();
+ g<A>();
+}
[-- Attachment #3: sfinae-decltype2.patch --]
[-- Type: text/plain, Size: 2764 bytes --]
commit c02c3cbfe41af41ffdb8a729c763b395c14979b3
Author: Jason Merrill <jason@redhat.com>
Date: Mon Apr 4 17:18:38 2011 -0400
* semantics.c (finish_decltype_type): Simplify handling of unknown
type.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 80ec028..5cbba33 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -4788,7 +4788,6 @@ tree
finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
tsubst_flags_t complain)
{
- tree orig_expr = expr;
tree type = NULL_TREE;
if (!expr || error_operand_p (expr))
@@ -4826,6 +4825,13 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
expr = resolve_nondeduced_context (expr);
+ if (type_unknown_p (expr))
+ {
+ if (complain & tf_error)
+ error ("decltype cannot resolve address of overloaded function");
+ return error_mark_node;
+ }
+
/* To get the size of a static data member declared as an array of
unknown bound, we need to instantiate it. */
if (TREE_CODE (expr) == VAR_DECL
@@ -4855,28 +4861,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
expr = TREE_OPERAND (expr, 1);
if (TREE_CODE (expr) == BASELINK)
- /* See through BASELINK nodes to the underlying functions. */
+ /* See through BASELINK nodes to the underlying function. */
expr = BASELINK_FUNCTIONS (expr);
- if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
- expr = TREE_OPERAND (expr, 0);
-
- if (TREE_CODE (expr) == OVERLOAD)
- {
- if (OVL_CHAIN (expr)
- || TREE_CODE (OVL_FUNCTION (expr)) == TEMPLATE_DECL)
- {
- if (complain & tf_error)
- error ("%qE refers to a set of overloaded functions",
- orig_expr);
- return error_mark_node;
- }
- else
- /* An overload set containing only one function: just look
- at that function. */
- expr = OVL_FUNCTION (expr);
- }
-
switch (TREE_CODE (expr))
{
case FIELD_DECL:
@@ -4918,10 +4905,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
break;
default:
- gcc_assert (TYPE_P (expr) || DECL_P (expr)
- || TREE_CODE (expr) == SCOPE_REF);
- if (complain & tf_error)
- error ("argument to decltype must be an expression");
+ gcc_unreachable ();
return error_mark_node;
}
}
@@ -4957,13 +4941,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
}
}
- if (!type || type == unknown_type_node)
- {
- if (complain & tf_error)
- error ("type of %qE is unknown", expr);
- return error_mark_node;
- }
-
return type;
}
[-- Attachment #4: sfinae-48449.patch --]
[-- Type: text/plain, Size: 4851 bytes --]
commit a4a17314e1356211a523d0673e0d3a83a11b2338
Author: Jason Merrill <jason@redhat.com>
Date: Mon Apr 4 20:48:54 2011 -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.
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/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");
[-- Attachment #5: sfinae-48449-2.patch --]
[-- Type: text/plain, Size: 4109 bytes --]
commit d8489e38cc7e65238665e0321650f356509cb03e
Author: Jason Merrill <jason@redhat.com>
Date: Thu Apr 7 17:11:44 2011 -0400
* init.c (build_value_init_noctor): Handle REFERENCE_TYPE at top
level.
(perform_member_init): Not here.
* typeck2.c (build_functional_cast): Limit REFERENCE_TYPE special
case to templates.
(abstract_virtuals_error_sfinae): Remove RESULT_DECL special case.
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 2e9eb680..005f8d6 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -388,14 +388,6 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
ftype = TREE_TYPE (field);
- if (TREE_CODE (ftype) == REFERENCE_TYPE)
- {
- if (complain & tf_error)
- error ("value-initialization of reference");
- else
- return error_mark_node;
- }
-
/* We could skip vfields and fields of types with
user-defined constructors, but I think that won't improve
performance at all; it should be simpler in general just
@@ -408,6 +400,9 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
all of the subobjects. */
value = build_value_init (ftype, complain);
+ if (value == error_mark_node)
+ return error_mark_node;
+
if (value)
CONSTRUCTOR_APPEND_ELT(v, field, value);
}
@@ -450,6 +445,9 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
ce->value = build_value_init (TREE_TYPE (type), complain);
+ if (ce->value == error_mark_node)
+ return error_mark_node;
+
/* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs. */
gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR
&& TREE_CODE (ce->value) != AGGR_INIT_EXPR);
@@ -464,6 +462,12 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
error ("value-initialization of function type %qT", type);
return error_mark_node;
}
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
+ {
+ if (complain & tf_error)
+ error ("value-initialization of reference type %qT", type);
+ return error_mark_node;
+ }
return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
}
@@ -504,16 +508,9 @@ perform_member_init (tree member, tree init)
}
else
{
- if (TREE_CODE (type) == REFERENCE_TYPE)
- permerror (DECL_SOURCE_LOCATION (current_function_decl),
- "value-initialization of %q#D, which has reference type",
- member);
- else
- {
- init = build2 (INIT_EXPR, type, decl,
- build_value_init (type, tf_warning_or_error));
- finish_expr_stmt (init);
- }
+ init = build2 (INIT_EXPR, type, decl,
+ build_value_init (type, tf_warning_or_error));
+ finish_expr_stmt (init);
}
}
/* Deal with this here, as we will get confused if we try to call the
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index f2046f7..f3a0079 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -301,9 +301,6 @@ abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
if (!pure)
return 0;
- if (decl && TREE_CODE (decl) == RESULT_DECL)
- return 0;
-
if (!(complain & tf_error))
return 1;
@@ -1536,16 +1533,21 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
else
type = exp;
- if (TREE_CODE (type) == REFERENCE_TYPE && !parms)
- {
- if (complain & tf_error)
- error ("invalid value-initialization of reference type");
- return error_mark_node;
- }
-
if (processing_template_decl)
{
- tree t = build_min (CAST_EXPR, type, parms);
+ tree t;
+
+ /* Diagnose this even in a template. We could also try harder
+ to give all the usual errors when the type and args are
+ non-dependent... */
+ if (TREE_CODE (type) == REFERENCE_TYPE && !parms)
+ {
+ if (complain & tf_error)
+ error ("invalid value-initialization of reference type");
+ return error_mark_node;
+ }
+
+ t = build_min (CAST_EXPR, type, parms);
/* We don't know if it will or will not have side effects. */
TREE_SIDE_EFFECTS (t) = 1;
return t;
[-- Attachment #6: sfinae-48450-abstract.patch --]
[-- Type: text/plain, Size: 7460 bytes --]
commit c1fb6653e14d8922f140569b606d681906779984
Author: Jason Merrill <jason@redhat.com>
Date: Tue Apr 5 14:19:56 2011 -0400
PR c++/48450
* tree.c (build_cplus_new, build_aggr_init_expr): Take complain.
(bot_manip): Adjust.
* cp-tree.h: Adjust.
* call.c (convert_like_real, build_cxx_call): Adjust.
(perform_direct_initialization_if_possible): Adjust.
* cvt.c (ocp_convert): Adjust.
* init.c (build_value_init): Adjust.
* semantics.c (maybe_add_lambda_conv_op): Adjust.
* typeck.c (unary_complex_lvalue, cp_build_modify_expr): Adjust.
* typeck2.c (build_functional_cast): Adjust.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index ad2de43..c273027 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5414,7 +5414,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
we need to build up a TARGET_EXPR. */
if (DECL_CONSTRUCTOR_P (convfn))
{
- expr = build_cplus_new (totype, expr);
+ expr = build_cplus_new (totype, expr, complain);
/* Remember that this was list-initialization. */
if (convs->check_narrowing)
@@ -5559,7 +5559,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
else if (diag_kind == DK_ERROR)
return error_mark_node;
}
- return build_cplus_new (totype, expr);
+ return build_cplus_new (totype, expr, complain);
case ck_ref_bind:
{
@@ -6476,7 +6476,7 @@ build_cxx_call (tree fn, int nargs, tree *argarray)
return error_mark_node;
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (fn)))
- fn = build_cplus_new (TREE_TYPE (fn), fn);
+ fn = build_cplus_new (TREE_TYPE (fn), fn, tf_warning_or_error);
return convert_from_reference (fn);
}
@@ -8119,7 +8119,7 @@ perform_direct_initialization_if_possible (tree type,
expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
&args, type, LOOKUP_NORMAL, complain);
release_tree_vector (args);
- return build_cplus_new (type, expr);
+ return build_cplus_new (type, expr, complain);
}
/* Get the high-water mark for the CONVERSION_OBSTACK. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 94bd3ce..ea251a8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5395,8 +5395,8 @@ extern tree build_min (enum tree_code, tree, ...);
extern tree build_min_nt (enum tree_code, ...);
extern tree build_min_non_dep (enum tree_code, tree, ...);
extern tree build_min_non_dep_call_vec (tree, tree, VEC(tree,gc) *);
-extern tree build_cplus_new (tree, tree);
-extern tree build_aggr_init_expr (tree, tree);
+extern tree build_cplus_new (tree, tree, tsubst_flags_t);
+extern tree build_aggr_init_expr (tree, tree, tsubst_flags_t);
extern tree get_target_expr (tree);
extern tree build_cplus_array_type (tree, tree);
extern tree build_array_of_n_type (tree, int);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 8ab0001..46c6eb4 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -813,7 +813,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
release_tree_vector (ctor_vec);
}
if (ctor)
- return build_cplus_new (type, ctor);
+ return build_cplus_new (type, ctor, tf_warning_or_error);
}
if (flags & LOOKUP_COMPLAIN)
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 005f8d6..3131690 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -342,7 +342,8 @@ build_value_init (tree type, tsubst_flags_t complain)
(type,
build_special_member_call (NULL_TREE, complete_ctor_identifier,
NULL, type, LOOKUP_NORMAL,
- complain));
+ complain),
+ complain);
else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type))
{
/* This is a class that needs constructing, but doesn't have
@@ -354,7 +355,7 @@ build_value_init (tree type, tsubst_flags_t complain)
NULL, type, LOOKUP_NORMAL, complain);
if (ctor != error_mark_node)
{
- ctor = build_aggr_init_expr (type, ctor);
+ ctor = build_aggr_init_expr (type, ctor, complain);
AGGR_INIT_ZERO_FIRST (ctor) = 1;
}
return ctor;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 5cbba33..30175af 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8429,7 +8429,7 @@ maybe_add_lambda_conv_op (tree type)
VEC_address (tree, argvec));
CALL_FROM_THUNK_P (call) = 1;
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
- call = build_cplus_new (TREE_TYPE (call), call);
+ call = build_cplus_new (TREE_TYPE (call), call, tf_warning_or_error);
call = convert_from_reference (call);
finish_return_stmt (call);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 070ba81..c2aa389 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -373,7 +373,7 @@ build_aggr_init_array (tree return_type, tree fn, tree slot, int nargs,
callable. */
tree
-build_aggr_init_expr (tree type, tree init)
+build_aggr_init_expr (tree type, tree init, tsubst_flags_t complain)
{
tree fn;
tree slot;
@@ -382,7 +382,9 @@ build_aggr_init_expr (tree type, tree init)
/* Make sure that we're not trying to create an instance of an
abstract class. */
- abstract_virtuals_error (NULL_TREE, type);
+ if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain)
+ && !(complain & tf_error))
+ return error_mark_node;
if (TREE_CODE (init) == CALL_EXPR)
fn = CALL_EXPR_FN (init);
@@ -437,9 +439,9 @@ build_aggr_init_expr (tree type, tree init)
and language-specific expression expanders. */
tree
-build_cplus_new (tree type, tree init)
+build_cplus_new (tree type, tree init, tsubst_flags_t complain)
{
- tree rval = build_aggr_init_expr (type, init);
+ tree rval = build_aggr_init_expr (type, init, complain);
tree slot;
if (TREE_CODE (rval) == AGGR_INIT_EXPR)
@@ -1805,7 +1807,8 @@ bot_manip (tree* tp, int* walk_subtrees, void* data)
tree u;
if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
- u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1));
+ u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1),
+ tf_warning_or_error);
else
u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t));
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a45ed2d..71cfd8c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5320,7 +5320,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
if (TREE_CODE (arg) == SAVE_EXPR)
targ = arg;
else
- targ = build_cplus_new (TREE_TYPE (arg), arg);
+ targ = build_cplus_new (TREE_TYPE (arg), arg, tf_warning_or_error);
return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), targ);
}
@@ -6742,7 +6742,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
{
if (TREE_CODE (newrhs) == CALL_EXPR
&& TYPE_NEEDS_CONSTRUCTING (lhstype))
- newrhs = build_cplus_new (lhstype, newrhs);
+ newrhs = build_cplus_new (lhstype, newrhs, complain);
/* Can't initialize directly from a TARGET_EXPR, since that would
cause the lhs to be constructed twice, and possibly result in
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index f3a0079..f67073b 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1614,7 +1614,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
if (exp == error_mark_node)
return error_mark_node;
- return build_cplus_new (type, exp);
+ return build_cplus_new (type, exp, complain);
}
\f
[-- Attachment #7: sfinae-48450-abstract-2.patch --]
[-- Type: text/plain, Size: 757 bytes --]
commit a6b0d17f42b4bb62fe638253cb8e032d416eb883
Author: Jason Merrill <jason@redhat.com>
Date: Wed Apr 6 00:27:18 2011 -0400
* tree.c (build_aggr_init_expr): Always return error_mark_node
on abstract violation.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index c2aa389..014986d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -382,8 +382,7 @@ build_aggr_init_expr (tree type, tree init, tsubst_flags_t complain)
/* Make sure that we're not trying to create an instance of an
abstract class. */
- if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain)
- && !(complain & tf_error))
+ if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
return error_mark_node;
if (TREE_CODE (init) == CALL_EXPR)
[-- Attachment #8: sfinae-48450-const.patch --]
[-- Type: text/plain, Size: 32316 bytes --]
commit e55c94447e50bdfaa1ca5c06ce57896364cbfeaf
Author: Jason Merrill <jason@redhat.com>
Date: Tue Apr 5 14:28:59 2011 -0400
PR c++/48450
* typeck.c (check_for_casting_away_constness): Take complain.
(build_static_cast_1, build_reinterpret_cast_1): Pass it.
(build_const_cast_1): Pass it. Take full complain parm.
(build_const_cast, cp_build_c_cast): Adjust.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 71cfd8c..8e3796e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5579,42 +5579,47 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain)
}
/* Issue a diagnostic message if casting from SRC_TYPE to DEST_TYPE
- casts away constness. CAST gives the type of cast.
+ casts away constness. CAST gives the type of cast. Returns true
+ if the cast is ill-formed, false if it is well-formed.
??? This function warns for casting away any qualifier not just
const. We would like to specify exactly what qualifiers are casted
away.
*/
-static void
+static bool
check_for_casting_away_constness (tree src_type, tree dest_type,
- enum tree_code cast)
+ enum tree_code cast, tsubst_flags_t complain)
{
/* C-style casts are allowed to cast away constness. With
WARN_CAST_QUAL, we still want to issue a warning. */
if (cast == CAST_EXPR && !warn_cast_qual)
- return;
+ return false;
if (!casts_away_constness (src_type, dest_type))
- return;
+ return false;
switch (cast)
{
case CAST_EXPR:
- warning (OPT_Wcast_qual,
- "cast from type %qT to type %qT casts away qualifiers",
- src_type, dest_type);
- return;
+ if (complain & tf_warning)
+ warning (OPT_Wcast_qual,
+ "cast from type %qT to type %qT casts away qualifiers",
+ src_type, dest_type);
+ return false;
case STATIC_CAST_EXPR:
- error ("static_cast from type %qT to type %qT casts away qualifiers",
- src_type, dest_type);
- return;
+ if (complain & tf_error)
+ error ("static_cast from type %qT to type %qT casts away qualifiers",
+ src_type, dest_type);
+ return true;
case REINTERPRET_CAST_EXPR:
- error ("reinterpret_cast from type %qT to type %qT casts away qualifiers",
- src_type, dest_type);
- return;
+ if (complain & tf_error)
+ error ("reinterpret_cast from type %qT to type %qT casts away qualifiers",
+ src_type, dest_type);
+ return true;
+
default:
gcc_unreachable();
}
@@ -5832,8 +5837,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
{
tree base;
- if (!c_cast_p)
- check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
+ if (!c_cast_p
+ && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
+ complain))
+ return error_mark_node;
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
c_cast_p ? ba_unique : ba_check,
NULL);
@@ -5868,10 +5875,13 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
}
if (can_convert (t1, t2) || can_convert (t2, t1))
{
- if (!c_cast_p)
- check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
+ if (!c_cast_p
+ && check_for_casting_away_constness (intype, type,
+ STATIC_CAST_EXPR,
+ complain))
+ return error_mark_node;
return convert_ptrmem (type, expr, /*allow_inverse_p=*/1,
- c_cast_p, tf_warning_or_error);
+ c_cast_p, complain);
}
}
@@ -5885,8 +5895,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
&& VOID_TYPE_P (TREE_TYPE (intype))
&& TYPE_PTROB_P (type))
{
- if (!c_cast_p)
- check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR);
+ if (!c_cast_p
+ && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
+ complain))
+ return error_mark_node;
return build_nop (type, expr);
}
@@ -6090,8 +6102,11 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
{
tree sexpr = expr;
- if (!c_cast_p)
- check_for_casting_away_constness (intype, type, REINTERPRET_CAST_EXPR);
+ if (!c_cast_p
+ && check_for_casting_away_constness (intype, type,
+ REINTERPRET_CAST_EXPR,
+ complain))
+ return error_mark_node;
/* Warn about possible alignment problems. */
if (STRICT_ALIGNMENT && warn_cast_align
&& (complain & tf_warning)
@@ -6168,7 +6183,7 @@ build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain)
whether or not the conversion succeeded. */
static tree
-build_const_cast_1 (tree dst_type, tree expr, bool complain,
+build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
bool *valid_p)
{
tree src_type;
@@ -6187,7 +6202,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
if (!POINTER_TYPE_P (dst_type) && !TYPE_PTRMEM_P (dst_type))
{
- if (complain)
+ if (complain & tf_error)
error ("invalid use of const_cast with type %qT, "
"which is not a pointer, "
"reference, nor a pointer-to-data-member type", dst_type);
@@ -6196,7 +6211,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
if (TREE_CODE (TREE_TYPE (dst_type)) == FUNCTION_TYPE)
{
- if (complain)
+ if (complain & tf_error)
error ("invalid use of const_cast with type %qT, which is a pointer "
"or reference to a function type", dst_type);
return error_mark_node;
@@ -6221,7 +6236,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
reference_type = dst_type;
if (! real_lvalue_p (expr))
{
- if (complain)
+ if (complain & tf_error)
error ("invalid const_cast of an rvalue of type %qT to type %qT",
src_type, dst_type);
return error_mark_node;
@@ -6248,12 +6263,12 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
*valid_p = true;
/* This cast is actually a C-style cast. Issue a warning if
the user is making a potentially unsafe cast. */
- check_for_casting_away_constness (src_type, dst_type, CAST_EXPR);
+ check_for_casting_away_constness (src_type, dst_type, CAST_EXPR,
+ complain);
}
if (reference_type)
{
- expr = cp_build_addr_expr (expr,
- complain ? tf_warning_or_error : tf_none);
+ expr = cp_build_addr_expr (expr, complain);
expr = build_nop (reference_type, expr);
return convert_from_reference (expr);
}
@@ -6270,7 +6285,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
}
}
- if (complain)
+ if (complain & tf_error)
error ("invalid const_cast from type %qT to type %qT",
src_type, dst_type);
return error_mark_node;
@@ -6293,7 +6308,7 @@ build_const_cast (tree type, tree expr, tsubst_flags_t complain)
return convert_from_reference (t);
}
- return build_const_cast_1 (type, expr, complain & tf_error,
+ return build_const_cast_1 (type, expr, complain,
/*valid_p=*/NULL);
}
@@ -6379,7 +6394,7 @@ cp_build_c_cast (tree type, tree expr, tsubst_flags_t complain)
"cast to pointer from integer of different size");
/* A C-style cast can be a const_cast. */
- result = build_const_cast_1 (type, value, /*complain=*/false,
+ result = build_const_cast_1 (type, value, complain & tf_warning,
&valid_p);
if (valid_p)
return result;
diff --git a/gcc/testsuite/c-c++-common/Wcast-qual-1.c b/gcc/testsuite/c-c++-common/Wcast-qual-1.c
new file mode 100644
index 0000000..640e4f0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wcast-qual-1.c
@@ -0,0 +1,162 @@
+/* { dg-do compile } */
+/* { dg-options "-Wcast-qual" } */
+
+void
+f1 (void *bar)
+{
+ const void *p1 = (const void *) bar;
+ const char *p2 = (const char *) bar;
+ const void **p3 = (const void **) bar;
+ const char **p4 = (const char **) bar;
+ const void * const *p5 = (const void * const *) bar;
+ const char * const *p6 = (const char * const *) bar;
+ void * const *p7 = (void * const *) bar;
+ char * const *p8 = (char * const *) bar;
+ const void ***p9 = (const void ***) bar;
+ const char ***p10 = (const char ***) bar;
+ void * const **p11 = (void * const **) bar;
+ char * const **p12 = (char * const **) bar;
+ void ** const *p13 = (void ** const *) bar;
+ char ** const *p14 = (char ** const *) bar;
+ const void * const **p15 = (const void * const **) bar;
+ const char * const **p16 = (const char * const **) bar;
+ const void ** const *p17 = (const void ** const *) bar;
+ const char ** const *p18 = (const char ** const *) bar;
+ void * const * const * p19 = (void * const * const *) bar;
+ char * const * const * p20 = (char * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+ const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f2 (void **bar)
+{
+ const void *p1 = (const void *) bar;
+ const char *p2 = (const char *) bar;
+ const void **p3 = (const void **) bar; /* { dg-warning "cast" } */
+ const char **p4 = (const char **) bar;
+ const void * const *p5 = (const void * const *) bar;
+ const char * const *p6 = (const char * const *) bar;
+ void * const *p7 = (void * const *) bar;
+ char * const *p8 = (char * const *) bar;
+ const void ***p9 = (const void ***) bar;
+ const char ***p10 = (const char ***) bar;
+ void * const **p11 = (void * const **) bar;
+ char * const **p12 = (char * const **) bar;
+ void ** const *p13 = (void ** const *) bar;
+ char ** const *p14 = (char ** const *) bar;
+ const void * const **p15 = (const void * const **) bar;
+ const char * const **p16 = (const char * const **) bar;
+ const void ** const *p17 = (const void ** const *) bar;
+ const char ** const *p18 = (const char ** const *) bar;
+ void * const * const * p19 = (void * const * const *) bar;
+ char * const * const * p20 = (char * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+ const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f3 (void ***bar)
+{
+ const void *p1 = (const void *) bar;
+ const char *p2 = (const char *) bar;
+ const void **p3 = (const void **) bar;
+ const char **p4 = (const char **) bar;
+ const void * const *p5 = (const void * const *) bar;
+ const char * const *p6 = (const char * const *) bar;
+ void * const *p7 = (void * const *) bar;
+ char * const *p8 = (char * const *) bar;
+ const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+ const char ***p10 = (const char ***) bar;
+ void * const **p11 = (void * const **) bar; /* { dg-warning "cast" } */
+ char * const **p12 = (char * const **) bar;
+ void ** const *p13 = (void ** const *) bar;
+ char ** const *p14 = (char ** const *) bar;
+ const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+ const char * const **p16 = (const char * const **) bar;
+ const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+ const char ** const *p18 = (const char ** const *) bar;
+ void * const * const * p19 = (void * const * const *) bar;
+ char * const * const * p20 = (char * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+ const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f4 (void * const **bar)
+{
+ const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+ void * const **p11 = (void * const **) bar;
+ void ** const *p13 = (void ** const *) bar; /* { dg-warning "cast" } */
+ const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+ const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+ void * const * const * p19 = (void * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+}
+
+void
+f5 (char ***bar)
+{
+ volatile const char ***p9 = (volatile const char ***) bar; /* { dg-warning "cast" } */
+ volatile char * const **p11 = (volatile char * const **) bar; /* { dg-warning "cast" } */
+ volatile char ** const *p13 = (volatile char ** const *) bar; /* { dg-warning "cast" } */
+ volatile const char * const **p15 = (volatile const char * const **) bar; /* { dg-warning "cast" } */
+ volatile const char ** const *p17 = (volatile const char ** const *) bar; /* { dg-warning "cast" } */
+ volatile char * const * const * p19 = (volatile char * const * const *) bar;
+ volatile const char * const * const *p21 = (volatile const char * const * const *) bar;
+}
+
+void
+f6 (char ***bar)
+{
+ const char * volatile **p9 = (const char * volatile **) bar; /* { dg-warning "cast" } */
+ char * volatile const **p11 = (char * volatile const **) bar; /* { dg-warning "cast" } */
+ char * volatile * const *p13 = (char * volatile * const *) bar;
+ const char * volatile const **p15 = (const char * volatile const **) bar; /* { dg-warning "cast" } */
+ const char * volatile * const *p17 = (const char * volatile * const *) bar; /* { dg-warning "cast" } */
+ char * volatile const * const * p19 = (char * volatile const * const *) bar;
+ const char * volatile const * const *p21 = (const char * volatile const * const *) bar;
+}
+
+void
+f7 (char ***bar)
+{
+ const char ** volatile *p9 = (const char ** volatile *) bar; /* { dg-warning "cast" } */
+ char * const * volatile *p11 = (char * const * volatile *) bar; /* { dg-warning "cast" } */
+ char ** volatile const *p13 = (char ** volatile const *) bar;
+ const char * const * volatile *p15 = (const char * const * volatile *) bar; /* { dg-warning "cast" } */
+ const char ** volatile const *p17 = (const char ** volatile const *) bar; /* { dg-warning "cast" } */
+ char * const * volatile const * p19 = (char * const * volatile const *) bar;
+ const char * const * volatile const *p21 = (const char * const * volatile const *) bar;
+}
+
+typedef int (intfn) (int);
+typedef intfn *pintfn;
+typedef const intfn *constfn;
+
+void
+f8 (constfn ***bar)
+{
+ const constfn *p1 = (const constfn *) bar;
+ const pintfn *p2 = (const pintfn *) bar;
+ const constfn **p3 = (const constfn **) bar;
+ const pintfn **p4 = (const pintfn **) bar;
+ const constfn * const *p5 = (const constfn * const *) bar;
+ const pintfn * const *p6 = (const pintfn * const *) bar;
+ constfn * const *p7 = (constfn * const *) bar;
+ pintfn * const *p8 = (pintfn * const *) bar;
+ const constfn ***p9 = (const constfn ***) bar; /* { dg-warning "cast" } */
+ const pintfn ***p10 = (const pintfn ***) bar; /* { dg-warning "cast" } */
+ constfn * const **p11 = (constfn * const **) bar; /* { dg-warning "cast" } */
+ pintfn * const **p12 = (pintfn * const **) bar; /* { dg-warning "cast" } */
+ constfn ** const *p13 = (constfn ** const *) bar;
+ pintfn ** const *p14 = (pintfn ** const *) bar;
+ const constfn * const **p15 = (const constfn * const **) bar; /* { dg-warning "cast" } */
+ const pintfn * const **p16 = (const pintfn * const **) bar; /* { dg-warning "cast" } */
+ const constfn ** const *p17 = (const constfn ** const *) bar; /* { dg-warning "cast" } */
+ const pintfn ** const *p18 = (const pintfn ** const *) bar; /* { dg-warning "cast" } */
+ constfn * const * const * p19 = (constfn * const * const *) bar;
+ pintfn * const * const * p20 = (pintfn * const * const *) bar;
+ const constfn * const * const *p21 = (const constfn * const * const *) bar;
+ const pintfn * const * const *p22 = (const pintfn * const * const *) bar;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wcast-qual2.C b/gcc/testsuite/g++.dg/warn/Wcast-qual2.C
deleted file mode 100644
index 88fdcfb..0000000
--- a/gcc/testsuite/g++.dg/warn/Wcast-qual2.C
+++ /dev/null
@@ -1,167 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-Wcast-qual" } */
-
-/* The files gcc.dg/cast-qual-3.c and g++.dg/warn/Wcast-qual2.c are
- duals. they are intended to show that gcc -Wcast-qual and g++
- -Wcast-qual emit warnings in the same cases. If you change this
- file, please also change the other one. */
-
-void
-f1 (void *bar)
-{
- const void *p1 = (const void *) bar;
- const char *p2 = (const char *) bar;
- const void **p3 = (const void **) bar;
- const char **p4 = (const char **) bar;
- const void * const *p5 = (const void * const *) bar;
- const char * const *p6 = (const char * const *) bar;
- void * const *p7 = (void * const *) bar;
- char * const *p8 = (char * const *) bar;
- const void ***p9 = (const void ***) bar;
- const char ***p10 = (const char ***) bar;
- void * const **p11 = (void * const **) bar;
- char * const **p12 = (char * const **) bar;
- void ** const *p13 = (void ** const *) bar;
- char ** const *p14 = (char ** const *) bar;
- const void * const **p15 = (const void * const **) bar;
- const char * const **p16 = (const char * const **) bar;
- const void ** const *p17 = (const void ** const *) bar;
- const char ** const *p18 = (const char ** const *) bar;
- void * const * const * p19 = (void * const * const *) bar;
- char * const * const * p20 = (char * const * const *) bar;
- const void * const * const *p21 = (const void * const * const *) bar;
- const char * const * const *p22 = (const char * const * const *) bar;
-}
-
-void
-f2 (void **bar)
-{
- const void *p1 = (const void *) bar;
- const char *p2 = (const char *) bar;
- const void **p3 = (const void **) bar; /* { dg-warning "cast" } */
- const char **p4 = (const char **) bar;
- const void * const *p5 = (const void * const *) bar;
- const char * const *p6 = (const char * const *) bar;
- void * const *p7 = (void * const *) bar;
- char * const *p8 = (char * const *) bar;
- const void ***p9 = (const void ***) bar;
- const char ***p10 = (const char ***) bar;
- void * const **p11 = (void * const **) bar;
- char * const **p12 = (char * const **) bar;
- void ** const *p13 = (void ** const *) bar;
- char ** const *p14 = (char ** const *) bar;
- const void * const **p15 = (const void * const **) bar;
- const char * const **p16 = (const char * const **) bar;
- const void ** const *p17 = (const void ** const *) bar;
- const char ** const *p18 = (const char ** const *) bar;
- void * const * const * p19 = (void * const * const *) bar;
- char * const * const * p20 = (char * const * const *) bar;
- const void * const * const *p21 = (const void * const * const *) bar;
- const char * const * const *p22 = (const char * const * const *) bar;
-}
-
-void
-f3 (void ***bar)
-{
- const void *p1 = (const void *) bar;
- const char *p2 = (const char *) bar;
- const void **p3 = (const void **) bar;
- const char **p4 = (const char **) bar;
- const void * const *p5 = (const void * const *) bar;
- const char * const *p6 = (const char * const *) bar;
- void * const *p7 = (void * const *) bar;
- char * const *p8 = (char * const *) bar;
- const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
- const char ***p10 = (const char ***) bar;
- void * const **p11 = (void * const **) bar; /* { dg-warning "cast" } */
- char * const **p12 = (char * const **) bar;
- void ** const *p13 = (void ** const *) bar;
- char ** const *p14 = (char ** const *) bar;
- const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
- const char * const **p16 = (const char * const **) bar;
- const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
- const char ** const *p18 = (const char ** const *) bar;
- void * const * const * p19 = (void * const * const *) bar;
- char * const * const * p20 = (char * const * const *) bar;
- const void * const * const *p21 = (const void * const * const *) bar;
- const char * const * const *p22 = (const char * const * const *) bar;
-}
-
-void
-f4 (void * const **bar)
-{
- const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
- void * const **p11 = (void * const **) bar;
- void ** const *p13 = (void ** const *) bar; /* { dg-warning "cast" } */
- const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
- const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
- void * const * const * p19 = (void * const * const *) bar;
- const void * const * const *p21 = (const void * const * const *) bar;
-}
-
-void
-f5 (char ***bar)
-{
- volatile const char ***p9 = (volatile const char ***) bar; /* { dg-warning "cast" } */
- volatile char * const **p11 = (volatile char * const **) bar; /* { dg-warning "cast" } */
- volatile char ** const *p13 = (volatile char ** const *) bar; /* { dg-warning "cast" } */
- volatile const char * const **p15 = (volatile const char * const **) bar; /* { dg-warning "cast" } */
- volatile const char ** const *p17 = (volatile const char ** const *) bar; /* { dg-warning "cast" } */
- volatile char * const * const * p19 = (volatile char * const * const *) bar;
- volatile const char * const * const *p21 = (volatile const char * const * const *) bar;
-}
-
-void
-f6 (char ***bar)
-{
- const char * volatile **p9 = (const char * volatile **) bar; /* { dg-warning "cast" } */
- char * volatile const **p11 = (char * volatile const **) bar; /* { dg-warning "cast" } */
- char * volatile * const *p13 = (char * volatile * const *) bar;
- const char * volatile const **p15 = (const char * volatile const **) bar; /* { dg-warning "cast" } */
- const char * volatile * const *p17 = (const char * volatile * const *) bar; /* { dg-warning "cast" } */
- char * volatile const * const * p19 = (char * volatile const * const *) bar;
- const char * volatile const * const *p21 = (const char * volatile const * const *) bar;
-}
-
-void
-f7 (char ***bar)
-{
- const char ** volatile *p9 = (const char ** volatile *) bar; /* { dg-warning "cast" } */
- char * const * volatile *p11 = (char * const * volatile *) bar; /* { dg-warning "cast" } */
- char ** volatile const *p13 = (char ** volatile const *) bar;
- const char * const * volatile *p15 = (const char * const * volatile *) bar; /* { dg-warning "cast" } */
- const char ** volatile const *p17 = (const char ** volatile const *) bar; /* { dg-warning "cast" } */
- char * const * volatile const * p19 = (char * const * volatile const *) bar;
- const char * const * volatile const *p21 = (const char * const * volatile const *) bar;
-}
-
-typedef int (intfn) (int);
-typedef intfn *pintfn;
-typedef const intfn *constfn;
-
-void
-f8 (constfn ***bar)
-{
- const constfn *p1 = (const constfn *) bar;
- const pintfn *p2 = (const pintfn *) bar;
- const constfn **p3 = (const constfn **) bar;
- const pintfn **p4 = (const pintfn **) bar;
- const constfn * const *p5 = (const constfn * const *) bar;
- const pintfn * const *p6 = (const pintfn * const *) bar;
- constfn * const *p7 = (constfn * const *) bar;
- pintfn * const *p8 = (pintfn * const *) bar;
- const constfn ***p9 = (const constfn ***) bar; /* { dg-warning "cast" } */
- const pintfn ***p10 = (const pintfn ***) bar; /* { dg-warning "cast" } */
- constfn * const **p11 = (constfn * const **) bar; /* { dg-warning "cast" } */
- pintfn * const **p12 = (pintfn * const **) bar; /* { dg-warning "cast" } */
- constfn ** const *p13 = (constfn ** const *) bar;
- pintfn ** const *p14 = (pintfn ** const *) bar;
- const constfn * const **p15 = (const constfn * const **) bar; /* { dg-warning "cast" } */
- const pintfn * const **p16 = (const pintfn * const **) bar; /* { dg-warning "cast" } */
- const constfn ** const *p17 = (const constfn ** const *) bar; /* { dg-warning "cast" } */
- const pintfn ** const *p18 = (const pintfn ** const *) bar; /* { dg-warning "cast" } */
- constfn * const * const * p19 = (constfn * const * const *) bar;
- pintfn * const * const * p20 = (pintfn * const * const *) bar;
- const constfn * const * const *p21 = (const constfn * const * const *) bar;
- const pintfn * const * const *p22 = (const pintfn * const * const *) bar;
-}
diff --git a/gcc/testsuite/gcc.dg/cast-qual-3.c b/gcc/testsuite/gcc.dg/cast-qual-3.c
deleted file mode 100644
index 88fdcfb..0000000
--- a/gcc/testsuite/gcc.dg/cast-qual-3.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-Wcast-qual" } */
-
-/* The files gcc.dg/cast-qual-3.c and g++.dg/warn/Wcast-qual2.c are
- duals. they are intended to show that gcc -Wcast-qual and g++
- -Wcast-qual emit warnings in the same cases. If you change this
- file, please also change the other one. */
-
-void
-f1 (void *bar)
-{
- const void *p1 = (const void *) bar;
- const char *p2 = (const char *) bar;
- const void **p3 = (const void **) bar;
- const char **p4 = (const char **) bar;
- const void * const *p5 = (const void * const *) bar;
- const char * const *p6 = (const char * const *) bar;
- void * const *p7 = (void * const *) bar;
- char * const *p8 = (char * const *) bar;
- const void ***p9 = (const void ***) bar;
- const char ***p10 = (const char ***) bar;
- void * const **p11 = (void * const **) bar;
- char * const **p12 = (char * const **) bar;
- void ** const *p13 = (void ** const *) bar;
- char ** const *p14 = (char ** const *) bar;
- const void * const **p15 = (const void * const **) bar;
- const char * const **p16 = (const char * const **) bar;
- const void ** const *p17 = (const void ** const *) bar;
- const char ** const *p18 = (const char ** const *) bar;
- void * const * const * p19 = (void * const * const *) bar;
- char * const * const * p20 = (char * const * const *) bar;
- const void * const * const *p21 = (const void * const * const *) bar;
- const char * const * const *p22 = (const char * const * const *) bar;
-}
-
-void
-f2 (void **bar)
-{
- const void *p1 = (const void *) bar;
- const char *p2 = (const char *) bar;
- const void **p3 = (const void **) bar; /* { dg-warning "cast" } */
- const char **p4 = (const char **) bar;
- const void * const *p5 = (const void * const *) bar;
- const char * const *p6 = (const char * const *) bar;
- void * const *p7 = (void * const *) bar;
- char * const *p8 = (char * const *) bar;
- const void ***p9 = (const void ***) bar;
- const char ***p10 = (const char ***) bar;
- void * const **p11 = (void * const **) bar;
- char * const **p12 = (char * const **) bar;
- void ** const *p13 = (void ** const *) bar;
- char ** const *p14 = (char ** const *) bar;
- const void * const **p15 = (const void * const **) bar;
- const char * const **p16 = (const char * const **) bar;
- const void ** const *p17 = (const void ** const *) bar;
- const char ** const *p18 = (const char ** const *) bar;
- void * const * const * p19 = (void * const * const *) bar;
- char * const * const * p20 = (char * const * const *) bar;
- const void * const * const *p21 = (const void * const * const *) bar;
- const char * const * const *p22 = (const char * const * const *) bar;
-}
-
-void
-f3 (void ***bar)
-{
- const void *p1 = (const void *) bar;
- const char *p2 = (const char *) bar;
- const void **p3 = (const void **) bar;
- const char **p4 = (const char **) bar;
- const void * const *p5 = (const void * const *) bar;
- const char * const *p6 = (const char * const *) bar;
- void * const *p7 = (void * const *) bar;
- char * const *p8 = (char * const *) bar;
- const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
- const char ***p10 = (const char ***) bar;
- void * const **p11 = (void * const **) bar; /* { dg-warning "cast" } */
- char * const **p12 = (char * const **) bar;
- void ** const *p13 = (void ** const *) bar;
- char ** const *p14 = (char ** const *) bar;
- const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
- const char * const **p16 = (const char * const **) bar;
- const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
- const char ** const *p18 = (const char ** const *) bar;
- void * const * const * p19 = (void * const * const *) bar;
- char * const * const * p20 = (char * const * const *) bar;
- const void * const * const *p21 = (const void * const * const *) bar;
- const char * const * const *p22 = (const char * const * const *) bar;
-}
-
-void
-f4 (void * const **bar)
-{
- const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
- void * const **p11 = (void * const **) bar;
- void ** const *p13 = (void ** const *) bar; /* { dg-warning "cast" } */
- const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
- const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
- void * const * const * p19 = (void * const * const *) bar;
- const void * const * const *p21 = (const void * const * const *) bar;
-}
-
-void
-f5 (char ***bar)
-{
- volatile const char ***p9 = (volatile const char ***) bar; /* { dg-warning "cast" } */
- volatile char * const **p11 = (volatile char * const **) bar; /* { dg-warning "cast" } */
- volatile char ** const *p13 = (volatile char ** const *) bar; /* { dg-warning "cast" } */
- volatile const char * const **p15 = (volatile const char * const **) bar; /* { dg-warning "cast" } */
- volatile const char ** const *p17 = (volatile const char ** const *) bar; /* { dg-warning "cast" } */
- volatile char * const * const * p19 = (volatile char * const * const *) bar;
- volatile const char * const * const *p21 = (volatile const char * const * const *) bar;
-}
-
-void
-f6 (char ***bar)
-{
- const char * volatile **p9 = (const char * volatile **) bar; /* { dg-warning "cast" } */
- char * volatile const **p11 = (char * volatile const **) bar; /* { dg-warning "cast" } */
- char * volatile * const *p13 = (char * volatile * const *) bar;
- const char * volatile const **p15 = (const char * volatile const **) bar; /* { dg-warning "cast" } */
- const char * volatile * const *p17 = (const char * volatile * const *) bar; /* { dg-warning "cast" } */
- char * volatile const * const * p19 = (char * volatile const * const *) bar;
- const char * volatile const * const *p21 = (const char * volatile const * const *) bar;
-}
-
-void
-f7 (char ***bar)
-{
- const char ** volatile *p9 = (const char ** volatile *) bar; /* { dg-warning "cast" } */
- char * const * volatile *p11 = (char * const * volatile *) bar; /* { dg-warning "cast" } */
- char ** volatile const *p13 = (char ** volatile const *) bar;
- const char * const * volatile *p15 = (const char * const * volatile *) bar; /* { dg-warning "cast" } */
- const char ** volatile const *p17 = (const char ** volatile const *) bar; /* { dg-warning "cast" } */
- char * const * volatile const * p19 = (char * const * volatile const *) bar;
- const char * const * volatile const *p21 = (const char * const * volatile const *) bar;
-}
-
-typedef int (intfn) (int);
-typedef intfn *pintfn;
-typedef const intfn *constfn;
-
-void
-f8 (constfn ***bar)
-{
- const constfn *p1 = (const constfn *) bar;
- const pintfn *p2 = (const pintfn *) bar;
- const constfn **p3 = (const constfn **) bar;
- const pintfn **p4 = (const pintfn **) bar;
- const constfn * const *p5 = (const constfn * const *) bar;
- const pintfn * const *p6 = (const pintfn * const *) bar;
- constfn * const *p7 = (constfn * const *) bar;
- pintfn * const *p8 = (pintfn * const *) bar;
- const constfn ***p9 = (const constfn ***) bar; /* { dg-warning "cast" } */
- const pintfn ***p10 = (const pintfn ***) bar; /* { dg-warning "cast" } */
- constfn * const **p11 = (constfn * const **) bar; /* { dg-warning "cast" } */
- pintfn * const **p12 = (pintfn * const **) bar; /* { dg-warning "cast" } */
- constfn ** const *p13 = (constfn ** const *) bar;
- pintfn ** const *p14 = (pintfn ** const *) bar;
- const constfn * const **p15 = (const constfn * const **) bar; /* { dg-warning "cast" } */
- const pintfn * const **p16 = (const pintfn * const **) bar; /* { dg-warning "cast" } */
- const constfn ** const *p17 = (const constfn ** const *) bar; /* { dg-warning "cast" } */
- const pintfn ** const *p18 = (const pintfn ** const *) bar; /* { dg-warning "cast" } */
- constfn * const * const * p19 = (constfn * const * const *) bar;
- pintfn * const * const * p20 = (pintfn * const * const *) bar;
- const constfn * const * const *p21 = (const constfn * const * const *) bar;
- const pintfn * const * const *p22 = (const pintfn * const * const *) bar;
-}
[-- Attachment #9: sfinae-48450-void-arg.patch --]
[-- Type: text/plain, Size: 3117 bytes --]
commit dae42c0509e234d0cbcb148d35b9aeb35b3cf5fa
Author: Jason Merrill <jason@redhat.com>
Date: Tue Apr 5 14:31:54 2011 -0400
PR c++/48450
* call.c (resolve_args): Take complain.
(build_new_function_call, build_operator_new_call): Pass it.
(build_op_call, build_new_op, build_new_method_call): Pass it.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c273027..f283bd1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -155,7 +155,6 @@ static tree convert_like_real (conversion *, tree, tree, int, int, bool,
bool, tsubst_flags_t);
static void op_error (enum tree_code, enum tree_code, tree, tree,
tree, bool);
-static VEC(tree,gc) *resolve_args (VEC(tree,gc) *);
static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
static void print_z_candidate (const char *, struct z_candidate *);
static void print_z_candidates (location_t, struct z_candidate *);
@@ -3525,7 +3524,7 @@ build_integral_nontype_arg_conv (tree type, tree expr, tsubst_flags_t complain)
/* Do any initial processing on the arguments to a function call. */
static VEC(tree,gc) *
-resolve_args (VEC(tree,gc) *args)
+resolve_args (VEC(tree,gc) *args, tsubst_flags_t complain)
{
unsigned int ix;
tree arg;
@@ -3536,7 +3535,8 @@ resolve_args (VEC(tree,gc) *args)
return NULL;
else if (VOID_TYPE_P (TREE_TYPE (arg)))
{
- error ("invalid use of void expression");
+ if (complain & tf_error)
+ error ("invalid use of void expression");
return NULL;
}
else if (invalid_nonstatic_memfn_p (arg, tf_warning_or_error))
@@ -3636,7 +3636,7 @@ build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p,
if (args != NULL && *args != NULL)
{
- *args = resolve_args (*args);
+ *args = resolve_args (*args, complain);
if (*args == NULL)
return error_mark_node;
}
@@ -3707,7 +3707,7 @@ build_operator_new_call (tree fnname, VEC(tree,gc) **args,
if (fn)
*fn = NULL_TREE;
VEC_safe_insert (tree, gc, *args, 0, *size);
- *args = resolve_args (*args);
+ *args = resolve_args (*args, tf_warning_or_error);
if (*args == NULL)
return error_mark_node;
@@ -3820,7 +3820,7 @@ build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain)
if (args != NULL && *args != NULL)
{
- *args = resolve_args (*args);
+ *args = resolve_args (*args, complain);
if (*args == NULL)
return error_mark_node;
}
@@ -4864,7 +4864,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
if (overloaded_p)
*overloaded_p = true;
- if (resolve_args (arglist) == NULL)
+ if (resolve_args (arglist, complain) == NULL)
result = error_mark_node;
else
result = build_over_call (cand, LOOKUP_NORMAL, complain);
@@ -6850,7 +6850,7 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
/* Process the argument list. */
if (args != NULL && *args != NULL)
{
- *args = resolve_args (*args);
+ *args = resolve_args (*args, complain);
if (*args == NULL)
return error_mark_node;
}
[-- Attachment #10: sfinae-48452.patch --]
[-- Type: text/plain, Size: 1359 bytes --]
commit 9690fccd312c95916260a0ba5f07e397af811b37
Author: Jason Merrill <jason@redhat.com>
Date: Tue Apr 5 22:02:35 2011 -0400
PR c++/48452
* typeck.c (build_x_compound_expr_from_list): Return error_mark_node
in SFINAE context.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 8e3796e..ecd7d41 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5472,6 +5472,8 @@ build_x_compound_expr_from_list (tree list, expr_list_kind exp,
default:
gcc_unreachable ();
}
+ else
+ return error_mark_node;
for (list = TREE_CHAIN (list); list; list = TREE_CHAIN (list))
expr = build_x_compound_expr (expr, TREE_VALUE (list),
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae10.C b/gcc/testsuite/g++.dg/cpp0x/sfinae10.C
new file mode 100644
index 0000000..ede8b70
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae10.C
@@ -0,0 +1,18 @@
+// PR c++/48452
+// { dg-options -std=c++0x }
+namespace std {
+ template <class T> T&& declval();
+}
+
+template<class T, class... Args>
+decltype(T(std::declval<Args>()...), char()) f(int);
+
+template<class, class...>
+char (&f(...))[2];
+
+struct A { virtual ~A() = 0; };
+struct B {};
+
+static_assert(sizeof(f<A, int, int>(0)) != 1, "Error"); // a
+static_assert(sizeof(f<B, void, int>(0)) != 1, "Error"); // b
+static_assert(sizeof(f<void, int, int>(0)) != 1, "Error"); // c
[-- Attachment #11: sfinae-48468.patch --]
[-- Type: text/plain, Size: 2902 bytes --]
commit 6248bb19d8ddf86496da79db44ec14f7cca6dcef
Author: Jason Merrill <jason@redhat.com>
Date: Wed Apr 6 09:39:28 2011 -0400
PR c++/48468
* except.c (build_noexcept_spec): Propagate error_mark_node.
(finish_noexcept_expr): Likewise.
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index a814d67..874f111 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -1125,6 +1125,9 @@ finish_noexcept_expr (tree expr, tsubst_flags_t complain)
{
tree fn;
+ if (expr == error_mark_node)
+ return error_mark_node;
+
if (processing_template_decl)
return build_min (NOEXCEPT_EXPR, boolean_type_node, expr);
@@ -1212,6 +1215,8 @@ build_noexcept_spec (tree expr, int complain)
return noexcept_true_spec;
else if (expr == boolean_false_node)
return noexcept_false_spec;
+ else if (expr == error_mark_node)
+ return error_mark_node;
else
{
gcc_assert (processing_template_decl || expr == error_mark_node);
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept02.C b/gcc/testsuite/g++.dg/cpp0x/noexcept02.C
index be6fa00..60015e7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept02.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept02.C
@@ -46,7 +46,9 @@ SA(!noexcept(f3(A())));
template <class T1, class T2>
void f (T1, T2) noexcept(noexcept(T1(), T2()));
-SA(noexcept(f3(1,1)));
+struct B { };
+
+SA(noexcept(f3(1,B())));
SA(!noexcept(f3(1,A())));
SA(!noexcept(f3(A(),1)));
SA(!noexcept(f3(A(),A())));
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C
new file mode 100644
index 0000000..a3ffc34
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C
@@ -0,0 +1,56 @@
+// PR c++/48468
+// { dg-options -std=c++0x }
+// { dg-prune-output "note" }
+
+template<class T>
+T&& declval() noexcept;
+
+template< class T >
+inline void f1( T& x ) noexcept( noexcept( declval<T&>().foo() ) )
+{
+ x.foo();
+}
+
+template< class T,
+ bool Noexcept = noexcept( declval<T&>().foo() )
+>
+inline void f2( T& x ) noexcept( Noexcept )
+{
+ x.foo();
+}
+
+// a common and trivial mistake
+template< class T >
+inline void f3( T& x ) noexcept( declval<T&>().foo() )
+{
+ x.foo();
+}
+
+struct X
+{
+ void foo();
+};
+
+struct Y
+{
+ void foo() noexcept;
+};
+
+struct Z {};
+
+int main()
+{
+ X x; Y y; Z z;
+
+ static_assert( !noexcept( f1(x) ), "OK." );
+ static_assert( !noexcept( f2(x) ), "OK." );
+ // static_assert( !noexcept( f3(x) ), "shall be ill-formed(OK)." );
+
+ static_assert( noexcept( f1(y) ), "OK." );
+ static_assert( noexcept( f2(y) ), "OK." );
+ // static_assert( noexcept( f3(y) ), "shall be ill-formed(OK)." );
+
+ static_assert( noexcept( f1(z) ), "shall be ill-formed." ); // { dg-error "no match" }
+ static_assert( noexcept( f2(z) ), "shall be ill-formed." ); // { dg-error "no match" }
+ static_assert( !noexcept( f3(z) ), "shall be ill-formed." ); // { dg-error "no match" }
+}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: Many C++ PATCHes for SFINAE fixes
2011-04-07 21:33 Many C++ PATCHes for SFINAE fixes Jason Merrill
@ 2011-04-09 14:00 ` H.J. Lu
0 siblings, 0 replies; 2+ messages in thread
From: H.J. Lu @ 2011-04-09 14:00 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches List
n Thu, Apr 7, 2011 at 2:32 PM, Jason Merrill <jason@redhat.com> wrote:
> People have been finding other places where we haven't been handling SFINAE
> properly. In many cases, there are two patches for each fix; the first one
> fixes the bug conservatively (for possible application to 4.6), and the
> second one reorganizes things to be cleaner.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.
>
>
> commit 9690fccd312c95916260a0ba5f07e397af811b37
> Author: Jason Merrill <jason@redhat.com>
> Date: Tue Apr 5 22:02:35 2011 -0400
>
> PR c++/48452
> * typeck.c (build_x_compound_expr_from_list): Return error_mark_node
> in SFINAE context.
>
> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> index 8e3796e..ecd7d41 100644
> --- a/gcc/cp/typeck.c
> +++ b/gcc/cp/typeck.c
> @@ -5472,6 +5472,8 @@ build_x_compound_expr_from_list (tree list,
> expr_list_kind exp,
> default:
> gcc_unreachable ();
> }
> + else
> + return error_mark_node;
>
> for (list = TREE_CHAIN (list); list; list = TREE_CHAIN (list))
> expr = build_x_compound_expr (expr, TREE_VALUE (list),
> diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae10.C
> b/gcc/testsuite/g++.dg/cpp0x/sfinae10.C
> new file mode 100644
> index 0000000..ede8b70
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae10.C
> @@ -0,0 +1,18 @@
> +// PR c++/48452
> +// { dg-options -std=c++0x }
> +namespace std {
> + template <class T> T&& declval();
> +}
> +
> +template<class T, class... Args>
> +decltype(T(std::declval<Args>()...), char()) f(int);
> +
> +template<class, class...>
> +char (&f(...))[2];
> +
> +struct A { virtual ~A() = 0; };
> +struct B {};
> +
> +static_assert(sizeof(f<A, int, int>(0)) != 1, "Error"); // a
> +static_assert(sizeof(f<B, void, int>(0)) != 1, "Error"); // b
> +static_assert(sizeof(f<void, int, int>(0)) != 1, "Error"); // c
>
This caused:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48528
--
H.J.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2011-04-09 14:00 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-07 21:33 Many C++ PATCHes for SFINAE fixes Jason Merrill
2011-04-09 14:00 ` H.J. Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).