diff mbox

C++ PATCH for c++/55127 (bogus required typename)

Message ID 50C28B8F.7060001@redhat.com
State New
Headers show

Commit Message

Jason Merrill Dec. 8, 2012, 12:36 a.m. UTC
My patch that introduced "instantiation-dependent" to the compiler 
treated all SCOPE_REFs as instantiation-dependent, on the principle that 
we might need to check accessibility at instantiation time.  But if the 
member reference is public, it will always be accessible, so we don't 
need to worry.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit d891f539e75bd20fd6fb303aff4a06a053f10ae6
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Dec 7 14:33:08 2012 -0500

    	PR c++/55127
    	* search.c (accessible_in_template_p): New.
    	* cp-tree.h: Declare it.
    	* pt.c (instantiation_dependent_scope_ref_p): New.
    	(value_dependent_expression_p): Use it.
    	(instantiation_dependent_r): Likewise.
    	* semantics.c (finish_decltype_type): Handle SCOPE_REF.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ceac093..1733250 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5489,6 +5489,7 @@  extern tree lookup_base                         (tree, tree, base_access,
 						 base_kind *, tsubst_flags_t);
 extern tree dcast_base_hint			(tree, tree);
 extern int accessible_p				(tree, tree, bool);
+extern int accessible_in_template_p		(tree, tree);
 extern tree lookup_field_1			(tree, tree, bool);
 extern tree lookup_field			(tree, tree, int, bool);
 extern int lookup_fnfields_1			(tree, tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 33044e0..1bc9e1b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19293,6 +19293,22 @@  dependent_scope_p (tree scope)
 	  && !currently_open_class (scope));
 }
 
+/* T is a SCOPE_REF; return whether we need to consider it
+    instantiation-dependent so that we can check access at instantiation
+    time even though we know which member it resolves to.  */
+
+static bool
+instantiation_dependent_scope_ref_p (tree t)
+{
+  if (DECL_P (TREE_OPERAND (t, 1))
+      && CLASS_TYPE_P (TREE_OPERAND (t, 0))
+      && accessible_in_template_p (TREE_OPERAND (t, 0),
+				   TREE_OPERAND (t, 1)))
+    return false;
+  else
+    return true;
+}
+
 /* Returns TRUE if the EXPRESSION is value-dependent, in the sense of
    [temp.dep.constexpr].  EXPRESSION is already known to be a constant
    expression.  */
@@ -19400,10 +19416,9 @@  value_dependent_expression_p (tree expression)
       return instantiation_dependent_expression_p (expression);
 
     case SCOPE_REF:
-      /* instantiation_dependent_r treats this as dependent so that we
-	 check access at instantiation time, and all instantiation-dependent
-	 expressions should also be considered value-dependent.  */
-      return true;
+      /* All instantiation-dependent expressions should also be considered
+	 value-dependent.  */
+      return instantiation_dependent_scope_ref_p (expression);
 
     case COMPONENT_REF:
       return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
@@ -19744,10 +19759,10 @@  instantiation_dependent_r (tree *tp, int *walk_subtrees,
       break;
 
     case SCOPE_REF:
-      /* Similarly, finish_qualified_id_expr builds up a SCOPE_REF in a
-	 template so that we can check access at instantiation time even
-	 though we know which member it resolves to.  */
-      return *tp;
+      if (instantiation_dependent_scope_ref_p (*tp))
+	return *tp;
+      else
+	break;
 
     default:
       break;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 92234a5..1cd4fc5 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -832,6 +832,19 @@  dfs_accessible_post (tree binfo, void * /*data*/)
   return NULL_TREE;
 }
 
+/* Like accessible_p below, but within a template returns true iff DECL is
+   accessible in TYPE to all possible instantiations of the template.  */
+
+int
+accessible_in_template_p (tree type, tree decl)
+{
+  int save_ptd = processing_template_decl;
+  processing_template_decl = 0;
+  int val = accessible_p (type, decl, false);
+  processing_template_decl = save_ptd;
+  return val;
+}
+
 /* DECL is a declaration from a base class of TYPE, which was the
    class used to name DECL.  Return nonzero if, in the current
    context, DECL is accessible.  If TYPE is actually a BINFO node,
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 491d97c..0fa251b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5261,7 +5261,8 @@  finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
         expr = TREE_OPERAND (expr, 0);
 
       if (TREE_CODE (expr) == OFFSET_REF
-          || TREE_CODE (expr) == MEMBER_REF)
+          || TREE_CODE (expr) == MEMBER_REF
+	  || TREE_CODE (expr) == SCOPE_REF)
         /* We're only interested in the field itself. If it is a
            BASELINK, we will need to see through it in the next
            step.  */
diff --git a/gcc/testsuite/g++.dg/template/defarg16.C b/gcc/testsuite/g++.dg/template/defarg16.C
new file mode 100644
index 0000000..ba78bfb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/defarg16.C
@@ -0,0 +1,28 @@ 
+// PR c++/55127
+
+struct some_class
+{
+  static const bool     is_valid_type = true;
+};
+
+template< typename Type
+        , bool Valid = Type::is_valid_type
+>
+struct wrapper;
+
+template< typename Type >
+struct wrapper< Type, true >
+{
+  typedef Type type;
+};
+
+template< typename T >
+void fun()
+{
+  wrapper<some_class>::type x;
+}
+
+int main()
+{
+  fun<int>();
+}