Patchwork C++ PATCH for c++/53619 (wrong base conversion in lambda)

login
register
mail settings
Submitter Jason Merrill
Date July 3, 2012, 5 a.m.
Message ID <4FF27C80.3020904@redhat.com>
Download mbox | patch
Permalink /patch/168684/
State New
Headers show

Comments

Jason Merrill - July 3, 2012, 5 a.m.
My change in 4.8 to use 'auto' for the return type of a lambda caused 
uses_template_parms (current_function_decl) to return true, causing us 
to skip the real adjustment to the base address.  Fixed by looking at 
DECL_TI_ARGS instead.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 7b3981302f5c25d7e800adc884690850585cb756
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jul 3 00:00:40 2012 -0400

    	PR c++/53619
    	* pt.c (in_template_function): New.
    	* cp-tree.h: Declare it.
    	* class.c (build_base_path, resolves_to_fixed_type_p): Use it.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index e70e674..0d4a40d 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -325,8 +325,7 @@  build_base_path (enum tree_code code,
      up properly yet, and the value doesn't matter there either; we're just
      interested in the result of overload resolution.  */
   if (cp_unevaluated_operand != 0
-      || (current_function_decl
-	  && uses_template_parms (current_function_decl)))
+      || in_template_function ())
     {
       expr = build_nop (ptr_target_type, expr);
       if (!want_pointer)
@@ -6523,8 +6522,7 @@  resolves_to_fixed_type_p (tree instance, int* nonnull)
 
   /* processing_template_decl can be false in a template if we're in
      fold_non_dependent_expr, but we still want to suppress this check.  */
-  if (current_function_decl
-      && uses_template_parms (current_function_decl))
+  if (in_template_function ())
     {
       /* In a template we only care about the type of the result.  */
       if (nonnull)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a4b7ae3..41ca83c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5330,6 +5330,7 @@  extern tree lookup_template_class		(tree, tree, tree, tree,
 extern tree lookup_template_function		(tree, tree);
 extern int uses_template_parms			(tree);
 extern int uses_template_parms_level		(tree, int);
+extern bool in_template_function		(void);
 extern tree instantiate_class_template		(tree);
 extern tree instantiate_template		(tree, tree, tsubst_flags_t);
 extern int fn_type_unification			(tree, tree, tree,
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d385ea7..f618fa5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8027,6 +8027,23 @@  uses_template_parms (tree t)
   return dependent_p;
 }
 
+/* Returns true iff current_function_decl is an incompletely instantiated
+   template.  Useful instead of processing_template_decl because the latter
+   is set to 0 during fold_non_dependent_expr.  */
+
+bool
+in_template_function (void)
+{
+  tree fn = current_function_decl;
+  bool ret;
+  ++processing_template_decl;
+  ret = (fn && DECL_LANG_SPECIFIC (fn)
+	 && DECL_TEMPLATE_INFO (fn)
+	 && any_dependent_template_arguments_p (DECL_TI_ARGS (fn)));
+  --processing_template_decl;
+  return ret;
+}
+
 /* Returns true if T depends on any template parameter with level LEVEL.  */
 
 int
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this5.C
new file mode 100644
index 0000000..8974641
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this5.C
@@ -0,0 +1,22 @@ 
+// PR c++/53619
+// { dg-do run { target c++11 } }
+
+struct C {
+  int x;
+};
+struct B {
+  int q;
+};
+struct A : public B , C  {
+  void foo();
+};
+
+void A::foo() {
+  auto k = [this]() {return (void *)(&x);};
+  if (k() != (void*)&x)
+    __builtin_abort();
+}
+
+int main(int l, char **) {
+  A a; a.foo();
+}