Commit fc6a28d7 by Mark Mitchell Committed by Mark Mitchell

re PR c++/18368 (C++ error message regression)

	PR c++/18368
	* parser.c (cp_parser_check_for_definition_in_return_type): Take
	the defined type as a parameter, and inform the user about the
	possibility of a missing semicolon.
	(cp_parser_explicit_instantiation): Adjust call to
	cp_parser_check_for_definition_in_return_type.
	(cp_parser_init_declarator): Likewise.
	(cp_parser_member_declaration): Likewise.

	PR c++/18674
	* cp-tree.def (TYPENAME_TYPE): Remove discussion of implicit
	typename from comments.
	* cp-tree.h (TYPENAME_IS_ENUM_P): New macro.
	(TYPENAME_IS_CLASS_P): Likewise.
	(make_typename_type): Change prototype.
	* decl.c (struct_typename_info): New type.
	(typename_compare): Expect the second argument to be a
	typename_info, not a tree.
	(build_typename_type): Add tag_type parameter.  Do not create a
	new type until necessary.
	(make_typename_type): Add tag_type parameter.
	* error.c (TYPENAME_TYPE): Print tags other than "typename" if
	appropriate.
	* friend.c (make_friend_class): Adjust call to make_typename_type.
	* parser.c (cp_parser_make_typename_type): Likewise.
	(cp_parser_primary_expression): Adjust call to
	cp_parser_lookup_name.
	(cp_parser_unqualified_id): Adjust calls to cp_parser_class_name.
	(cp_parser_class_or_namespace_name): Likewise.
	(cp_parser_postfix_expression): Adjust calls to
	make_typename_type.
	(cp_parser_mem_initializer_id): Adjust calls to
	cp_parser_class_name.
	(cp_parser_type_parameter): Adjust calls to cp_parser_lookup_name.
	(cp_parser_template_name): Likewise.
	(cp_parser_template_argument): Likewise.
	(cp_parser_type_name): Adjust call to cp_parser_class_name.
	(cp_parser_elaborated_type_specifier): Adjust calls to
	make_typename_type and cp_parser_lookup_name.
	(cp_parser_namespace_name): Likewise.
	(cp_parser_class_name): Replace type_p parameter with tag_type.
	Adjust calls to make_typename_type and cp_parser_lookup_name.
	(cp_parser_class_head): Adjust calls to cp_parser_class_name.
	(cp_parser_base_specifier): Likewise.
	(cp_parser_lookup_name): Replace is_type parameter with tag_type.
	Adjust calls to make_typename_type and lookup_qualified_name.
	(cp_parser_lookup_name_simple): Adjust call to
	cp_parser_lookup_name.
	(cp_parser_constructor_declarator_p): Adjust call to
	cp_parser_class_name.
	* pt.c (convert_template_argument): Adjust all to
	make_typename_type.
	(tsubst_decl): Do not pre-substitute the type of the declaration.
	(tsubst): Hand off declarations more quickly.  Adjust call to
	make_typename_type.

	PR c++/18512
	* parser.c (cp_parser_postfix_dot_deref_expression): Robustify.

	PR c++/18674
	* g++.old-deja/g++.brendan/crash16.C: Adjust error messages.
	* g++.old-deja/g++.law/ctors5.C: Likewise.
	* g++.old-deja/g++.other/crash25.C: Likewise.

	PR c++/18674
	* g++.dg/template/error16.C: New test.

	PR c++/18512
	* g++.dg/template/crash29.C: New test.

From-SVN: r91483
parent b7034e06
2004-11-27 Mark Mitchell <mark@codesourcery.com>
PR c++/18368
* parser.c (cp_parser_check_for_definition_in_return_type): Take
the defined type as a parameter, and inform the user about the
possibility of a missing semicolon.
(cp_parser_explicit_instantiation): Adjust call to
cp_parser_check_for_definition_in_return_type.
(cp_parser_init_declarator): Likewise.
(cp_parser_member_declaration): Likewise.
PR c++/18674
* cp-tree.def (TYPENAME_TYPE): Remove discussion of implicit
typename from comments.
* cp-tree.h (TYPENAME_IS_ENUM_P): New macro.
(TYPENAME_IS_CLASS_P): Likewise.
(make_typename_type): Change prototype.
* decl.c (struct_typename_info): New type.
(typename_compare): Expect the second argument to be a
typename_info, not a tree.
(build_typename_type): Add tag_type parameter. Do not create a
new type until necessary.
(make_typename_type): Add tag_type parameter.
* error.c (TYPENAME_TYPE): Print tags other than "typename" if
appropriate.
* friend.c (make_friend_class): Adjust call to make_typename_type.
* parser.c (cp_parser_make_typename_type): Likewise.
(cp_parser_primary_expression): Adjust call to
cp_parser_lookup_name.
(cp_parser_unqualified_id): Adjust calls to cp_parser_class_name.
(cp_parser_class_or_namespace_name): Likewise.
(cp_parser_postfix_expression): Adjust calls to
make_typename_type.
(cp_parser_mem_initializer_id): Adjust calls to
cp_parser_class_name.
(cp_parser_type_parameter): Adjust calls to cp_parser_lookup_name.
(cp_parser_template_name): Likewise.
(cp_parser_template_argument): Likewise.
(cp_parser_type_name): Adjust call to cp_parser_class_name.
(cp_parser_elaborated_type_specifier): Adjust calls to
make_typename_type and cp_parser_lookup_name.
(cp_parser_namespace_name): Likewise.
(cp_parser_class_name): Replace type_p parameter with tag_type.
Adjust calls to make_typename_type and cp_parser_lookup_name.
(cp_parser_class_head): Adjust calls to cp_parser_class_name.
(cp_parser_base_specifier): Likewise.
(cp_parser_lookup_name): Replace is_type parameter with tag_type.
Adjust calls to make_typename_type and lookup_qualified_name.
(cp_parser_lookup_name_simple): Adjust call to
cp_parser_lookup_name.
(cp_parser_constructor_declarator_p): Adjust call to
cp_parser_class_name.
* pt.c (convert_template_argument): Adjust all to
make_typename_type.
(tsubst_decl): Do not pre-substitute the type of the declaration.
(tsubst): Hand off declarations more quickly. Adjust call to
make_typename_type.
PR c++/18512
* parser.c (cp_parser_postfix_dot_deref_expression): Robustify.
2004-11-29 Daniel Jacobowitz <dan@codesourcery.com>
PR c/7544
......
......@@ -182,9 +182,7 @@ DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm",
/* A type designated by `typename T::t'. TYPE_CONTEXT is `T',
TYPE_NAME is an IDENTIFIER_NODE for `t'. If the type was named via
template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.
If TREE_TYPE is present, this type was generated by the implicit
typename extension, and the TREE_TYPE is a _TYPE from a baseclass
of `T'. */
TREE_TYPE is always NULL. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0)
/* For template template argument of the form `T::template C'.
......
......@@ -47,6 +47,7 @@ struct diagnostic_context;
STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST).
EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
......@@ -54,6 +55,7 @@ struct diagnostic_context;
(TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
ICS_ELLIPSIS_FLAG (in _CONV)
DECL_INITIALIZED_P (in VAR_DECL)
TYPENAME_IS_CLASS_P (in TYPENAME_TYPE)
2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
ICS_THIS_FLAG (in _CONV)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
......@@ -2254,6 +2256,15 @@ struct lang_decl GTY(())
TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'. */
#define TYPENAME_TYPE_FULLNAME(NODE) (TYPENAME_TYPE_CHECK (NODE))->type.values
/* True if a TYPENAME_TYPE was declared as an "enum". */
#define TYPENAME_IS_ENUM_P(NODE) \
(TREE_LANG_FLAG_0 (TYPENAME_TYPE_CHECK (NODE)))
/* True if a TYPENAME_TYPE was declared as a "class", "struct", or
"union". */
#define TYPENAME_IS_CLASS_P(NODE) \
(TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE)))
/* Nonzero in INTEGER_CST means that this int is negative by dint of
using a twos-complement negated operand. */
#define TREE_NEGATED_INT(NODE) TREE_LANG_FLAG_0 (INTEGER_CST_CHECK (NODE))
......@@ -3718,7 +3729,7 @@ extern tree declare_local_label (tree);
extern tree define_label (location_t, tree);
extern void check_goto (tree);
extern void define_case_label (void);
extern tree make_typename_type (tree, tree, tsubst_flags_t);
extern tree make_typename_type (tree, tree, enum tag_types, tsubst_flags_t);
extern tree make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
extern tree check_for_out_of_scope_variable (tree);
extern tree build_library_fn (tree, tree);
......
......@@ -121,7 +121,6 @@ static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
static tree reshape_init (tree, tree *);
static tree build_typename_type (tree, tree, tree);
/* Erroneous argument lists can use this *IFF* they do not modify it. */
tree error_mark_list;
......@@ -2538,83 +2537,101 @@ typename_hash (const void* k)
return hash;
}
typedef struct typename_info {
tree scope;
tree name;
tree template_id;
bool enum_p;
bool class_p;
} typename_info;
/* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
static int
typename_compare (const void * k1, const void * k2)
{
tree t1;
tree t2;
tree d1;
tree d2;
const typename_info *t2;
t1 = (tree) k1;
t2 = (tree) k2;
d1 = TYPE_NAME (t1);
d2 = TYPE_NAME (t2);
t2 = (const typename_info *) k2;
return (DECL_NAME (d1) == DECL_NAME (d2)
&& TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2)
&& ((TREE_TYPE (t1) != NULL_TREE)
== (TREE_TYPE (t2) != NULL_TREE))
&& same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
&& TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
return (DECL_NAME (TYPE_NAME (t1)) == t2->name
&& TYPE_CONTEXT (t1) == t2->scope
&& TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
&& TYPENAME_IS_ENUM_P (t1) == t2->enum_p
&& TYPENAME_IS_CLASS_P (t1) == t2->class_p);
}
/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is
the type of `T', NAME is the IDENTIFIER_NODE for `t'. If BASE_TYPE
is non-NULL, this type is being created by the implicit typename
extension, and BASE_TYPE is a type named `t' in some base class of
`T' which depends on template parameters.
the type of `T', NAME is the IDENTIFIER_NODE for `t'.
Returns the new TYPENAME_TYPE. */
static GTY ((param_is (union tree_node))) htab_t typename_htab;
static tree
build_typename_type (tree context, tree name, tree fullname)
build_typename_type (tree context, tree name, tree fullname,
enum tag_types tag_type)
{
tree t;
tree d;
typename_info ti;
void **e;
hashval_t hash;
if (typename_htab == NULL)
{
typename_htab = htab_create_ggc (61, &typename_hash,
&typename_compare, NULL);
}
/* Build the TYPENAME_TYPE. */
t = make_aggr_type (TYPENAME_TYPE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
TYPENAME_TYPE_FULLNAME (t) = fullname;
/* Build the corresponding TYPE_DECL. */
d = build_decl (TYPE_DECL, name, t);
TYPE_NAME (TREE_TYPE (d)) = d;
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
DECL_ARTIFICIAL (d) = 1;
typename_htab = htab_create_ggc (61, &typename_hash,
&typename_compare, NULL);
ti.scope = FROB_CONTEXT (context);
ti.name = name;
ti.template_id = fullname;
ti.enum_p = tag_type == enum_type;
ti.class_p = (tag_type == class_type
|| tag_type == record_type
|| tag_type == union_type);
hash = (htab_hash_pointer (ti.scope)
^ htab_hash_pointer (ti.name));
/* See if we already have this type. */
e = htab_find_slot (typename_htab, t, INSERT);
e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT);
if (*e)
t = (tree) *e;
else
*e = t;
{
/* Build the TYPENAME_TYPE. */
t = make_aggr_type (TYPENAME_TYPE);
TYPE_CONTEXT (t) = ti.scope;
TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
TYPENAME_IS_ENUM_P (t) = ti.enum_p;
TYPENAME_IS_CLASS_P (t) = ti.class_p;
/* Build the corresponding TYPE_DECL. */
d = build_decl (TYPE_DECL, name, t);
TYPE_NAME (TREE_TYPE (d)) = d;
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
DECL_ARTIFICIAL (d) = 1;
/* Store it in the hash table. */
*e = t;
}
return t;
}
/* Resolve `typename CONTEXT::NAME'. Returns an appropriate type,
unless an error occurs, in which case error_mark_node is returned.
If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
set, we return that, rather than the _TYPE it corresponds to, in
other cases we look through the type decl. If TF_ERROR is set,
complain about errors, otherwise be quiet. */
/* Resolve `typename CONTEXT::NAME'. TAG_TYPE indicates the tag
provided to name the type. Returns an appropriate type, unless an
error occurs, in which case error_mark_node is returned. If we
locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
return that, rather than the _TYPE it corresponds to, in other
cases we look through the type decl. If TF_ERROR is set, complain
about errors, otherwise be quiet. */
tree
make_typename_type (tree context, tree name, tsubst_flags_t complain)
make_typename_type (tree context, tree name, enum tag_types tag_type,
tsubst_flags_t complain)
{
tree fullname;
......@@ -2728,7 +2745,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
return error_mark_node;
}
return build_typename_type (context, name, fullname);
return build_typename_type (context, name, fullname, tag_type);
}
/* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name
......
......@@ -348,7 +348,10 @@ dump_type (tree t, int flags)
}
case TYPENAME_TYPE:
pp_cxx_cv_qualifier_seq (cxx_pp, t);
pp_cxx_identifier (cxx_pp, "typename");
pp_cxx_identifier (cxx_pp,
TYPENAME_IS_ENUM_P (t) ? "enum"
: TYPENAME_IS_CLASS_P (t) ? "class"
: "typename");
dump_typename (t, flags);
break;
......
......@@ -300,7 +300,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
tf_error);
else
friend_type
= make_typename_type (ctype, name, tf_error);
= make_typename_type (ctype, name, class_type, tf_error);
}
else
{
......
......@@ -140,7 +140,6 @@ static tree most_specialized (tree, tree, tree);
static tree most_specialized_class (tree, tree);
static int template_class_depth_real (tree, int);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_decl (tree, tree, tree, tsubst_flags_t);
static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
static void check_specialization_scope (void);
......@@ -3833,6 +3832,7 @@ convert_template_argument (tree parm,
arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
typename_type,
complain & tf_error);
is_type = 1;
}
......@@ -6140,13 +6140,12 @@ tsubst_default_arguments (tree fn)
TREE_PURPOSE (arg));
}
/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
(already computed) substitution of ARGS into TREE_TYPE (T), if
appropriate. Return the result of the substitution. Issue error
and warning messages under control of COMPLAIN. */
/* Substitute the ARGS into the T, which is a _DECL. Return the
result of the substitution. Issue error and warning messages under
control of COMPLAIN. */
static tree
tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
tsubst_decl (tree t, tree args, tsubst_flags_t complain)
{
location_t saved_loc;
tree r = NULL_TREE;
......@@ -6267,6 +6266,7 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
tree argvec = NULL_TREE;
tree *friends;
tree gen_tmpl;
tree type;
int member;
int args_depth;
int parms_depth;
......@@ -6376,7 +6376,7 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
member = 0;
ctx = DECL_CONTEXT (t);
}
type = tsubst (type, args, complain, in_decl);
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
......@@ -6485,10 +6485,13 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
case PARM_DECL:
{
tree type;
r = copy_node (t);
if (DECL_TEMPLATE_PARM_P (t))
SET_DECL_TEMPLATE_PARM_P (r);
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
......@@ -6513,7 +6516,12 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
case FIELD_DECL:
{
tree type;
r = copy_decl (t);
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r);
......@@ -6541,19 +6549,6 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
break;
case TYPE_DECL:
if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
|| t == TYPE_MAIN_DECL (TREE_TYPE (t)))
{
/* If this is the canonical decl, we don't have to mess with
instantiations, and often we can't (for typename, template
type parms and such). Note that TYPE_NAME is not correct for
the above test if we've copied the type for a typedef. */
r = TYPE_NAME (type);
break;
}
/* Fall through. */
case VAR_DECL:
{
tree argvec = NULL_TREE;
......@@ -6561,8 +6556,25 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
tree spec;
tree tmpl = NULL_TREE;
tree ctx;
tree type = NULL_TREE;
int local_p;
if (TREE_CODE (t) == TYPE_DECL)
{
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
|| t == TYPE_MAIN_DECL (TREE_TYPE (t)))
{
/* If this is the canonical decl, we don't have to
mess with instantiations, and often we can't (for
typename, template type parms and such). Note that
TYPE_NAME is not correct for the above test if
we've copied the type for a typedef. */
r = TYPE_NAME (type);
break;
}
}
/* Assume this is a non-local variable. */
local_p = 0;
......@@ -6600,6 +6612,9 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL)
{
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
type = complete_type (type);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t);
......@@ -6885,6 +6900,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|| TREE_CODE (t) == NAMESPACE_DECL)
return t;
if (DECL_P (t))
return tsubst_decl (t, args, complain);
if (TREE_CODE (t) == IDENTIFIER_NODE)
type = IDENTIFIER_TYPE_VALUE (t);
else
......@@ -6892,9 +6910,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (type != unknown_type_node);
if (type && TREE_CODE (t) != FUNCTION_DECL
if (type
&& TREE_CODE (t) != TYPENAME_TYPE
&& TREE_CODE (t) != TEMPLATE_DECL
&& TREE_CODE (t) != IDENTIFIER_NODE
&& TREE_CODE (t) != FUNCTION_TYPE
&& TREE_CODE (t) != METHOD_TYPE)
......@@ -6902,9 +6919,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (type == error_mark_node)
return error_mark_node;
if (DECL_P (t))
return tsubst_decl (t, args, type, complain);
switch (TREE_CODE (t))
{
case RECORD_TYPE:
......@@ -7364,7 +7378,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
}
f = make_typename_type (ctx, f,
f = make_typename_type (ctx, f, typename_type,
(complain & tf_error) | tf_keep_type_decl);
if (f == error_mark_node)
return f;
......@@ -7374,6 +7388,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
f = TREE_TYPE (f);
}
if (TREE_CODE (f) != TYPENAME_TYPE)
{
if (TYPENAME_IS_ENUM_P (t) && TREE_CODE (f) != ENUMERAL_TYPE)
error ("%qT resolves to %qT, which is not an enumeration type",
t, f);
else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f))
error ("%qT resolves to %qT, which is is not a class type",
t, f);
}
return cp_build_qualified_type_real
(f, cp_type_quals (f) | cp_type_quals (t), complain);
}
......
2004-11-29 Mark Mitchell <mark@codesourcery.com>
PR c++/18674
* g++.old-deja/g++.brendan/crash16.C: Adjust error messages.
* g++.old-deja/g++.law/ctors5.C: Likewise.
* g++.old-deja/g++.other/crash25.C: Likewise.
PR c++/18674
* g++.dg/template/error16.C: New test.
PR c++/18512
* g++.dg/template/crash29.C: New test.
2004-11-29 Diego Novillo <dnovillo@redhat.com>
PR tree-optimization/18712
......
// PR c++/18512
template <int> struct A {};
struct B : A<0>
{
void foo() { this->A<0>; } // { dg-error "" }
};
// PR c++/18674
template <typename I>
static void g() {
enum I::t a; // { dg-error "" }
(void) a;
}
struct B {
typedef int t;
};
void h()
{
g<B>();
}
......@@ -6,7 +6,7 @@ public:
Graph(void) {}; // { dg-error "previously defined here" }
}
Graph::Graph(void) // { dg-error "return type|redefinition" }
Graph::Graph(void) // { dg-error "return type|redefinition|semicolon" }
{ N = 10;
}
......@@ -20,7 +20,7 @@ class Y
public:
Y();
}
X::X( int xi ) // { dg-error "return type|X::X" }
X::X( int xi ) // { dg-error "return type|X::X|semicolon" }
{
x = xi;
}
......
......@@ -7,7 +7,7 @@ public:
virtual ~X();
}
X::x() // { dg-error "return type|member function" }
X::x() // { dg-error "return type|member function|semicolon" }
{
}
......
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