aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-01-10 20:30:56 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-01-10 20:30:56 +0000
commit2050a1bbac14451de357a7d78ffdc6621f49ab30 (patch)
tree2cea45ec7f50f69c10cd2f4336195b5e297a14be
parent0cdca92b467aa92deec2819ff65652b87af6f1ea (diff)
downloadgcc-2050a1bbac14451de357a7d78ffdc6621f49ab30.zip
gcc-2050a1bbac14451de357a7d78ffdc6621f49ab30.tar.gz
gcc-2050a1bbac14451de357a7d78ffdc6621f49ab30.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog36
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl2.c129
-rw-r--r--gcc/cp/parser.c144
-rw-r--r--gcc/cp/rtti.c26
-rw-r--r--gcc/cp/typeck.c49
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/g++.dg/parse/lookup1.C9
-rw-r--r--gcc/testsuite/g++.dg/rtti/typeid1.C11
-rw-r--r--gcc/testsuite/g++.dg/template/spec5.C3
10 files changed, 209 insertions, 213 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 696391d..6ea43a4 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,39 @@
+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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index aad82c0..46fd5b1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 2491c8a..47b841c 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 629ba5d..d626939 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1764,6 +1764,8 @@ static void cp_parser_check_class_key
(enum tag_types, tree type);
static bool cp_parser_optional_template_keyword
(cp_parser *);
+static void cp_parser_pre_parsed_nested_name_specifier
+ (cp_parser *);
static void cp_parser_cache_group
(cp_parser *, cp_token_cache *, enum cpp_ttype, unsigned);
static void cp_parser_parse_tentatively
@@ -3091,15 +3093,6 @@ cp_parser_primary_expression (cp_parser *parser,
function does not do this in order to avoid wastefully creating
SCOPE_REFs when they are not required.
- If ASSUME_TYPENAME_P is true then we assume that qualified names
- are typenames. This flag is set when parsing a declarator-id;
- for something like:
-
- template <class T>
- int S<T>::R::i = 3;
-
- we are supposed to assume that `S<T>::R' is a class.
-
If TEMPLATE_KEYWORD_P is true, then we have just seen the
`template' keyword.
@@ -3460,25 +3453,19 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
bool success = false;
tree access_check = NULL_TREE;
ptrdiff_t start;
+ cp_token* token;
/* If the next token corresponds to a nested name specifier, there
- is no need to reparse it. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_NESTED_NAME_SPECIFIER))
- {
- tree value;
- tree check;
-
- /* Get the stored value. */
- value = cp_lexer_consume_token (parser->lexer)->value;
- /* Perform any access checks that were deferred. */
- for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
- cp_parser_defer_access_check (parser,
- TREE_PURPOSE (check),
- TREE_VALUE (check));
- /* Set the scope from the stored value. */
- parser->scope = TREE_VALUE (value);
- parser->qualifying_scope = TREE_TYPE (value);
- parser->object_scope = NULL_TREE;
+ is no need to reparse it. However, if CHECK_DEPENDENCY_P is
+ false, it may have been true before, in which case something
+ like `A<X>::B<Y>::C' may have resulted in a nested-name-specifier
+ of `A<X>::', where it should now be `A<X>::B<Y>::'. So, when
+ CHECK_DEPENDENCY_P is false, we have to fall through into the
+ main loop. */
+ if (check_dependency_p
+ && cp_lexer_next_token_is (parser->lexer, CPP_NESTED_NAME_SPECIFIER))
+ {
+ cp_parser_pre_parsed_nested_name_specifier (parser);
return parser->scope;
}
@@ -3486,10 +3473,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
{
- cp_token *next_token = cp_lexer_peek_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
start = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
- next_token);
+ token);
access_check = parser->context->deferred_access_checks;
}
else
@@ -3500,13 +3487,25 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
tree new_scope;
tree old_scope;
tree saved_qualifying_scope;
- cp_token *token;
bool template_keyword_p;
/* Spot cases that cannot be the beginning of a
+ nested-name-specifier. */
+ token = cp_lexer_peek_token (parser->lexer);
+
+ /* If the next token is CPP_NESTED_NAME_SPECIFIER, just process
+ the already parsed nested-name-specifier. */
+ if (token->type == CPP_NESTED_NAME_SPECIFIER)
+ {
+ /* Grab the nested-name-specifier and continue the loop. */
+ cp_parser_pre_parsed_nested_name_specifier (parser);
+ success = true;
+ continue;
+ }
+
+ /* Spot cases that cannot be the beginning of a
nested-name-specifier. On the second and subsequent times
through the loop, we look for the `template' keyword. */
- token = cp_lexer_peek_token (parser->lexer);
if (success && token->keyword == RID_TEMPLATE)
;
/* A template-id can start a nested-name-specifier. */
@@ -3631,7 +3630,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
we issue duplicate error messages. */
if (success && start >= 0)
{
- cp_token *token;
tree c;
/* Find the token that corresponds to the start of the
@@ -4232,20 +4230,16 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
postfix_expression = (build_offset_ref_call_from_tree
(postfix_expression, args));
else if (idk == CP_PARSER_ID_KIND_QUALIFIED)
- {
- /* A call to a static class member, or a
- namespace-scope function. */
- postfix_expression
- = finish_call_expr (postfix_expression, args,
- /*disallow_virtual=*/true);
- }
+ /* A call to a static class member, or a namespace-scope
+ function. */
+ postfix_expression
+ = finish_call_expr (postfix_expression, args,
+ /*disallow_virtual=*/true);
else
- {
- /* All other function calls. */
- postfix_expression
- = finish_call_expr (postfix_expression, args,
- /*disallow_virtual=*/false);
- }
+ /* All other function calls. */
+ postfix_expression
+ = finish_call_expr (postfix_expression, args,
+ /*disallow_virtual=*/false);
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
idk = CP_PARSER_ID_KIND_NONE;
@@ -6903,6 +6897,7 @@ cp_parser_decl_specifier_seq (parser, flags, attributes,
{
tree decl_specs = NULL_TREE;
bool friend_p = false;
+ bool constructor_possible_p = true;
/* Assume no class or enumeration type is declared. */
*declares_class_or_enum = false;
@@ -6961,6 +6956,8 @@ cp_parser_decl_specifier_seq (parser, flags, attributes,
decl_spec = token->value;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
+ /* A constructor declarator cannot appear in a typedef. */
+ constructor_possible_p = false;
break;
/* storage-class-specifier:
@@ -6988,6 +6985,7 @@ cp_parser_decl_specifier_seq (parser, flags, attributes,
/* Constructors are a special case. The `S' in `S()' is not a
decl-specifier; it is the beginning of the declarator. */
constructor_p = (!decl_spec
+ && constructor_possible_p
&& cp_parser_constructor_declarator_p (parser,
friend_p));
@@ -7045,6 +7043,9 @@ cp_parser_decl_specifier_seq (parser, flags, attributes,
error message later. */
if (decl_spec && !is_cv_qualifier)
flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
+ /* A constructor declarator cannot follow a type-specifier. */
+ if (decl_spec)
+ constructor_possible_p = false;
}
/* If we still do not have a DECL_SPEC, then there are no more
@@ -8102,10 +8103,12 @@ cp_parser_template_id (cp_parser *parser,
bool saved_greater_than_is_operator_p;
ptrdiff_t start_of_id;
tree access_check = NULL_TREE;
+ cp_token *next_token;
/* If the next token corresponds to a template-id, there is no need
to reparse it. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_TEMPLATE_ID))
+ next_token = cp_lexer_peek_token (parser->lexer);
+ if (next_token->type == CPP_TEMPLATE_ID)
{
tree value;
tree check;
@@ -8121,11 +8124,21 @@ cp_parser_template_id (cp_parser *parser,
return TREE_VALUE (value);
}
+ /* Avoid performing name lookup if there is no possibility of
+ finding a template-id. */
+ if ((next_token->type != CPP_NAME && next_token->keyword != RID_OPERATOR)
+ || (next_token->type == CPP_NAME
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS))
+ {
+ cp_parser_error (parser, "expected template-id");
+ return error_mark_node;
+ }
+
/* Remember where the template-id starts. */
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
{
- cp_token *next_token = cp_lexer_peek_token (parser->lexer);
+ next_token = cp_lexer_peek_token (parser->lexer);
start_of_id = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
next_token);
@@ -10177,7 +10190,7 @@ cp_parser_direct_declarator (parser, dcl_kind, ctor_dtor_or_conv_p)
{
/* This is either a parameter-declaration-clause, or a
parenthesized declarator. When we know we are parsing a
- named declaratory, it must be a paranthesized declarator
+ named declarator, it must be a paranthesized declarator
if FIRST is true. For instance, `(int)' is a
parameter-declaration-clause, with an omitted
direct-abstract-declarator. But `((*))', is a
@@ -11851,7 +11864,7 @@ cp_parser_class_head (parser,
Handle this gracefully by accepting the extra qualifier, and then
issuing an error about it later if this really is a
- class-header. If it turns out just to be an elaborated type
+ class-head. If it turns out just to be an elaborated type
specifier, remain silent. */
if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false))
qualified_p = true;
@@ -11920,7 +11933,8 @@ cp_parser_class_head (parser,
if (TYPE_P (scope)
&& CLASS_TYPE_P (scope)
&& CLASSTYPE_TEMPLATE_INFO (scope)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope))
+ && !CLASSTYPE_TEMPLATE_SPECIALIZATION (scope))
++num_templates;
}
}
@@ -13983,6 +13997,16 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
bool constructor_p;
tree type_decl = NULL_TREE;
bool nested_name_p;
+ cp_token *next_token;
+
+ /* The common case is that this is not a constructor declarator, so
+ try to avoid doing lots of work if at all possible. */
+ next_token = cp_lexer_peek_token (parser->lexer);
+ if (next_token->type != CPP_NAME
+ && next_token->type != CPP_SCOPE
+ && next_token->type != CPP_NESTED_NAME_SPECIFIER
+ && next_token->type != CPP_TEMPLATE_ID)
+ return false;
/* Parse tentatively; we are going to roll back all of the tokens
consumed here. */
@@ -14830,6 +14854,28 @@ cp_parser_optional_template_keyword (cp_parser *parser)
return false;
}
+/* The next token is a CPP_NESTED_NAME_SPECIFIER. Consume the token,
+ set PARSER->SCOPE, and perform other related actions. */
+
+static void
+cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
+{
+ tree value;
+ tree check;
+
+ /* Get the stored value. */
+ value = cp_lexer_consume_token (parser->lexer)->value;
+ /* Perform any access checks that were deferred. */
+ for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
+ cp_parser_defer_access_check (parser,
+ TREE_PURPOSE (check),
+ TREE_VALUE (check));
+ /* Set the scope from the stored value. */
+ parser->scope = TREE_VALUE (value);
+ parser->qualifying_scope = TREE_TYPE (value);
+ parser->object_scope = NULL_TREE;
+}
+
/* Add tokens to CACHE until an non-nested END token appears. */
static void
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index d89f133..71b8e34 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -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. */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index dd7c26b..e7921c5 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f71130f..e642d44 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+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.
diff --git a/gcc/testsuite/g++.dg/parse/lookup1.C b/gcc/testsuite/g++.dg/parse/lookup1.C
new file mode 100644
index 0000000..0325d3c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/lookup1.C
@@ -0,0 +1,9 @@
+#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;
+};
diff --git a/gcc/testsuite/g++.dg/rtti/typeid1.C b/gcc/testsuite/g++.dg/rtti/typeid1.C
new file mode 100644
index 0000000..e265175
--- /dev/null
+++ b/gcc/testsuite/g++.dg/rtti/typeid1.C
@@ -0,0 +1,11 @@
+#include <typeinfo>
+
+struct A {
+ virtual ~A() {}
+};
+
+int main() {
+ A* a = new A;
+ typeid(*a).name();
+}
+
diff --git a/gcc/testsuite/g++.dg/template/spec5.C b/gcc/testsuite/g++.dg/template/spec5.C
new file mode 100644
index 0000000..ad101b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec5.C
@@ -0,0 +1,3 @@
+template <int i> struct A;
+template <> struct A<0> { struct B; };
+struct A<0>::B {};