aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-06-16 06:08:49 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2006-06-16 06:08:49 +0000
commit4e95268d59d17d5d58d60f2067a79a215d65db73 (patch)
tree2cd5e1744fea5e85f23366a250ecce719577ca85 /gcc
parent2954333afc6cbb12f5628368b5f557a5730d1242 (diff)
downloadgcc-4e95268d59d17d5d58d60f2067a79a215d65db73.zip
gcc-4e95268d59d17d5d58d60f2067a79a215d65db73.tar.gz
gcc-4e95268d59d17d5d58d60f2067a79a215d65db73.tar.bz2
re PR c++/27689 (function template incorrectly selected as candidate)
PR c++/27689 * cp-tree.h (CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P): New macro. * pt.c (unify): Use it. PR c++/27689 * g++.dg/template/ttp18.C: New test. * g++.dg/template/ttp19.C: Likewise. From-SVN: r114703
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/cp-tree.h76
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/template/ttp18.C10
-rw-r--r--gcc/testsuite/g++.dg/template/ttp19.C7
6 files changed, 77 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 778658af..bb1ea7f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2006-06-15 Mark Mitchell <mark@codesourcery.com>
+ PR c++/27689
+ * cp-tree.h (CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P): New
+ macro.
+ * pt.c (unify): Use it.
+
PR c++/27666
* call.c (build_conditional_expr): Robustify.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c0897a0..e9f28a6 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1117,14 +1117,6 @@ struct lang_type GTY(())
#endif /* ENABLE_TREE_CHECKING */
-/* Indicates whether or not (and how) a template was expanded for this class.
- 0=no information yet/non-template class
- 1=implicit template instantiation
- 2=explicit template specialization
- 3=explicit template instantiation */
-#define CLASSTYPE_USE_TEMPLATE(NODE) \
- (LANG_TYPE_CLASS_CHECK (NODE)->use_template)
-
/* Fields used for storing information before the class is defined.
After the class is defined, these fields hold other information. */
@@ -2096,15 +2088,15 @@ extern void decl_shadowed_for_var_insert (tree, tree);
(DECL_LANG_SPECIFIC (DECL)->decl_flags.deferred)
/* If non-NULL for a VAR_DECL, FUNCTION_DECL, TYPE_DECL or
- TEMPLATE_DECL, the entity is a template specialization. In that
- case, DECL_TEMPLATE_INFO is a TREE_LIST, whose TREE_PURPOSE is the
- TEMPLATE_DECL of which this entity is a specialization. The TREE_
- TREE_VALUE is the template arguments used to specialize the
- template.
-
- In general, DECL_TEMPLATE_INFO is non-NULL only if
- DECL_USE_TEMPLATE is nonzero. However, for friends, we sometimes
- have DECL_TEMPLATE_INFO even when DECL_USE_TEMPLATE is zero.
+ TEMPLATE_DECL, the entity is either a template specialization (if
+ DECL_USE_TEMPLATE is non-zero) or the abstract instance of the
+ template itself.
+
+ In either case, DECL_TEMPLATE_INFO is a TREE_LIST, whose
+ TREE_PURPOSE is the TEMPLATE_DECL of which this entity is a
+ specialization or abstract instance. The TREE_VALUE is the
+ template arguments used to specialize the template.
+
Consider:
template <typename T> struct S { friend void f(T) {} };
@@ -2112,7 +2104,8 @@ extern void decl_shadowed_for_var_insert (tree, tree);
In this case, S<int>::f is, from the point of view of the compiler,
an instantiation of a template -- but, from the point of view of
the language, each instantiation of S results in a wholly unrelated
- global function f. */
+ global function f. In this case, DECL_TEMPLATE_INFO for S<int>::f
+ will be non-NULL, but DECL_USE_TEMPLATE will be zero. */
#define DECL_TEMPLATE_INFO(NODE) \
(DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \
->decl_flags.u.template_info)
@@ -2240,6 +2233,16 @@ extern void decl_shadowed_for_var_insert (tree, tree);
are always the full set of arguments required to instantiate this
declaration from the most general template specialized here. */
#define DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE))
+
+/* The TEMPLATE_DECL associated with NODE, a class type. Even if NODE
+ will be generated from a partial specialization, the TEMPLATE_DECL
+ referred to here will be the original template. For example,
+ given:
+
+ template <typename T> struct S {};
+ template <typename T> struct S<T*> {};
+
+ the CLASSTPYE_TI_TEMPLATE for S<int*> will be S, not the S<T*>. */
#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
@@ -2252,7 +2255,7 @@ extern void decl_shadowed_for_var_insert (tree, tree);
(CLASSTYPE_TI_TEMPLATE ((TYPE))))) \
: (TYPE))
-/* Like DECL_TI_TEMPLATE, but for an ENUMERAL_, RECORD_, or UNION_TYPE. */
+/* Like CLASS_TI_TEMPLATE, but also works for ENUMERAL_TYPEs. */
#define TYPE_TI_TEMPLATE(NODE) \
(TI_TEMPLATE (TYPE_TEMPLATE_INFO (NODE)))
@@ -2845,17 +2848,38 @@ extern void decl_shadowed_for_var_insert (tree, tree);
/* Returns nonzero if NODE is a primary template. */
#define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == (NODE))
-/* Indicates whether or not (and how) a template was expanded for this
- FUNCTION_DECL or VAR_DECL.
- 0=normal declaration, e.g. int min (int, int);
- 1=implicit template instantiation
- 2=explicit template specialization, e.g. int min<int> (int, int);
- 3=explicit template instantiation, e.g. template int min<int> (int, int);
+/* Non-zero iff NODE is a specialization of a template. The value
+ indicates the type of specializations:
+
+ 1=implicit instantiation
+ 2=explicit specialization, e.g. int min<int> (int, int);
+ 3=explicit instantiation, e.g. template int min<int> (int, int);
- If DECL_USE_TEMPLATE is nonzero, then DECL_TEMPLATE_INFO will also
+ Note that NODE will be marked as a specialization even if the
+ template it is instantiating is not a primary template. For
+ example, given:
+
+ template <typename T> struct O {
+ void f();
+ struct I {};
+ };
+
+ both O<int>::f and O<int>::I will be marked as instantiations.
+
+ If DECL_USE_TEMPLATE is non-zero, then DECL_TEMPLATE_INFO will also
be non-NULL. */
#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.use_template)
+/* Like DECL_USE_TEMPLATE, but for class types. */
+#define CLASSTYPE_USE_TEMPLATE(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->use_template)
+
+/* True if NODE is a specialization of a primary template. */
+#define CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P(NODE) \
+ (CLASS_TYPE_P (NODE) \
+ && CLASSTYPE_USE_TEMPLATE (NODE) \
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg)))
+
#define DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1)
#define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) & 1)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d25ea79..79183f5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10166,7 +10166,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
/* ARG must be constructed from a template class or a template
template parameter. */
if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
- && (TREE_CODE (arg) != RECORD_TYPE || !CLASSTYPE_TEMPLATE_INFO (arg)))
+ && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg))
return 1;
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0696d9a..313a39f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2006-06-15 Mark Mitchell <mark@codesourcery.com>
+ PR c++/27689
+ * g++.dg/template/ttp18.C: New test.
+ * g++.dg/template/ttp19.C: Likewise.
+
PR c++/27666
* g++.dg/expr/cond9.C: New test.
diff --git a/gcc/testsuite/g++.dg/template/ttp18.C b/gcc/testsuite/g++.dg/template/ttp18.C
new file mode 100644
index 0000000..095c07f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp18.C
@@ -0,0 +1,10 @@
+template <template <typename> class T>
+void f(T<int>) {}
+
+template <typename T>
+union U {};
+
+void g() {
+ f(U<int>());
+}
+
diff --git a/gcc/testsuite/g++.dg/template/ttp19.C b/gcc/testsuite/g++.dg/template/ttp19.C
new file mode 100644
index 0000000..12a37c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp19.C
@@ -0,0 +1,7 @@
+// PR c++/27689
+
+void f (...);
+template <template <typename> class F, typename T> void f (F<T>);
+template <typename> struct foo { struct bar {}; };
+void g (foo<int>::bar x) { f(x); }
+