This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/53619 (wrong base conversion in lambda)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 03 Jul 2012 01:00:48 -0400
- Subject: C++ PATCH for c++/53619 (wrong base conversion in lambda)
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.
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();
+}