This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH to tsubst for c++/28385
- From: Jason Merrill <jason at redhat dot com>
- To: "gcc-patches >> GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 16 Aug 2006 20:50:32 -0400
- Subject: C++ PATCH to tsubst for c++/28385
When Doug Gregor allowed cv-qualifiers on FUNCTION_TYPEs in order to
support
typedef void fntype() const;
we started applying them incorrectly from template substitution as well.
Fixed thus.
Tested x86_64-pc-linux-gnu, applied to trunk.
2006-08-16 Jason Merrill <jason@redhat.com>
PR c++/28385
* pt.c (tsubst) [TEMPLATE_TYPE_PARM]: Ignore quals from template
if arg is a function.
Index: pt.c
===================================================================
*** pt.c (revision 116184)
--- pt.c (working copy)
*************** tsubst (tree t, tree args, tsubst_flags_
*** 7238,7247 ****
{
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
{
gcc_assert (TYPE_P (arg));
return cp_build_qualified_type_real
! (arg, cp_type_quals (arg) | cp_type_quals (t),
! complain | tf_ignore_bad_quals);
}
else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
--- 7238,7257 ----
{
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
{
+ int quals;
gcc_assert (TYPE_P (arg));
+
+ /* cv-quals from the template are discarded when
+ substituting in a function or reference type. */
+ if (TREE_CODE (arg) == FUNCTION_TYPE
+ || TREE_CODE (arg) == METHOD_TYPE
+ || TREE_CODE (arg) == REFERENCE_TYPE)
+ quals = cp_type_quals (arg);
+ else
+ quals = cp_type_quals (arg) | cp_type_quals (t);
+
return cp_build_qualified_type_real
! (arg, quals, complain | tf_ignore_bad_quals);
}
else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
Index: /home/jason/ged/template/const1.C
===================================================================
*** /home/jason/ged/template/const1.C (revision 0)
--- /home/jason/ged/template/const1.C (revision 0)
***************
*** 0 ****
--- 1,30 ----
+ // PR c++/28385
+ // instantiating op() with void()() was making the compiler think that 'fcn'
+ // was const, so it could eliminate the call.
+
+ // { dg-do run }
+
+ extern "C" void abort (void);
+
+ int barcnt = 0;
+
+ class Foo {
+ public:
+ template<typename T>
+ void operator()(const T& fcn) {
+ fcn();
+ }
+ };
+
+ void bar() {
+ barcnt++;
+ }
+
+ int main() {
+ Foo myFoo;
+ myFoo(bar);
+ myFoo(&bar);
+ if (barcnt != 2)
+ abort ();
+ return 0;
+ }