Fix type-dependence and the current instantiation.
PR c++/10200 PR c++/69753 * pt.c (tsubst_decl): Use uses_template_parms. (instantiate_template_1): Handle non-dependent calls in templates. (value_dependent_expression_p): Handle BASELINK, FUNCTION_DECL. (type_dependent_expression_p): Only consider innermost template args. (dependent_template_arg_p): Check enclosing class of a template here. (dependent_template_p): Not here. (type_dependent_object_expression_p): New. * typeck.c (finish_class_member_access_expr): Use it. * parser.c (cp_parser_postfix_expression): Use it. (cp_parser_postfix_dot_deref_expression): Use it. Use comptypes to detect the current instantiation. (cp_parser_lookup_name): Really implement DR 141. * search.c (lookup_field_r): Prefer a dependent using-declaration. (any_dependent_bases_p): Split out from... * name-lookup.c (do_class_using_decl): ...here. * call.c (build_new_method_call_1): Use it. * semantics.c (finish_call_expr): 'this' doesn't make a call dependent. * tree.c (non_static_member_function_p): Remove. * typeck2.c (build_x_arrow): Use dependent_scope_p. From-SVN: r236221
This commit is contained in:
parent
827e5d3f70
commit
23cb726630
14 changed files with 207 additions and 118 deletions
|
@ -1,5 +1,27 @@
|
|||
2016-05-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/10200
|
||||
PR c++/69753
|
||||
* pt.c (tsubst_decl): Use uses_template_parms.
|
||||
(instantiate_template_1): Handle non-dependent calls in templates.
|
||||
(value_dependent_expression_p): Handle BASELINK, FUNCTION_DECL.
|
||||
(type_dependent_expression_p): Only consider innermost template args.
|
||||
(dependent_template_arg_p): Check enclosing class of a template here.
|
||||
(dependent_template_p): Not here.
|
||||
(type_dependent_object_expression_p): New.
|
||||
* typeck.c (finish_class_member_access_expr): Use it.
|
||||
* parser.c (cp_parser_postfix_expression): Use it.
|
||||
(cp_parser_postfix_dot_deref_expression): Use it. Use comptypes
|
||||
to detect the current instantiation.
|
||||
(cp_parser_lookup_name): Really implement DR 141.
|
||||
* search.c (lookup_field_r): Prefer a dependent using-declaration.
|
||||
(any_dependent_bases_p): Split out from...
|
||||
* name-lookup.c (do_class_using_decl): ...here.
|
||||
* call.c (build_new_method_call_1): Use it.
|
||||
* semantics.c (finish_call_expr): 'this' doesn't make a call dependent.
|
||||
* tree.c (non_static_member_function_p): Remove.
|
||||
* typeck2.c (build_x_arrow): Use dependent_scope_p.
|
||||
|
||||
* parser.c (cp_parser_postfix_dot_deref_expression): Use
|
||||
complete_type_or_else for unknown_type_node, too.
|
||||
|
||||
|
|
|
@ -8407,6 +8407,9 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
|
|||
we know we really need it. */
|
||||
cand->first_arg = instance;
|
||||
}
|
||||
else if (any_dependent_bases_p ())
|
||||
/* We can't tell until instantiation time whether we can use
|
||||
*this as the implicit object argument. */;
|
||||
else
|
||||
{
|
||||
if (complain & tf_error)
|
||||
|
|
|
@ -6125,6 +6125,7 @@ extern bool any_dependent_template_arguments_p (const_tree);
|
|||
extern bool dependent_template_p (tree);
|
||||
extern bool dependent_template_id_p (tree, tree);
|
||||
extern bool type_dependent_expression_p (tree);
|
||||
extern bool type_dependent_object_expression_p (tree);
|
||||
extern bool any_type_dependent_arguments_p (const vec<tree, va_gc> *);
|
||||
extern bool any_type_dependent_elements_p (const_tree);
|
||||
extern bool type_dependent_expression_p_push (tree);
|
||||
|
@ -6233,6 +6234,7 @@ extern tree adjust_result_of_qualified_name_lookup
|
|||
extern tree copied_binfo (tree, tree);
|
||||
extern tree original_binfo (tree, tree);
|
||||
extern int shared_member_p (tree);
|
||||
extern bool any_dependent_bases_p (tree = current_nonlambda_class_type ());
|
||||
|
||||
/* The representation of a deferred access check. */
|
||||
|
||||
|
@ -6525,7 +6527,6 @@ extern tree get_first_fn (tree);
|
|||
extern tree ovl_cons (tree, tree);
|
||||
extern tree build_overload (tree, tree);
|
||||
extern tree ovl_scope (tree);
|
||||
extern bool non_static_member_function_p (tree);
|
||||
extern const char *cxx_printable_name (tree, int);
|
||||
extern const char *cxx_printable_name_translate (tree, int);
|
||||
extern tree build_exception_variant (tree, tree);
|
||||
|
|
|
@ -3333,8 +3333,6 @@ do_class_using_decl (tree scope, tree name)
|
|||
/* True if any of the bases of CURRENT_CLASS_TYPE are dependent. */
|
||||
bool bases_dependent_p;
|
||||
tree binfo;
|
||||
tree base_binfo;
|
||||
int i;
|
||||
|
||||
if (name == error_mark_node)
|
||||
return NULL_TREE;
|
||||
|
@ -3371,16 +3369,7 @@ do_class_using_decl (tree scope, tree name)
|
|||
|| (IDENTIFIER_TYPENAME_P (name)
|
||||
&& dependent_type_p (TREE_TYPE (name))));
|
||||
|
||||
bases_dependent_p = false;
|
||||
if (processing_template_decl)
|
||||
for (binfo = TYPE_BINFO (current_class_type), i = 0;
|
||||
BINFO_BASE_ITERATE (binfo, i, base_binfo);
|
||||
i++)
|
||||
if (dependent_type_p (TREE_TYPE (base_binfo)))
|
||||
{
|
||||
bases_dependent_p = true;
|
||||
break;
|
||||
}
|
||||
bases_dependent_p = any_dependent_bases_p ();
|
||||
|
||||
decl = NULL_TREE;
|
||||
|
||||
|
|
|
@ -6851,7 +6851,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
tree fn = TREE_OPERAND (postfix_expression, 1);
|
||||
|
||||
if (processing_template_decl
|
||||
&& (type_dependent_expression_p (instance)
|
||||
&& (type_dependent_object_expression_p (instance)
|
||||
|| (!BASELINK_P (fn)
|
||||
&& TREE_CODE (fn) != FIELD_DECL)
|
||||
|| type_dependent_expression_p (fn)
|
||||
|
@ -7186,8 +7186,9 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
|
|||
if (token_type == CPP_DEREF)
|
||||
postfix_expression = build_x_arrow (location, postfix_expression,
|
||||
tf_warning_or_error);
|
||||
/* Check to see whether or not the expression is type-dependent. */
|
||||
dependent_p = type_dependent_expression_p (postfix_expression);
|
||||
/* Check to see whether or not the expression is type-dependent and
|
||||
not the current instantiation. */
|
||||
dependent_p = type_dependent_object_expression_p (postfix_expression);
|
||||
/* The identifier following the `->' or `.' is not qualified. */
|
||||
parser->scope = NULL_TREE;
|
||||
parser->qualifying_scope = NULL_TREE;
|
||||
|
@ -7211,7 +7212,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
|
|||
required to be of complete type for purposes of class member
|
||||
access (5.2.5) outside the member function body. */
|
||||
if (postfix_expression != current_class_ref
|
||||
&& !(processing_template_decl && scope == current_class_type))
|
||||
&& !(processing_template_decl
|
||||
&& current_class_type
|
||||
&& (same_type_ignoring_top_level_qualifiers_p
|
||||
(scope, current_class_type))))
|
||||
scope = complete_type_or_else (scope, postfix_expression);
|
||||
/* Let the name lookup machinery know that we are processing a
|
||||
class member access expression. */
|
||||
|
@ -24806,24 +24810,11 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
|
|||
decl = NULL_TREE;
|
||||
|
||||
if (!decl)
|
||||
{
|
||||
/* Look it up in the enclosing context. */
|
||||
decl = lookup_name_real (name, tag_type != none_type,
|
||||
/*nonclass=*/0,
|
||||
/*block_p=*/true, is_namespace, 0);
|
||||
/* DR 141 says when looking for a template-name after -> or ., only
|
||||
consider class templates. We need to fix our handling of
|
||||
dependent expressions to implement that properly, but for now
|
||||
let's ignore namespace-scope function templates. */
|
||||
if (decl && is_template && !DECL_TYPE_TEMPLATE_P (decl))
|
||||
{
|
||||
tree d = decl;
|
||||
if (is_overloaded_fn (d))
|
||||
d = get_first_fn (d);
|
||||
if (DECL_P (d) && !DECL_CLASS_SCOPE_P (d))
|
||||
decl = NULL_TREE;
|
||||
}
|
||||
}
|
||||
/* Look it up in the enclosing context. DR 141: When looking for a
|
||||
template-name after -> or ., only consider class templates. */
|
||||
decl = lookup_name_real (name, tag_type != none_type || is_template,
|
||||
/*nonclass=*/0,
|
||||
/*block_p=*/true, is_namespace, 0);
|
||||
if (object_type == unknown_type_node)
|
||||
/* The object is type-dependent, so we can't look anything up; we used
|
||||
this to get the DR 141 behavior. */
|
||||
|
|
103
gcc/cp/pt.c
103
gcc/cp/pt.c
|
@ -11700,16 +11700,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
|||
if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL)
|
||||
{
|
||||
tree spec;
|
||||
bool dependent_p;
|
||||
|
||||
/* If T is not dependent, just return it. We have to
|
||||
increment PROCESSING_TEMPLATE_DECL because
|
||||
value_dependent_expression_p assumes that nothing is
|
||||
dependent when PROCESSING_TEMPLATE_DECL is zero. */
|
||||
++processing_template_decl;
|
||||
dependent_p = value_dependent_expression_p (t);
|
||||
--processing_template_decl;
|
||||
if (!dependent_p)
|
||||
/* If T is not dependent, just return it. */
|
||||
if (!uses_template_parms (DECL_TI_ARGS (t)))
|
||||
RETURN (t);
|
||||
|
||||
/* Calculate the most general template of which R is a
|
||||
|
@ -17328,12 +17321,14 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
|
|||
|
||||
/* Check to see if we already have this specialization. */
|
||||
gen_tmpl = most_general_template (tmpl);
|
||||
if (tmpl != gen_tmpl)
|
||||
/* The TMPL is a partial instantiation. To get a full set of
|
||||
arguments we must add the arguments used to perform the
|
||||
partial instantiation. */
|
||||
targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
|
||||
targ_ptr);
|
||||
if (TMPL_ARGS_DEPTH (targ_ptr)
|
||||
< TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (gen_tmpl)))
|
||||
/* targ_ptr only has the innermost template args, so add the outer ones
|
||||
from tmpl, which could be either a partial instantiation or gen_tmpl (in
|
||||
the case of a non-dependent call within a template definition). */
|
||||
targ_ptr = (add_outermost_template_args
|
||||
(DECL_TI_ARGS (DECL_TEMPLATE_RESULT (tmpl)),
|
||||
targ_ptr));
|
||||
|
||||
/* It would be nice to avoid hashing here and then again in tsubst_decl,
|
||||
but it doesn't seem to be on the hot path. */
|
||||
|
@ -22653,6 +22648,22 @@ value_dependent_expression_p (tree expression)
|
|||
|
||||
switch (TREE_CODE (expression))
|
||||
{
|
||||
case BASELINK:
|
||||
/* A member function of a dependent class has dependent template
|
||||
arguments from its class. */
|
||||
if (dependent_type_p (BINFO_TYPE (BASELINK_BINFO (expression))))
|
||||
return true;
|
||||
return value_dependent_expression_p (BASELINK_FUNCTIONS (expression));
|
||||
|
||||
case FUNCTION_DECL:
|
||||
/* A function template specialization is value-dependent if it has any
|
||||
dependent template arguments, since that means it cannot be
|
||||
instantiated for constexpr evaluation. */
|
||||
if (DECL_LANG_SPECIFIC (expression)
|
||||
&& DECL_TEMPLATE_INFO (expression))
|
||||
return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
|
||||
break;
|
||||
|
||||
case IDENTIFIER_NODE:
|
||||
/* A name that has not been looked up -- must be dependent. */
|
||||
return true;
|
||||
|
@ -22797,10 +22808,10 @@ value_dependent_expression_p (tree expression)
|
|||
|
||||
case CALL_EXPR:
|
||||
{
|
||||
if (value_dependent_expression_p (CALL_EXPR_FN (expression)))
|
||||
return true;
|
||||
tree fn = get_callee_fndecl (expression);
|
||||
int i, nargs;
|
||||
if (!fn && value_dependent_expression_p (CALL_EXPR_FN (expression)))
|
||||
return true;
|
||||
nargs = call_expr_nargs (expression);
|
||||
for (i = 0; i < nargs; ++i)
|
||||
{
|
||||
|
@ -22964,13 +22975,6 @@ type_dependent_expression_p (tree expression)
|
|||
|| dependent_scope_p (scope));
|
||||
}
|
||||
|
||||
/* A function template specialization is type-dependent if it has any
|
||||
dependent template arguments. */
|
||||
if (TREE_CODE (expression) == FUNCTION_DECL
|
||||
&& DECL_LANG_SPECIFIC (expression)
|
||||
&& DECL_TEMPLATE_INFO (expression))
|
||||
return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
|
||||
|
||||
if (TREE_CODE (expression) == TEMPLATE_DECL
|
||||
&& !DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
|
||||
return false;
|
||||
|
@ -23023,13 +23027,18 @@ type_dependent_expression_p (tree expression)
|
|||
&& DECL_INITIAL (expression))
|
||||
return true;
|
||||
|
||||
/* A variable template specialization is type-dependent if it has any
|
||||
dependent template arguments. */
|
||||
if (VAR_P (expression)
|
||||
/* A function or variable template-id is type-dependent if it has any
|
||||
dependent template arguments. Note that we only consider the innermost
|
||||
template arguments here, since those are the ones that come from the
|
||||
template-id; the template arguments for the enclosing class do not make it
|
||||
type-dependent, they only make a member function value-dependent. */
|
||||
if (VAR_OR_FUNCTION_DECL_P (expression)
|
||||
&& DECL_LANG_SPECIFIC (expression)
|
||||
&& DECL_TEMPLATE_INFO (expression)
|
||||
&& variable_template_p (DECL_TI_TEMPLATE (expression)))
|
||||
return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
|
||||
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression))
|
||||
&& (any_dependent_template_arguments_p
|
||||
(INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
|
||||
return true;
|
||||
|
||||
/* Always dependent, on the number of arguments if nothing else. */
|
||||
if (TREE_CODE (expression) == EXPR_PACK_EXPANSION)
|
||||
|
@ -23087,6 +23096,22 @@ type_dependent_expression_p (tree expression)
|
|||
return (dependent_type_p (TREE_TYPE (expression)));
|
||||
}
|
||||
|
||||
/* [temp.dep.expr]/5: A class member access expression (5.2.5) is
|
||||
type-dependent if the expression refers to a member of the current
|
||||
instantiation and the type of the referenced member is dependent, or the
|
||||
class member access expression refers to a member of an unknown
|
||||
specialization.
|
||||
|
||||
This function returns true if the OBJECT in such a class member access
|
||||
expression is of an unknown specialization. */
|
||||
|
||||
bool
|
||||
type_dependent_object_expression_p (tree object)
|
||||
{
|
||||
tree scope = TREE_TYPE (object);
|
||||
return (!scope || dependent_scope_p (scope));
|
||||
}
|
||||
|
||||
/* walk_tree callback function for instantiation_dependent_expression_p,
|
||||
below. Returns non-zero if a dependent subexpression is found. */
|
||||
|
||||
|
@ -23291,9 +23316,18 @@ dependent_template_arg_p (tree arg)
|
|||
if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
|
||||
arg = ARGUMENT_PACK_SELECT_ARG (arg);
|
||||
|
||||
if (TREE_CODE (arg) == TEMPLATE_DECL
|
||||
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
|
||||
return dependent_template_p (arg);
|
||||
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
|
||||
return true;
|
||||
if (TREE_CODE (arg) == TEMPLATE_DECL)
|
||||
{
|
||||
if (DECL_TEMPLATE_PARM_P (arg))
|
||||
return true;
|
||||
/* A member template of a dependent class is not necessarily
|
||||
type-dependent, but it is a dependent template argument because it
|
||||
will be a member of an unknown specialization to that template. */
|
||||
tree scope = CP_DECL_CONTEXT (arg);
|
||||
return TYPE_P (scope) && dependent_type_p (scope);
|
||||
}
|
||||
else if (ARGUMENT_PACK_P (arg))
|
||||
{
|
||||
tree args = ARGUMENT_PACK_ARGS (arg);
|
||||
|
@ -23389,7 +23423,7 @@ any_dependent_template_arguments_p (const_tree args)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Returns TRUE if the template TMPL is dependent. */
|
||||
/* Returns TRUE if the template TMPL is type-dependent. */
|
||||
|
||||
bool
|
||||
dependent_template_p (tree tmpl)
|
||||
|
@ -23412,9 +23446,6 @@ dependent_template_p (tree tmpl)
|
|||
/* So are names that have not been looked up. */
|
||||
if (TREE_CODE (tmpl) == SCOPE_REF || identifier_p (tmpl))
|
||||
return true;
|
||||
/* So are member templates of dependent classes. */
|
||||
if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
|
||||
return dependent_type_p (DECL_CONTEXT (tmpl));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1106,6 +1106,14 @@ lookup_field_r (tree binfo, void *data)
|
|||
if (!nval)
|
||||
/* Look for a data member or type. */
|
||||
nval = lookup_field_1 (type, lfi->name, lfi->want_type);
|
||||
else if (TREE_CODE (nval) == OVERLOAD && OVL_USED (nval))
|
||||
{
|
||||
/* If we have both dependent and non-dependent using-declarations, return
|
||||
the dependent one rather than an incomplete list of functions. */
|
||||
tree dep_using = lookup_field_1 (type, lfi->name, lfi->want_type);
|
||||
if (dep_using && TREE_CODE (dep_using) == USING_DECL)
|
||||
nval = dep_using;
|
||||
}
|
||||
|
||||
/* If there is no declaration with the indicated name in this type,
|
||||
then there's nothing to do. */
|
||||
|
@ -2844,3 +2852,21 @@ original_binfo (tree binfo, tree here)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* True iff TYPE has any dependent bases (and therefore we can't say
|
||||
definitively that another class is not a base of an instantiation of
|
||||
TYPE). */
|
||||
|
||||
bool
|
||||
any_dependent_bases_p (tree type)
|
||||
{
|
||||
if (!type || !CLASS_TYPE_P (type) || !processing_template_decl)
|
||||
return false;
|
||||
|
||||
unsigned i;
|
||||
tree base_binfo;
|
||||
FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_BINFOS (TYPE_BINFO (type)), i, base_binfo)
|
||||
if (BINFO_DEPENDENT_BASE_P (base_binfo))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -2300,18 +2300,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
|
|||
with no type; type_dependent_expression_p recognizes
|
||||
expressions with no type as being dependent. */
|
||||
if (type_dependent_expression_p (fn)
|
||||
|| any_type_dependent_arguments_p (*args)
|
||||
/* For a non-static member function that doesn't have an
|
||||
explicit object argument, we need to specifically
|
||||
test the type dependency of the "this" pointer because it
|
||||
is not included in *ARGS even though it is considered to
|
||||
be part of the list of arguments. Note that this is
|
||||
related to CWG issues 515 and 1005. */
|
||||
|| (TREE_CODE (fn) != COMPONENT_REF
|
||||
&& non_static_member_function_p (fn)
|
||||
&& !DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (get_first_fn (fn))
|
||||
&& current_class_ref
|
||||
&& type_dependent_expression_p (current_class_ref)))
|
||||
|| any_type_dependent_arguments_p (*args))
|
||||
{
|
||||
result = build_nt_call_vec (fn, *args);
|
||||
SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location));
|
||||
|
@ -2399,17 +2388,6 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
|
|||
object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
|
||||
NULL);
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
if (type_dependent_expression_p (object))
|
||||
{
|
||||
tree ret = build_nt_call_vec (orig_fn, orig_args);
|
||||
release_tree_vector (orig_args);
|
||||
return ret;
|
||||
}
|
||||
object = build_non_dependent_expr (object);
|
||||
}
|
||||
|
||||
result = build_new_method_call (object, fn, args, NULL_TREE,
|
||||
(disallow_virtual
|
||||
? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
|
||||
|
|
|
@ -2127,23 +2127,6 @@ ovl_scope (tree ovl)
|
|||
ovl = OVL_CHAIN (ovl);
|
||||
return CP_DECL_CONTEXT (OVL_CURRENT (ovl));
|
||||
}
|
||||
|
||||
/* Return TRUE if FN is a non-static member function, FALSE otherwise.
|
||||
This function looks into BASELINK and OVERLOAD nodes. */
|
||||
|
||||
bool
|
||||
non_static_member_function_p (tree fn)
|
||||
{
|
||||
if (fn == NULL_TREE)
|
||||
return false;
|
||||
|
||||
if (is_overloaded_fn (fn))
|
||||
fn = get_first_fn (fn);
|
||||
|
||||
return (DECL_P (fn)
|
||||
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (fn));
|
||||
}
|
||||
|
||||
|
||||
#define PRINT_RING_SIZE 4
|
||||
|
||||
|
|
|
@ -2668,7 +2668,7 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
|
|||
if (processing_template_decl)
|
||||
{
|
||||
if (/* If OBJECT is dependent, so is OBJECT.NAME. */
|
||||
type_dependent_expression_p (object)
|
||||
type_dependent_object_expression_p (object)
|
||||
/* If NAME is "f<args>", where either 'f' or 'args' is
|
||||
dependent, then the expression is dependent. */
|
||||
|| (TREE_CODE (name) == TEMPLATE_ID_EXPR
|
||||
|
@ -2678,9 +2678,12 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
|
|||
expression is dependent. */
|
||||
|| (TREE_CODE (name) == SCOPE_REF
|
||||
&& TYPE_P (TREE_OPERAND (name, 0))
|
||||
&& dependent_type_p (TREE_OPERAND (name, 0))))
|
||||
return build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF,
|
||||
object.get_value (), name, NULL_TREE);
|
||||
&& dependent_scope_p (TREE_OPERAND (name, 0))))
|
||||
{
|
||||
dependent:
|
||||
return build_min_nt_loc (UNKNOWN_LOCATION, COMPONENT_REF,
|
||||
orig_object, name, NULL_TREE);
|
||||
}
|
||||
object = build_non_dependent_expr (object);
|
||||
}
|
||||
else if (c_dialect_objc ()
|
||||
|
@ -2805,7 +2808,12 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
|
|||
}
|
||||
|
||||
if (TREE_CODE (name) == BIT_NOT_EXPR)
|
||||
member = lookup_destructor (object, scope, name, complain);
|
||||
{
|
||||
if (dependent_type_p (object_type))
|
||||
/* The destructor isn't declared yet. */
|
||||
goto dependent;
|
||||
member = lookup_destructor (object, scope, name, complain);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Look up the member. */
|
||||
|
@ -2813,6 +2821,9 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
|
|||
/*want_type=*/false, complain);
|
||||
if (member == NULL_TREE)
|
||||
{
|
||||
if (dependent_type_p (object_type))
|
||||
/* Try again at instantiation time. */
|
||||
goto dependent;
|
||||
if (complain & tf_error)
|
||||
{
|
||||
tree guessed_id = lookup_member_fuzzy (access_path, name,
|
||||
|
@ -2842,6 +2853,8 @@ finish_class_member_access_expr (cp_expr object, tree name, bool template_p,
|
|||
}
|
||||
if (member == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (TREE_CODE (member) == USING_DECL && DECL_DEPENDENT_P (member))
|
||||
goto dependent;
|
||||
}
|
||||
|
||||
if (is_template_id)
|
||||
|
|
|
@ -1703,7 +1703,10 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain)
|
|||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
if (type_dependent_expression_p (expr))
|
||||
if (type && TREE_CODE (type) == POINTER_TYPE
|
||||
&& !dependent_scope_p (TREE_TYPE (type)))
|
||||
/* Pointer to current instantiation, don't treat as dependent. */;
|
||||
else if (type_dependent_expression_p (expr))
|
||||
return build_min_nt_loc (loc, ARROW_EXPR, expr);
|
||||
expr = build_non_dependent_expr (expr);
|
||||
}
|
||||
|
|
17
gcc/testsuite/g++.dg/lookup/member4.C
Normal file
17
gcc/testsuite/g++.dg/lookup/member4.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
// PR c++/69753
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
class A {
|
||||
public:
|
||||
template <typename> void As();
|
||||
static A *FromWebContents();
|
||||
A *FromWebContents2();
|
||||
};
|
||||
template <typename T> class B : A {
|
||||
void FromWebContents() {
|
||||
auto guest = this->A::FromWebContents();
|
||||
guest ? guest->As<T>() : nullptr;
|
||||
auto guest2 = this->A::FromWebContents2();
|
||||
guest2 ? guest2->As<T>() : nullptr;
|
||||
}
|
||||
};
|
32
gcc/testsuite/g++.dg/lookup/member5.C
Normal file
32
gcc/testsuite/g++.dg/lookup/member5.C
Normal file
|
@ -0,0 +1,32 @@
|
|||
// PR c++/69753
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
struct B {
|
||||
template <class> void bfn ();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
constexpr int x(T) { return 42; }
|
||||
|
||||
template <int I>
|
||||
struct C
|
||||
{
|
||||
template <class> void cfn ();
|
||||
};
|
||||
|
||||
template <typename T> struct A {
|
||||
static B fn(int);
|
||||
template <class U> static B ft(U);
|
||||
|
||||
void g()
|
||||
{
|
||||
auto b = this->fn(42);
|
||||
b.bfn<int>();
|
||||
|
||||
auto b2 = this->ft(42);
|
||||
b2.bfn<int>();
|
||||
|
||||
auto c = C<x(42)>();
|
||||
c.cfn<int>();
|
||||
}
|
||||
};
|
|
@ -17,5 +17,5 @@ template <class T> struct C : public B1<T>, public B2
|
|||
int main()
|
||||
{
|
||||
C<int> c;
|
||||
c.f(); // { dg-message "required" }
|
||||
c.f();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue