This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR9128, PR9153, PR9171
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 10 Jan 2003 12:30:04 -0800
- Subject: C++ PATCH: PR9128, PR9153, PR9171
- Reply-to: mark at codesourcery dot com
This patch is last night's Starbucks hacking; fixes three open
regressions against GCC 3.4. I also got rid of the no-longer-used
(thank goodness) reparse_* functions.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
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 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.
Index: testsuite/g++.dg/parse/lookup1.C
===================================================================
RCS file: testsuite/g++.dg/parse/lookup1.C
diff -N testsuite/g++.dg/parse/lookup1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/lookup1.C 10 Jan 2003 20:28:24 -0000
***************
*** 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;
+ };
Index: testsuite/g++.dg/rtti/typeid1.C
===================================================================
RCS file: testsuite/g++.dg/rtti/typeid1.C
diff -N testsuite/g++.dg/rtti/typeid1.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/rtti/typeid1.C 10 Jan 2003 20:28:24 -0000
***************
*** 0 ****
--- 1,11 ----
+ #include <typeinfo>
+
+ struct A {
+ virtual ~A() {}
+ };
+
+ int main() {
+ A* a = new A;
+ typeid(*a).name();
+ }
+
Index: testsuite/g++.dg/template/spec5.C
===================================================================
RCS file: testsuite/g++.dg/template/spec5.C
diff -N testsuite/g++.dg/template/spec5.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/spec5.C 10 Jan 2003 20:28:24 -0000
***************
*** 0 ****
--- 1,3 ----
+ template <int i> struct A;
+ template <> struct A<0> { struct B; };
+ struct A<0>::B {};
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.795
diff -c -5 -p -r1.795 cp-tree.h
*** cp/cp-tree.h 10 Jan 2003 02:22:14 -0000 1.795
--- cp/cp-tree.h 10 Jan 2003 20:28:33 -0000
*************** extern void comdat_linkage (tree);
*** 3863,3879 ****
extern void import_export_vtable (tree, tree, int);
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));
extern void pop_decl_namespace PARAMS ((void));
extern void push_scope PARAMS ((tree));
--- 3863,3875 ----
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.593
diff -c -5 -p -r1.593 decl2.c
*** cp/decl2.c 10 Jan 2003 02:22:15 -0000 1.593
--- cp/decl2.c 10 Jan 2003 20:28:33 -0000
*************** finish_file ()
*** 2874,2956 ****
dump_tree_statistics ();
dump_time_statistics ();
}
}
- /* 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. */
tree
build_expr_from_tree (t)
--- 2874,2883 ----
*************** build_call_from_tree (tree fn, tree args
*** 3457,3522 ****
else
fn = template_id;
}
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
--- 3384,3393 ----
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.24
diff -c -5 -p -r1.24 parser.c
*** cp/parser.c 10 Jan 2003 02:22:18 -0000 1.24
--- cp/parser.c 10 Jan 2003 20:28:36 -0000
*************** static enum tag_types cp_parser_token_is
*** 1762,1771 ****
--- 1762,1773 ----
PARAMS ((cp_token *));
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
PARAMS ((cp_parser *));
static void cp_parser_commit_to_tentative_parse
*************** cp_parser_primary_expression (cp_parser
*** 3089,3107 ****
Often, if the id-expression was a qualified-id, the caller will
want to make a SCOPE_REF to represent the qualified-id. This
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.
If CHECK_DEPENDENCY_P is false, then names are looked up inside
uninstantiated templates.
--- 3091,3100 ----
*************** cp_parser_nested_name_specifier_opt (cp_
*** 3458,3514 ****
bool type_p)
{
bool success = false;
tree access_check = NULL_TREE;
ptrdiff_t start;
/* 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;
return parser->scope;
}
/* Remember where the nested-name-specifier starts. */
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
{
! cp_token *next_token = cp_lexer_peek_token (parser->lexer);
start = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
! next_token);
access_check = parser->context->deferred_access_checks;
}
else
start = -1;
while (true)
{
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. 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. */
else if (token->type == CPP_TEMPLATE_ID)
;
--- 3451,3513 ----
bool type_p)
{
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. 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;
}
/* Remember where the nested-name-specifier starts. */
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
{
! token = cp_lexer_peek_token (parser->lexer);
start = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
! token);
access_check = parser->context->deferred_access_checks;
}
else
start = -1;
while (true)
{
tree new_scope;
tree old_scope;
tree saved_qualifying_scope;
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. */
if (success && token->keyword == RID_TEMPLATE)
;
/* A template-id can start a nested-name-specifier. */
else if (token->type == CPP_TEMPLATE_ID)
;
*************** cp_parser_nested_name_specifier_opt (cp_
*** 3629,3639 ****
token. That way, should we re-parse the token stream, we will
not have to repeat the effort required to do the parse, nor will
we issue duplicate error messages. */
if (success && start >= 0)
{
- cp_token *token;
tree c;
/* Find the token that corresponds to the start of the
template-id. */
token = cp_lexer_advance_token (parser->lexer,
--- 3628,3637 ----
*************** cp_parser_postfix_expression (cp_parser
*** 4230,4253 ****
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
else if (TREE_CODE (postfix_expression) == OFFSET_REF)
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);
! }
else
! {
! /* 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;
}
break;
--- 4228,4247 ----
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
else if (TREE_CODE (postfix_expression) == OFFSET_REF)
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);
else
! /* 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;
}
break;
*************** cp_parser_decl_specifier_seq (parser, fl
*** 6901,6910 ****
--- 6895,6905 ----
tree *attributes;
bool *declares_class_or_enum;
{
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;
/* Assume there are no attributes. */
*************** cp_parser_decl_specifier_seq (parser, fl
*** 6959,6968 ****
--- 6954,6965 ----
/* The representation of the specifier is simply the
appropriate TREE_IDENTIFIER node. */
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:
auto
register
*************** cp_parser_decl_specifier_seq (parser, fl
*** 6986,6995 ****
--- 6983,6993 ----
}
/* 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));
/* If we don't have a DECL_SPEC yet, then we must be looking at
a type-specifier. */
*************** cp_parser_decl_specifier_seq (parser, fl
*** 7043,7052 ****
--- 7041,7053 ----
user-defined types. We *do* still allow things like `int
int' to be considered a decl-specifier-seq, and issue the
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
decl-specifiers. */
if (!decl_spec)
*************** cp_parser_template_id (cp_parser *parser
*** 8100,8113 ****
tree saved_object_scope;
tree template_id;
bool saved_greater_than_is_operator_p;
ptrdiff_t start_of_id;
tree access_check = NULL_TREE;
/* 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))
{
tree value;
tree check;
/* Get the stored value. */
--- 8101,8116 ----
tree saved_object_scope;
tree template_id;
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. */
! next_token = cp_lexer_peek_token (parser->lexer);
! if (next_token->type == CPP_TEMPLATE_ID)
{
tree value;
tree check;
/* Get the stored value. */
*************** cp_parser_template_id (cp_parser *parser
*** 8119,8133 ****
TREE_VALUE (check));
/* Return the stored value. */
return TREE_VALUE (value);
}
/* 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);
start_of_id = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
next_token);
access_check = parser->context->deferred_access_checks;
}
--- 8122,8146 ----
TREE_VALUE (check));
/* Return the stored value. */
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))
{
! next_token = cp_lexer_peek_token (parser->lexer);
start_of_id = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
next_token);
access_check = parser->context->deferred_access_checks;
}
*************** cp_parser_direct_declarator (parser, dcl
*** 10175,10185 ****
token = cp_lexer_peek_token (parser->lexer);
if (token->type == CPP_OPEN_PAREN)
{
/* 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
if FIRST is true. For instance, `(int)' is a
parameter-declaration-clause, with an omitted
direct-abstract-declarator. But `((*))', is a
parenthesized abstract declarator. Finally, when T is a
template parameter `(T)' is a
--- 10188,10198 ----
token = cp_lexer_peek_token (parser->lexer);
if (token->type == CPP_OPEN_PAREN)
{
/* This is either a parameter-declaration-clause, or a
parenthesized declarator. When we know we are parsing a
! 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
parenthesized abstract declarator. Finally, when T is a
template parameter `(T)' is a
*************** cp_parser_class_head (parser,
*** 11849,11859 ****
struct ::S {};
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
specifier, remain silent. */
if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false))
qualified_p = true;
/* Determine the name of the class. Begin by looking for an
--- 11862,11872 ----
struct ::S {};
Handle this gracefully by accepting the extra qualifier, and then
issuing an error about it later if this really is a
! 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;
/* Determine the name of the class. Begin by looking for an
*************** cp_parser_class_head (parser,
*** 11918,11928 ****
? TYPE_CONTEXT (scope)
: DECL_CONTEXT (scope)))
if (TYPE_P (scope)
&& CLASS_TYPE_P (scope)
&& CLASSTYPE_TEMPLATE_INFO (scope)
! && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
++num_templates;
}
}
/* Otherwise, the identifier is optional. */
else
--- 11931,11942 ----
? TYPE_CONTEXT (scope)
: DECL_CONTEXT (scope)))
if (TYPE_P (scope)
&& CLASS_TYPE_P (scope)
&& CLASSTYPE_TEMPLATE_INFO (scope)
! && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope))
! && !CLASSTYPE_TEMPLATE_SPECIALIZATION (scope))
++num_templates;
}
}
/* Otherwise, the identifier is optional. */
else
*************** static bool
*** 13981,13990 ****
--- 13995,14014 ----
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. */
cp_parser_parse_tentatively (parser);
/* Assume that we are looking at a constructor declarator. */
*************** cp_parser_optional_template_keyword (cp_
*** 14826,14835 ****
--- 14850,14881 ----
return true;
}
}
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
Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.151
diff -c -5 -p -r1.151 rtti.c
*** cp/rtti.c 1 Jan 2003 11:58:58 -0000 1.151
--- cp/rtti.c 10 Jan 2003 20:28:36 -0000
*************** throw_bad_cast (void)
*** 172,181 ****
--- 172,184 ----
void_list_node));
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)
{
tree fn = get_identifier ("__cxa_bad_typeid");
if (IDENTIFIER_GLOBAL_VALUE (fn))
*************** throw_bad_typeid (void)
*** 185,205 ****
tree t = build_qualified_type (type_info_type_node, TYPE_QUAL_CONST);
t = build_function_type (build_reference_type (t), void_list_node);
fn = push_throw_library_fn (fn, t);
}
! return 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;
otherwise return the static type of the expression. */
static tree
get_tinfo_decl_dynamic (tree exp)
{
tree type;
if (exp == error_mark_node)
return error_mark_node;
type = TREE_TYPE (exp);
--- 188,210 ----
tree t = build_qualified_type (type_info_type_node, TYPE_QUAL_CONST);
t = build_function_type (build_reference_type (t), void_list_node);
fn = push_throw_library_fn (fn, t);
}
! return convert_from_reference (build_call (fn, NULL_TREE));
}
! /* 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;
type = TREE_TYPE (exp);
*************** get_tinfo_decl_dynamic (tree exp)
*** 219,240 ****
/* If exp is a reference to polymorphic type, get the real type_info. */
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;
}
! /* Otherwise return the type_info for the static type of the expr. */
! return get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
}
static bool
typeid_ok_p (void)
{
--- 224,245 ----
/* If exp is a reference to polymorphic type, get the real type_info. */
if (TYPE_POLYMORPHIC_P (type) && ! resolves_to_fixed_type_p (exp, 0))
{
/* build reference to type_info from vtable. */
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;
}
+ else
+ /* Otherwise return the type_info for the static type of the expr. */
+ t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
! return build_indirect_ref (t, NULL);
}
static bool
typeid_ok_p (void)
{
*************** typeid_ok_p (void)
*** 251,260 ****
--- 256,268 ----
}
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)
{
tree cond = NULL_TREE;
int nonnull = 0;
*************** build_typeid (tree exp)
*** 278,297 ****
exp = get_tinfo_decl_dynamic (exp);
if (exp == error_mark_node)
return error_mark_node;
- exp = build_indirect_ref (exp, NULL);
-
if (cond)
{
tree bad = throw_bad_typeid ();
exp = build (COND_EXPR, TREE_TYPE (exp), cond, exp, bad);
}
! return convert_from_reference (exp);
}
/* Generate the NTBS name of a type. */
static tree
tinfo_name (tree type)
--- 286,303 ----
exp = get_tinfo_decl_dynamic (exp);
if (exp == error_mark_node)
return error_mark_node;
if (cond)
{
tree bad = throw_bad_typeid ();
exp = build (COND_EXPR, TREE_TYPE (exp), cond, exp, bad);
}
! return exp;
}
/* Generate the NTBS name of a type. */
static tree
tinfo_name (tree type)
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.442
diff -c -5 -p -r1.442 typeck.c
*** cp/typeck.c 1 Jan 2003 11:58:58 -0000 1.442
--- cp/typeck.c 10 Jan 2003 20:28:37 -0000
*************** build_class_member_access_expr (tree obj
*** 1863,1893 ****
return 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
complete type). */
object_type = TREE_TYPE (object);
--- 1863,1872 ----
*************** build_class_member_access_expr (tree obj
*** 1921,1930 ****
--- 1900,1937 ----
member_scope = TYPE_CONTEXT (member_scope);
if (!member_scope || !DERIVED_FROM_P (member_scope, object_type))
{
error ("`%D' is not a member of `%T'", member, object_type);
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)