Commit 4e95268d by Mark Mitchell Committed by Mark Mitchell

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
parent 2954333a
2006-06-15 Mark Mitchell <mark@codesourcery.com> 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 PR c++/27666
* call.c (build_conditional_expr): Robustify. * call.c (build_conditional_expr): Robustify.
......
...@@ -1117,14 +1117,6 @@ struct lang_type GTY(()) ...@@ -1117,14 +1117,6 @@ struct lang_type GTY(())
#endif /* ENABLE_TREE_CHECKING */ #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. /* Fields used for storing information before the class is defined.
After the class is defined, these fields hold other information. */ After the class is defined, these fields hold other information. */
...@@ -2096,15 +2088,15 @@ extern void decl_shadowed_for_var_insert (tree, tree); ...@@ -2096,15 +2088,15 @@ extern void decl_shadowed_for_var_insert (tree, tree);
(DECL_LANG_SPECIFIC (DECL)->decl_flags.deferred) (DECL_LANG_SPECIFIC (DECL)->decl_flags.deferred)
/* If non-NULL for a VAR_DECL, FUNCTION_DECL, TYPE_DECL or /* If non-NULL for a VAR_DECL, FUNCTION_DECL, TYPE_DECL or
TEMPLATE_DECL, the entity is a template specialization. In that TEMPLATE_DECL, the entity is either a template specialization (if
case, DECL_TEMPLATE_INFO is a TREE_LIST, whose TREE_PURPOSE is the DECL_USE_TEMPLATE is non-zero) or the abstract instance of the
TEMPLATE_DECL of which this entity is a specialization. The TREE_ template itself.
TREE_VALUE is the template arguments used to specialize the
template. In either case, DECL_TEMPLATE_INFO is a TREE_LIST, whose
TREE_PURPOSE is the TEMPLATE_DECL of which this entity is a
In general, DECL_TEMPLATE_INFO is non-NULL only if specialization or abstract instance. The TREE_VALUE is the
DECL_USE_TEMPLATE is nonzero. However, for friends, we sometimes template arguments used to specialize the template.
have DECL_TEMPLATE_INFO even when DECL_USE_TEMPLATE is zero.
Consider: Consider:
template <typename T> struct S { friend void f(T) {} }; template <typename T> struct S { friend void f(T) {} };
...@@ -2112,7 +2104,8 @@ extern void decl_shadowed_for_var_insert (tree, tree); ...@@ -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, 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 an instantiation of a template -- but, from the point of view of
the language, each instantiation of S results in a wholly unrelated 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) \ #define DECL_TEMPLATE_INFO(NODE) \
(DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \ (DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \
->decl_flags.u.template_info) ->decl_flags.u.template_info)
...@@ -2240,6 +2233,16 @@ extern void decl_shadowed_for_var_insert (tree, tree); ...@@ -2240,6 +2233,16 @@ extern void decl_shadowed_for_var_insert (tree, tree);
are always the full set of arguments required to instantiate this are always the full set of arguments required to instantiate this
declaration from the most general template specialized here. */ declaration from the most general template specialized here. */
#define DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE)) #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_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (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); ...@@ -2252,7 +2255,7 @@ extern void decl_shadowed_for_var_insert (tree, tree);
(CLASSTYPE_TI_TEMPLATE ((TYPE))))) \ (CLASSTYPE_TI_TEMPLATE ((TYPE))))) \
: (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) \ #define TYPE_TI_TEMPLATE(NODE) \
(TI_TEMPLATE (TYPE_TEMPLATE_INFO (NODE))) (TI_TEMPLATE (TYPE_TEMPLATE_INFO (NODE)))
...@@ -2845,17 +2848,38 @@ extern void decl_shadowed_for_var_insert (tree, tree); ...@@ -2845,17 +2848,38 @@ extern void decl_shadowed_for_var_insert (tree, tree);
/* Returns nonzero if NODE is a primary template. */ /* Returns nonzero if NODE is a primary template. */
#define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == (NODE)) #define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == (NODE))
/* Indicates whether or not (and how) a template was expanded for this /* Non-zero iff NODE is a specialization of a template. The value
FUNCTION_DECL or VAR_DECL. indicates the type of specializations:
0=normal declaration, e.g. int min (int, int);
1=implicit template instantiation 1=implicit instantiation
2=explicit template specialization, e.g. int min<int> (int, int); 2=explicit specialization, e.g. int min<int> (int, int);
3=explicit template instantiation, e.g. template 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. */ be non-NULL. */
#define DECL_USE_TEMPLATE(NODE) (DECL_LANG_SPECIFIC (NODE)->decl_flags.use_template) #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 DECL_TEMPLATE_INSTANTIATION(NODE) (DECL_USE_TEMPLATE (NODE) & 1)
#define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \ #define CLASSTYPE_TEMPLATE_INSTANTIATION(NODE) \
(CLASSTYPE_USE_TEMPLATE (NODE) & 1) (CLASSTYPE_USE_TEMPLATE (NODE) & 1)
......
...@@ -10166,7 +10166,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) ...@@ -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 /* ARG must be constructed from a template class or a template
template parameter. */ template parameter. */
if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM 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; return 1;
{ {
......
2006-06-15 Mark Mitchell <mark@codesourcery.com> 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 PR c++/27666
* g++.dg/expr/cond9.C: New test. * g++.dg/expr/cond9.C: New test.
template <template <typename> class T>
void f(T<int>) {}
template <typename T>
union U {};
void g() {
f(U<int>());
}
// 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); }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment