From: Dodji Seketeli <dodji@redhat.com>
To: Jason Merrill <jason@redhat.com>
Cc: GCC Patches <gcc-patches@gcc.gnu.org>
Subject: Re: Require canonical type comparison for typedefs again.
Date: Wed, 27 Oct 2010 15:59:00 -0000 [thread overview]
Message-ID: <m34oc7ww5r.fsf@tutu.torimasen.com> (raw)
In-Reply-To: <m3k4l7hvxq.fsf@tutu.torimasen.com> (Dodji Seketeli's message of "Mon, 25 Oct 2010 04:01:53 +0200")
Hello,
So I forgot to remove the wrong "optimization" on the parms of
template template parameters. In the patch at the end of this message
this hunks fixes that:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5305595..64a3f64 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3815,16 +3815,6 @@ fixup_template_parm (tree parm_desc,
TREE_VEC_ELT (innermost_args, j) =
template_parm_to_arg (parameter);
- /* Only substitute into template non-type parms. */
- if (parameter != NULL_TREE
- && TREE_CODE (parameter) == TREE_LIST
- && (TREE_CODE (TREE_VALUE (parameter)) == TYPE_DECL
- || TREE_CODE (TREE_VALUE (parameter)) == TEMPLATE_DECL))
- continue;
-
- if (!dependent_type_p (TREE_TYPE (TREE_VALUE (parameter))))
- continue;
-
fixup_template_parm (parameter, j,
TREE_VEC_LENGTH (tparms),
targs);
Doing this uncovered an issue though. It boils down to tsubst* now
possibly seeing more invalid template parameter arguments.
As a first observation, consider this unvalid testcase:
template<template<typename... T, typename T1 = T> class V> struct B {};
The parameter T1 is invalid because T [being a variadic template
parameter T] should have been the last parameter. At some point
current_template_args (so now template_parm_to_arg) builds a
TREE_LIST containing an error_mark_node to represent the invalid T1.
Later while substituting into a template parm tsubst sees an argument
that is a TREE_LIST containing an error_mark_node and that violates
the following assertion:
if (code == TEMPLATE_TYPE_PARM)
{
int quals;
gcc_assert (TYPE_P (arg)); // <-- arg is a TREE_LIST with an
// error_mark_node here. Boom.
So after our offline discussion about this I modified
template_parm_to_arg to make its behaviour consistent in cases of an
invalid argumentr i.e. make the invalid argument be an error_mark_node
instead of a TREE_LIST containing an error_mark_node.
This is what the hunk below does:
@@ -3940,17 +3930,20 @@ end_template_decl (void)
/* Takes a TREE_LIST representing a template parameter and convert it
into an argument suitable to be passed to the type substitution
- functions. */
+ functions. Note that If the TREE_LIST contains an error_mark
+ node, the returned argument is error_mark_node. */
static tree
template_parm_to_arg (tree t)
{
if (t == NULL_TREE
- || TREE_CODE (t) != TREE_LIST
- || error_operand_p (TREE_VALUE (t)))
+ || TREE_CODE (t) != TREE_LIST)
return t;
+ if (error_operand_p (TREE_VALUE (t)))
+ return error_mark_node;
+
t = TREE_VALUE (t);
if (TREE_CODE (t) == TYPE_DECL
But then some code breaks because it implicitely expects invalid args
to be represented as a TREE_LIST containing an error_mark_node.
E.g: in this example from testsuite/g++.dg/templates/void11.C:
template<void> struct A // #0 <-- the template parm is invalid
{
template<int> friend void foo(); // #1 <-- we shouldn't put foo in
// the global scope symbol table b/c
// of [temp.inject/2]
};
void bar()
{
foo<0>(); // <-- looking up foo should fail because foo is not visible
}
In our case, in #1, push_template_decl_real wrongly inserts foo in the
global scope symbol table because in this code
if (new_template_p && !ctx
&& !(is_friend && template_class_depth (current_class_type) > 0))
{
tmpl = pushdecl_namespace_level (tmpl, is_friend);
template_class_depth (current_class_type) returns 0 even though
current_class_type (A in this case) is a template here. The problem is
that uses_template_parms fails to return true on the invalid template
parm. Making dependent_template_arg_p recognize error_mark_node as
being a dependent type fixes the problem:
@@ -18363,6 +18356,13 @@ dependent_template_arg_p (tree arg)
if (!processing_template_decl)
return false;
+ /* Assume a template argument that was wrongly written by the user
+ is dependent. This is consistent with what
+ any_dependent_template_arguments_p [that calls this function]
+ does. */
+ if (arg == error_mark_node)
+ return true;
+
if (TREE_CODE (arg) == TEMPLATE_DECL
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
return dependent_template_p (arg);
Below is the fully updated patch. Fully bootstrapped and tested on
x86_64-unknown-linux-gnu.
--
Dodji
commit c21c5f024f47a9a55facbd70c0d1f36956cff7c4
Author: Dodji Seketeli <dodji@redhat.com>
Date: Mon Sep 13 12:12:21 2010 +0200
Restore canonical type comparison for dependent typedefs
gcc/cp/ChangeLog:
PR c++/45606
* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
(struct template_parm_index_s)<num_siblings>: New field.
(TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
(process_template_parm): Extend the API to accept the number of
template parms in argument.
(cp_set_underlying_type): Remove this.
* class.c (build_self_reference): Require canonical type equality
back on the self reference of class.
* decl2.c (grokfield): Require canonical type equality back on
typedef class fields.
* name-lookup.c (pushdecl_maybe_friend): Require canonical type
equality back on typedefs.
* parser.c (cp_parser_template_parameter_list): Do not require
canonical type equality on dependent types created during
template parameters parsing.
* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
(fixup_template_parm, fixup_template_parms): New private
functions.
(current_template_args): Declare this.
(process_template_parm): Pass the total number of template parms
to canonical_type_parameter.
(build_template_parm_index): Add a new argument to carry the total
number of template parms.
(reduce_template_parm_level, process_template_parm, make_auto): Adjust.
(current_template_args): Fix this for template template
parameters.
(tsubst_template_parm): Split out of ...
(tsubst_template_parms): ... this.
(reduce_template_parm_level): Don't loose
TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
(template_parm_to_arg): Extracted this function from
current_template_args. Make it represent invalid template parms
with an error_mark_node instead of a LIST_TREE containing an
error_mark_node.
(current_template_args): Use template_parm_to_arg.
(dependent_template_arg_p): Consider an invalid template argument
as dependent.
(end_template_parm_list): Do not update template sibling parms
here anymore. Use fixup_template_parms instead.
(process_template_parm): Pass the number of template parms to
canonical_type_parameter.
(make_auto): Require structural equality on auto
TEMPLATE_TYPE_PARM for now.
(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
using all the arguments deduced so far.
(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
canonical_type_parameter.
* tree.c (cp_set_underlying_type): Remove.
* typeck.c (get_template_parms_of_dependent_type)
(incompatible_dependent_types_p): Remove.
(structural_comptypes): Do not call incompatible_dependent_types_p
anymore.
(comp_template_parms_position): Re-organized. Take the length of
template parms list in account.
gcc/testsuite/ChangeLog:
PR c++/45606
* g++.dg/template/typedef36.C: New test.
* gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
* g++.dg/template/canon-type-10.C: Likewise.
* g++.dg/template/canon-type-11.C: Likewise.
* g++.dg/template/canon-type-12.C: Likewise.
* g++.dg/template/canon-type-13.C: Likewise.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f76c2be..d03b5b1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6690,7 +6690,7 @@ build_self_reference (void)
DECL_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
SET_DECL_SELF_REFERENCE_P (value);
- cp_set_underlying_type (value);
+ set_underlying_type (value);
if (processing_template_decl)
value = push_template_decl (value);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 626e452..1c009e5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -236,6 +236,7 @@ struct GTY(()) template_parm_index_s {
int index;
int level;
int orig_level;
+ int num_siblings;
tree decl;
};
typedef struct template_parm_index_s template_parm_index;
@@ -4306,6 +4307,9 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
((template_parm_index*)TEMPLATE_PARM_INDEX_CHECK (NODE))
#define TEMPLATE_PARM_IDX(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->index)
#define TEMPLATE_PARM_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->level)
+/* The Number of sibling parms this template parm has. */
+#define TEMPLATE_PARM_NUM_SIBLINGS(NODE) \
+ (TEMPLATE_PARM_INDEX_CAST (NODE)->num_siblings)
#define TEMPLATE_PARM_DESCENDANTS(NODE) (TREE_CHAIN (NODE))
#define TEMPLATE_PARM_ORIG_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->orig_level)
#define TEMPLATE_PARM_DECL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->decl)
@@ -4327,10 +4331,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
(TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
#define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
(TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
-/* The list of template parms that a given template parameter of type
- TEMPLATE_TYPE_PARM belongs to.*/
-#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
- (TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
/* These constants can used as bit flags in the process of tree formatting.
@@ -5012,7 +5012,7 @@ extern void append_type_to_template_for_access_check (tree, tree, tree,
extern tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree);
extern tree process_template_parm (tree, location_t, tree,
- bool, bool);
+ bool, bool, unsigned);
extern tree end_template_parm_list (tree);
extern void end_template_decl (void);
extern tree maybe_update_decl_type (tree, tree);
@@ -5348,7 +5348,6 @@ extern bool type_has_nontrivial_copy_init (const_tree);
extern bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree);
extern tree strip_typedefs (tree);
-extern void cp_set_underlying_type (tree);
extern tree copy_binfo (tree, tree, tree,
tree *, int);
extern int member_p (const_tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f27e7d6..0c64661 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -879,7 +879,7 @@ grokfield (const cp_declarator *declarator,
if (declspecs->specs[(int)ds_typedef]
&& TREE_TYPE (value) != error_mark_node
&& TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
- cp_set_underlying_type (value);
+ set_underlying_type (value);
return value;
}
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8b2e542..0a93da8 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
inlining. */
&& (!TYPE_NAME (type)
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
- cp_set_underlying_type (x);
+ set_underlying_type (x);
if (type != error_mark_node
&& TYPE_NAME (type)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8c0129b..26eeca7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11026,6 +11026,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
tree parameter_list = NULL_TREE;
begin_template_parm_list ();
+
+ /* The loop below parses the template parms. We first need to know
+ the total number of template parms to be able to compute proper
+ canonical types of each dependent type. So after the loop, when
+ we know the total number of template parms,
+ end_template_parm_list computes the proper canonical types and
+ fixes up the dependent types accordingly. */
while (true)
{
tree parameter;
@@ -11044,11 +11051,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
parm_loc,
parameter,
is_non_type,
- is_parameter_pack);
+ is_parameter_pack,
+ 0);
else
{
tree err_parm = build_tree_list (parameter, parameter);
- TREE_VALUE (err_parm) = error_mark_node;
parameter_list = chainon (parameter_list, err_parm);
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 85a5ea5..64a3f64 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -137,7 +137,7 @@ static tree convert_template_argument (tree, tree, tree,
static int for_each_template_parm (tree, tree_fn_t, void*,
struct pointer_set_t*, bool);
static tree expand_template_argument_pack (tree);
-static tree build_template_parm_index (int, int, int, tree, tree);
+static tree build_template_parm_index (int, int, int, int, tree, tree);
static bool inline_needs_template_parms (tree);
static void push_inline_template_parms_recursive (tree, int);
static tree retrieve_local_specialization (tree);
@@ -190,6 +190,12 @@ static void append_type_to_template_for_access_check_1 (tree, tree, tree,
static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
static tree listify (tree);
static tree listify_autos (tree, tree);
+static tree template_parm_to_arg (tree t);
+static tree current_template_args (void);
+static tree fixup_template_type_parm_type (tree, int);
+static tree fixup_template_parm_index (tree, tree, int);
+static void fixup_template_parms (void);
+static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@@ -3346,12 +3352,14 @@ check_template_shadow (tree decl)
}
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
- ORIG_LEVEL, DECL, and TYPE. */
+ ORIG_LEVEL, DECL, and TYPE. NUM_SIBLINGS is the total number of
+ template parameters. */
static tree
build_template_parm_index (int index,
int level,
int orig_level,
+ int num_siblings,
tree decl,
tree type)
{
@@ -3359,6 +3367,7 @@ build_template_parm_index (int index,
TEMPLATE_PARM_IDX (t) = index;
TEMPLATE_PARM_LEVEL (t) = level;
TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level;
+ TEMPLATE_PARM_NUM_SIBLINGS (t) = num_siblings;
TEMPLATE_PARM_DECL (t) = decl;
TREE_TYPE (t) = type;
TREE_CONSTANT (t) = TREE_CONSTANT (decl);
@@ -3370,6 +3379,7 @@ build_template_parm_index (int index,
/* Find the canonical type parameter for the given template type
parameter. Returns the canonical type parameter, which may be TYPE
if no such parameter existed. */
+
static tree
canonical_type_parameter (tree type)
{
@@ -3423,6 +3433,7 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
t = build_template_parm_index (TEMPLATE_PARM_IDX (index),
TEMPLATE_PARM_LEVEL (index) - levels,
TEMPLATE_PARM_ORIG_LEVEL (index),
+ TEMPLATE_PARM_NUM_SIBLINGS (index),
decl, type);
TEMPLATE_PARM_DESCENDANTS (index) = t;
TEMPLATE_PARM_PARAMETER_PACK (t)
@@ -3438,15 +3449,20 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
return TEMPLATE_PARM_DESCENDANTS (index);
}
-/* Process information from new template parameter PARM and append it to the
- LIST being built. This new parameter is a non-type parameter iff
- IS_NON_TYPE is true. This new parameter is a parameter
- pack iff IS_PARAMETER_PACK is true. The location of PARM is in
- PARM_LOC. */
+/* Process information from new template parameter PARM and append it
+ to the LIST being built. This new parameter is a non-type
+ parameter iff IS_NON_TYPE is true. This new parameter is a
+ parameter pack iff IS_PARAMETER_PACK is true. The location of PARM
+ is in PARM_LOC. NUM_TEMPLATE_PARMS is the size of the template
+ parameter list PARM belongs to. This is used used to create a
+ proper canonical type for the type of PARM that is to be created,
+ iff PARM is a type. If the size is not known, this parameter shall
+ be set to 0. */
tree
-process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_type,
- bool is_parameter_pack)
+process_template_parm (tree list, location_t parm_loc, tree parm,
+ bool is_non_type, bool is_parameter_pack,
+ unsigned num_template_parms)
{
tree decl = 0;
tree defval;
@@ -3521,6 +3537,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
DECL_INITIAL (parm) = DECL_INITIAL (decl)
= build_template_parm_index (idx, processing_template_decl,
processing_template_decl,
+ num_template_parms,
decl, TREE_TYPE (parm));
TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
@@ -3554,6 +3571,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
TEMPLATE_TYPE_PARM_INDEX (t)
= build_template_parm_index (idx, processing_template_decl,
processing_template_decl,
+ num_template_parms,
decl, TREE_TYPE (parm));
TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
TYPE_CANONICAL (t) = canonical_type_parameter (t);
@@ -3586,16 +3604,313 @@ end_template_parm_list (tree parms)
next = TREE_CHAIN (parm);
TREE_VEC_ELT (saved_parmlist, nparms) = parm;
TREE_CHAIN (parm) = NULL_TREE;
- if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
- TEMPLATE_TYPE_PARM_SIBLING_PARMS (TREE_TYPE (TREE_VALUE (parm))) =
- current_template_parms;
}
+ fixup_template_parms ();
+
--processing_template_parmlist;
return saved_parmlist;
}
+/* Create a new type almost identical to TYPE but which has the
+ following differences:
+
+ 1/ T has a new TEMPLATE_PARM_INDEX that carries the new number of
+ template sibling parameters of T.
+
+ 2/ T has a new canonical type that matches the new number
+ of sibling parms.
+
+ 3/ From now on, T is going to be what lookups referring to the
+ name of TYPE will return. No lookup should return TYPE anymore.
+
+ NUM_PARMS is the new number of sibling parms TYPE belongs to.
+
+ This is a subroutine of fixup_template_parms. */
+
+static tree
+fixup_template_type_parm_type (tree type, int num_parms)
+{
+ tree orig_idx = TEMPLATE_TYPE_PARM_INDEX (type), idx;
+ tree t;
+ /* This is the decl which name is inserted into the symbol table for
+ the template parm type. So whenever we lookup the type name, this
+ is the DECL we get. */
+ tree decl;
+
+ /* Do not fix up the type twice. */
+ if (orig_idx && TEMPLATE_PARM_NUM_SIBLINGS (orig_idx) != 0)
+ return type;
+
+ t = copy_type (type);
+ decl = TYPE_NAME (t);
+
+ TYPE_MAIN_VARIANT (t) = t;
+ TYPE_NEXT_VARIANT (t)= NULL_TREE;
+ TYPE_POINTER_TO (t) = 0;
+ TYPE_REFERENCE_TO (t) = 0;
+
+ idx = build_template_parm_index (TEMPLATE_PARM_IDX (orig_idx),
+ TEMPLATE_PARM_LEVEL (orig_idx),
+ TEMPLATE_PARM_ORIG_LEVEL (orig_idx),
+ num_parms,
+ decl, t);
+ TEMPLATE_PARM_DESCENDANTS (idx) = TEMPLATE_PARM_DESCENDANTS (orig_idx);
+ TEMPLATE_PARM_PARAMETER_PACK (idx) = TEMPLATE_PARM_PARAMETER_PACK (orig_idx);
+ TEMPLATE_TYPE_PARM_INDEX (t) = idx;
+
+ TYPE_STUB_DECL (t) = decl;
+ TEMPLATE_TYPE_DECL (t) = decl;
+ if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
+ TREE_TYPE (DECL_TEMPLATE_RESULT (decl)) = t;
+
+ /* Update the type associated to the type name stored in the symbol
+ table. Now, whenever the type name is looked up, the resulting
+ type is properly fixed up. */
+ TREE_TYPE (decl) = t;
+
+ TYPE_CANONICAL (t) = canonical_type_parameter (t);
+
+ return t;
+}
+
+/* Create and return a new TEMPLATE_PARM_INDEX that is almost
+ identical to I, but that is fixed up as to:
+
+ 1/ carry the number of sibling parms (NUM_PARMS) of the template
+ parm represented by I.
+
+ 2/ replace all references to template parm types declared before I
+ (in the same template parm list as I) by references to template
+ parm types contained in ARGS. ARGS should contain the list of
+ template parms that have been fixed up so far, in a form suitable
+ to be passed to tsubst.
+
+ This is a subroutine of fixup_template_parms. */
+
+static tree
+fixup_template_parm_index (tree i, tree args, int num_parms)
+{
+ tree index, decl, type;
+
+ if (i == NULL_TREE
+ || TREE_CODE (i) != TEMPLATE_PARM_INDEX
+ /* Do not fix up the index twice. */
+ || (TEMPLATE_PARM_NUM_SIBLINGS (i) != 0))
+ return i;
+
+ decl = TEMPLATE_PARM_DECL (i);
+ type = TREE_TYPE (decl);
+
+ index = build_template_parm_index (TEMPLATE_PARM_IDX (i),
+ TEMPLATE_PARM_LEVEL (i),
+ TEMPLATE_PARM_ORIG_LEVEL (i),
+ num_parms,
+ decl, type);
+
+ TEMPLATE_PARM_DESCENDANTS (index) = TEMPLATE_PARM_DESCENDANTS (i);
+ TEMPLATE_PARM_PARAMETER_PACK (index) = TEMPLATE_PARM_PARAMETER_PACK (i);
+
+ type = tsubst (type, args, tf_none, NULL_TREE);
+
+ TREE_TYPE (decl) = type;
+ TREE_TYPE (index) = type;
+
+ return index;
+}
+
+/*
+ This is a subroutine of fixup_template_parms.
+
+ It computes the canonical type of the type of the template
+ parameter PARM_DESC and update all references to that type so that
+ they use the newly computed canonical type. No access check is
+ performed during the fixup. PARM_DESC is a TREE_LIST which
+ TREE_VALUE is the template parameter and its TREE_PURPOSE is the
+ default argument of the template parm if any. IDX is the index of
+ the template parameter, starting at 0. NUM_PARMS is the number of
+ template parameters in the set PARM_DESC belongs to. ARGLIST is a
+ TREE_VEC containing the full set of template parameters in a form
+ suitable to be passed to substs functions as their ARGS
+ argument. This is what current_template_args returns for a given
+ template. The innermost vector of args in ARGLIST is the set of
+ template parms that have been fixed up so far. This function adds
+ the fixed up parameter into that vector. */
+
+static void
+fixup_template_parm (tree parm_desc,
+ int idx,
+ int num_parms,
+ tree arglist)
+{
+ tree parm = TREE_VALUE (parm_desc);
+ tree fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+ push_deferring_access_checks (dk_no_check);
+
+ if (TREE_CODE (parm) == TYPE_DECL)
+ {
+ /* PARM is a template type parameter. Fix up its type, add
+ the fixed-up template parm to the vector of fixed-up
+ template parms so far, and substitute the fixed-up
+ template parms into the default argument of this
+ parameter. */
+ tree t =
+ fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
+ TREE_TYPE (parm) = t;
+
+ TREE_VEC_ELT (fixedup_args, idx) = template_parm_to_arg (parm_desc);
+ }
+ else if (TREE_CODE (parm) == TEMPLATE_DECL)
+ {
+ /* PARM is a template template parameter. This is going to
+ be interesting. */
+ tree tparms, targs, innermost_args;
+ int j;
+
+ /* First, fix up the type of the parm. */
+
+ tree t =
+ fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
+ TREE_TYPE (parm) = t;
+
+ TREE_VEC_ELT (fixedup_args, idx) =
+ template_parm_to_arg (parm_desc);
+
+ /* Now we need to substitute the template parm types that
+ have been fixed up so far into the non-type template
+ parms of this template template parm. E.g, consider this:
+
+ template<class T, template<T u> class TT> class S;
+
+ In this case we want to substitute T into the
+ template parameters of TT.
+
+ So let's walk the template parms of PARM here, and
+ tsubst ARGLIST into into each of the template
+ parms. */
+
+ /* For this substitution we need to build the full set of
+ template parameters and use that as arguments for the
+ tsubsting function. */
+ tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm));
+
+ /* This will contain the innermost parms of PARM into which
+ we have substituted so far. */
+ innermost_args = make_tree_vec (TREE_VEC_LENGTH (tparms));
+ targs = add_to_template_args (arglist, innermost_args);
+ for (j = 0; j < TREE_VEC_LENGTH (tparms); ++j)
+ {
+ tree parameter;
+
+ parameter = TREE_VEC_ELT (tparms, j);
+
+ /* INNERMOST_ARGS needs to have at least the same number
+ of elements as the index PARAMETER, ortherwise
+ tsubsting into PARAMETER will result in partially
+ instantiating it, reducing its tempate parm
+ level. Let's tactically fill INNERMOST_ARGS for that
+ purpose. */
+ TREE_VEC_ELT (innermost_args, j) =
+ template_parm_to_arg (parameter);
+
+ fixup_template_parm (parameter, j,
+ TREE_VEC_LENGTH (tparms),
+ targs);
+ }
+ }
+ else if (TREE_CODE (parm) == PARM_DECL)
+ {
+ /* PARM is a non-type template parameter. We need to:
+
+ * Fix up its TEMPLATE_PARM_INDEX to make it carry the
+ proper number of sibling parameters.
+
+ * Make lookups of the template parameter return a reference
+ to the fixed-up index. No lookup should return references
+ to the former index anymore.
+
+ * Substitute the template parms that got fixed up so far
+
+ * into the type of PARM. */
+
+ tree index = DECL_INITIAL (parm);
+
+ /* PUSHED_DECL is the decl added to the symbol table with
+ the name of the parameter. E,g:
+
+ template<class T, T u> //#0
+ auto my_function(T t) -> decltype(u); //#1
+
+ Here, when looking up u at //#1, we get the decl of u
+ resulting from the declaration in #0. This is what
+ PUSHED_DECL is. We need to replace the reference to the
+ old TEMPLATE_PARM_INDEX carried by PUSHED_DECL by the
+ fixed-up TEMPLATE_PARM_INDEX. */
+ tree pushed_decl = TEMPLATE_PARM_DECL (index);
+
+ /* Let's fix up the TEMPLATE_PARM_INDEX then. Note that we must
+ fixup the type of PUSHED_DECL as well and luckily
+ fixup_template_parm_index does it for us too. */
+ tree fixed_up_index =
+ fixup_template_parm_index (index, arglist, num_parms);
+
+ DECL_INITIAL (pushed_decl) = DECL_INITIAL (parm) = fixed_up_index;
+
+ /* Add this fixed up PARM to the template parms we've fixed
+ up so far and use that to substitute the fixed-up
+ template parms into the type of PARM. */
+ TREE_VEC_ELT (fixedup_args, idx) =
+ template_parm_to_arg (parm_desc);
+ TREE_TYPE (parm) = tsubst (TREE_TYPE (parm), arglist,
+ tf_none, NULL_TREE);
+ }
+
+ TREE_PURPOSE (parm_desc) =
+ tsubst_template_arg (TREE_PURPOSE (parm_desc),
+ arglist, tf_none, parm);
+
+ pop_deferring_access_checks ();
+}
+
+/* Walk current the template parms and properly compute the canonical
+ types of the dependent types created during
+ cp_parser_template_parameter_list. */
+
+static void
+fixup_template_parms (void)
+{
+ tree arglist;
+ tree parameter_vec;
+ tree fixedup_args;
+ int i, num_parms;
+
+ parameter_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+ if (parameter_vec == NULL_TREE)
+ return;
+
+ num_parms = TREE_VEC_LENGTH (parameter_vec);
+
+ /* This vector contains the current innermost template parms that
+ have been fixed up so far. The form of FIXEDUP_ARGS is suitable
+ to be passed to tsubst* functions as their ARGS argument. */
+ fixedup_args = make_tree_vec (num_parms);
+
+ /* This vector contains the full set of template parms in a form
+ suitable to be passed to substs functions as their ARGS
+ argument. */
+ arglist = current_template_args ();
+ arglist = add_outermost_template_args (arglist, fixedup_args);
+
+ fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
+
+ /* Let's do the proper fixup now. */
+ for (i = 0; i < num_parms; ++i)
+ fixup_template_parm (TREE_VEC_ELT (parameter_vec, i),
+ i, num_parms, arglist);
+}
+
/* end_template_decl is called after a template declaration is seen. */
void
@@ -3613,6 +3928,68 @@ end_template_decl (void)
current_template_parms = TREE_CHAIN (current_template_parms);
}
+/* Takes a TREE_LIST representing a template parameter and convert it
+ into an argument suitable to be passed to the type substitution
+ functions. Note that If the TREE_LIST contains an error_mark
+ node, the returned argument is error_mark_node. */
+
+static tree
+template_parm_to_arg (tree t)
+{
+
+ if (t == NULL_TREE
+ || TREE_CODE (t) != TREE_LIST)
+ return t;
+
+ if (error_operand_p (TREE_VALUE (t)))
+ return error_mark_node;
+
+ t = TREE_VALUE (t);
+
+ if (TREE_CODE (t) == TYPE_DECL
+ || TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ t = TREE_TYPE (t);
+
+ if (TEMPLATE_TYPE_PARAMETER_PACK (t))
+ {
+ /* Turn this argument into a TYPE_ARGUMENT_PACK
+ with a single element, which expands T. */
+ tree vec = make_tree_vec (1);
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+ (vec, TREE_VEC_LENGTH (vec));
+#endif
+ TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+ t = cxx_make_type (TYPE_ARGUMENT_PACK);
+ SET_ARGUMENT_PACK_ARGS (t, vec);
+ }
+ }
+ else
+ {
+ t = DECL_INITIAL (t);
+
+ if (TEMPLATE_PARM_PARAMETER_PACK (t))
+ {
+ /* Turn this argument into a NONTYPE_ARGUMENT_PACK
+ with a single element, which expands T. */
+ tree vec = make_tree_vec (1);
+ tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+ (vec, TREE_VEC_LENGTH (vec));
+#endif
+ TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
+
+ t = make_node (NONTYPE_ARGUMENT_PACK);
+ SET_ARGUMENT_PACK_ARGS (t, vec);
+ TREE_TYPE (t) = type;
+ }
+ }
+ return t;
+}
+
/* Within the declaration of a template, return all levels of template
parameters that apply. The template parameters are represented as
a TREE_VEC, in the form documented in cp-tree.h for template
@@ -3639,63 +4016,7 @@ current_template_args (void)
TREE_TYPE (a) = NULL_TREE;
for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
- {
- tree t = TREE_VEC_ELT (a, i);
-
- /* T will be a list if we are called from within a
- begin/end_template_parm_list pair, but a vector directly
- if within a begin/end_member_template_processing pair. */
- if (TREE_CODE (t) == TREE_LIST)
- {
- t = TREE_VALUE (t);
-
- if (!error_operand_p (t))
- {
- if (TREE_CODE (t) == TYPE_DECL
- || TREE_CODE (t) == TEMPLATE_DECL)
- {
- t = TREE_TYPE (t);
-
- if (TEMPLATE_TYPE_PARAMETER_PACK (t))
- {
- /* Turn this argument into a TYPE_ARGUMENT_PACK
- with a single element, which expands T. */
- tree vec = make_tree_vec (1);
-#ifdef ENABLE_CHECKING
- SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
- (vec, TREE_VEC_LENGTH (vec));
-#endif
- TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-
- t = cxx_make_type (TYPE_ARGUMENT_PACK);
- SET_ARGUMENT_PACK_ARGS (t, vec);
- }
- }
- else
- {
- t = DECL_INITIAL (t);
-
- if (TEMPLATE_PARM_PARAMETER_PACK (t))
- {
- /* Turn this argument into a NONTYPE_ARGUMENT_PACK
- with a single element, which expands T. */
- tree vec = make_tree_vec (1);
- tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
-#ifdef ENABLE_CHECKING
- SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
- (vec, TREE_VEC_LENGTH (vec));
-#endif
- TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
-
- t = make_node (NONTYPE_ARGUMENT_PACK);
- SET_ARGUMENT_PACK_ARGS (t, vec);
- TREE_TYPE (t) = type;
- }
- }
- TREE_VEC_ELT (a, i) = t;
- }
- }
- }
+ TREE_VEC_ELT (a, i) = template_parm_to_arg (TREE_VEC_ELT (a, i));
#ifdef ENABLE_CHECKING
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
@@ -3707,6 +4028,21 @@ current_template_args (void)
args = a;
}
+ if (length > 1 && TREE_VEC_ELT (args, 0) == NULL_TREE)
+ /* This can happen for template parms of a template template
+ parameter, e.g:
+
+ template<template<class T, class U> class TT> struct S;
+
+ Consider the level of the parms of TT; T and U both have
+ level 2; TT has no template parm of level 1. So in this case
+ the first element of full_template_args is NULL_TREE. If we
+ leave it like this TMPL_ARG_DEPTH on args returns 1 instead
+ of 2. This will make tsubst wrongly consider that T and U
+ have level 1. Instead, let's create a dummy vector as the
+ first element of full_template_args so that TMPL_ARG_DEPTH
+ returns the correct depth for args. */
+ TREE_VEC_ELT (args, 0) = make_tree_vec (1);
return args;
}
@@ -8744,8 +9080,6 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
{
tree tuple;
- tree default_value;
- tree parm_decl;
if (parms == error_mark_node)
continue;
@@ -8755,18 +9089,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
if (tuple == error_mark_node)
continue;
- default_value = TREE_PURPOSE (tuple);
- parm_decl = TREE_VALUE (tuple);
-
- parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
- if (TREE_CODE (parm_decl) == PARM_DECL
- && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
- parm_decl = error_mark_node;
- default_value = tsubst_template_arg (default_value, args,
- complain, NULL_TREE);
-
- tuple = build_tree_list (default_value, parm_decl);
- TREE_VEC_ELT (new_vec, i) = tuple;
+ TREE_VEC_ELT (new_vec, i) =
+ tsubst_template_parm (tuple, args, complain);
}
*new_parms =
@@ -8780,6 +9104,36 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
return r;
}
+/* Return the result of substituting ARGS into one template parameter
+ given by T. T Must be a TREE_LIST which TREE_VALUE is the template
+ parameter and which TREE_PURPOSE is the default argument of the
+ template parameter. */
+
+static tree
+tsubst_template_parm (tree t, tree args, tsubst_flags_t complain)
+{
+ tree default_value, parm_decl;
+
+ if (args == NULL_TREE
+ || t == NULL_TREE
+ || t == error_mark_node)
+ return t;
+
+ gcc_assert (TREE_CODE (t) == TREE_LIST);
+
+ default_value = TREE_PURPOSE (t);
+ parm_decl = TREE_VALUE (t);
+
+ parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+ if (TREE_CODE (parm_decl) == PARM_DECL
+ && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+ parm_decl = error_mark_node;
+ default_value = tsubst_template_arg (default_value, args,
+ complain, NULL_TREE);
+
+ return build_tree_list (default_value, parm_decl);
+}
+
/* Substitute the ARGS into the indicated aggregate (or enumeration)
type T. If T is not an aggregate or enumeration type, it is
handled as if by tsubst. IN_DECL is as for tsubst. If
@@ -14720,6 +15074,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
{
tree parmvec = TYPE_TI_ARGS (parm);
tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
+ tree full_argvec = add_to_template_args (targs, argvec);
tree parm_parms
= DECL_INNERMOST_TEMPLATE_PARMS
(TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
@@ -14754,7 +15109,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
the global operator+ will be used; if they are not, the
Lvalue_proxy will be converted to float. */
if (coerce_template_parms (parm_parms,
- argvec,
+ full_argvec,
TYPE_TI_TEMPLATE (parm),
tf_none,
/*require_all_args=*/true,
@@ -18001,6 +18356,13 @@ dependent_template_arg_p (tree arg)
if (!processing_template_decl)
return false;
+ /* Assume a template argument that was wrongly written by the user
+ is dependent. This is consistent with what
+ any_dependent_template_arguments_p [that calls this function]
+ does. */
+ if (arg == error_mark_node)
+ return true;
+
if (TREE_CODE (arg) == TEMPLATE_DECL
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
return dependent_template_p (arg);
@@ -18428,7 +18790,7 @@ make_auto (void)
TYPE_STUB_DECL (au) = TYPE_NAME (au);
TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
(0, processing_template_decl + 1, processing_template_decl + 1,
- TYPE_NAME (au), NULL_TREE);
+ 0, TYPE_NAME (au), NULL_TREE);
TYPE_CANONICAL (au) = canonical_type_parameter (au);
DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index b8f76b0..7e33693 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1062,22 +1062,6 @@ strip_typedefs (tree t)
return cp_build_qualified_type (result, cp_type_quals (t));
}
-/* Setup a TYPE_DECL node as a typedef representation.
- See comments of set_underlying_type in c-common.c. */
-
-void
-cp_set_underlying_type (tree t)
-{
- set_underlying_type (t);
- /* If T is a template type parm, make it require structural equality.
- This is useful when comparing two template type parms,
- because it forces the comparison of the template parameters of their
- decls. */
- if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
- SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\f
/* Makes a copy of BINFO and TYPE, which is to be inherited into a
graph dominated by T. If BINFO is NULL, TYPE is a dependent base,
and we do a shallow copy. If BINFO is non-NULL, we do a deep copy.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 160198b..76d6f12 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1143,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
static bool
comp_template_parms_position (tree t1, tree t2)
{
+ tree index1, index2;
gcc_assert (t1 && t2
&& TREE_CODE (t1) == TREE_CODE (t2)
&& (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
- if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
- || TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
- || (TEMPLATE_TYPE_PARAMETER_PACK (t1)
- != TEMPLATE_TYPE_PARAMETER_PACK (t2)))
- return false;
-
- return true;
-}
-
-/* Subroutine of incompatible_dependent_types_p.
- Return the template parameter of the dependent type T.
- If T is a typedef, return the template parameters of
- the _decl_ of the typedef. T must be a dependent type. */
-
-static tree
-get_template_parms_of_dependent_type (tree t)
-{
- tree tinfo = NULL_TREE, tparms = NULL_TREE;
-
- /* First, try the obvious case of getting the
- template info from T itself. */
- if ((tinfo = get_template_info (t)))
- ;
- else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
- return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
- else if (typedef_variant_p (t)
- && !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
- tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
- /* If T is a TYPENAME_TYPE which context is a template type
- parameter, get the template parameters from that context. */
- else if (TYPE_CONTEXT (t)
- && TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
- return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
- else if (TYPE_CONTEXT (t)
- && !NAMESPACE_SCOPE_P (t))
- tinfo = get_template_info (TYPE_CONTEXT (t));
-
- if (tinfo)
- tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
-
- return tparms;
-}
-
-/* Subroutine of structural_comptypes.
- Compare the dependent types T1 and T2.
- Return TRUE if we are sure they can't be equal, FALSE otherwise.
- The whole point of this function is to support cases where either T1 or
- T2 is a typedef. In those cases, we need to compare the template parameters
- of the _decl_ of the typedef. If those don't match then we know T1
- and T2 cannot be equal. */
-
-static bool
-incompatible_dependent_types_p (tree t1, tree t2)
-{
- tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
- bool t1_typedef_variant_p, t2_typedef_variant_p;
-
- if (!uses_template_parms (t1) || !uses_template_parms (t2))
- return false;
-
- if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
- {
- /* If T1 and T2 don't have the same relative position in their
- template parameters set, they can't be equal. */
- if (!comp_template_parms_position (t1, t2))
- return true;
- }
-
- t1_typedef_variant_p = typedef_variant_p (t1);
- t2_typedef_variant_p = typedef_variant_p (t2);
+ index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
+ index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
- /* Either T1 or T2 must be a typedef. */
- if (!t1_typedef_variant_p && !t2_typedef_variant_p)
+ /* If T1 and T2 belong to template parm lists of different size,
+ let's assume they are different. */
+ if (TEMPLATE_PARM_NUM_SIBLINGS (index1)
+ != TEMPLATE_PARM_NUM_SIBLINGS (index2))
return false;
- if (!t1_typedef_variant_p || !t2_typedef_variant_p)
- /* Either T1 or T2 is not a typedef so we cannot compare the
- template parms of the typedefs of T1 and T2.
- At this point, if the main variant type of T1 and T2 are equal
- it means the two types can't be incompatible, from the perspective
- of this function. */
- if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
- return false;
-
- /* So if we reach this point, it means either T1 or T2 is a typedef variant.
- Let's compare their template parameters. */
-
- tparms1 = get_template_parms_of_dependent_type (t1);
- tparms2 = get_template_parms_of_dependent_type (t2);
-
- /* If T2 is a template type parm and if we could not get the template
- parms it belongs to, that means we have not finished parsing the
- full set of template parameters of the template declaration it
- belongs to yet. If we could get the template parms T1 belongs to,
- that mostly means T1 and T2 belongs to templates that are
- different and incompatible. */
- if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
- && (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
- && tparms1 != tparms2)
- return true;
-
- if (tparms1 == NULL_TREE
- || tparms2 == NULL_TREE
- || tparms1 == tparms2)
+ /* Then compare their relative position. */
+ if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
+ || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
+ || (TEMPLATE_PARM_PARAMETER_PACK (index1)
+ != TEMPLATE_PARM_PARAMETER_PACK (index2)))
return false;
- /* And now compare the mighty template parms! */
- return !comp_template_parms (tparms1, tparms2);
+ return true;
}
/* Subroutine in comptypes. */
@@ -1301,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict)
if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
return false;
- /* If T1 and T2 are dependent typedefs then check upfront that
- the template parameters of their typedef DECLs match before
- going down checking their subtypes. */
- if (incompatible_dependent_types_p (t1, t2))
- return false;
-
/* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type
qualifiers (just above). */
@@ -1407,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict)
break;
case TEMPLATE_TYPE_PARM:
- /* If incompatible_dependent_types_p called earlier didn't decide
- T1 and T2 were different, they might be equal. */
+ /* If T1 and T2 don't have the same relative position in their
+ template parameters set, they can't be equal. */
+ if (!comp_template_parms_position (t1, t2))
+ return false;
break;
case TYPENAME_TYPE:
diff --git a/gcc/testsuite/g++.dg/template/canon-type-10.C b/gcc/testsuite/g++.dg/template/canon-type-10.C
new file mode 100644
index 0000000..0c38946
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-10.C
@@ -0,0 +1,23 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+};
+
+template<class T,
+ template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+ class U = TT<int, C> >
+struct S
+{
+ void foo(TT<T, C>);
+};
+
+template<class T,
+ template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
+ class U>
+void
+S<T, TT, U>::foo(TT<T, C>)
+{
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-11.C b/gcc/testsuite/g++.dg/template/canon-type-11.C
new file mode 100644
index 0000000..698fe31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-11.C
@@ -0,0 +1,39 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct C
+{
+ void bar();
+};
+
+template<class T>
+void
+C<T>::bar()
+{
+}
+
+
+template<class U,
+ template<class TT0_T0> class TT0 = C,
+ template<class TT1_T0> class TT1 = TT0>
+struct S
+{
+ C<U> s;
+
+ void foo(TT1<U>);
+
+ void bar()
+ {
+ foo(s);
+ }
+};
+
+template<class T,
+ template<class TT0_T0> class TT0,
+ template<class TT1_T0> class TT1>
+void
+S<T, TT0, TT1>::foo(TT1<T>)
+{
+ C<T> c;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-12.C b/gcc/testsuite/g++.dg/template/canon-type-12.C
new file mode 100644
index 0000000..694cc5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-12.C
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++0x" }
+
+template<class T, T t = (T)0>
+struct S
+{
+ void
+ foo(decltype(t) = t);
+};
+
+template<class T, T t>
+void
+S<T, t>::foo(T)
+{
+}
+
+void
+bar()
+{
+ S<int> s;
+ s.foo();
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-13.C b/gcc/testsuite/g++.dg/template/canon-type-13.C
new file mode 100644
index 0000000..ca39cea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-13.C
@@ -0,0 +1,27 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-do "compile" }
+
+template<class T>
+struct S0
+{
+};
+
+template<class T>
+struct S1
+{
+};
+
+template<class T, template<class T> class A, template<class T> class B = A>
+struct C
+{
+ B<T> m;
+};
+
+void
+foo()
+{
+ C<int, S0> s;
+ S0<int> s0;
+
+ s.m = s0;
+}
diff --git a/gcc/testsuite/g++.dg/template/canon-type-9.C b/gcc/testsuite/g++.dg/template/canon-type-9.C
new file mode 100644
index 0000000..de6170e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-9.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// { dg-options "-std=c++0x" }
+// { dg-do "compile" }
+
+struct F { F(int) {}};
+
+template<class T, T* u>
+struct S
+{
+ decltype(u) foo(T);
+};
+
+template<class T, T *u>
+T* S<T, u>::foo(T)
+{
+ T t;
+ return t;
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef36.C b/gcc/testsuite/g++.dg/template/typedef36.C
new file mode 100644
index 0000000..318deef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef36.C
@@ -0,0 +1,23 @@
+// Origin: PR c++/45606
+// { dg-do compile }
+
+template<class T, class U = int>
+struct S0
+{
+ typedef int const_iterator;
+};
+
+template<class T>
+struct Test
+{
+ typedef S0<T> SAlias;
+ typedef typename SAlias::const_iterator const_iterator;
+ const_iterator begin ();
+};
+
+template<class T>
+typename S0<T>::const_iterator
+Test<T>::begin()
+{
+ return 0;
+}
next prev parent reply other threads:[~2010-10-27 14:30 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-11 18:30 [Dodji Seketeli] Patch PR c++/45200 Dodji Seketeli
2010-08-11 21:04 ` Jason Merrill
2010-08-11 21:06 ` Andrew Pinski
2010-08-12 13:20 ` Dodji Seketeli
2010-08-12 14:35 ` Jason Merrill
2010-08-13 10:30 ` Dodji Seketeli
2010-08-13 15:09 ` Jason Merrill
2010-09-19 22:34 ` Require canonical type comparison for typedefs again. (was Patch PR c++/45200) Dodji Seketeli
2010-09-19 22:47 ` Paolo Carlini
2010-09-20 10:28 ` Require canonical type comparison for typedefs again Dodji Seketeli
2010-09-20 15:35 ` H.J. Lu
2010-09-20 17:07 ` Dodji Seketeli
2010-09-20 21:44 ` Jason Merrill
2010-09-26 14:44 ` Dodji Seketeli
2010-09-26 15:10 ` Jason Merrill
2010-09-28 15:12 ` Dodji Seketeli
2010-09-28 15:15 ` Dodji Seketeli
2010-09-28 16:51 ` Jason Merrill
2010-09-30 8:55 ` Dodji Seketeli
2010-09-30 9:10 ` Jason Merrill
2010-10-06 18:53 ` Dodji Seketeli
2010-10-06 22:15 ` Paolo Carlini
2010-10-15 16:09 ` Dodji Seketeli
2010-10-20 15:43 ` Jason Merrill
2010-10-20 21:10 ` Dodji Seketeli
2010-10-20 21:21 ` Jason Merrill
2010-10-20 22:06 ` Dodji Seketeli
2010-10-21 1:06 ` Jason Merrill
2010-10-23 22:46 ` Dodji Seketeli
2010-10-23 23:39 ` Jason Merrill
2010-10-24 2:33 ` Dodji Seketeli
2010-10-24 3:03 ` Jason Merrill
2010-10-25 11:52 ` Dodji Seketeli
2010-10-27 15:59 ` Dodji Seketeli [this message]
2010-10-28 17:54 ` Jason Merrill
2010-12-17 20:51 ` H.J. Lu
2011-10-28 21:47 ` H.J. Lu
2010-10-07 18:30 ` Jason Merrill
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=m34oc7ww5r.fsf@tutu.torimasen.com \
--to=dodji@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).