From e0e1b357435272f8906e8fd70d92c7862e1bc07b Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 3 Jul 2012 01:03:34 -0400 Subject: [PATCH] re PR c++/53619 ([C++11] wrong capture of "this" in lambda in case of multiple inheritance) 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. From-SVN: r189191 --- gcc/cp/ChangeLog | 5 +++++ gcc/cp/class.c | 6 ++--- gcc/cp/cp-tree.h | 1 + gcc/cp/pt.c | 17 ++++++++++++++ gcc/testsuite/ChangeLog | 3 +++ .../g++.dg/cpp0x/lambda/lambda-this5.C | 22 +++++++++++++++++++ 6 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this5.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 580f8cda3abb..2c524230fe43 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2012-07-02 Jason Merrill + 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. + PR c++/53783 * pt.c (tsubst_copy_and_build) [LAMBDA_EXPR]: Use tsubst for LAMBDA_EXPR_EXTRA_SCOPE. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index e70e6747b55b..0d4a40d4dbec 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 a4b7ae3716df..41ca83ca8c9b 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 d385ea7ee76c..f618fa557d10 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/ChangeLog b/gcc/testsuite/ChangeLog index cb62b113a1ae..7ce574a64f55 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2012-07-02 Jason Merrill + PR c++/53619 + * g++.dg/cpp0x/lambda/lambda-this5.C: New. + PR c++/53783 * g++.dg/cpp0x/lambda/lambda-template7.C: New. 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 000000000000..8974641643cb --- /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(); +}