]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
call.c (standard_conversion): Use build_ptrmem_type.
authorMark Mitchell <mark@codesourcery.com>
Fri, 9 Aug 2002 19:57:01 +0000 (19:57 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 9 Aug 2002 19:57:01 +0000 (19:57 +0000)
* call.c (standard_conversion): Use build_ptrmem_type.
* cp-tree.h (build_ptrmem_type): New function.
(adjust_result_of_qualified_name_lookup): Likewise.
* decl.c (grokvardecl): Do not look for OFFSET_TYPEs to indicate
static data members.
(build_ptrmem_type): New function.
(grokdeclarator): Do not use build_offset_type when encountering a
qualified name.
* parse.y (parse_finish_call_expr): Use
adjust_result_of_qualified_name_lookup.
* search.c (adjust_result_of_qualified_name_lookup): New function.
* typeck.c (qualify_type_recursive): Use TYPE_PTRMEM_* rather than
accessing OFFSET_TYPEs directly.

* g++.dg/template/crash1.C: New test.

From-SVN: r56169

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parse.y
gcc/cp/search.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/crash1.C

index f9f55ea4865c8729c771c9e197aa7641286d5999..bb028f6273ff0d5d50dd858e356807ca94b2aec5 100644 (file)
@@ -1,3 +1,19 @@
+2002-08-09  Mark Mitchell  <mark@codesourcery.com>
+
+       * call.c (standard_conversion): Use build_ptrmem_type.
+       * cp-tree.h (build_ptrmem_type): New function.
+       (adjust_result_of_qualified_name_lookup): Likewise.
+       * decl.c (grokvardecl): Do not look for OFFSET_TYPEs to indicate
+       static data members.
+       (build_ptrmem_type): New function.
+       (grokdeclarator): Do not use build_offset_type when encountering a
+       qualified name.
+       * parse.y (parse_finish_call_expr): Use
+       adjust_result_of_qualified_name_lookup.
+       * search.c (adjust_result_of_qualified_name_lookup): New function.
+       * typeck.c (qualify_type_recursive): Use TYPE_PTRMEM_* rather than
+       accessing OFFSET_TYPEs directly.
+       
 2002-08-08  Mike Stump  <mrs@apple.com>
 
        * call.c (add_builtin_candidate): legal -> valid, illegal -> invalid.
index 00df003cffbd28f749665b2b5d39b1956e95eb5a..cbd7faf31a92af6d311c0e81dd1fcc519319852e 100644 (file)
@@ -838,8 +838,7 @@ standard_conversion (to, from, expr)
                  (TREE_TYPE (TREE_TYPE (from)),
                   TREE_TYPE (TREE_TYPE (to)))))
            {
-             from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
-             from = build_pointer_type (from);
+             from = build_ptrmem_type (tbase, TREE_TYPE (TREE_TYPE (from)));
              conv = build_conv (PMEM_CONV, from, conv);
            }
        }
index 25b6e949d2d5dd1cb0d44061187c61595d85a0ac..44a52fc8e78e760cbb045b4885bf87948ee27614 100644 (file)
@@ -3682,6 +3682,7 @@ extern void expand_static_init                    PARAMS ((tree, tree));
 extern tree start_handler_parms                 PARAMS ((tree, tree));
 extern int complete_array_type                 PARAMS ((tree, tree, int));
 extern tree build_ptrmemfunc_type              PARAMS ((tree));
+extern tree build_ptrmem_type                   (tree, tree);
 /* the grokdeclarator prototype is in decl.h */
 extern int parmlist_is_exprlist                        PARAMS ((tree));
 extern int copy_fn_p                           PARAMS ((tree));
@@ -4056,7 +4057,8 @@ extern tree find_vbase_instance                 PARAMS ((tree, tree));
 extern tree binfo_for_vbase                     PARAMS ((tree, tree));
 extern tree binfo_via_virtual                   PARAMS ((tree, tree));
 extern tree build_baselink                      (tree, tree, tree, tree);
-
+extern tree adjust_result_of_qualified_name_lookup
+                                                (tree, tree, tree);
 /* in semantics.c */
 extern void init_cp_semantics                   PARAMS ((void));
 extern tree finish_expr_stmt                    PARAMS ((tree));
index 15566e5f1135d38e80dbcef84741bfd37ce801fd..2a185148f51c6ffe7ebba0f70f7fc885511ee18c 100644 (file)
@@ -9137,64 +9137,68 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
   return decl;
 }
 
+/* Create a VAR_DECL named NAME with the indicated TYPE.  
+
+   If SCOPE is non-NULL, it is the class type or namespace containing
+   the variable.  If SCOPE is NULL, the variable should is created in
+   the innermost enclosings scope.  */
+
 static tree
-grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
+grokvardecl (type, name, specbits_in, initialized, constp, scope)
      tree type;
-     tree declarator;
+     tree name;
      RID_BIT_TYPE *specbits_in;
      int initialized;
      int constp;
-     tree in_namespace;
+     tree scope;
 {
   tree decl;
   RID_BIT_TYPE specbits;
 
+  my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE, 
+                     20020808);
+
   specbits = *specbits_in;
 
-  if (TREE_CODE (type) == OFFSET_TYPE)
+  /* Compute the scope in which to place the variable.  */
+  if (!scope)
     {
-      /* If you declare a static member so that it
-        can be initialized, the code will reach here.  */
-      tree basetype = TYPE_OFFSET_BASETYPE (type);
-      type = TREE_TYPE (type);
-      decl = build_lang_decl (VAR_DECL, declarator, type);
-      DECL_CONTEXT (decl) = basetype;
-    }
+      /* An explicit "extern" specifier indicates a namespace-scope
+        variable.  */
+      if (RIDBIT_SETP (RID_EXTERN, specbits))
+       scope = current_namespace;
+      else if (!at_function_scope_p ())
+       {
+         scope = current_scope ();
+         if (!scope)
+           scope = current_namespace;
+       }
+    }
+
+  if (scope
+      && (/* If the variable is a namespace-scope variable declared in a
+            template, we need DECL_LANG_SPECIFIC.  */
+         (TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl)
+         /* Similarly for namespace-scope variables with language linkage
+            other than C++.  */
+         || (TREE_CODE (scope) == NAMESPACE_DECL 
+             && current_lang_name != lang_name_cplusplus)
+         /* Similarly for static data members.  */
+         || TYPE_P (scope)))
+    decl = build_lang_decl (VAR_DECL, name, type);
   else
-    {
-      tree context;
-
-      if (in_namespace)
-       context = in_namespace;
-      else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits))
-       context = current_namespace;
-      else
-       context = NULL_TREE;
-
-      /* For namespace-scope variables, declared in a template, we
-        need the full lang_decl.  The same is true for
-        namespace-scope variables that do not have C++ language
-        linkage.  */
-      if (context 
-         && (processing_template_decl 
-             || current_lang_name != lang_name_cplusplus))
-       decl = build_lang_decl (VAR_DECL, declarator, type);
-      else
-       decl = build_decl (VAR_DECL, declarator, type);
-
-      if (context)
-       set_decl_namespace (decl, context, 0);
+    decl = build_decl (VAR_DECL, name, type);
 
-      context = DECL_CONTEXT (decl);
-      if (declarator && context && current_lang_name != lang_name_c)
-       /* We can't mangle lazily here because we don't have any
-          way to recover whether or not a variable was `extern
-          "C"' later.  */
-       mangle_decl (decl);
-    }
+  if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
+    set_decl_namespace (decl, scope, 0);
+  else
+    DECL_CONTEXT (decl) = scope;
 
-  if (in_namespace)
-    set_decl_namespace (decl, in_namespace, 0);
+  if (name && scope && current_lang_name != lang_name_c)
+    /* We can't mangle lazily here because we don't have any
+       way to recover whether or not a variable was `extern
+       "C"' later.  */
+    mangle_decl (decl);
 
   if (RIDBIT_SETP (RID_EXTERN, specbits))
     {
@@ -9320,6 +9324,14 @@ build_ptrmemfunc_type (type)
   return t;
 }
 
+/* Create and return a pointer to data member type.  */
+
+tree
+build_ptrmem_type (tree class_type, tree member_type)
+{
+  return build_pointer_type (build_offset_type (class_type, member_type));
+}
+
 /* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
    Check to see that the definition is valid.  Issue appropriate error
    messages.  Return 1 if the definition is particularly bad, or 0
@@ -9811,6 +9823,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
                tree attributes;
 
+               if (decl_context != NORMAL)
+                 {
+                   error ("variable declaration is not allowed here");
+                   return error_mark_node;
+                 }
+
                *next = TREE_OPERAND (decl, 0);
                init = CALL_DECLARATOR_PARMS (decl);
 
@@ -9835,7 +9853,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  }
                else
                  error ("invalid declarator");
-               return 0;
+               return NULL_TREE;
              }
            innermost_code = TREE_CODE (decl);
            if (decl_context == FIELD && ctype == NULL_TREE)
@@ -10580,7 +10598,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
   /* Now figure out the structure of the declarator proper.
      Descend through it, creating more complex types, until we reach
-     the declared identifier (or NULL_TREE, in an absolute declarator).  */
+     the declared identifier (or NULL_TREE, in an abstract declarator).  */
 
   while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
         && TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
@@ -10892,9 +10910,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
              continue;
            }
 
-         if (TREE_CODE (type) == OFFSET_TYPE
-             && (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE
-                 || TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE))
+         if (ctype
+             && (TREE_CODE (type) == VOID_TYPE
+                 || TREE_CODE (type) == REFERENCE_TYPE))
            {
              error ("cannot declare pointer to `%#T' member",
                        TREE_TYPE (type));
@@ -10917,6 +10935,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            }
          else if (TREE_CODE (type) == METHOD_TYPE)
            type = build_ptrmemfunc_type (build_pointer_type (type));
+         else if (ctype)
+           type = build_ptrmem_type (ctype, type);
          else
            type = build_pointer_type (type);
 
@@ -11102,7 +11122,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                                  ctype, name, current_class_type);
                        return void_type_node;
                      }
-                   type = build_offset_type (ctype, type);
                  }
                else
                  {
@@ -11121,14 +11140,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                if (declarator && TREE_CODE (declarator) == CALL_EXPR)
                  /* In this case, we will deal with it later.  */
                  ;
-               else
-                 {
-                   if (TREE_CODE (type) == FUNCTION_TYPE)
-                     type = build_cplus_method_type (ctype, TREE_TYPE (type),
-                                                     TYPE_ARG_TYPES (type));
-                   else
-                     type = build_offset_type (ctype, type);
-                 }
+               else if (TREE_CODE (type) == FUNCTION_TYPE)
+                 type = build_cplus_method_type (ctype, TREE_TYPE (type),
+                                                 TYPE_ARG_TYPES (type));
              }
          }
          break;
@@ -11846,7 +11860,7 @@ friend declaration requires class-key, i.e. `friend %#T'",
        decl = grokvardecl (type, declarator, &specbits,
                            initialized,
                            (type_quals & TYPE_QUAL_CONST) != 0,
-                           in_namespace);
+                           ctype ? ctype : in_namespace);
        bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
                        inlinep, friendp, raises != NULL_TREE);
 
index 01181d73b4c313ffd255e54a056ff2cd39ebe92b..1134939f84042cf456354e5e7996a550e6cae2a0 100644 (file)
@@ -4156,22 +4156,9 @@ parse_finish_call_expr (tree fn, tree args, int koenig)
                                  BASELINK_FUNCTIONS (fn),
                                  template_args);
                }
-             if (BASELINK_P (fn) 
-                 && current_class_type 
-                 && DERIVED_FROM_P (scope, current_class_type))
-               {
-                 scope = lookup_base (current_class_type, scope,
-                                      ba_ignore | ba_quiet, NULL);
-                 if (scope)
-                   {
-                     BASELINK_ACCESS_BINFO (fn) = scope;
-                     BASELINK_BINFO (fn) 
-                       = lookup_base (scope,
-                                      BINFO_TYPE (BASELINK_BINFO (fn)),
-                                      ba_ignore | ba_quiet,
-                                      NULL);
-                   }
-               }
+             if (current_class_type)
+               fn = (adjust_result_of_qualified_name_lookup 
+                     (fn, scope, current_class_type));
            }
        }
       disallow_virtual = true;
index 071a551fbe36b929f18a83d12fd2b8c9bb0c2ec6..e4e8baa9ad274c7f5d5971c4df41950977799dbb 100644 (file)
@@ -1640,6 +1640,50 @@ lookup_fnfields_1 (type, name)
 
   return -1;
 }
+
+/* DECL is the result of a qualified name lookup.  QUALIFYING_CLASS
+   was the class used to qualify the name.  CONTEXT_CLASS is the class
+   corresponding to the object in which DECL will be used.  Return a
+   possibly modified version of DECL that takes into account the
+   CONTEXT_CLASS.
+
+   In particular, consider an expression like `B::m' in the context of
+   a derived class `D'.  If `B::m' has been resolved to a BASELINK,
+   then the most derived class indicated by the BASELINK_BINFO will be
+   `B', not `D'.  This function makes that adjustment.  */
+
+tree
+adjust_result_of_qualified_name_lookup (tree decl, 
+                                       tree qualifying_class,
+                                       tree context_class)
+{
+  my_friendly_assert (CLASS_TYPE_P (qualifying_class), 20020808);
+  my_friendly_assert (CLASS_TYPE_P (context_class), 20020808);
+
+  if (BASELINK_P (decl) 
+      && DERIVED_FROM_P (qualifying_class, context_class))
+    {
+      tree base;
+
+      /* Look for the QUALIFYING_CLASS as a base of the
+        CONTEXT_CLASS.  If QUALIFYING_CLASS is ambiguous, we cannot
+        be sure yet than an error has occurred; perhaps the function
+        chosen by overload resolution will be static.  */
+      base = lookup_base (context_class, qualifying_class,
+                         ba_ignore | ba_quiet, NULL);
+      if (base)
+       {
+         BASELINK_ACCESS_BINFO (decl) = base;
+         BASELINK_BINFO (decl) 
+           = lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
+                          ba_ignore | ba_quiet,
+                          NULL);
+       }
+    }
+
+  return decl;
+}
+
 \f
 /* Walk the class hierarchy dominated by TYPE.  FN is called for each
    type in the hierarchy, in a breadth-first preorder traversal.
index 09ecd66b4ad1ca2044ec5bea0f1ffbf4a02b82d2..f8bc3786358bfeb0f5186dde56acc2bedb2b1251 100644 (file)
@@ -203,28 +203,33 @@ qualify_type_recursive (t1, t2)
   if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2))
       || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)))
     {
-      tree tt1 = TREE_TYPE (t1);
-      tree tt2 = TREE_TYPE (t2);
+      tree tt1;
+      tree tt2;
       tree b1;
       int type_quals;
       tree tgt;
       tree attributes = (*targetm.merge_type_attributes) (t1, t2);
 
-      if (TREE_CODE (tt1) == OFFSET_TYPE)
+      if (TYPE_PTRMEM_P (t1))
        {
-         b1 = TYPE_OFFSET_BASETYPE (tt1);
-         tt1 = TREE_TYPE (tt1);
-         tt2 = TREE_TYPE (tt2);
+         b1 = TYPE_PTRMEM_CLASS_TYPE (t1);
+         tt1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1);
+         tt2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2);
        }
       else
-       b1 = NULL_TREE;
+       {
+         b1 = NULL_TREE;
+         tt1 = TREE_TYPE (t1);
+         tt2 = TREE_TYPE (t2);
+       }
 
       type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2));
       tgt = qualify_type_recursive (tt1, tt2);
       tgt = cp_build_qualified_type (tgt, type_quals);
       if (b1)
-       tgt = build_offset_type (b1, tgt);
-      t1 = build_pointer_type (tgt);
+       t1 = build_ptrmem_type (b1, tgt);
+      else
+       t1 = build_pointer_type (tgt);
       t1 = build_type_attribute_variant (t1, attributes);
     }
   return t1;
@@ -4390,9 +4395,7 @@ unary_complex_lvalue (code, arg)
              return error_mark_node;
            }
 
-         type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
-         type = build_pointer_type (type);
-
+         type = build_ptrmem_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
          t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
          return t;
        }
index 3e18dc1c34075f534ac4490f0f836953289cbdfe..c1bd99ba9e7198af98f77cea3ff350f30b419e52 100644 (file)
@@ -1,3 +1,7 @@
+2002-08-09  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/template/crash1.C: New test.
+
 2002-08-08  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/tls/opt-2.c: New test.
index 27e89641ac75d29b2033917a776b567b71141ab6..e3c83bcd22f57ab2258bdc0f2d61ea9216f3ae74 100644 (file)
@@ -1,7 +1,7 @@
 // { dg-do compile }
 
-// Copyright (C) 2001 Free Software Foundation, Inc.
-// Contributed by Nathan Sidwell 29 Dec 2001 <nathan@nathan@codesourcery.com>
+// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 29 Dec 2001 <nathan@codesourcery.com>
 
 // PR 5125. ICE
 
@@ -13,5 +13,5 @@ class S
 
 template <class I>
 void S::Foo(int (*f)(TYPO&o) )
-{ // { dg-error "template definition of non-template|prototype" "" }
+{ // { dg-error "template definition|variable declaration|prototype" "" }
 }