1) While working on 66260, it struck me as odd that finish_id_expression
had its own code for determining whether an id-expression is dependent,
rather than using type_dependent_expression_p. So this patch tears out
a bunch of code and replaces it with a call; t_d_e_p already handled
everything except a TEMPLATE_ID_EXPR with an IDENTIFIER_NODE as its lhs.
I also needed to tweak handling of CONST_DECLs so that we return them
unchanged even if there is an explicit scope.
2) When we reject an explicit specialization because there is no
template that matches it, it would be friendly to print a list of the
candidates considered.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 8b381ca4290de9a06b1ae437d04703ae84308270
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Aug 5 12:04:27 2015 -0400
* decl.c (cp_finish_decl): Tidy.
* typeck.c (finish_class_member_access_expr): Use
type_dependent_expression_p.
* semantics.c (finish_id_expression): Use
type_dependent_expression_p. Don't build_qualified_name for a
decl in non-dependent scope.
* pt.c (type_dependent_expression_p): A TEMPLATE_ID_EXPR of an
identifier is dependent. Remove variable_template_p check.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 52584c5..208173a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6525,11 +6525,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
then it can be used in future constant expressions, so its value
must be available. */
- if (!VAR_P (decl) || dependent_type_p (type))
+ if (!VAR_P (decl) || type_dependent_p)
/* We can't do anything if the decl has dependent type. */;
else if (init
&& init_const_expr_p
- && !type_dependent_p
&& TREE_CODE (type) != REFERENCE_TYPE
&& decl_maybe_constant_var_p (decl)
&& !type_dependent_init_p (init)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f8c123c..5f28f1b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -21671,11 +21671,10 @@ type_dependent_expression_p (tree expression)
(TREE_OPERAND (expression, 1)))
return true;
expression = TREE_OPERAND (expression, 0);
+ if (identifier_p (expression))
+ return true;
}
- if (variable_template_p (expression))
- return dependent_type_p (TREE_TYPE (expression));
-
gcc_assert (TREE_CODE (expression) == OVERLOAD
|| TREE_CODE (expression) == FUNCTION_DECL);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d42838e..17b0a14 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3362,7 +3362,7 @@ finish_id_expression (tree id_expression,
}
else
{
- bool dependent_p;
+ bool dependent_p = type_dependent_expression_p (decl);
/* If the declaration was explicitly qualified indicate
that. The semantics of `A::f(3)' are different than
@@ -3371,79 +3371,25 @@ finish_id_expression (tree id_expression,
? CP_ID_KIND_QUALIFIED
: (TREE_CODE (decl) == TEMPLATE_ID_EXPR
? CP_ID_KIND_TEMPLATE_ID
- : CP_ID_KIND_UNQUALIFIED));
-
-
- /* [temp.dep.expr]
-
- An id-expression is type-dependent if it contains an
- identifier that was declared with a dependent type.
-
- The standard is not very specific about an id-expression that
- names a set of overloaded functions. What if some of them
- have dependent types and some of them do not? Presumably,
- such a name should be treated as a dependent name. */
- /* Assume the name is not dependent. */
- dependent_p = false;
- if (!processing_template_decl)
- /* No names are dependent outside a template. */
- ;
- else if (TREE_CODE (decl) == CONST_DECL)
- /* We don't want to treat enumerators as dependent. */
- ;
- /* A template-id where the name of the template was not resolved
- is definitely dependent. */
- else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
- && (identifier_p (TREE_OPERAND (decl, 0))))
- dependent_p = true;
- /* For anything except an overloaded function, just check its
- type. */
- else if (!is_overloaded_fn (decl))
- dependent_p
- = dependent_type_p (TREE_TYPE (decl));
- /* For a set of overloaded functions, check each of the
- functions. */
- else
- {
- tree fns = decl;
-
- if (BASELINK_P (fns))
- fns = BASELINK_FUNCTIONS (fns);
-
- /* For a template-id, check to see if the template
- arguments are dependent. */
- if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
- {
- tree args = TREE_OPERAND (fns, 1);
- dependent_p = any_dependent_template_arguments_p (args);
- /* The functions are those referred to by the
- template-id. */
- fns = TREE_OPERAND (fns, 0);
- }
-
- /* If there are no dependent template arguments, go through
- the overloaded functions. */
- while (fns && !dependent_p)
- {
- tree fn = OVL_CURRENT (fns);
-
- /* Member functions of dependent classes are
- dependent. */
- if (TREE_CODE (fn) == FUNCTION_DECL
- && type_dependent_expression_p (fn))
- dependent_p = true;
- else if (TREE_CODE (fn) == TEMPLATE_DECL
- && dependent_template_p (fn))
- dependent_p = true;
-
- fns = OVL_NEXT (fns);
- }
- }
+ : (dependent_p
+ ? CP_ID_KIND_UNQUALIFIED_DEPENDENT
+ : CP_ID_KIND_UNQUALIFIED)));
/* If the name was dependent on a template parameter, we will
resolve the name at instantiation time. */
if (dependent_p)
{
+ /* If we found a variable, then name lookup during the
+ instantiation will always resolve to the same VAR_DECL
+ (or an instantiation thereof). */
+ if (VAR_P (decl)
+ || TREE_CODE (decl) == CONST_DECL
+ || TREE_CODE (decl) == PARM_DECL)
+ {
+ mark_used (decl);
+ return convert_from_reference (decl);
+ }
+
/* Create a SCOPE_REF for qualified names, if the scope is
dependent. */
if (scope)
@@ -3475,16 +3421,6 @@ finish_id_expression (tree id_expression,
need. */
if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
return id_expression;
- *idk = CP_ID_KIND_UNQUALIFIED_DEPENDENT;
- /* If we found a variable, then name lookup during the
- instantiation will always resolve to the same VAR_DECL
- (or an instantiation thereof). */
- if (VAR_P (decl)
- || TREE_CODE (decl) == PARM_DECL)
- {
- mark_used (decl);
- return convert_from_reference (decl);
- }
/* The same is true for FIELD_DECL, but we also need to
make sure that the syntax is correct. */
else if (TREE_CODE (decl) == FIELD_DECL)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a7a8844..5d754f1 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2636,11 +2636,8 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
if (processing_template_decl)
{
- if (/* If OBJECT_TYPE is dependent, so is OBJECT.NAME. */
- dependent_type_p (object_type)
- /* If NAME is just an IDENTIFIER_NODE, then the expression
- is dependent. */
- || identifier_p (object)
+ if (/* If OBJECT is dependent, so is OBJECT.NAME. */
+ type_dependent_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
commit a54cb70add522cfa4c10cc1efc39108db7a7d60f
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Aug 5 17:03:08 2015 -0400
* pt.c (determine_specialization): Print candidates after 'no
match' error.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5f28f1b..08fb2ff 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1952,6 +1952,8 @@ determine_specialization (tree template_id,
b = b->level_chain)
++header_count;
+ tree orig_fns = fns;
+
if (variable_template_p (fns))
{
tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (fns));
@@ -2168,6 +2170,8 @@ determine_specialization (tree template_id,
inform (input_location, "saw %d %<template<>%>, need %d for "
"specializing a member function template",
header_count, template_count + 1);
+ else
+ print_candidates (orig_fns);
return error_mark_node;
}
else if ((templates && TREE_CHAIN (templates))
diff --git a/gcc/testsuite/g++.dg/template/spec39.C b/gcc/testsuite/g++.dg/template/spec39.C
new file mode 100644
index 0000000..9e4f8be
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec39.C
@@ -0,0 +1,3 @@
+template <class T> void f(T); // { dg-message "void f" }
+template <> int f(int); // { dg-error "does not match" }
+