This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR9128, PR9153, PR9171


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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]