OSDN Git Service

PR c++/36334
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Jan 2009 18:14:32 +0000 (18:14 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Jan 2009 18:14:32 +0000 (18:14 +0000)
        PR c++/37646
        * tree.c (lvalue_p_1): Handle BASELINK.  A COMPONENT_REF to
        a function isn't necessarily an lvalue. Take tree, not const_tree.
        (lvalue_p, real_lvalue_p): Take tree, not const_tree.
        * typeck.c (lvalue_or_else): Likewise.
        * cp-tree.h: Adjust prototypes.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@143404 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/conversion/memfn1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/conversion/memfn2.C [new file with mode: 0644]

index af7f0c0..4b23d31 100644 (file)
@@ -1,3 +1,13 @@
+2009-01-15  Jason Merrill  <jason@redhat.com>
+
+       PR c++/36334
+       PR c++/37646
+       * tree.c (lvalue_p_1): Handle BASELINK.  A COMPONENT_REF to
+       a function isn't necessarily an lvalue. Take tree, not const_tree.
+       (lvalue_p, real_lvalue_p): Take tree, not const_tree.
+       * typeck.c (lvalue_or_else): Likewise.
+       * cp-tree.h: Adjust prototypes.
+
 2009-01-15  Steve Ellcey  <sje@cup.hp.com>
 
        PR c++/38357
index 718167f..186ec9a 100644 (file)
@@ -4836,7 +4836,7 @@ extern tree canonical_type_variant                (tree);
 extern tree copy_binfo                         (tree, tree, tree,
                                                 tree *, int);
 extern int member_p                            (const_tree);
-extern cp_lvalue_kind real_lvalue_p            (const_tree);
+extern cp_lvalue_kind real_lvalue_p            (tree);
 extern bool builtin_valid_in_constant_expr_p    (const_tree);
 extern tree build_min                          (enum tree_code, tree, ...);
 extern tree build_min_nt                       (enum tree_code, ...);
@@ -4984,9 +4984,9 @@ extern tree lookup_anon_field                     (tree, tree);
 extern bool invalid_nonstatic_memfn_p          (const_tree, tsubst_flags_t);
 extern tree convert_member_func_to_ptr         (tree, tree);
 extern tree convert_ptrmem                     (tree, tree, bool, bool);
-extern int lvalue_or_else                      (const_tree, enum lvalue_use,
+extern int lvalue_or_else                      (tree, enum lvalue_use,
                                                  tsubst_flags_t);
-extern int lvalue_p                            (const_tree);
+extern int lvalue_p                            (tree);
 
 /* in typeck2.c */
 extern void require_complete_eh_spec_types     (tree, tree);
index 8ac2720..3347bfb 100644 (file)
@@ -44,7 +44,7 @@ static tree build_cplus_array_type_1 (tree, tree);
 static int list_hash_eq (const void *, const void *);
 static hashval_t list_hash_pieces (tree, tree, tree);
 static hashval_t list_hash (const void *);
-static cp_lvalue_kind lvalue_p_1 (const_tree, int);
+static cp_lvalue_kind lvalue_p_1 (tree, int);
 static tree build_target_expr (tree, tree);
 static tree count_trees_r (tree *, int *, void *);
 static tree verify_stmt_tree_r (tree *, int *, void *);
@@ -59,7 +59,7 @@ static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
    nonzero, rvalues of class type are considered lvalues.  */
 
 static cp_lvalue_kind
-lvalue_p_1 (const_tree ref,
+lvalue_p_1 (tree ref,
            int treat_class_rvalues_as_lvalues)
 {
   cp_lvalue_kind op1_lvalue_kind = clk_none;
@@ -110,11 +110,13 @@ lvalue_p_1 (const_tree ref,
       op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
                                    treat_class_rvalues_as_lvalues);
       /* Look at the member designator.  */
-      if (!op1_lvalue_kind
-         /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
-            situations.  */
-         || TREE_CODE (TREE_OPERAND (ref, 1)) != FIELD_DECL)
+      if (!op1_lvalue_kind)
        ;
+      else if (is_overloaded_fn (TREE_OPERAND (ref, 1)))
+       /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
+          situations.  */
+       op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
+                                     treat_class_rvalues_as_lvalues);
       else if (DECL_C_BIT_FIELD (TREE_OPERAND (ref, 1)))
        {
          /* Clear the ordinary bit.  If this object was a class
@@ -195,6 +197,12 @@ lvalue_p_1 (const_tree ref,
       return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
              ? clk_none : clk_ordinary);
 
+    case BASELINK:
+      /* We now represent a reference to a single static member function
+        with a BASELINK.  */
+      return lvalue_p_1 (BASELINK_FUNCTIONS (ref),
+                        treat_class_rvalues_as_lvalues);
+
     case NON_DEPENDENT_EXPR:
       /* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
         things like "&E" where "E" is an expression with a
@@ -227,7 +235,7 @@ lvalue_p_1 (const_tree ref,
    computes the C++ definition of lvalue.  */
 
 cp_lvalue_kind
-real_lvalue_p (const_tree ref)
+real_lvalue_p (tree ref)
 {
   return lvalue_p_1 (ref,
                     /*treat_class_rvalues_as_lvalues=*/0);
@@ -237,7 +245,7 @@ real_lvalue_p (const_tree ref)
    considered lvalues.  */
 
 int
-lvalue_p (const_tree ref)
+lvalue_p (tree ref)
 {
   return
     (lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
index 3c7787c..415b8a2 100644 (file)
@@ -7339,7 +7339,7 @@ non_reference (tree t)
    how the lvalue is being used and so selects the error message.  */
 
 int
-lvalue_or_else (const_tree ref, enum lvalue_use use, tsubst_flags_t complain)
+lvalue_or_else (tree ref, enum lvalue_use use, tsubst_flags_t complain)
 {
   int win = lvalue_p (ref);
 
index f7c4833..198ba97 100644 (file)
@@ -1,3 +1,11 @@
+2009-01-15  Jason Merrill  <jason@redhat.com>
+
+       PR c++/36334
+       * g++.dg/conversion/memfn1.C: New test.
+
+       PR c++/37646
+       * g++.dg/conversion/memfn2.C: New test.
+
 2008-01-15  Steve Ellcey  <sje@cup.hp.com>
 
        PR c++/38357
diff --git a/gcc/testsuite/g++.dg/conversion/memfn1.C b/gcc/testsuite/g++.dg/conversion/memfn1.C
new file mode 100644 (file)
index 0000000..da2fb0f
--- /dev/null
@@ -0,0 +1,26 @@
+// PR c++/36334
+
+struct X
+{
+  typedef int* foobar();
+  static void foo(foobar&);
+};
+
+void X::foo(foobar&)
+{
+}
+
+struct Y : public X
+{
+  static foobar bar;
+  static void foo();
+};
+
+void Y::foo()
+{
+  X::foo(bar);
+}
+int* Y::bar()
+{
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/conversion/memfn2.C b/gcc/testsuite/g++.dg/conversion/memfn2.C
new file mode 100644 (file)
index 0000000..c3d7613
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/37646
+
+struct A
+{
+  void foo();
+
+  void bar(int i)
+  {
+    void (*p)() = i ? foo : foo; // { dg-error "invalid use of member" }
+  }
+};