re PR c++/9128 (Typeid does not work on polymorphic classes)
authorMark Mitchell <mark@codesourcery.com>
Fri, 10 Jan 2003 20:30:56 +0000 (20:30 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 10 Jan 2003 20:30:56 +0000 (20:30 +0000)
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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/parser.c
gcc/cp/rtti.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/lookup1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/rtti/typeid1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/spec5.C [new file with mode: 0644]

index 696391d392136c0827c7ea522ba3dd81c3935376..6ea43a423d470b15c6ca864b427b6ae21b02bb79 100644 (file)
@@ -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.
index aad82c019b2d5c6c12ecc4c6d5701ba3dd7d50cd..46fd5b1c3514d6c95da5090a94c48a10330a082c 100644 (file)
@@ -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));
index 2491c8a397949e461599728ecd4ce5a5d06fdab6..47b841cbd3bdf90d463d87e37bd5e50aef159256 100644 (file)
@@ -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
index 629ba5d81780d88ee5241a83f085c2d7385c559f..d626939e281aa07a18b56a8797507bac77c59280 100644 (file)
@@ -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
index d89f13332d704f3e98f0cbc367218e1536ac5983..71b8e34b19982868f599dd6d8474815d230310ab 100644 (file)
@@ -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));
 }
 \f
-/* 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.  */
index dd7c26bd8f68d9bad87795d2355beacb1ad65722..e7921c55e1009e5c3c384bdecf6972c830887adc 100644 (file)
@@ -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)
index f71130fe65c2fe0fc714c57f36b80329342edcb1..e642d44faa571b309d3f57999c47a9a2d4a16f01 100644 (file)
@@ -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 (file)
index 0000000..0325d3c
--- /dev/null
@@ -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 (file)
index 0000000..e265175
--- /dev/null
@@ -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 (file)
index 0000000..ad101b0
--- /dev/null
@@ -0,0 +1,3 @@
+template <int i> struct A;
+template <> struct A<0> { struct B; };
+struct A<0>::B {};