PR c++/11094, DR 408
PR c++/11094, DR 408 * cp-tree.h (VAR_HAD_UNKNOWN_BOUND, SET_VAR_HAD_UNKNOWN_BOUND): New. * decl2.c (finish_static_data_member_decl): Set it. * decl.c (duplicate_decls): Propagate it. * pt.c (tsubst_decl): Don't substitute the domain of an array VAR_DECL if it's set. (regenerate_decl_from_template): Substitute it here. (type_dependent_expression_p): Return true if it's set. * semantics.c (finish_decltype_type): Instantiate such a variable. * typeck.c (cxx_sizeof_expr): Likewise. (strip_array_domain): New. From-SVN: r158075
This commit is contained in:
parent
ae099258d3
commit
483264879c
@ -1,5 +1,17 @@
|
||||
2010-04-07 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/11094, DR 408
|
||||
* cp-tree.h (VAR_HAD_UNKNOWN_BOUND, SET_VAR_HAD_UNKNOWN_BOUND): New.
|
||||
* decl2.c (finish_static_data_member_decl): Set it.
|
||||
* decl.c (duplicate_decls): Propagate it.
|
||||
* pt.c (tsubst_decl): Don't substitute the domain of an array
|
||||
VAR_DECL if it's set.
|
||||
(regenerate_decl_from_template): Substitute it here.
|
||||
(type_dependent_expression_p): Return true if it's set.
|
||||
* semantics.c (finish_decltype_type): Instantiate such a variable.
|
||||
* typeck.c (cxx_sizeof_expr): Likewise.
|
||||
(strip_array_domain): New.
|
||||
|
||||
* name-lookup.c (current_decl_namespace): Non-static.
|
||||
(pop_nested_namespace): Sanity check.
|
||||
* cp-tree.h: Declare current_decl_namespace.
|
||||
|
@ -1758,7 +1758,7 @@ struct GTY(()) lang_decl_base {
|
||||
unsigned threadprivate_or_deleted_p : 1; /* var or fn */
|
||||
unsigned anticipated_p : 1; /* fn or type */
|
||||
unsigned friend_attr : 1; /* fn or type */
|
||||
unsigned template_conv_p : 1; /* template only? */
|
||||
unsigned template_conv_p : 1; /* var or template */
|
||||
unsigned odr_used : 1; /* var or fn */
|
||||
unsigned u2sel : 1;
|
||||
/* 1 spare bit */
|
||||
@ -2088,6 +2088,15 @@ struct GTY(()) lang_decl {
|
||||
#define DECL_TEMPLATE_CONV_FN_P(NODE) \
|
||||
(DECL_LANG_SPECIFIC (TEMPLATE_DECL_CHECK (NODE))->u.base.template_conv_p)
|
||||
|
||||
/* Nonzero if NODE, a static data member, was declared in its class as an
|
||||
array of unknown bound. */
|
||||
#define VAR_HAD_UNKNOWN_BOUND(NODE) \
|
||||
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE)) \
|
||||
? DECL_LANG_SPECIFIC (NODE)->u.base.template_conv_p \
|
||||
: false)
|
||||
#define SET_VAR_HAD_UNKNOWN_BOUND(NODE) \
|
||||
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.template_conv_p = true)
|
||||
|
||||
/* Set the overloaded operator code for NODE to CODE. */
|
||||
#define SET_OVERLOADED_OPERATOR_CODE(NODE, CODE) \
|
||||
(LANG_DECL_FN_CHECK (NODE)->operator_code = (CODE))
|
||||
@ -5393,6 +5402,7 @@ extern tree composite_pointer_type (tree, tree, tree, tree,
|
||||
composite_pointer_operation,
|
||||
tsubst_flags_t);
|
||||
extern tree merge_types (tree, tree);
|
||||
extern tree strip_array_domain (tree);
|
||||
extern tree check_return_expr (tree, bool *);
|
||||
extern tree cp_build_binary_op (location_t,
|
||||
enum tree_code, tree, tree,
|
||||
|
@ -1929,6 +1929,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
|
||||
if (DECL_VIRTUAL_P (newdecl))
|
||||
DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
|
||||
}
|
||||
/* Only variables have this field. */
|
||||
else if (TREE_CODE (newdecl) == VAR_DECL
|
||||
&& VAR_HAD_UNKNOWN_BOUND (olddecl))
|
||||
SET_VAR_HAD_UNKNOWN_BOUND (newdecl);
|
||||
}
|
||||
|
||||
if (TREE_CODE (newdecl) == FUNCTION_DECL)
|
||||
|
@ -785,6 +785,10 @@ finish_static_data_member_decl (tree decl,
|
||||
DECL_INITIAL (decl) = init;
|
||||
DECL_IN_AGGR_P (decl) = 1;
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
|
||||
&& TYPE_DOMAIN (TREE_TYPE (decl)) == NULL_TREE)
|
||||
SET_VAR_HAD_UNKNOWN_BOUND (decl);
|
||||
|
||||
cp_finish_decl (decl, init, init_const_expr_p, asmspec_tree, flags);
|
||||
}
|
||||
|
||||
|
24
gcc/cp/pt.c
24
gcc/cp/pt.c
@ -9496,6 +9496,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
||||
type = DECL_ORIGINAL_TYPE (t);
|
||||
else
|
||||
type = TREE_TYPE (t);
|
||||
if (TREE_CODE (t) == VAR_DECL && VAR_HAD_UNKNOWN_BOUND (t))
|
||||
type = strip_array_domain (type);
|
||||
type = tsubst (type, args, complain, in_decl);
|
||||
}
|
||||
if (TREE_CODE (r) == VAR_DECL)
|
||||
@ -16456,10 +16458,15 @@ regenerate_decl_from_template (tree decl, tree tmpl)
|
||||
DECL_DECLARED_INLINE_P (decl) = 1;
|
||||
}
|
||||
else if (TREE_CODE (decl) == VAR_DECL)
|
||||
DECL_INITIAL (decl) =
|
||||
tsubst_expr (DECL_INITIAL (code_pattern), args,
|
||||
tf_error, DECL_TI_TEMPLATE (decl),
|
||||
/*integral_constant_expression_p=*/false);
|
||||
{
|
||||
DECL_INITIAL (decl) =
|
||||
tsubst_expr (DECL_INITIAL (code_pattern), args,
|
||||
tf_error, DECL_TI_TEMPLATE (decl),
|
||||
/*integral_constant_expression_p=*/false);
|
||||
if (VAR_HAD_UNKNOWN_BOUND (decl))
|
||||
TREE_TYPE (decl) = tsubst (TREE_TYPE (code_pattern), args,
|
||||
tf_error, DECL_TI_TEMPLATE (decl));
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
@ -17730,6 +17737,15 @@ type_dependent_expression_p (tree expression)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* A static data member of the current instantiation with incomplete
|
||||
array type is type-dependent, as the definition and specializations
|
||||
can have different bounds. */
|
||||
if (TREE_CODE (expression) == VAR_DECL
|
||||
&& DECL_CLASS_SCOPE_P (expression)
|
||||
&& dependent_type_p (DECL_CONTEXT (expression))
|
||||
&& VAR_HAD_UNKNOWN_BOUND (expression))
|
||||
return true;
|
||||
|
||||
if (TREE_TYPE (expression) == unknown_type_node)
|
||||
{
|
||||
if (TREE_CODE (expression) == ADDR_EXPR)
|
||||
|
@ -4836,6 +4836,14 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
|
||||
/* The type denoted by decltype(e) is defined as follows: */
|
||||
|
||||
expr = resolve_nondeduced_context (expr);
|
||||
|
||||
/* 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
|
||||
&& VAR_HAD_UNKNOWN_BOUND (expr)
|
||||
&& DECL_TEMPLATE_INSTANTIATION (expr))
|
||||
instantiate_decl (expr, /*defer_ok*/true, /*expl_inst_mem*/false);
|
||||
|
||||
if (id_expression_or_member_access_p)
|
||||
{
|
||||
/* If e is an id-expression or a class member access (5.2.5
|
||||
|
@ -878,6 +878,19 @@ merge_types (tree t1, tree t2)
|
||||
return cp_build_type_attribute_variant (t1, attributes);
|
||||
}
|
||||
|
||||
/* Return the ARRAY_TYPE type without its domain. */
|
||||
|
||||
tree
|
||||
strip_array_domain (tree type)
|
||||
{
|
||||
tree t2;
|
||||
gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
|
||||
if (TYPE_DOMAIN (type) == NULL_TREE)
|
||||
return type;
|
||||
t2 = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
|
||||
return cp_build_type_attribute_variant (t2, TYPE_ATTRIBUTES (type));
|
||||
}
|
||||
|
||||
/* Wrapper around cp_common_type that is used by c-common.c and other
|
||||
front end optimizations that remove promotions.
|
||||
|
||||
@ -1596,6 +1609,13 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
|
||||
return e;
|
||||
}
|
||||
|
||||
/* To get the size of a static data member declared as an array of
|
||||
unknown bound, we need to instantiate it. */
|
||||
if (TREE_CODE (e) == VAR_DECL
|
||||
&& VAR_HAD_UNKNOWN_BOUND (e)
|
||||
&& DECL_TEMPLATE_INSTANTIATION (e))
|
||||
instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false);
|
||||
|
||||
if (TREE_CODE (e) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
|
||||
&& DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
|
||||
|
@ -1,5 +1,7 @@
|
||||
2010-04-07 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/template/dr408.C: New.
|
||||
|
||||
* g++.dg/lookup/ns4.C: New.
|
||||
|
||||
PR c++/38392
|
||||
|
45
gcc/testsuite/g++.dg/template/dr408.C
Normal file
45
gcc/testsuite/g++.dg/template/dr408.C
Normal file
@ -0,0 +1,45 @@
|
||||
// DR 408
|
||||
// { dg-do link }
|
||||
|
||||
// Test that a size given in the out-of-class definition isn't used until
|
||||
// instantiation time.
|
||||
template<typename T>
|
||||
struct X
|
||||
{
|
||||
static char s[];
|
||||
int c;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
char X<T>::s[sizeof(X<T>)];
|
||||
|
||||
#define sassert(EXP) int ar[(EXP)?1:-1]
|
||||
sassert(sizeof (X<char>::s) == sizeof (int));
|
||||
|
||||
// Test that a specialization can have a different size.
|
||||
|
||||
template <int> void g();
|
||||
template <> void g<2>() { }
|
||||
|
||||
template <typename T>
|
||||
struct S {
|
||||
static int i[];
|
||||
void f();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
int S<T>::i[] = { 1 };
|
||||
|
||||
template <typename T>
|
||||
void S<T>::f() {
|
||||
g<sizeof (i) / sizeof (int)>();
|
||||
}
|
||||
|
||||
template <>
|
||||
int S<int>::i[] = { 1, 2 };
|
||||
|
||||
int main()
|
||||
{
|
||||
S<int> s;
|
||||
s.f();
|
||||
}
|
Loading…
Reference in New Issue
Block a user