semantics.c (finish_pseudo_destructor_expr): Allow differing cv-qualification between...
authorMark Mitchell <mark@codesourcery.com>
Fri, 19 Mar 2004 07:27:30 +0000 (07:27 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 19 Mar 2004 07:27:30 +0000 (07:27 +0000)
* semantics.c (finish_pseudo_destructor_expr): Allow differing
cv-qualification between the type named by the
pseudo-destructor-name and the object-type.

* search.c (accessible_base_p): Handle non-proper bases.

* name-lookup.c (do_nonmember_using_decl): If a using declaration
refers to a single overloaded function, set the type of the
function.
* tree.c (lvalue_type): Simplify.
* typeck.c (type_unknown_p): Do not assume all OVERLOADs have an
unknown type.
(build_unary_op): Handle OVERLOADs with known types.

* decl.c (duplicate_decls): Do not destroy DECL_ARGUMENTS for
function templates.

* parser.c (cp_parser_postfix_expression): Handle the use of
"typename" in non-dependent contexts.  Convert appropriately when
when using a qualified name after "->" or ".".

* call.c (conditional_conversion): Honor the requirement that some
conversions refer to the original object.

* g++.dg/expr/dtor2.C: New test.

* g++.dg/lookup/anon4.C: New test.

* g++.dg/overload/using1.C: New test.

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

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

* g++.dg/expr/cond6.C: New test.

From-SVN: r79671

16 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/decl.c
gcc/cp/name-lookup.c
gcc/cp/parser.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/expr/cond6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/expr/dtor2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/anon4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/overload/using1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/lookup7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/typename6.C [new file with mode: 0644]

index 1052abe..3822563 100644 (file)
@@ -1,5 +1,31 @@
 2004-03-18  Mark Mitchell  <mark@codesourcery.com>
 
+       * semantics.c (finish_pseudo_destructor_expr): Allow differing
+       cv-qualification between the type named by the
+       pseudo-destructor-name and the object-type.
+
+       * search.c (accessible_base_p): Handle non-proper bases.
+
+       * name-lookup.c (do_nonmember_using_decl): If a using declaration
+       refers to a single overloaded function, set the type of the
+       function.
+       * tree.c (lvalue_type): Simplify.
+       * typeck.c (type_unknown_p): Do not assume all OVERLOADs have an
+       unknown type.
+       (build_unary_op): Handle OVERLOADs with known types.
+
+       * decl.c (duplicate_decls): Do not destroy DECL_ARGUMENTS for
+       function templates.
+
+       * parser.c (cp_parser_postfix_expression): Handle the use of
+       "typename" in non-dependent contexts.  Convert appropriately when
+       when using a qualified name after "->" or ".".
+
+       * call.c (conditional_conversion): Honor the requirement that some
+       conversions refer to the original object.
+
+2004-03-18  Mark Mitchell  <mark@codesourcery.com>
+
        * call.c (build_conditional_expr): Do not call force_rvalue for
        operands of void_type when the conditional expression itself has
        void type.
index 7a3039b..7270ed6 100644 (file)
@@ -3072,10 +3072,7 @@ conditional_conversion (tree e1, tree e2)
      same cv-qualification as, or a greater cv-qualification than, the
      cv-qualification of T1.  If the conversion is applied, E1 is
      changed to an rvalue of type T2 that still refers to the original
-     source class object (or the appropriate subobject thereof).
-
-     FIXME we can't express an rvalue that refers to the original object;
-     we have to create a new one.  */
+     source class object (or the appropriate subobject thereof).  */
   if (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
       && ((good_base = DERIVED_FROM_P (t2, t1)) || DERIVED_FROM_P (t1, t2)))
     {
@@ -3084,10 +3081,7 @@ conditional_conversion (tree e1, tree e2)
          conv = build_identity_conv (t1, e1);
          if (!same_type_p (TYPE_MAIN_VARIANT (t1), 
                            TYPE_MAIN_VARIANT (t2)))
-           {
-             conv = build_conv (ck_base, t2, conv);
-             conv->need_temporary_p = true;
-           }
+           conv = build_conv (ck_base, t2, conv);
          else
            conv = build_conv (ck_rvalue, t2, conv);
          return conv;
index 29232f2..29d6588 100644 (file)
@@ -1581,6 +1581,9 @@ duplicate_decls (tree newdecl, tree olddecl)
          DECL_SOURCE_LOCATION (olddecl) 
            = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
            = DECL_SOURCE_LOCATION (newdecl);
+         if (DECL_FUNCTION_TEMPLATE_P (newdecl))
+           DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (olddecl))
+             = DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (newdecl));
        }
 
       if (DECL_FUNCTION_TEMPLATE_P (newdecl))
index 1589682..e0a919d 100644 (file)
@@ -2194,9 +2194,21 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
          if (tmp1)
            continue;
            
+         /* If we are adding to an existing OVERLOAD, then we no
+            longer know the type of the set of functions.  */
+         if (*newval && TREE_CODE (*newval) == OVERLOAD)
+           TREE_TYPE (*newval) = unknown_type_node;
+         /* Add this new function to the set.  */
          *newval = build_overload (OVL_CURRENT (tmp), *newval);
+         /* If there is only one function, then we use its type.  (A
+            using-declaration naming a single function can be used in
+            contexts where overload resolution cannot be
+            performed.)  */
          if (TREE_CODE (*newval) != OVERLOAD)
-           *newval = ovl_cons (*newval, NULL_TREE);
+           {
+             *newval = ovl_cons (*newval, NULL_TREE);
+             TREE_TYPE (*newval) = TREE_TYPE (OVL_CURRENT (tmp));
+           }
          OVL_USED (*newval) = 1;
        }
     }
index 0dc63cd..c05e375 100644 (file)
@@ -3629,10 +3629,16 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
        /* If that didn't work, try an identifier.  */
        if (!cp_parser_parse_definitely (parser))
          id = cp_parser_identifier (parser);
+       /* If we look up a template-id in a non-dependent qualifying
+          scope, there's no need to create a dependent type.  */
+       if (TREE_CODE (id) == TYPE_DECL
+           && !dependent_type_p (parser->scope))
+         type = TREE_TYPE (id);
        /* Create a TYPENAME_TYPE to represent the type to which the
           functional cast is being performed.  */
-       type = make_typename_type (parser->scope, id,
-                                  /*complain=*/1);
+       else
+         type = make_typename_type (parser->scope, id, 
+                                    /*complain=*/1);
 
        postfix_expression = cp_parser_functional_cast (parser, type);
       }
@@ -3971,6 +3977,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                    parser->qualifying_scope = NULL_TREE;
                    parser->object_scope = NULL_TREE;
                  }
+               if (scope && name && BASELINK_P (name))
+                 adjust_result_of_qualified_name_lookup 
+                   (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
                postfix_expression
                  = finish_class_member_access_expr (postfix_expression, name);
              }
index 30dc0d2..11c7ded 100644 (file)
@@ -232,7 +232,7 @@ lookup_base_r (tree binfo, tree base, base_access access,
 }
 
 /* Returns true if type BASE is accessible in T.  (BASE is known to be
-   a base class of T.)  */
+   a (possibly non-proper) base class of T.)  */
 
 bool
 accessible_base_p (tree t, tree base)
@@ -242,7 +242,12 @@ accessible_base_p (tree t, tree base)
   /* [class.access.base]
 
      A base class is said to be accessible if an invented public
-     member of the base class is accessible.  */
+     member of the base class is accessible.  
+
+     If BASE is a non-proper base, this condition is trivially
+     true.  */
+  if (same_type_p (t, base))
+    return true;
   /* Rather than inventing a public member, we use the implicit
      public typedef created in the scope of every class.  */
   decl = TYPE_FIELDS (base);
index e7d3771..50cb153 100644 (file)
@@ -1803,7 +1803,21 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor)
          return error_mark_node;
        }
       
-      if (!same_type_p (TREE_TYPE (object), destructor))
+      /* [expr.pseudo] says both:
+
+           The type designated by the pseudo-destructor-name shall be
+          the same as the object type.
+
+         and:
+
+           The cv-unqualified versions of the object type and of the
+          type designated by the pseudo-destructor-name shall be the
+          same type.
+
+         We implement the more generous second sentence, since that is
+         what most other compilers do.  */
+      if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object), 
+                                                     destructor))
        {
          error ("`%E' is not of type `%T'", object, destructor);
          return error_mark_node;
index 290317e..85855ac 100644 (file)
@@ -1646,8 +1646,6 @@ tree
 lvalue_type (tree arg)
 {
   tree type = TREE_TYPE (arg);
-  if (TREE_CODE (arg) == OVERLOAD)
-    type = unknown_type_node;
   return type;
 }
 
index e353d3f..32d8177 100644 (file)
@@ -163,8 +163,7 @@ complete_type_or_diagnostic (tree type, tree value, int diag_type)
 int
 type_unknown_p (tree exp)
 {
-  return (TREE_CODE (exp) == OVERLOAD
-          || TREE_CODE (exp) == TREE_LIST
+  return (TREE_CODE (exp) == TREE_LIST
          || TREE_TYPE (exp) == unknown_type_node);
 }
 
@@ -4022,7 +4021,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
          if (! lvalue_p (arg) && pedantic)
            pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression");
          break;
-         
+
+       case OVERLOAD:
+         arg = OVL_CURRENT (arg);
+         break;
+
        default:
          break;
        }
index 03a37e6..391bfa3 100644 (file)
@@ -1,3 +1,17 @@
+2004-03-18  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/expr/dtor2.C: New test.
+
+       * g++.dg/lookup/anon4.C: New test.
+
+       * g++.dg/overload/using1.C: New test.
+
+       * g++.dg/template/lookup7.C: New test.
+
+       * g++.dg/template/typename6.C: New test.
+
+       * g++.dg/expr/cond6.C: New test.
+
 2004-03-18  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * gcc.dg/torture/builtin-convert-1.c: Test more math builtins.
diff --git a/gcc/testsuite/g++.dg/expr/cond6.C b/gcc/testsuite/g++.dg/expr/cond6.C
new file mode 100644 (file)
index 0000000..9308c17
--- /dev/null
@@ -0,0 +1,24 @@
+// { dg-do "run" }
+
+extern "C" void abort ();
+
+struct B {
+  B() {}
+  B(const B& b) { abort (); }
+};
+
+struct D : public B {
+  D() {}
+  D(const D& d) : B() {}
+};
+
+D d;
+B b;
+
+D f() {
+  return d;
+}
+
+int main () {
+  b = (true ? f() : b);
+}
diff --git a/gcc/testsuite/g++.dg/expr/dtor2.C b/gcc/testsuite/g++.dg/expr/dtor2.C
new file mode 100644 (file)
index 0000000..5f37242
--- /dev/null
@@ -0,0 +1,6 @@
+typedef const int I;
+int i;
+
+void f() {
+  i.I::~I();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/anon4.C b/gcc/testsuite/g++.dg/lookup/anon4.C
new file mode 100644 (file)
index 0000000..40c4ab4
--- /dev/null
@@ -0,0 +1,9 @@
+static union {
+  int i;
+};
+
+int *ip;
+
+void g() {
+  ip = &i;
+}
diff --git a/gcc/testsuite/g++.dg/overload/using1.C b/gcc/testsuite/g++.dg/overload/using1.C
new file mode 100644 (file)
index 0000000..bc46c60
--- /dev/null
@@ -0,0 +1,11 @@
+void f();
+
+namespace N { 
+  using ::f;
+}
+
+bool b;
+
+void g() {
+  b = N::f == ::f;
+}
diff --git a/gcc/testsuite/g++.dg/template/lookup7.C b/gcc/testsuite/g++.dg/template/lookup7.C
new file mode 100644 (file)
index 0000000..0e05c5f
--- /dev/null
@@ -0,0 +1,9 @@
+class S;
+
+template<class T>
+int f(T, S);
+
+class S {
+  template<class T>
+  friend int f(T t, S) { t; return 0; }
+};
diff --git a/gcc/testsuite/g++.dg/template/typename6.C b/gcc/testsuite/g++.dg/template/typename6.C
new file mode 100644 (file)
index 0000000..937ea96
--- /dev/null
@@ -0,0 +1,11 @@
+struct O {
+  template <typename T>
+  struct I {
+    I (int);
+  };
+};
+
+template <typename T>
+void f() {
+  typename ::O::I<int>(3);
+}