]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/28385 (templated function call goes awry)
authorJason Merrill <jason@redhat.com>
Fri, 18 Aug 2006 16:27:03 +0000 (12:27 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 18 Aug 2006 16:27:03 +0000 (12:27 -0400)
        PR c++/28385
        * pt.c (tsubst) [TEMPLATE_TYPE_PARM]: Ignore quals from template
        if arg is a function.

From-SVN: r116243

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/cp/search.c
gcc/testsuite/g++.dg/template/const1.C [new file with mode: 0644]

index e2fada81d90588053c3800bfa617ce3fb46c79e8..0f842278c763d954b9e8dd154cd594330c0971b4 100644 (file)
@@ -1,3 +1,9 @@
+2006-08-17  Jason Merrill  <jason@redhat.com>
+
+       PR c++/28385
+       * pt.c (tsubst) [TEMPLATE_TYPE_PARM]: Ignore quals from template
+       if arg is a function.
+
 2006-08-17  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c++/28606
index 7fe9f124e12556c7d93289a20ad27669896e88bc..c296c715c31ffa0dea4f90a65429f7c9068641b2 100644 (file)
@@ -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)
              {
index 3eb279170ebc8fb1e24e2d7093092c1501de3ff4..ce313c9b411f1f57d97ef419dc3d639d93423e4b 100644 (file)
@@ -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 (file)
index 0000000..629c4d4
--- /dev/null
@@ -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;
+}