From 0e5cde0cdaed60a49d7e1d79c6884ce0a84624e7 Mon Sep 17 00:00:00 2001 From: mmitchel Date: Sat, 26 Aug 2006 16:23:33 +0000 Subject: [PATCH] PR c++/28588 * class.c (resolve_address_of_overloaded_function): Add access_path parameter. Perform access checks. (instantiate_type): Adjust call to resolve_address_of_overloaded_function. Remove unnecessary code. * tree.c (is_overloaded_fn): Document. Return 2 when there are acutally multiple functions. (really_overloaded_fn): Use is_overloaded_fn. * mangle.c (write_expression): Handle BASELINKs. * cp-tree.h (really_overloaded_fn): Return bool. (baselink_for_fns): Declare. * search.c (lookup_member): Check access for single static functions here. * pt.c (convert_nontype_argument_function): Handle BASELINKs. (tsubst_copy_and_build): Generate BASELINKs for template-ids. * semantics.c (finish_call_expr): Use baselink_for_fns. (baselink_for_fns): New function. (finish_id_expression): Use it. * parser.c (cp_parser_template_argument): Don't strip BASELINKs. PR c++/28595 * pt.c (tsubst): Issue errors about attempts to create VLAs at template-instantiation time. PR c++/28588 * g++.dg/inherit/access6.C: New test. * g++.dg/inherit/access7.C: Likewise. PR c++/28595 * g++.dg/template/array15.C: New test. * g++.dg/template/crash2.C: Tweak error markers. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116468 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 26 ++++++ gcc/cp/class.c | 161 +++++++------------------------- gcc/cp/cp-tree.h | 3 +- gcc/cp/mangle.c | 6 ++ gcc/cp/parser.c | 5 - gcc/cp/pt.c | 16 +++- gcc/cp/search.c | 22 ++++- gcc/cp/semantics.c | 60 +++++++----- gcc/cp/tree.c | 33 ++++--- gcc/testsuite/ChangeLog | 10 ++ gcc/testsuite/g++.dg/inherit/access6.C | 15 +++ gcc/testsuite/g++.dg/inherit/access7.C | 15 +++ gcc/testsuite/g++.dg/template/array15.C | 13 +++ gcc/testsuite/g++.dg/template/crash2.C | 2 +- 14 files changed, 215 insertions(+), 172 deletions(-) create mode 100644 gcc/testsuite/g++.dg/inherit/access6.C create mode 100644 gcc/testsuite/g++.dg/inherit/access7.C create mode 100644 gcc/testsuite/g++.dg/template/array15.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 171103b..d7c952d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,29 @@ +2006-08-26 Mark Mitchell + + PR c++/28588 + * class.c (resolve_address_of_overloaded_function): Add + access_path parameter. Perform access checks. + (instantiate_type): Adjust call to + resolve_address_of_overloaded_function. Remove unnecessary code. + * tree.c (is_overloaded_fn): Document. Return 2 when there are + acutally multiple functions. + (really_overloaded_fn): Use is_overloaded_fn. + * mangle.c (write_expression): Handle BASELINKs. + * cp-tree.h (really_overloaded_fn): Return bool. + (baselink_for_fns): Declare. + * search.c (lookup_member): Check access for single static + functions here. + * pt.c (convert_nontype_argument_function): Handle BASELINKs. + (tsubst_copy_and_build): Generate BASELINKs for template-ids. + * semantics.c (finish_call_expr): Use baselink_for_fns. + (baselink_for_fns): New function. + (finish_id_expression): Use it. + * parser.c (cp_parser_template_argument): Don't strip BASELINKs. + + PR c++/28595 + * pt.c (tsubst): Issue errors about attempts to create VLAs at + template-instantiation time. + 2006-08-25 Volker Reichelt PR c++/28853 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 06f8cbc..673b07f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -134,8 +134,6 @@ static int method_name_cmp (const void *, const void *); static int resort_method_name_cmp (const void *, const void *); static void add_implicitly_declared_members (tree, int, int); static tree fixed_type_or_null (tree, int *, int *); -static tree resolve_address_of_overloaded_function (tree, tree, tsubst_flags_t, - bool, tree); static tree build_simple_base_path (tree expr, tree binfo); static tree build_vtbl_ref_1 (tree, tree); static tree build_vtbl_initializer (tree, tree, tree, tree, int *); @@ -5673,18 +5671,21 @@ pop_lang_context (void) /* Given an OVERLOAD and a TARGET_TYPE, return the function that matches the TARGET_TYPE. If there is no satisfactory match, return - error_mark_node, and issue an error & warning messages under control - of FLAGS. Permit pointers to member function if FLAGS permits. If - TEMPLATE_ONLY, the name of the overloaded function was a - template-id, and EXPLICIT_TARGS are the explicitly provided - template arguments. */ + error_mark_node, and issue an error & warning messages under + control of FLAGS. Permit pointers to member function if FLAGS + permits. If TEMPLATE_ONLY, the name of the overloaded function was + a template-id, and EXPLICIT_TARGS are the explicitly provided + template arguments. If OVERLOAD is for one or more member + functions, then ACCESS_PATH is the base path used to reference + those member functions. */ static tree resolve_address_of_overloaded_function (tree target_type, tree overload, tsubst_flags_t flags, bool template_only, - tree explicit_targs) + tree explicit_targs, + tree access_path) { /* Here's what the standard says: @@ -5935,7 +5936,17 @@ resolve_address_of_overloaded_function (tree target_type, function used. If this conversion sequence is selected, the function will be marked as used at this point. */ if (!(flags & tf_conv)) - mark_used (fn); + { + mark_used (fn); + /* We could not check access when this expression was originally + created since we did not know at that time to which function + the expression referred. */ + if (DECL_FUNCTION_MEMBER_P (fn)) + { + gcc_assert (access_path); + perform_or_defer_access_check (access_path, fn); + } + } if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type)) return build_unary_op (ADDR_EXPR, fn, 0); @@ -5964,6 +5975,7 @@ tree instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) { tsubst_flags_t flags_in = flags; + tree access_path = NULL_TREE; flags &= ~tf_ptrmem_ok; @@ -5994,7 +6006,10 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) } if (TREE_CODE (rhs) == BASELINK) - rhs = BASELINK_FUNCTIONS (rhs); + { + access_path = BASELINK_ACCESS_BINFO (rhs); + rhs = BASELINK_FUNCTIONS (rhs); + } /* If we are in a template, and have a NON_DEPENDENT_EXPR, we cannot deduce any type information. */ @@ -6005,6 +6020,13 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) return error_mark_node; } + /* There only a few kinds of expressions that may have a type + dependent on overload resolution. */ + gcc_assert (TREE_CODE (rhs) == ADDR_EXPR + || TREE_CODE (rhs) == COMPONENT_REF + || TREE_CODE (rhs) == COMPOUND_EXPR + || really_overloaded_fn (rhs)); + /* We don't overwrite rhs if it is an overloaded function. Copying it would destroy the tree link. */ if (TREE_CODE (rhs) != OVERLOAD) @@ -6017,32 +6039,6 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) switch (TREE_CODE (rhs)) { - case TYPE_EXPR: - case CONVERT_EXPR: - case SAVE_EXPR: - case CONSTRUCTOR: - gcc_unreachable (); - - case INDIRECT_REF: - case ARRAY_REF: - { - tree new_rhs; - - new_rhs = instantiate_type (build_pointer_type (lhstype), - TREE_OPERAND (rhs, 0), flags); - if (new_rhs == error_mark_node) - return error_mark_node; - - TREE_TYPE (rhs) = lhstype; - TREE_OPERAND (rhs, 0) = new_rhs; - return rhs; - } - - case NOP_EXPR: - rhs = copy_node (TREE_OPERAND (rhs, 0)); - TREE_TYPE (rhs) = unknown_type_node; - return instantiate_type (lhstype, rhs, flags); - case COMPONENT_REF: { tree member = TREE_OPERAND (rhs, 1); @@ -6059,7 +6055,7 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) case OFFSET_REF: rhs = TREE_OPERAND (rhs, 1); if (BASELINK_P (rhs)) - return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags_in); + return instantiate_type (lhstype, rhs, flags_in); /* This can happen if we are forming a pointer-to-member for a member template. */ @@ -6075,7 +6071,7 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) return resolve_address_of_overloaded_function (lhstype, fns, flags_in, /*template_only=*/true, - args); + args, access_path); } case OVERLOAD: @@ -6083,14 +6079,9 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) return resolve_address_of_overloaded_function (lhstype, rhs, flags_in, /*template_only=*/false, - /*explicit_targs=*/NULL_TREE); + /*explicit_targs=*/NULL_TREE, + access_path); - case CALL_EXPR: - /* This is too hard for now. */ - gcc_unreachable (); - - case PLUS_EXPR: - case MINUS_EXPR: case COMPOUND_EXPR: TREE_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags); @@ -6104,86 +6095,6 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags) TREE_TYPE (rhs) = lhstype; return rhs; - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case FLOOR_DIV_EXPR: - case CEIL_DIV_EXPR: - case ROUND_DIV_EXPR: - case RDIV_EXPR: - case TRUNC_MOD_EXPR: - case FLOOR_MOD_EXPR: - case CEIL_MOD_EXPR: - case ROUND_MOD_EXPR: - case FIX_ROUND_EXPR: - case FIX_FLOOR_EXPR: - case FIX_CEIL_EXPR: - case FIX_TRUNC_EXPR: - case FLOAT_EXPR: - case NEGATE_EXPR: - case ABS_EXPR: - case MAX_EXPR: - case MIN_EXPR: - - case BIT_AND_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - case LROTATE_EXPR: - case RROTATE_EXPR: - - case PREINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - if (flags & tf_error) - error ("invalid operation on uninstantiated type"); - return error_mark_node; - - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_XOR_EXPR: - case LT_EXPR: - case LE_EXPR: - case GT_EXPR: - case GE_EXPR: - case EQ_EXPR: - case NE_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_NOT_EXPR: - if (flags & tf_error) - error ("not enough type information"); - return error_mark_node; - - case COND_EXPR: - if (type_unknown_p (TREE_OPERAND (rhs, 0))) - { - if (flags & tf_error) - error ("not enough type information"); - return error_mark_node; - } - TREE_OPERAND (rhs, 1) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags); - if (TREE_OPERAND (rhs, 1) == error_mark_node) - return error_mark_node; - TREE_OPERAND (rhs, 2) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), flags); - if (TREE_OPERAND (rhs, 2) == error_mark_node) - return error_mark_node; - - TREE_TYPE (rhs) = lhstype; - return rhs; - - case MODIFY_EXPR: - TREE_OPERAND (rhs, 1) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags); - if (TREE_OPERAND (rhs, 1) == error_mark_node) - return error_mark_node; - - TREE_TYPE (rhs) = lhstype; - return rhs; - case ADDR_EXPR: { if (PTRMEM_OK_P (rhs)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 713d371..c50836b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4321,6 +4321,7 @@ extern tree cxx_omp_clause_copy_ctor (tree, tree, tree); extern tree cxx_omp_clause_assign_op (tree, tree, tree); extern tree cxx_omp_clause_dtor (tree, tree); extern bool cxx_omp_privatize_by_reference (tree); +extern tree baselink_for_fns (tree); /* in tree.c */ extern void lang_check_failed (const char *, int, @@ -4364,7 +4365,7 @@ extern bool decl_anon_ns_mem_p (tree); extern tree lvalue_type (tree); extern tree error_type (tree); extern int varargs_function_p (tree); -extern int really_overloaded_fn (tree); +extern bool really_overloaded_fn (tree); extern bool cp_tree_equal (tree, tree); extern tree no_linkage_check (tree, bool); extern void debug_binfo (tree); diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 8c8eff9..74ff854 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -2023,6 +2023,12 @@ write_expression (tree expr) code = TREE_CODE (expr); } + if (code == BASELINK) + { + expr = BASELINK_FUNCTIONS (expr); + code = TREE_CODE (expr); + } + /* Handle pointers-to-members by making them look like expression nodes. */ if (code == PTRMEM_CST) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 729d0ca..4e62340 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -9237,11 +9237,6 @@ cp_parser_template_argument (cp_parser* parser) argument = TREE_OPERAND (argument, 0); } - if (TREE_CODE (argument) == BASELINK) - /* We don't need the information about what class was used - to name the overloaded functions. */ - argument = BASELINK_FUNCTIONS (argument); - if (TREE_CODE (argument) == VAR_DECL) { /* A variable without external linkage might still be a diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 749291c..e078149 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3454,7 +3454,9 @@ convert_nontype_argument_function (tree type, tree expr) fn_no_ptr = fn; if (TREE_CODE (fn_no_ptr) == ADDR_EXPR) fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0); - + if (TREE_CODE (fn_no_ptr) == BASELINK) + fn_no_ptr = BASELINK_FUNCTIONS (fn_no_ptr); + /* [temp.arg.nontype]/1 A template-argument for a non-type, non-template template-parameter @@ -7192,6 +7194,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) max = tsubst_template_arg (omax, args, complain, in_decl); max = fold_decl_constant_value (max); + if (TREE_CODE (max) != INTEGER_CST + && TREE_CODE (max) != TEMPLATE_PARM_INDEX + && !at_function_scope_p ()) + { + if (complain & tf_error) + error ("array bound is not an integer constant"); + return error_mark_node; + } + /* [temp.deduct] Type deduction may fail for any of the following @@ -7204,7 +7215,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) indicated by the state of complain), so that another substitution can be found. */ return error_mark_node; - else if (TREE_CODE (max) == INTEGER_CST && INT_CST_LT (max, integer_zero_node)) { @@ -8824,7 +8834,7 @@ tsubst_copy_and_build (tree t, return build3 (COMPONENT_REF, TREE_TYPE (template), object, template, NULL_TREE); else - return template; + return baselink_for_fns (template); } case INDIRECT_REF: diff --git a/gcc/cp/search.c b/gcc/cp/search.c index d54e607..45a5ea3 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1253,8 +1253,26 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type) /* [class.access] In the case of overloaded function names, access control is - applied to the function selected by overloaded resolution. */ - if (rval && protect && !is_overloaded_fn (rval)) + applied to the function selected by overloaded resolution. + + We cannot check here, even if RVAL is only a single non-static + member function, since we do not know what the "this" pointer + will be. For: + + class A { protected: void f(); }; + class B : public A { + void g(A *p) { + f(); // OK + p->f(); // Not OK. + } + }; + + only the first call to "f" is valid. However, if the function is + static, we can check. */ + if (rval && protect + && !really_overloaded_fn (rval) + && !(TREE_CODE (rval) == FUNCTION_DECL + && DECL_NONSTATIC_MEMBER_FUNCTION_P (rval))) perform_or_defer_access_check (basetype_path, rval); if (errstr && protect) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 56dbe6f..94e6dfd 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1774,26 +1774,8 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) args = build_non_dependent_args (orig_args); } - /* A reference to a member function will appear as an overloaded - function (rather than a BASELINK) if an unqualified name was used - to refer to it. */ - if (!BASELINK_P (fn) && is_overloaded_fn (fn)) - { - tree f = fn; - - if (TREE_CODE (f) == TEMPLATE_ID_EXPR) - f = TREE_OPERAND (f, 0); - f = get_first_fn (f); - if (DECL_FUNCTION_MEMBER_P (f)) - { - tree type = currently_open_derived_class (DECL_CONTEXT (f)); - if (!type) - type = DECL_CONTEXT (f); - fn = build_baselink (TYPE_BINFO (type), - TYPE_BINFO (type), - fn, /*optype=*/NULL_TREE); - } - } + if (is_overloaded_fn (fn)) + fn = baselink_for_fns (fn); result = NULL_TREE; if (BASELINK_P (fn)) @@ -2405,6 +2387,36 @@ qualified_name_lookup_error (tree scope, tree name, tree decl) error ("%<::%D%> has not been declared", name); } +/* If FNS is a member function, a set of member functions, or a + template-id referring to one or more member functions, return a + BASELINK for FNS, incorporating the current access context. + Otherwise, return FNS unchanged. */ + +tree +baselink_for_fns (tree fns) +{ + tree fn; + tree cl; + + if (BASELINK_P (fns) + || processing_template_decl + || error_operand_p (fns)) + return fns; + + fn = fns; + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) + fn = TREE_OPERAND (fn, 0); + fn = get_first_fn (fn); + if (!DECL_FUNCTION_MEMBER_P (fn)) + return fns; + + cl = currently_open_derived_class (DECL_CONTEXT (fn)); + if (!cl) + cl = DECL_CONTEXT (fn); + cl = TYPE_BINFO (cl); + return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE); +} + /* ID_EXPRESSION is a representation of parsed, but unprocessed, id-expression. (See cp_parser_id_expression for details.) SCOPE, if non-NULL, is the type or namespace used to explicitly qualify @@ -2793,8 +2805,12 @@ finish_id_expression (tree id_expression, } else if (is_overloaded_fn (decl)) { - tree first_fn = OVL_CURRENT (decl); + tree first_fn; + first_fn = decl; + if (TREE_CODE (first_fn) == TEMPLATE_ID_EXPR) + first_fn = TREE_OPERAND (first_fn, 0); + first_fn = get_first_fn (first_fn); if (TREE_CODE (first_fn) == TEMPLATE_DECL) first_fn = DECL_TEMPLATE_RESULT (first_fn); @@ -2811,6 +2827,8 @@ finish_id_expression (tree id_expression, return finish_class_member_access_expr (decl, id_expression, /*template_p=*/false); } + + decl = baselink_for_fns (decl); } else { diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 1cedec5..db7e40a 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -842,6 +842,13 @@ build_qualified_name (tree type, tree scope, tree name, bool template_p) return t; } +/* Returns non-zero if X is an expression for a (possibly overloaded) + function. If "f" is a function or function template, "f", "c->f", + "c.f", "C::f", and "f" will all be considered possibly + overloaded functions. Returns 2 if the function is actually + overloaded, i.e., if it is impossible to know the the type of the + function without performing overload resolution. */ + int is_overloaded_fn (tree x) { @@ -850,24 +857,22 @@ is_overloaded_fn (tree x) x = TREE_OPERAND (x, 1); if (BASELINK_P (x)) x = BASELINK_FUNCTIONS (x); - return (TREE_CODE (x) == FUNCTION_DECL - || TREE_CODE (x) == TEMPLATE_ID_EXPR - || DECL_FUNCTION_TEMPLATE_P (x) - || TREE_CODE (x) == OVERLOAD); + if (TREE_CODE (x) == TEMPLATE_ID_EXPR + || DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x)) + || (TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x))) + return 2; + return (TREE_CODE (x) == FUNCTION_DECL + || TREE_CODE (x) == OVERLOAD); } -int +/* Returns true iff X is an expression for an overloaded function + whose type cannot be known without performing overload + resolution. */ + +bool really_overloaded_fn (tree x) { - if (TREE_CODE (x) == OFFSET_REF) - x = TREE_OPERAND (x, 1); - /* A baselink is also considered an overloaded function. */ - if (BASELINK_P (x)) - x = BASELINK_FUNCTIONS (x); - - return ((TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x)) - || DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x)) - || TREE_CODE (x) == TEMPLATE_ID_EXPR); + return is_overloaded_fn (x) == 2; } tree diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b9ddcf0..017de89 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2006-08-26 Mark Mitchell + + PR c++/28588 + * g++.dg/inherit/access6.C: New test. + * g++.dg/inherit/access7.C: Likewise. + + PR c++/28595 + * g++.dg/template/array15.C: New test. + * g++.dg/template/crash2.C: Tweak error markers. + 2006-08-26 Jakub Jelinek PR middle-end/28683 diff --git a/gcc/testsuite/g++.dg/inherit/access6.C b/gcc/testsuite/g++.dg/inherit/access6.C new file mode 100644 index 0000000..7645c2d --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/access6.C @@ -0,0 +1,15 @@ +// PR c++/28588 + +class Foo { + static void f(); // { dg-error "private" } + static void f(int); + static void g(); // { dg-error "private" } +}; + +void h() +{ + Foo foo; + void (*f)(); + f = foo.f; // { dg-error "context" } + f = foo.g; // { dg-error "context" } +} diff --git a/gcc/testsuite/g++.dg/inherit/access7.C b/gcc/testsuite/g++.dg/inherit/access7.C new file mode 100644 index 0000000..4e2db14 --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/access7.C @@ -0,0 +1,15 @@ +struct B { + static void f(); +}; + +template +struct D : private B { + void g() { + f(); + } +}; + +void h() { + D d; + d.g(); +} diff --git a/gcc/testsuite/g++.dg/template/array15.C b/gcc/testsuite/g++.dg/template/array15.C new file mode 100644 index 0000000..b1e047d --- /dev/null +++ b/gcc/testsuite/g++.dg/template/array15.C @@ -0,0 +1,13 @@ +// PR c++/28595 + +template struct A +{ + static const int i; +}; + +template struct B +{ + char c[A::i], d; // { dg-error "constant" } +}; + +B<0> b; diff --git a/gcc/testsuite/g++.dg/template/crash2.C b/gcc/testsuite/g++.dg/template/crash2.C index a02787a..47c95ab 100644 --- a/gcc/testsuite/g++.dg/template/crash2.C +++ b/gcc/testsuite/g++.dg/template/crash2.C @@ -5,7 +5,7 @@ class A { public: static const EnumType size = max; // { dg-error "" } - int table[size]; + int table[size]; // { dg-error "constant" } }; template const EnumType A::size; -- 2.7.4