* New C++ PATCH for c++/10200 et al
@ 2016-02-17 0:49 Jason Merrill
2016-05-13 19:17 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2016-02-17 0:49 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 500 bytes --]
Clearly the DR 141 change is requiring much larger adjustments in the
rest of the compiler than I'm comfortable making at this point in the
GCC 6 schedule, so I'm backing out my earlier changes for 10200 and
69753 and replacing them with a more modest fix for 10200: Now we will
still find member function templates by unqualified lookup, we just
won't find namespace-scope function templates. The earlier approach
will return in GCC 7 stage 1.
Tested x86_64-pc-linux-gnu, applying to trunk.
[-- Attachment #2: 10200-gcc6.patch --]
[-- Type: text/x-patch, Size: 12043 bytes --]
commit 862c6a750fc12cb41d29aa8f91c013f7705836c1
Author: Jason Merrill <jason@redhat.com>
Date: Tue Feb 16 19:11:35 2016 -0500
PR c++/10200
PR c++/69753
* call.c, cp-tree.h, name-lookup.c, pt.c, search.c, semantics.c,
tree.c, typeck2.c: Revert earlier changes.
* parser.c (cp_parser_lookup_name): Ignore namespace-scope
non-type templates after -> or .
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index db40654..cb71176 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8160,7 +8160,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
if (permerror (input_location,
"cannot call constructor %<%T::%D%> directly",
- BINFO_TYPE (access_binfo), name))
+ basetype, name))
inform (input_location, "for a function-style cast, remove the "
"redundant %<::%D%>", name);
call = build_functional_cast (basetype, build_tree_list_vec (user_args),
@@ -8377,9 +8377,6 @@ 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)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b7d7bc6..3b91089 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6252,7 +6252,6 @@ 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. */
@@ -6543,6 +6542,7 @@ 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);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index b73f3f7..89d84d7 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3333,6 +3333,8 @@ 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;
@@ -3369,7 +3371,16 @@ do_class_using_decl (tree scope, tree name)
|| (IDENTIFIER_TYPENAME_P (name)
&& dependent_type_p (TREE_TYPE (name))));
- bases_dependent_p = any_dependent_bases_p (current_class_type);
+ 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;
+ }
decl = NULL_TREE;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b8d8237..18f3902 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7184,16 +7184,8 @@ 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);
- /* According to the standard, no expression should ever have
- reference type. Unfortunately, we do not currently match
- the standard in this respect in that our internal representation
- of an expression may have reference type even when the standard
- says it does not. Therefore, we have to manually obtain the
- underlying type here. */
- scope = non_reference (TREE_TYPE (postfix_expression));
- /* Check to see whether or not the expression is type-dependent and
- not the current instantiation. */
- dependent_p = !scope || dependent_scope_p (scope);
+ /* Check to see whether or not the expression is type-dependent. */
+ dependent_p = type_dependent_expression_p (postfix_expression);
/* The identifier following the `->' or `.' is not qualified. */
parser->scope = NULL_TREE;
parser->qualifying_scope = NULL_TREE;
@@ -7202,8 +7194,16 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
/* Enter the scope corresponding to the type of the object
given by the POSTFIX_EXPRESSION. */
- if (!dependent_p)
+ if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE)
{
+ scope = TREE_TYPE (postfix_expression);
+ /* According to the standard, no expression should ever have
+ reference type. Unfortunately, we do not currently match
+ the standard in this respect in that our internal representation
+ of an expression may have reference type even when the standard
+ says it does not. Therefore, we have to manually obtain the
+ underlying type here. */
+ scope = non_reference (scope);
/* The type of the POSTFIX_EXPRESSION must be complete. */
if (scope == unknown_type_node)
{
@@ -7215,10 +7215,7 @@ 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. */
else if (postfix_expression != current_class_ref
- && !(processing_template_decl
- && current_class_type
- && (same_type_ignoring_top_level_qualifiers_p
- (scope, current_class_type))))
+ && !(processing_template_decl && scope == current_class_type))
scope = complete_type_or_else (scope, NULL_TREE);
/* Let the name lookup machinery know that we are processing a
class member access expression. */
@@ -24727,11 +24724,24 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
decl = NULL_TREE;
if (!decl)
- /* 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);
+ {
+ /* 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;
+ }
+ }
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. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 52e60b9..a55dc10 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -22904,16 +22904,9 @@ type_dependent_expression_p (tree expression)
&& DECL_TEMPLATE_INFO (expression))
return any_dependent_template_arguments_p (DECL_TI_ARGS (expression));
- if (TREE_CODE (expression) == TEMPLATE_DECL)
- {
- if (DECL_CLASS_SCOPE_P (expression)
- && dependent_type_p (DECL_CONTEXT (expression)))
- /* A template's own parameters don't make it dependent, since those can
- be deduced, but the enclosing class does. */
- return true;
- if (!DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
- return false;
- }
+ if (TREE_CODE (expression) == TEMPLATE_DECL
+ && !DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
+ return false;
if (TREE_CODE (expression) == STMT_EXPR)
expression = stmt_expr_value_expr (expression);
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 49f3bc5..7924611 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -2842,21 +2842,3 @@ 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;
-}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 70a7aa5..f0288ea 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2264,7 +2264,17 @@ 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))
+ || 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)
+ && current_class_ref
+ && type_dependent_expression_p (current_class_ref)))
{
result = build_nt_call_vec (fn, *args);
SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location));
@@ -2344,6 +2354,17 @@ 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
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 041facd..3203aca 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2071,6 +2071,23 @@ 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));
+}
+
\f
#define PRINT_RING_SIZE 4
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 54a432f..2a76c96 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1694,10 +1694,7 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain)
if (processing_template_decl)
{
- 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))
+ if (type_dependent_expression_p (expr))
return build_min_nt_loc (loc, ARROW_EXPR, expr);
expr = build_non_dependent_expr (expr);
}
diff --git a/gcc/testsuite/g++.dg/template/dependent-expr9.C b/gcc/testsuite/g++.dg/template/dependent-expr9.C
new file mode 100644
index 0000000..7da060d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-expr9.C
@@ -0,0 +1,10 @@
+// PR c++/69753
+
+class A {
+public:
+ template <class> void m_fn1();
+};
+A *fn1(int *);
+template <typename> class B : A {
+ static int *m_fn2() { fn1(m_fn2())->m_fn1<A>(); }
+};
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: New C++ PATCH for c++/10200 et al
2016-02-17 0:49 New C++ PATCH for c++/10200 et al Jason Merrill
@ 2016-05-13 19:17 ` Jason Merrill
2016-05-18 17:42 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2016-05-13 19:17 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 1740 bytes --]
On 02/16/2016 07:49 PM, Jason Merrill wrote:
> Clearly the DR 141 change is requiring much larger adjustments in the
> rest of the compiler than I'm comfortable making at this point in the
> GCC 6 schedule, so I'm backing out my earlier changes for 10200 and
> 69753 and replacing them with a more modest fix for 10200: Now we will
> still find member function templates by unqualified lookup, we just
> won't find namespace-scope function templates. The earlier approach
> will return in GCC 7 stage 1.
As promised. The prerequisite for the DR 141 change was fixing the
C++11 handling of type-dependence of member access expressions,
including calls. 14.6.2.2 says,
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. [ Note: In
an expression of the form x.y or xp->y the type of the expression is
usually the type of the member y of the class of x (or the class pointed
to by xp). However, if x or xp refers to a dependent type that is not
the current instantiation, the type of y is always dependent. If x or xp
refers to a non-dependent type or refers to the current instantiation,
the type of y is the type of the class member access expression. âend note ]
Previously we had been treating such expressions as type-dependent if
the object-expression is type-dependent, even if its type is the current
instantiation. Fixing this required a few changes in other areas that
now have to deal with non-dependent member function calls within a template.
Tested x86_64-pc-linux-gnu, applying to trunk.
[-- Attachment #2: 10200-3.diff --]
[-- Type: text/x-patch, Size: 25987 bytes --]
commit 92bfc5a7586b8d862951d2e1a94398a3ab19ef47
Author: Jason Merrill <jason@redhat.com>
Date: Fri May 13 11:36:35 2016 -0400
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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a49bbb5..0b59c40 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 556c256..ad21cdf 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 86d260c..d32a153 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7030740..539f165 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1289d64..65bfd42 100644
--- a/gcc/cp/pt.c
+++ b/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;
}
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 503e34b..f47833f 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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;
+}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 817ef99..06dee5a 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 57fc5c1..04702ee 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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));
-}
-
\f
#define PRINT_RING_SIZE 4
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0d8a980..cd058fa 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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)
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 1c4e832..833be20 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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);
}
diff --git a/gcc/testsuite/g++.dg/lookup/member4.C b/gcc/testsuite/g++.dg/lookup/member4.C
new file mode 100644
index 0000000..6fab2f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/member4.C
@@ -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;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/lookup/member5.C b/gcc/testsuite/g++.dg/lookup/member5.C
new file mode 100644
index 0000000..fec1ecd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/member5.C
@@ -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>();
+ }
+};
diff --git a/gcc/testsuite/g++.dg/template/using14.C b/gcc/testsuite/g++.dg/template/using14.C
index 276c40b..f1d97993 100644
--- a/gcc/testsuite/g++.dg/template/using14.C
+++ b/gcc/testsuite/g++.dg/template/using14.C
@@ -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();
}
commit 2f6192ba7d231ef7801b55146f9781d0429e34ba
Author: Jason Merrill <jason@redhat.com>
Date: Thu May 12 15:02:36 2016 -0400
Improve diagnostic for forgotten ().
* parser.c (cp_parser_postfix_dot_deref_expression): Use
complete_type_or_else for unknown_type_node, too.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f4c6f74..7030740 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7207,18 +7207,12 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
underlying type here. */
scope = non_reference (scope);
/* The type of the POSTFIX_EXPRESSION must be complete. */
- if (scope == unknown_type_node)
- {
- error_at (location, "%qE does not have class type",
- postfix_expression.get_value ());
- scope = NULL_TREE;
- }
/* Unlike the object expression in other contexts, *this is not
required to be of complete type for purposes of class member
access (5.2.5) outside the member function body. */
- else if (postfix_expression != current_class_ref
- && !(processing_template_decl && scope == current_class_type))
- scope = complete_type_or_else (scope, NULL_TREE);
+ if (postfix_expression != current_class_ref
+ && !(processing_template_decl && 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. */
parser->context->object_type = scope;
diff --git a/gcc/testsuite/g++.dg/gomp/udr-4.C b/gcc/testsuite/g++.dg/gomp/udr-4.C
index 566d7d1..012ff0c 100644
--- a/gcc/testsuite/g++.dg/gomp/udr-4.C
+++ b/gcc/testsuite/g++.dg/gomp/udr-4.C
@@ -1,7 +1,7 @@
// { dg-do compile }
struct S; // { dg-message "forward declaration" }
-#pragma omp declare reduction (+:S:omp_out.s += omp_in.s) // { dg-error "invalid use of incomplete type" }
+#pragma omp declare reduction (+:S:omp_out.s += omp_in.s) // { dg-error "incomplete type" }
struct S { int s; S () : s (1) {} };
#pragma omp declare reduction (*:S:omp_out.s *= omp_in.s)
diff --git a/gcc/testsuite/g++.dg/parse/dot1.C b/gcc/testsuite/g++.dg/parse/dot1.C
index 3b027d7..416ef92 100644
--- a/gcc/testsuite/g++.dg/parse/dot1.C
+++ b/gcc/testsuite/g++.dg/parse/dot1.C
@@ -1,4 +1,4 @@
// PR c++/24560
struct A { void f(); };
-void g() { A().f.a; } // { dg-error "class" }
+void g() { A().f.a; } // { dg-error "invalid use of member function" }
diff --git a/gcc/testsuite/g++.dg/template/pseudodtor3.C b/gcc/testsuite/g++.dg/template/pseudodtor3.C
index 8700bb9..8f1f6a7 100644
--- a/gcc/testsuite/g++.dg/template/pseudodtor3.C
+++ b/gcc/testsuite/g++.dg/template/pseudodtor3.C
@@ -5,7 +5,7 @@ struct A
{
typedef int T;
T &foo ();
- A () { foo.~T (); } // { dg-error "10:does not have class type|expected" }
+ A () { foo.~T (); } // { dg-error "10:invalid use of member function|expected" }
};
template <typename T> struct B
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: New C++ PATCH for c++/10200 et al
2016-05-13 19:17 ` Jason Merrill
@ 2016-05-18 17:42 ` Jason Merrill
2016-05-19 19:14 ` Jason Merrill
0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2016-05-18 17:42 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 1873 bytes --]
On 05/13/2016 03:17 PM, Jason Merrill wrote:
> On 02/16/2016 07:49 PM, Jason Merrill wrote:
>> Clearly the DR 141 change is requiring much larger adjustments in the
>> rest of the compiler than I'm comfortable making at this point in the
>> GCC 6 schedule, so I'm backing out my earlier changes for 10200 and
>> 69753 and replacing them with a more modest fix for 10200: Now we will
>> still find member function templates by unqualified lookup, we just
>> won't find namespace-scope function templates. The earlier approach
>> will return in GCC 7 stage 1.
>
> As promised. The prerequisite for the DR 141 change was fixing the
> C++11 handling of type-dependence of member access expressions,
> including calls. 14.6.2.2 says,
>
> 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. [ Note: In
> an expression of the form x.y or xp->y the type of the expression is
> usually the type of the member y of the class of x (or the class pointed
> to by xp). However, if x or xp refers to a dependent type that is not
> the current instantiation, the type of y is always dependent. If x or xp
> refers to a non-dependent type or refers to the current instantiation,
> the type of y is the type of the class member access expression. âend
> note ]
>
> Previously we had been treating such expressions as type-dependent if
> the object-expression is type-dependent, even if its type is the current
> instantiation. Fixing this required a few changes in other areas that
> now have to deal with non-dependent member function calls within a
> template.
A small tweak to handling of value-dependent functions to better match
the text of the standard.
[-- Attachment #2: val-dep-tweak.diff --]
[-- Type: text/x-patch, Size: 1493 bytes --]
commit 9a4d77c31e361644e4deffb6a6e21a87948b0ac0
Author: Jason Merrill <jason@redhat.com>
Date: Mon May 16 15:52:25 2016 -0400
* pt.c (value_dependent_expression_p): Tweak new cases to better
match the wording in the standard.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 65bfd42..fde3091 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -22649,19 +22649,14 @@ 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));
+ /* A dependent member function of the current instantiation. */
+ return dependent_type_p (BINFO_TYPE (BASELINK_BINFO (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));
+ /* A dependent member function of the current instantiation. */
+ if (DECL_CLASS_SCOPE_P (expression)
+ && dependent_type_p (DECL_CONTEXT (expression)))
+ return true;
break;
case IDENTIFIER_NODE:
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: New C++ PATCH for c++/10200 et al
2016-05-18 17:42 ` Jason Merrill
@ 2016-05-19 19:14 ` Jason Merrill
0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2016-05-19 19:14 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 2098 bytes --]
On 05/18/2016 01:42 PM, Jason Merrill wrote:
> On 05/13/2016 03:17 PM, Jason Merrill wrote:
>> On 02/16/2016 07:49 PM, Jason Merrill wrote:
>>> Clearly the DR 141 change is requiring much larger adjustments in the
>>> rest of the compiler than I'm comfortable making at this point in the
>>> GCC 6 schedule, so I'm backing out my earlier changes for 10200 and
>>> 69753 and replacing them with a more modest fix for 10200: Now we will
>>> still find member function templates by unqualified lookup, we just
>>> won't find namespace-scope function templates. The earlier approach
>>> will return in GCC 7 stage 1.
>>
>> As promised. The prerequisite for the DR 141 change was fixing the
>> C++11 handling of type-dependence of member access expressions,
>> including calls. 14.6.2.2 says,
>>
>> 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. [ Note: In
>> an expression of the form x.y or xp->y the type of the expression is
>> usually the type of the member y of the class of x (or the class pointed
>> to by xp). However, if x or xp refers to a dependent type that is not
>> the current instantiation, the type of y is always dependent. If x or xp
>> refers to a non-dependent type or refers to the current instantiation,
>> the type of y is the type of the class member access expression. âend
>> note ]
>>
>> Previously we had been treating such expressions as type-dependent if
>> the object-expression is type-dependent, even if its type is the current
>> instantiation. Fixing this required a few changes in other areas that
>> now have to deal with non-dependent member function calls within a
>> template.
>
> A small tweak to handling of value-dependent functions to better match
> the text of the standard.
And some other places that needed to be updated to handle multiple
levels of template args due to non-dependent member function calls.
Jason
[-- Attachment #2: 10200-4.diff --]
[-- Type: text/x-patch, Size: 4248 bytes --]
commit 19e3a881e67edf3181b33cb064e9fea699aba8c9
Author: Jason Merrill <jason@redhat.com>
Date: Wed May 18 16:52:58 2016 -0400
Fix handling of non-dependent calls with default template args.
PR c++/10200
* pt.c (fn_type_unification): Add outer template args if needed.
(type_unification_real): Handle getting full args.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index fde3091..3908592 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -17578,6 +17578,13 @@ fn_type_unification (tree fn,
tree tinst;
tree r = error_mark_node;
+ tree full_targs = targs;
+ if (TMPL_ARGS_DEPTH (targs)
+ < TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (fn)))
+ full_targs = (add_outermost_template_args
+ (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (fn)),
+ targs));
+
if (decltype_p)
complain |= tf_decltype;
@@ -17623,6 +17630,14 @@ fn_type_unification (tree fn,
location_t loc = input_location;
bool incomplete = false;
+ if (explicit_targs == error_mark_node)
+ goto fail;
+
+ if (TMPL_ARGS_DEPTH (explicit_targs)
+ < TMPL_ARGS_DEPTH (full_targs))
+ explicit_targs = add_outermost_template_args (full_targs,
+ explicit_targs);
+
/* Adjust any explicit template arguments before entering the
substitution context. */
explicit_targs
@@ -17702,6 +17717,7 @@ fn_type_unification (tree fn,
goto fail;
/* Place the explicitly specified arguments in TARGS. */
+ explicit_targs = INNERMOST_TEMPLATE_ARGS (explicit_targs);
for (i = NUM_TMPL_ARGS (explicit_targs); i--;)
TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (explicit_targs, i);
}
@@ -17751,7 +17767,7 @@ fn_type_unification (tree fn,
checks = NULL;
ok = !type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
- targs, parms, args, nargs, /*subr=*/0,
+ full_targs, parms, args, nargs, /*subr=*/0,
strict, flags, &checks, explain_p);
if (!explain_p)
pop_tinst_level ();
@@ -18247,7 +18263,7 @@ unify_one_argument (tree tparms, tree targs, tree parm, tree arg,
static int
type_unification_real (tree tparms,
- tree targs,
+ tree full_targs,
tree xparms,
const tree *xargs,
unsigned int xnargs,
@@ -18270,6 +18286,8 @@ type_unification_real (tree tparms,
gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
gcc_assert (ntparms > 0);
+ tree targs = INNERMOST_TEMPLATE_ARGS (full_targs);
+
/* Reset the number of non-defaulted template arguments contained
in TARGS. */
NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs) = NULL_TREE;
@@ -18304,7 +18322,7 @@ type_unification_real (tree tparms,
arg = args[ia];
++ia;
- if (unify_one_argument (tparms, targs, parm, arg, subr, strict,
+ if (unify_one_argument (tparms, full_targs, parm, arg, subr, strict,
explain_p))
return 1;
}
@@ -18324,7 +18342,7 @@ type_unification_real (tree tparms,
/* Copy the parameter into parmvec. */
TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
- if (unify_pack_expansion (tparms, targs, parmvec, argvec, strict,
+ if (unify_pack_expansion (tparms, full_targs, parmvec, argvec, strict,
/*subr=*/subr, explain_p))
return 1;
@@ -18485,8 +18503,8 @@ type_unification_real (tree tparms,
location_t save_loc = input_location;
if (DECL_P (parm))
input_location = DECL_SOURCE_LOCATION (parm);
- arg = tsubst_template_arg (arg, targs, complain, NULL_TREE);
- arg = convert_template_argument (parm, arg, targs, complain,
+ arg = tsubst_template_arg (arg, full_targs, complain, NULL_TREE);
+ arg = convert_template_argument (parm, arg, full_targs, complain,
i, NULL_TREE);
input_location = save_loc;
*checks = get_deferred_access_checks ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg6.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg6.C
new file mode 100644
index 0000000..1e0dc54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg6.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+
+template <class T>
+struct A {
+ template <int I = 42, int J = (T)42> int f() { return I; }
+ template <int I = 42> int g() { return f(); }
+};
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2016-05-19 19:14 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-17 0:49 New C++ PATCH for c++/10200 et al Jason Merrill
2016-05-13 19:17 ` Jason Merrill
2016-05-18 17:42 ` Jason Merrill
2016-05-19 19:14 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).