Commit cf3c30d3 by Jason Merrill Committed by Jason Merrill

re PR c++/55127 (Incorrect "dependent scope" error with partial specialization…

re PR c++/55127 (Incorrect "dependent scope" error with partial specialization of non-type parameter)

	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.

From-SVN: r194318
parent 4eaee921
2012-12-07 Jason Merrill <jason@redhat.com>
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.
PR c++/55419
* tree.c (build_target_expr): Don't set TREE_CONSTANT.
......
......@@ -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);
......
......@@ -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;
......
......@@ -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,
......
......@@ -5268,7 +5268,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. */
......
// 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>();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment