From 8ee63818c0036fa3114a5a1207c88de12f33a0f8 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 18 Aug 2006 12:27:03 -0400 Subject: [PATCH] re PR c++/28385 (templated function call goes awry) PR c++/28385 * pt.c (tsubst) [TEMPLATE_TYPE_PARM]: Ignore quals from template if arg is a function. From-SVN: r116243 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/pt.c | 14 ++++++++++-- gcc/cp/search.c | 6 +++--- gcc/testsuite/g++.dg/template/const1.C | 30 ++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/const1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e2fada81d905..0f842278c763 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2006-08-17 Jason Merrill + + PR c++/28385 + * pt.c (tsubst) [TEMPLATE_TYPE_PARM]: Ignore quals from template + if arg is a function. + 2006-08-17 Volker Reichelt PR c++/28606 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7fe9f124e125..c296c715c31f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7065,10 +7065,20 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) { 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, cp_type_quals (arg) | cp_type_quals (t), - complain | tf_ignore_bad_quals); + (arg, quals, complain | tf_ignore_bad_quals); } else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM) { diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 3eb279170ebc..ce313c9b411f 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1192,9 +1192,6 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type) tree type = NULL_TREE, basetype_path = NULL_TREE; struct lookup_field_info lfi; - if (name == error_mark_node) - return NULL_TREE; - /* rval_binfo is the binfo associated with the found member, note, this can be set with useful information, even when rval is not set, because it must deal with ALL members, not just non-function @@ -1204,6 +1201,9 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type) const char *errstr = 0; + if (name == error_mark_node) + return NULL_TREE; + gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); if (TREE_CODE (xbasetype) == TREE_BINFO) diff --git a/gcc/testsuite/g++.dg/template/const1.C b/gcc/testsuite/g++.dg/template/const1.C new file mode 100644 index 000000000000..629c4d4a916e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/const1.C @@ -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 + void operator()(const T& fcn) { + fcn(); + } +}; + +void bar() { + barcnt++; +} + +int main() { + Foo myFoo; + myFoo(bar); + myFoo(&bar); + if (barcnt != 2) + abort (); + return 0; +} -- 2.47.2