Commit 2050a1bb by Mark Mitchell Committed by Mark Mitchell

re PR c++/9128 (Typeid does not work on polymorphic classes)


	PR c++/9128
	* g++.dg/rtti/typeid1.C: New file.

	PR c++/9153
	* g++.dg/parse/lookup1.C: New file.

	PR c++/9171
	* g++.dg/templ/spec5.C: New file.

	* cp-tree.h (reparse_absdcl_as_expr): Remove.
	(reparse_absdcl_as_casts): Likewise.
	(reparse_decl_as_expr): Likewise.
	(finish_decl_parsing): Likewise.
	* decl2.c (reparse_absdcl_as_expr): Remove.
	(reparse_absdcl_as_casts): Likewise.
	(repase_decl_as_expr): Likewise.
	(finish_decl_parsing): Likewise.

	PR c++/9128
	PR c++/9153
	PR c++/9171
	* parser.c (cp_parser_pre_parsed_nested_name_specifier): New
	function.
	(cp_parser_nested_name_specifier_opt): Correct the
	check_dependency_p false.
	(cp_parser_postfix_expression): Fix formatting.
	(cp_parser_decl_specifier_seq): Avoid looking for constructor
	declarators when possible.
	(cp_parser_template_id): Avoid performing name-lookup when
	possible.
	(cp_parser_class_head): Do not count specializations when counting
	levels of templates.
	(cp_parser_constructor_declarator_p): Return immediately if
	there's no chance that the tokens form a constructor declarator.
	* rtti.c (throw_bad_typeid): Add comment.  Do not return an
	expression with reference type.
	(get_tinfo_decl_dynamic): Do not return an expression with
	reference type.
	(build_typeid): Add comment.  Do not return an expression with
	reference type.
	* typeck.c (build_class_member_access_expr): Improve handling of
	conditionals and comma-expressions as objects.

From-SVN: r61166
parent 0cdca92b
2003-01-10 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (reparse_absdcl_as_expr): Remove.
(reparse_absdcl_as_casts): Likewise.
(reparse_decl_as_expr): Likewise.
(finish_decl_parsing): Likewise.
* decl2.c (reparse_absdcl_as_expr): Remove.
(reparse_absdcl_as_casts): Likewise.
(repase_decl_as_expr): Likewise.
(finish_decl_parsing): Likewise.
PR c++/9128
PR c++/9153
PR c++/9171
* parser.c (cp_parser_pre_parsed_nested_name_specifier): New
function.
(cp_parser_nested_name_specifier_opt): Correct the
check_dependency_p false.
(cp_parser_postfix_expression): Fix formatting.
(cp_parser_decl_specifier_seq): Avoid looking for constructor
declarators when possible.
(cp_parser_template_id): Avoid performing name-lookup when
possible.
(cp_parser_class_head): Do not count specializations when counting
levels of templates.
(cp_parser_constructor_declarator_p): Return immediately if
there's no chance that the tokens form a constructor declarator.
* rtti.c (throw_bad_typeid): Add comment. Do not return an
expression with reference type.
(get_tinfo_decl_dynamic): Do not return an expression with
reference type.
(build_typeid): Add comment. Do not return an expression with
reference type.
* typeck.c (build_class_member_access_expr): Improve handling of
conditionals and comma-expressions as objects.
2003-01-09 Nathanael Nerode <neroden@gcc.gnu.org>
* decl.c (bad_specifiers): Fix parameter order error I introduced.
......
......@@ -3865,13 +3865,9 @@ extern void import_export_decl (tree);
extern void import_export_tinfo (tree, tree, bool);
extern tree build_cleanup PARAMS ((tree));
extern void finish_file PARAMS ((void));
extern tree reparse_absdcl_as_expr PARAMS ((tree, tree));
extern tree reparse_absdcl_as_casts PARAMS ((tree, tree));
extern tree build_expr_from_tree PARAMS ((tree));
extern tree build_offset_ref_call_from_tree (tree, tree);
extern tree build_call_from_tree (tree, tree, bool);
extern tree reparse_decl_as_expr (tree, tree);
extern tree finish_decl_parsing (tree);
extern void set_decl_namespace (tree, tree, bool);
extern tree current_decl_namespace PARAMS ((void));
extern void push_decl_namespace PARAMS ((tree));
......
......@@ -2876,79 +2876,6 @@ finish_file ()
}
}
/* This is something of the form 'A()()()()()+1' that has turned out to be an
expr. Since it was parsed like a type, we need to wade through and fix
that. Unfortunately, since operator() is left-associative, we can't use
tail recursion. In the above example, TYPE is `A', and DECL is
`()()()()()'.
Maybe this shouldn't be recursive, but how often will it actually be
used? (jason) */
tree
reparse_absdcl_as_expr (type, decl)
tree type, decl;
{
/* do build_functional_cast (type, NULL_TREE) at bottom */
if (TREE_OPERAND (decl, 0) == NULL_TREE)
return build_functional_cast (type, NULL_TREE);
/* recurse */
decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
return finish_call_expr (decl, NULL_TREE, /*disallow_virtual=*/false);
}
/* This is something of the form `int ((int)(int)(int)1)' that has turned
out to be an expr. Since it was parsed like a type, we need to wade
through and fix that. Since casts are right-associative, we are
reversing the order, so we don't have to recurse.
In the above example, DECL is the `(int)(int)(int)', and EXPR is the
`1'. */
tree
reparse_absdcl_as_casts (decl, expr)
tree decl, expr;
{
tree type;
int non_void_p = 0;
if (TREE_CODE (expr) == CONSTRUCTOR
&& TREE_TYPE (expr) == 0)
{
type = groktypename (TREE_VALUE (CALL_DECLARATOR_PARMS (decl)));
decl = TREE_OPERAND (decl, 0);
if (processing_template_decl)
TREE_TYPE (expr) = type;
else
{
expr = digest_init (type, expr, (tree *) 0);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
int failure = complete_array_type (type, expr, 1);
my_friendly_assert (!failure, 78);
}
}
}
while (decl)
{
type = groktypename (TREE_VALUE (CALL_DECLARATOR_PARMS (decl)));
decl = TREE_OPERAND (decl, 0);
if (!VOID_TYPE_P (type))
non_void_p = 1;
expr = build_c_cast (type, expr);
}
if (warn_old_style_cast && ! in_system_header
&& non_void_p && current_lang_name != lang_name_c)
warning ("use of old-style cast");
return expr;
}
/* T is the parse tree for an expression. Return the expression after
performing semantic analysis. */
......@@ -3461,62 +3388,6 @@ build_call_from_tree (tree fn, tree args, bool disallow_virtual)
return finish_call_expr (fn, args, disallow_virtual);
}
/* This is something of the form `int (*a)++' that has turned out to be an
expr. It was only converted into parse nodes, so we need to go through
and build up the semantics. Most of the work is done by
build_expr_from_tree, above.
In the above example, TYPE is `int' and DECL is `*a'. */
tree
reparse_decl_as_expr (tree type, tree decl)
{
decl = build_expr_from_tree (decl);
if (type)
return build_functional_cast (type, build_tree_list (NULL_TREE, decl));
else
return decl;
}
/* This is something of the form `int (*a)' that has turned out to be a
decl. It was only converted into parse nodes, so we need to do the
checking that make_{pointer,reference}_declarator do. */
tree
finish_decl_parsing (tree decl)
{
switch (TREE_CODE (decl))
{
case IDENTIFIER_NODE:
return decl;
case INDIRECT_REF:
return make_pointer_declarator
(NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0)));
case ADDR_EXPR:
return make_reference_declarator
(NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0)));
case BIT_NOT_EXPR:
TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
return decl;
case SCOPE_REF:
push_nested_class (TREE_TYPE (TREE_OPERAND (decl, 0)), 3);
TREE_COMPLEXITY (decl) = current_class_depth;
return decl;
case ARRAY_REF:
TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
return decl;
case TREE_LIST:
/* For attribute handling. */
TREE_VALUE (decl) = finish_decl_parsing (TREE_VALUE (decl));
return decl;
case TEMPLATE_ID_EXPR:
return decl;
default:
abort ();
return NULL_TREE;
}
}
/* Return 1 if root encloses child. */
static bool
......
......@@ -174,6 +174,9 @@ throw_bad_cast (void)
return build_call (fn, NULL_TREE);
}
/* Return an expression for "__cxa_bad_typeid()". The expression
returned is an lvalue of type "const std::type_info". */
static tree
throw_bad_typeid (void)
{
......@@ -187,17 +190,19 @@ throw_bad_typeid (void)
fn = push_throw_library_fn (fn, t);
}
return build_call (fn, NULL_TREE);
return convert_from_reference (build_call (fn, NULL_TREE));
}
/* Return a pointer to type_info function associated with the expression EXP.
If EXP is a reference to a polymorphic class, return the dynamic type;
/* Return an lvalue expression whose type is "const std::type_info"
and whose value indicates the type of the expression EXP. If EXP
is a reference to a polymorphic class, return the dynamic type;
otherwise return the static type of the expression. */
static tree
get_tinfo_decl_dynamic (tree exp)
{
tree type;
tree t;
if (exp == error_mark_node)
return error_mark_node;
......@@ -221,18 +226,18 @@ get_tinfo_decl_dynamic (tree exp)
if (TYPE_POLYMORPHIC_P (type) && ! resolves_to_fixed_type_p (exp, 0))
{
/* build reference to type_info from vtable. */
tree t;
tree index;
/* The RTTI information is at index -1. */
index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
t = build_vtbl_ref (exp, index);
TREE_TYPE (t) = type_info_ptr_type;
return t;
}
else
/* Otherwise return the type_info for the static type of the expr. */
t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
/* Otherwise return the type_info for the static type of the expr. */
return get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
return build_indirect_ref (t, NULL);
}
static bool
......@@ -253,6 +258,9 @@ typeid_ok_p (void)
return true;
}
/* Return an expression for "typeid(EXP)". The expression returned is
an lvalue of type "const std::type_info". */
tree
build_typeid (tree exp)
{
......@@ -280,8 +288,6 @@ build_typeid (tree exp)
if (exp == error_mark_node)
return error_mark_node;
exp = build_indirect_ref (exp, NULL);
if (cond)
{
tree bad = throw_bad_typeid ();
......@@ -289,7 +295,7 @@ build_typeid (tree exp)
exp = build (COND_EXPR, TREE_TYPE (exp), cond, exp, bad);
}
return convert_from_reference (exp);
return exp;
}
/* Generate the NTBS name of a type. */
......
......@@ -1865,27 +1865,6 @@ build_class_member_access_expr (tree object, tree member,
my_friendly_assert (DECL_P (member) || BASELINK_P (member),
20020801);
/* Transform `(a, b).x' into `a, b.x' and `(a ? b : c).x' into
`a ? b.x : c.x'. These transformations should not really be
necessary, but they are. */
if (TREE_CODE (object) == COMPOUND_EXPR)
{
result = build_class_member_access_expr (TREE_OPERAND (object, 1),
member, access_path,
preserve_reference);
return build (COMPOUND_EXPR, TREE_TYPE (result),
TREE_OPERAND (object, 0), result);
}
else if (TREE_CODE (object) == COND_EXPR)
return (build_conditional_expr
(TREE_OPERAND (object, 0),
build_class_member_access_expr (TREE_OPERAND (object, 1),
member, access_path,
preserve_reference),
build_class_member_access_expr (TREE_OPERAND (object, 2),
member, access_path,
preserve_reference)));
/* [expr.ref]
The type of the first expression shall be "class object" (of a
......@@ -1925,6 +1904,34 @@ build_class_member_access_expr (tree object, tree member,
return error_mark_node;
}
/* Transform `(a, b).x' into `(*(a, &b)).x' and `(a ? b : c).x' into
`(*(a ? &b : &c)).x'. Unfortunately, expand_expr cannot handle a
COMPONENT_REF where the first operand is a conditional or comma
expression with class type. */
if (TREE_CODE (object) == COMPOUND_EXPR)
{
object = build (COMPOUND_EXPR,
build_pointer_type (object_type),
TREE_OPERAND (object, 0),
build_unary_op (ADDR_EXPR,
TREE_OPERAND (object, 1),
/*noconvert=*/1));
object = build_indirect_ref (object, NULL);
}
else if (TREE_CODE (object) == COND_EXPR)
{
object = build (COND_EXPR,
build_pointer_type (object_type),
TREE_OPERAND (object, 0),
build_unary_op (ADDR_EXPR,
TREE_OPERAND (object, 1),
/*noconvert=*/1),
build_unary_op (ADDR_EXPR,
TREE_OPERAND (object, 2),
/*noconvert=*/1));
object = build_indirect_ref (object, NULL);
}
/* In [expr.ref], there is an explicit list of the valid choices for
MEMBER. We check for each of those cases here. */
if (TREE_CODE (member) == VAR_DECL)
......
2003-01-10 Mark Mitchell <mark@codesourcery.com>
PR c++/9128
* g++.dg/rtti/typeid1.C: New file.
PR c++/9153
* g++.dg/parse/lookup1.C: New file.
PR c++/9171
* g++.dg/templ/spec5.C: New file.
2003-01-10 Josef Zlomek <zlomekj@suse.cz>
* gcc.c-torture/compile/20030110-1.c: New test.
......
#include <list>
using namespace std;
template <class T, class Alloc>
class new_list : public list<T, Alloc> {
public:
typedef typename list<T, Alloc>::iterator iterator;
};
#include <typeinfo>
struct A {
virtual ~A() {}
};
int main() {
A* a = new A;
typeid(*a).name();
}
template <int i> struct A;
template <> struct A<0> { struct B; };
struct A<0>::B {};
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