From 26d880e6480291217e03622c7423dda93b172497 Mon Sep 17 00:00:00 2001
From: nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Fri, 18 Jul 2003 17:19:41 +0000
Subject: [PATCH] cp: 	* cp-tree.h (finish_non_static_data_member): Add
 object param. 	* method.c (hack_identifier): Adjust. 	* pt.c
 (tsubst_copy_and_build) <COMPONENT_REF case>: Don't search 	again for a
 FIELD_DECL. 	* semantics.c (finish_non_static_data_member): Add object 
 parameter. Always save the DECL in the COMPONENT_REF. 	* call.c
 (resolve_scoped_fn_name): Adjust. testsuite: 	*
 g++.dg/parse/non-dependent2.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@69564 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/call.c                               |  2 +-
 gcc/cp/cp-tree.h                            |  2 +-
 gcc/cp/method.c                             |  2 +-
 gcc/cp/pt.c                                 |  2 +
 gcc/cp/semantics.c                          | 50 ++++++++++++++-------
 gcc/testsuite/ChangeLog                     |  4 ++
 gcc/testsuite/g++.dg/parse/non-dependent2.C | 37 +++++++++++++++
 7 files changed, 79 insertions(+), 20 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/non-dependent2.C

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a9323cc1f91d..6f677a5243b2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2651,7 +2651,7 @@ resolve_scoped_fn_name (tree scope, tree name)
 
       /* It might be the name of a function pointer member.  */
       if (fn && TREE_CODE (fn) == FIELD_DECL)
-	fn = finish_non_static_data_member (fn, scope);
+	fn = finish_non_static_data_member (fn, current_class_ref, scope);
     }
   
   if (!fn)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1728b3793535..4f2a1432e466 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4129,7 +4129,7 @@ extern tree finish_label_stmt                   (tree);
 extern void finish_label_decl                   (tree);
 extern void finish_subobject                    (tree);
 extern tree finish_parenthesized_expr           (tree);
-extern tree finish_non_static_data_member       (tree, tree);
+extern tree finish_non_static_data_member       (tree, tree, tree);
 extern tree begin_stmt_expr                     (void);
 extern tree finish_stmt_expr                    (tree);
 extern tree perform_koenig_lookup               (tree, tree);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index e1ffaad3769a..fdc026b3476f 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -117,7 +117,7 @@ hack_identifier (tree value, tree name)
 
   type = TREE_TYPE (value);
   if (TREE_CODE (value) == FIELD_DECL)
-    value = finish_non_static_data_member (value, 
+    value = finish_non_static_data_member (value, current_class_ref,
 					   /*qualifying_scope=*/NULL_TREE);
   else if ((TREE_CODE (value) == FUNCTION_DECL
 	    && DECL_FUNCTION_MEMBER_P (value))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bbce47e769ae..9d66c3c0addb 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8273,6 +8273,8 @@ tsubst_copy_and_build (tree t,
 		return error_mark_node;
 	      }
 	  }
+	else if (TREE_CODE (member) == FIELD_DECL)
+	  return finish_non_static_data_member (member, object, NULL_TREE);
 
 	return finish_class_member_access_expr (object, member);
       }
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3d704ebe1942..812ef6df2dc1 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1218,11 +1218,11 @@ finish_parenthesized_expr (tree expr)
    preceded by `.' or `->'.  */
 
 tree
-finish_non_static_data_member (tree decl, tree qualifying_scope)
+finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
 {
   my_friendly_assert (TREE_CODE (decl) == FIELD_DECL, 20020909);
 
-  if (current_class_ptr == NULL_TREE)
+  if (!object)
     {
       if (current_function_decl 
 	  && DECL_STATIC_FUNCTION_P (current_function_decl))
@@ -1236,27 +1236,42 @@ finish_non_static_data_member (tree decl, tree qualifying_scope)
     }
   TREE_USED (current_class_ptr) = 1;
   if (processing_template_decl)
-    return build_min (COMPONENT_REF, TREE_TYPE (decl),
-		      current_class_ref, DECL_NAME (decl));
-  else
     {
-      tree access_type = current_class_type;
-      tree object = current_class_ref;
+      tree type = TREE_TYPE (decl);
 
-      while (access_type
-	     && !DERIVED_FROM_P (context_for_name_lookup (decl), access_type))
+      if (TREE_CODE (type) == REFERENCE_TYPE)
+	type = TREE_TYPE (type);
+      else
+	{
+	  /* Set the cv qualifiers */
+	  int quals = cp_type_quals (TREE_TYPE (current_class_ref));
+	  
+	  if (DECL_MUTABLE_P (decl))
+	    quals &= ~TYPE_QUAL_CONST;
+	  
+	  quals |= cp_type_quals (TREE_TYPE (decl));
+	  type = cp_build_qualified_type (type, quals);
+	}
+
+      return build_min (COMPONENT_REF, type, object, decl);
+    }
+  else
+    {
+      tree access_type = TREE_TYPE (object);
+      tree lookup_context = context_for_name_lookup (decl);
+      
+      while (!DERIVED_FROM_P (lookup_context, access_type))
 	{
 	  access_type = TYPE_CONTEXT (access_type);
 	  while (access_type && DECL_P (access_type))
 	    access_type = DECL_CONTEXT (access_type);
-	}
 
-      if (!access_type)
-	{
-	  cp_error_at ("object missing in reference to `%D'",
-		       decl);
-	  error ("from this location");
-	  return error_mark_node;
+	  if (!access_type)
+	    {
+	      cp_error_at ("object missing in reference to `%D'", decl);
+	      error ("from this location");
+	      return error_mark_node;
+	    }
 	}
 
       perform_or_defer_access_check (TYPE_BINFO (access_type), decl);
@@ -1357,7 +1372,8 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
     }
 
   if (TREE_CODE (expr) == FIELD_DECL)
-    expr = finish_non_static_data_member (expr, qualifying_class);
+    expr = finish_non_static_data_member (expr, current_class_ref,
+					  qualifying_class);
   else if (BASELINK_P (expr) && !processing_template_decl)
     {
       tree fn;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 60a68bb9b01f..4a3fcb97aca1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-07-18  Nathan Sidwell  <nathan@codesourcery.com>
+
+	* g++.dg/parse/non-dependent2.C: New test.
+
 2003-07-18  Andrew Pinski  <pinskia@physics.uc.edu>
 
 	* g++.dg/init/init-ref4.C: xfail on targets without 
diff --git a/gcc/testsuite/g++.dg/parse/non-dependent2.C b/gcc/testsuite/g++.dg/parse/non-dependent2.C
new file mode 100644
index 000000000000..46335c56bcce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/non-dependent2.C
@@ -0,0 +1,37 @@
+// { dg-do compile }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 16 Jul 2003 <nathan@codesourcery.com>
+
+// A non-dependent field_decl can bind at parse time.
+
+template <class T>
+struct Foo {
+  int j; // we never see this one.
+  int k; // { dg-error "" "" }
+  
+};
+
+struct Baz 
+{
+  int j;
+  int k; // { dg-error "" "" }
+  
+};
+
+template <class T>
+struct Bar : public Foo<T>, Baz {
+  
+  int baz () { return j; } // binds to Baz::j
+  int foo () { return this->k; } // { dg-error "request for member" "" }
+};
+
+int main()
+{
+  Bar<int> bar;
+
+  bar.baz ();
+  bar.foo ();
+  
+  return 0;
+}
-- 
GitLab