PR c++/43558
Dodji Seketeli
dodji@redhat.com
Mon Mar 29 15:20:00 GMT 2010
Hello,
Consider this example:
template<class T, class U> struct S; //tmpl#1
template<class T>
class S<T*, int> //tmpl#2
{
typedef T TT;
TT f(T); //f#1
}; //#2
template<class T>
T
S<T*, int>::f(T t) //f#2
{
return t;
}
During the comparison of the return types of f#1 and f#2, when we
consider TT, we want to get the template parms of tmpl#2 and compare
them with the template parms of //f#2.
The problem is we get the template parms of the most general template
tmpl#1 instead.
This is because get_template_info called on the context of TT yields the
template info of the most general template tmpl#1 so we get the template
parms of that tmpl#1 instead of getting the template parms of tmpl#2.
Thus the patch below introduces a new function
get_most_specialized_template_info that yields the the template info of
tmpl#2 when called on TT.
I couldn't find a direct way of getting the template parms (T) of
the partial specialization template<class T> S<T*, int> because its
CLASSTYPE_TEMPLATE_INFO points to the template info of tmpl#1.
So I ressorted to getting the CLASSTYPE_TEMPLATE_INFO of the self
reference of S<T*, int> because it represents the template info of this
partial specialization so its DECL_TEMPLATE_PARMS (TI_TEMPLATE())
really is the template parms set T I want. Is there a better way of
doing this?
Tested on x86_64-unknown-linux-gnu against trunk.
Dodji
commit 750822c2b384f2192c3ed6b9bcce00af137ed7a8
Author: Dodji Seketeli <dodji@redhat.com>
Date: Mon Mar 29 15:10:42 2010 +0200
Fix PR c++/43558
gcc/cp/ChangeLog:
PR c++/43558
* cp-tree.h (get_self_reference,
get_most_specialized_template_info): Declare new fns.
* class.c (get_self_reference): Define new fn.
* pt.c (get_most_specialized_template_info): Define new fn. Use
get_self_reference.
* typeck.c (get_template_parms_of_dependent_type): Get template parms
of typedefs from the most specialized template info of their
context. Use get_most_specialized_template_info.
gcc/testsuite/ChangeLog:
PR c++/43558
* g++.dg/template/typedef31.C: New test.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1bab07d..2af3f1e 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6533,6 +6533,24 @@ build_self_reference (void)
current_access_specifier = saved_cas;
}
+/* Get the reference to CLASS_TYPE that has been built by
+ build_self_reference. */
+
+tree
+get_self_reference (tree class_type)
+{
+ tree t;
+
+ if (!class_type || !CLASS_TYPE_P (class_type))
+ return NULL_TREE;
+
+ for (t = TYPE_FIELDS (class_type); t; t = TREE_CHAIN (t))
+ if (DECL_SELF_REFERENCE_P (t))
+ return t;
+
+ return NULL_TREE;
+}
+
/* Returns 1 if TYPE contains only padding bytes. */
int
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2eaee84..38df5fe 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4588,6 +4588,7 @@ extern void pop_lang_context (void);
extern tree instantiate_type (tree, tree, tsubst_flags_t);
extern void print_class_statistics (void);
extern void build_self_reference (void);
+extern tree get_self_reference (tree);
extern int same_signature_p (const_tree, const_tree);
extern void maybe_add_class_template_decl_list (tree, tree, int);
extern void unreverse_member_declarations (tree);
@@ -4926,6 +4927,7 @@ extern tree make_pack_expansion (tree);
extern bool check_for_bare_parameter_packs (tree);
extern tree build_template_info (tree, tree);
extern tree get_template_info (const_tree);
+extern tree get_most_specialized_template_info (tree);
extern VEC(qualified_typedef_usage_t,gc)* get_types_needing_access_check (tree);
extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3bd45f7..15fad01 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -321,6 +321,34 @@ get_template_info (const_tree t)
return tinfo;
}
+/* Return the template info corresponding to T.
+ If T is an instantiation of a partial class template specialization,
+ this function returns the template info corresponding to the partial
+ specialization instead of the one corresponding to the most general
+ template.
+
+ E.g:
+
+ template<class T, class U> struct S; //#1
+ template<class T> struct S<T*, int> {}; //#2
+
+ When called on S<char*, int>, this function returns the template info
+ corresponding to //#2. */
+
+tree
+get_most_specialized_template_info (tree t)
+{
+ if (t && TAGGED_TYPE_P (t)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
+ && !explicit_class_specialization_p (t))
+ {
+ tree self = get_self_reference (t);
+ if (self)
+ return get_template_info (self);
+ }
+ return get_template_info (t);
+}
+
/* Returns the template nesting level of the indicated class TYPE.
For example, in:
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a4c64ea..e9c7e5c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1110,11 +1110,10 @@ get_template_parms_of_dependent_type (tree t)
template info from T itself. */
if ((tinfo = get_template_info (t)))
;
- /* If T1 is a typedef or whatever has a template info associated
- to its context, get the template parameters from that context. */
+ /* If T1 is a typedef, get the template parameters from its context. */
else if (typedef_variant_p (t)
&& !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
- tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
+ tinfo = get_most_specialized_template_info (DECL_CONTEXT (TYPE_NAME (t)));
else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
&& DECL_CONTEXT (TYPE_NAME (t)) == NULL_TREE)
/* We have not yet created the DECL_TEMPLATE this
diff --git a/gcc/testsuite/g++.dg/template/typedef31.C b/gcc/testsuite/g++.dg/template/typedef31.C
new file mode 100644
index 0000000..7d66e3f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef31.C
@@ -0,0 +1,21 @@
+// Origin: PR c++/43558
+// { dg-do compile }
+
+class Compressible;
+template <class T, class EngineTag> class Engine;
+template <class T>
+class Engine<T, Compressible>
+{
+ public:
+ typedef T Element_t;
+ //Element_t read(int);
+ T read(int);
+};
+
+template <class T>
+T Engine<T, Compressible>::read(int)
+{
+}
+
+Engine<int, Compressible> x;
+
More information about the Gcc-patches
mailing list