Commit 309714d4 by Jason Merrill Committed by Jason Merrill

typeck.c (complete_type_or_maybe_complain): Split out from...

	* typeck.c (complete_type_or_maybe_complain): Split out from...
	(complete_type_or_else): Here.
	(build_class_member_access_expr): Call it.
	(finish_class_member_access_expr): Likewise.
	* call.c (build_special_member_call): Likewise.
	* cvt.c (build_expr_type_conversion): Likewise.
	* init.c (build_new): Likewise.
	* typeck2.c (build_functional_cast): Likewise.
	* cp-tree.h: Declare it.

	* init.c (build_value_init): Add complain parm.
	(build_value_init_noctor): Likewise.
	(perform_member_init): Pass it.
	(expand_aggr_init_1): Likewise.
	(build_new_1): Likewise.
	(build_vec_init): Likewise.
	* pt.c (tsubst_expr): Likewise.
	* typeck2.c (build_functional_cast): Likewise.
	* cp-tree.h: Adjust.
	* tree.c (build_target_expr_with_type): Handle error_mark_node.

From-SVN: r162953
parent 0c32fb95
2010-08-06 Jason Merrill <jason@redhat.com> 2010-08-06 Jason Merrill <jason@redhat.com>
* typeck.c (complete_type_or_maybe_complain): Split out from...
(complete_type_or_else): Here.
(build_class_member_access_expr): Call it.
(finish_class_member_access_expr): Likewise.
* call.c (build_special_member_call): Likewise.
* cvt.c (build_expr_type_conversion): Likewise.
* init.c (build_new): Likewise.
* typeck2.c (build_functional_cast): Likewise.
* cp-tree.h: Declare it.
* init.c (build_value_init): Add complain parm.
(build_value_init_noctor): Likewise.
(perform_member_init): Pass it.
(expand_aggr_init_1): Likewise.
(build_new_1): Likewise.
(build_vec_init): Likewise.
* pt.c (tsubst_expr): Likewise.
* typeck2.c (build_functional_cast): Likewise.
* cp-tree.h: Adjust.
* tree.c (build_target_expr_with_type): Handle error_mark_node.
* typeck.c (decay_conversion): Any expression with type nullptr_t * typeck.c (decay_conversion): Any expression with type nullptr_t
decays to nullptr. decays to nullptr.
......
...@@ -6189,7 +6189,7 @@ build_special_member_call (tree instance, tree name, VEC(tree,gc) **args, ...@@ -6189,7 +6189,7 @@ build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
if (TYPE_P (binfo)) if (TYPE_P (binfo))
{ {
/* Resolve the name. */ /* Resolve the name. */
if (!complete_type_or_else (binfo, NULL_TREE)) if (!complete_type_or_maybe_complain (binfo, NULL_TREE, complain))
return error_mark_node; return error_mark_node;
binfo = TYPE_BINFO (binfo); binfo = TYPE_BINFO (binfo);
......
...@@ -4915,8 +4915,8 @@ extern tree build_aggr_init (tree, tree, int, ...@@ -4915,8 +4915,8 @@ extern tree build_aggr_init (tree, tree, int,
extern int is_class_type (tree, int); extern int is_class_type (tree, int);
extern tree get_type_value (tree); extern tree get_type_value (tree);
extern tree build_zero_init (tree, tree, bool); extern tree build_zero_init (tree, tree, bool);
extern tree build_value_init (tree); extern tree build_value_init (tree, tsubst_flags_t);
extern tree build_value_init_noctor (tree); extern tree build_value_init_noctor (tree, tsubst_flags_t);
extern tree build_offset_ref (tree, tree, bool); extern tree build_offset_ref (tree, tree, bool);
extern tree build_new (VEC(tree,gc) **, tree, tree, extern tree build_new (VEC(tree,gc) **, tree, tree,
VEC(tree,gc) **, int, VEC(tree,gc) **, int,
...@@ -5419,6 +5419,7 @@ extern tree condition_conversion (tree); ...@@ -5419,6 +5419,7 @@ extern tree condition_conversion (tree);
extern tree require_complete_type (tree); extern tree require_complete_type (tree);
extern tree complete_type (tree); extern tree complete_type (tree);
extern tree complete_type_or_else (tree, tree); extern tree complete_type_or_else (tree, tree);
extern tree complete_type_or_maybe_complain (tree, tree, tsubst_flags_t);
extern int type_unknown_p (const_tree); extern int type_unknown_p (const_tree);
enum { ce_derived, ce_normal, ce_exact }; enum { ce_derived, ce_normal, ce_exact };
extern bool comp_except_specs (const_tree, const_tree, int); extern bool comp_except_specs (const_tree, const_tree, int);
......
...@@ -1468,7 +1468,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain) ...@@ -1468,7 +1468,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
/* The code for conversions from class type is currently only used for /* The code for conversions from class type is currently only used for
delete expressions. Other expressions are handled by build_new_op. */ delete expressions. Other expressions are handled by build_new_op. */
if (!complete_type_or_else (basetype, expr)) if (!complete_type_or_maybe_complain (basetype, expr, complain))
return error_mark_node; return error_mark_node;
if (!TYPE_HAS_CONVERSION (basetype)) if (!TYPE_HAS_CONVERSION (basetype))
return NULL_TREE; return NULL_TREE;
......
...@@ -269,7 +269,7 @@ build_zero_init (tree type, tree nelts, bool static_storage_p) ...@@ -269,7 +269,7 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
TYPE, as described in [dcl.init]. */ TYPE, as described in [dcl.init]. */
tree tree
build_value_init (tree type) build_value_init (tree type, tsubst_flags_t complain)
{ {
/* [dcl.init] /* [dcl.init]
...@@ -302,7 +302,7 @@ build_value_init (tree type) ...@@ -302,7 +302,7 @@ build_value_init (tree type)
(type, (type,
build_special_member_call (NULL_TREE, complete_ctor_identifier, build_special_member_call (NULL_TREE, complete_ctor_identifier,
NULL, type, LOOKUP_NORMAL, NULL, type, LOOKUP_NORMAL,
tf_warning_or_error)); complain));
else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type)) else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type))
{ {
/* This is a class that needs constructing, but doesn't have /* This is a class that needs constructing, but doesn't have
...@@ -311,21 +311,21 @@ build_value_init (tree type) ...@@ -311,21 +311,21 @@ build_value_init (tree type)
This will be handled in simplify_aggr_init_expr. */ This will be handled in simplify_aggr_init_expr. */
tree ctor = build_special_member_call tree ctor = build_special_member_call
(NULL_TREE, complete_ctor_identifier, (NULL_TREE, complete_ctor_identifier,
NULL, type, LOOKUP_NORMAL, tf_warning_or_error); NULL, type, LOOKUP_NORMAL, complain);
ctor = build_aggr_init_expr (type, ctor); ctor = build_aggr_init_expr (type, ctor);
AGGR_INIT_ZERO_FIRST (ctor) = 1; AGGR_INIT_ZERO_FIRST (ctor) = 1;
return ctor; return ctor;
} }
} }
return build_value_init_noctor (type); return build_value_init_noctor (type, complain);
} }
/* Like build_value_init, but don't call the constructor for TYPE. Used /* Like build_value_init, but don't call the constructor for TYPE. Used
for base initializers. */ for base initializers. */
tree tree
build_value_init_noctor (tree type) build_value_init_noctor (tree type, tsubst_flags_t complain)
{ {
if (CLASS_TYPE_P (type)) if (CLASS_TYPE_P (type))
{ {
...@@ -347,7 +347,12 @@ build_value_init_noctor (tree type) ...@@ -347,7 +347,12 @@ build_value_init_noctor (tree type)
ftype = TREE_TYPE (field); ftype = TREE_TYPE (field);
if (TREE_CODE (ftype) == REFERENCE_TYPE) if (TREE_CODE (ftype) == REFERENCE_TYPE)
error ("value-initialization of reference"); {
if (complain & tf_error)
error ("value-initialization of reference");
else
return error_mark_node;
}
/* We could skip vfields and fields of types with /* We could skip vfields and fields of types with
user-defined constructors, but I think that won't improve user-defined constructors, but I think that won't improve
...@@ -359,7 +364,7 @@ build_value_init_noctor (tree type) ...@@ -359,7 +364,7 @@ build_value_init_noctor (tree type)
corresponding to base classes as well. Thus, iterating corresponding to base classes as well. Thus, iterating
over TYPE_FIELDs will result in correct initialization of over TYPE_FIELDs will result in correct initialization of
all of the subobjects. */ all of the subobjects. */
value = build_value_init (ftype); value = build_value_init (ftype, complain);
if (value) if (value)
CONSTRUCTOR_APPEND_ELT(v, field, value); CONSTRUCTOR_APPEND_ELT(v, field, value);
...@@ -401,7 +406,7 @@ build_value_init_noctor (tree type) ...@@ -401,7 +406,7 @@ build_value_init_noctor (tree type)
ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node, ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
max_index); max_index);
ce->value = build_value_init (TREE_TYPE (type)); ce->value = build_value_init (TREE_TYPE (type), complain);
/* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs. */ /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs. */
gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR
...@@ -459,7 +464,8 @@ perform_member_init (tree member, tree init) ...@@ -459,7 +464,8 @@ perform_member_init (tree member, tree init)
member); member);
else else
{ {
init = build2 (INIT_EXPR, type, decl, build_value_init (type)); init = build2 (INIT_EXPR, type, decl,
build_value_init (type, tf_warning_or_error));
finish_expr_stmt (init); finish_expr_stmt (init);
} }
} }
...@@ -1473,7 +1479,8 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, ...@@ -1473,7 +1479,8 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
then just zero out the object and we're done. */ then just zero out the object and we're done. */
else else
{ {
init = build2 (INIT_EXPR, type, exp, build_value_init_noctor (type)); init = build2 (INIT_EXPR, type, exp,
build_value_init_noctor (type, complain));
finish_expr_stmt (init); finish_expr_stmt (init);
return; return;
} }
...@@ -2314,8 +2321,10 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, ...@@ -2314,8 +2321,10 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
else if (explicit_value_init_p) else if (explicit_value_init_p)
{ {
/* Something like `new int()'. */ /* Something like `new int()'. */
init_expr = build2 (INIT_EXPR, type, tree val = build_value_init (type, complain);
init_expr, build_value_init (type)); if (val == error_mark_node)
return error_mark_node;
init_expr = build2 (INIT_EXPR, type, init_expr, val);
} }
else else
{ {
...@@ -2534,7 +2543,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts, ...@@ -2534,7 +2543,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
/* The type allocated must be complete. If the new-type-id was /* The type allocated must be complete. If the new-type-id was
"T[N]" then we are just checking that "T" is complete here, but "T[N]" then we are just checking that "T" is complete here, but
that is equivalent, since the value of "N" doesn't matter. */ that is equivalent, since the value of "N" doesn't matter. */
if (!complete_type_or_else (type, NULL_TREE)) if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
return error_mark_node; return error_mark_node;
rval = build_new_1 (placement, type, nelts, init, use_global_new, complain); rval = build_new_1 (placement, type, nelts, init, use_global_new, complain);
...@@ -3041,8 +3050,13 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -3041,8 +3050,13 @@ build_vec_init (tree base, tree maxindex, tree init,
0, complain); 0, complain);
} }
else if (explicit_value_init_p) else if (explicit_value_init_p)
elt_init = build2 (INIT_EXPR, type, to, {
build_value_init (type)); elt_init = build_value_init (type, complain);
if (elt_init == error_mark_node)
return error_mark_node;
else
elt_init = build2 (INIT_EXPR, type, to, elt_init);
}
else else
{ {
gcc_assert (TYPE_NEEDS_CONSTRUCTING (type)); gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
......
...@@ -11705,7 +11705,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, ...@@ -11705,7 +11705,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
pack expansion where the parameter packs pack expansion where the parameter packs
used in that expansion were of length used in that expansion were of length
zero. */ zero. */
init = build_value_init (TREE_TYPE (decl)); init = build_value_init (TREE_TYPE (decl),
complain);
if (TREE_CODE (init) == AGGR_INIT_EXPR) if (TREE_CODE (init) == AGGR_INIT_EXPR)
init = get_target_expr (init); init = get_target_expr (init);
} }
......
...@@ -477,7 +477,8 @@ build_target_expr_with_type (tree init, tree type) ...@@ -477,7 +477,8 @@ build_target_expr_with_type (tree init, tree type)
{ {
gcc_assert (!VOID_TYPE_P (type)); gcc_assert (!VOID_TYPE_P (type));
if (TREE_CODE (init) == TARGET_EXPR) if (TREE_CODE (init) == TARGET_EXPR
|| init == error_mark_node)
return init; return init;
else if (CLASS_TYPE_P (type) && type_has_nontrivial_copy_init (type) else if (CLASS_TYPE_P (type) && type_has_nontrivial_copy_init (type)
&& !VOID_TYPE_P (TREE_TYPE (init)) && !VOID_TYPE_P (TREE_TYPE (init))
......
...@@ -135,7 +135,7 @@ complete_type (tree type) ...@@ -135,7 +135,7 @@ complete_type (tree type)
Returns NULL_TREE if the type cannot be made complete. */ Returns NULL_TREE if the type cannot be made complete. */
tree tree
complete_type_or_else (tree type, tree value) complete_type_or_maybe_complain (tree type, tree value, tsubst_flags_t complain)
{ {
type = complete_type (type); type = complete_type (type);
if (type == error_mark_node) if (type == error_mark_node)
...@@ -143,13 +143,20 @@ complete_type_or_else (tree type, tree value) ...@@ -143,13 +143,20 @@ complete_type_or_else (tree type, tree value)
return NULL_TREE; return NULL_TREE;
else if (!COMPLETE_TYPE_P (type)) else if (!COMPLETE_TYPE_P (type))
{ {
cxx_incomplete_type_diagnostic (value, type, DK_ERROR); if (complain & tf_error)
cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
return NULL_TREE; return NULL_TREE;
} }
else else
return type; return type;
} }
tree
complete_type_or_else (tree type, tree value)
{
return complete_type_or_maybe_complain (type, value, tf_warning_or_error);
}
/* Return truthvalue of whether type of EXP is instantiated. */ /* Return truthvalue of whether type of EXP is instantiated. */
int int
...@@ -2209,7 +2216,7 @@ build_class_member_access_expr (tree object, tree member, ...@@ -2209,7 +2216,7 @@ build_class_member_access_expr (tree object, tree member,
complete type). */ complete type). */
object_type = TREE_TYPE (object); object_type = TREE_TYPE (object);
if (!currently_open_class (object_type) if (!currently_open_class (object_type)
&& !complete_type_or_else (object_type, object)) && !complete_type_or_maybe_complain (object_type, object, complain))
return error_mark_node; return error_mark_node;
if (!CLASS_TYPE_P (object_type)) if (!CLASS_TYPE_P (object_type))
{ {
...@@ -2585,7 +2592,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p, ...@@ -2585,7 +2592,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
The type of the first expression shall be "class object" (of a The type of the first expression shall be "class object" (of a
complete type). */ complete type). */
if (!currently_open_class (object_type) if (!currently_open_class (object_type)
&& !complete_type_or_else (object_type, object)) && !complete_type_or_maybe_complain (object_type, object, complain))
return error_mark_node; return error_mark_node;
if (!CLASS_TYPE_P (object_type)) if (!CLASS_TYPE_P (object_type))
{ {
......
...@@ -1606,7 +1606,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain) ...@@ -1606,7 +1606,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
then the slot being initialized will be filled in. */ then the slot being initialized will be filled in. */
if (!complete_type_or_else (type, NULL_TREE)) if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
return error_mark_node; return error_mark_node;
if (abstract_virtuals_error (NULL_TREE, type)) if (abstract_virtuals_error (NULL_TREE, type))
return error_mark_node; return error_mark_node;
...@@ -1631,7 +1631,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain) ...@@ -1631,7 +1631,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
just calling the constructor, so fall through. */ just calling the constructor, so fall through. */
&& !TYPE_HAS_USER_CONSTRUCTOR (type)) && !TYPE_HAS_USER_CONSTRUCTOR (type))
{ {
exp = build_value_init (type); exp = build_value_init (type, complain);
return get_target_expr (exp); return get_target_expr (exp);
} }
......
2010-08-06 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/sfinae3.C: New.
* g++.dg/cpp0x/sfinae4.C: New.
2010-08-06 Richard Guenther <rguenther@suse.de> 2010-08-06 Richard Guenther <rguenther@suse.de>
* gcc.dg/tree-ssa/ssa-dce-3.c: XFAIL. * gcc.dg/tree-ssa/ssa-dce-3.c: XFAIL.
......
// { dg-options -std=c++0x }
namespace std { template <class T> T&& declval(); }
template<typename _Tp, typename... _Args>
class is_constructible_mini
{
typedef char __one;
typedef struct { char __arr[2]; } __two;
template<typename _Tp1, typename... _Args1>
static decltype(::new _Tp1(std::declval<_Args1>()...), __one())
__test(int);
template<typename, typename...>
static __two __test(...);
public:
static const bool value = sizeof(__test<_Tp, _Args...>(0)) == 1;
};
/*
template<typename _Tp>
class is_constructible_mini<_Tp>
{
typedef char __one;
typedef struct { char __arr[2]; } __two;
template<typename _Tp1>
static decltype(::new _Tp1, __one()) __test(int);
template<typename>
static __two __test(...);
public:
static const bool value
= sizeof(__test<typename std::remove_cv<_Tp>::type>(0)) == 1;
};
*/
struct A
{
A(int);
};
struct B { };
static_assert( is_constructible_mini<A, int>::value, "");
static_assert( is_constructible_mini<A, A>::value, "");
static_assert( !is_constructible_mini<A, int, double>::value, "");
static_assert( !is_constructible_mini<A>::value, ""); // doesn't compile without the
// partial specialization
static_assert( is_constructible_mini<B>::value, "");
static_assert( is_constructible_mini<const B>::value, "");
// { dg-options -std=c++0x }
namespace std { template <class T> T&& declval(); }
template<typename _Tp, typename... _Args>
class is_constructible_mini
{
typedef char __one;
typedef struct { char __arr[2]; } __two;
template<typename _Tp1, typename... _Args1>
static decltype(::new _Tp1(std::declval<_Args1>()...), __one())
__test(int);
template<typename, typename...>
static __two __test(...);
public:
static const bool value = sizeof(__test<_Tp, _Args...>(0)) == 1;
};
static_assert( !is_constructible_mini<int[], int>::value, "");
static_assert( !is_constructible_mini<void, int>::value, "");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment