From f5a28e87f595dd160e4688c96fdcc4a51853b717 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 8 Apr 2011 02:08:31 -0400 Subject: [PATCH] re PR c++/48500 (Regression: Failing to convert template argument to concrete type, in C++0x mode.) PR c++/48500 * semantics.c (potential_constant_expression_1) [CALL_EXPR]: Check arguments even if we don't know the function. From-SVN: r172165 --- gcc/cp/ChangeLog | 4 + gcc/cp/semantics.c | 92 +++++++++++++--------- gcc/testsuite/ChangeLog | 2 + gcc/testsuite/g++.dg/cpp0x/regress/call1.C | 13 +++ 4 files changed, 72 insertions(+), 39 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/regress/call1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 027eac822fe..1b8f87363af 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2011-04-07 Jason Merrill + PR c++/48500 + * semantics.c (potential_constant_expression_1) [CALL_EXPR]: Check + arguments even if we don't know the function. + PR c++/48481 * tree.c (build_overload): Allow an unwrapped FUNCTION_DECL at the end of the chain. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 2184a53558e..0b4d1ec497a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7358,6 +7358,8 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) class member access expression, including the result of the implicit transformation in the body of the non-static member function (9.3.1); */ + /* FIXME this restriction seems pointless since the standard dropped + "potential constant expression". */ if (is_this_parameter (t)) { if (flags & tf_error) @@ -7373,51 +7375,63 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) { tree fun = get_function_named_in_call (t); const int nargs = call_expr_nargs (t); - if (TREE_CODE (fun) != FUNCTION_DECL) - { - if (potential_constant_expression_1 (fun, rval, flags)) - /* Might end up being a constant function pointer. */ - return true; - if (flags & tf_error) - error ("%qE is not a function name", fun); - return false; - } - /* Skip initial arguments to base constructors. */ - if (DECL_BASE_CONSTRUCTOR_P (fun)) - i = num_artificial_parms_for (fun); + i = 0; + + if (is_overloaded_fn (fun)) + { + if (TREE_CODE (fun) == FUNCTION_DECL) + { + if (builtin_valid_in_constant_expr_p (fun)) + return true; + if (!DECL_DECLARED_CONSTEXPR_P (fun) + && !morally_constexpr_builtin_function_p (fun)) + { + if (flags & tf_error) + error ("%qD is not %", fun); + return false; + } + /* A call to a non-static member function takes the address + of the object as the first argument. But in a constant + expression the address will be folded away, so look + through it now. */ + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun) + && !DECL_CONSTRUCTOR_P (fun)) + { + tree x = get_nth_callarg (t, 0); + if (is_this_parameter (x)) + /* OK. */; + else if (!potential_constant_expression_1 (x, rval, flags)) + { + if (flags & tf_error) + error ("object argument is not a potential " + "constant expression"); + return false; + } + i = 1; + } + } + else + fun = get_first_fn (fun); + /* Skip initial arguments to base constructors. */ + if (DECL_BASE_CONSTRUCTOR_P (fun)) + i = num_artificial_parms_for (fun); + fun = DECL_ORIGIN (fun); + } else - i = 0; - fun = DECL_ORIGIN (fun); - if (builtin_valid_in_constant_expr_p (fun)) - return true; - if (!DECL_DECLARED_CONSTEXPR_P (fun) - && !morally_constexpr_builtin_function_p (fun)) { - if (flags & tf_error) - error ("%qD is not %", fun); - return false; + if (potential_constant_expression_1 (fun, rval, flags)) + /* Might end up being a constant function pointer. */; + else + { + if (flags & tf_error) + error ("%qE is not a function name", fun); + return false; + } } for (; i < nargs; ++i) { tree x = get_nth_callarg (t, i); - /* A call to a non-static member function takes the - address of the object as the first argument. - But in a constant expression the address will be folded - away, so look through it now. */ - if (i == 0 && DECL_NONSTATIC_MEMBER_P (fun) - && !DECL_CONSTRUCTOR_P (fun)) - { - if (is_this_parameter (x)) - /* OK. */; - else if (!potential_constant_expression_1 (x, rval, flags)) - { - if (flags & tf_error) - error ("object argument is not a potential constant " - "expression"); - return false; - } - } - else if (!potential_constant_expression_1 (x, rval, flags)) + if (!potential_constant_expression_1 (x, rval, flags)) { if (flags & tf_error) error ("argument in position %qP is not a " diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8f52da21e08..436404b0136 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2011-04-07 Jason Merrill + * g++.dg/cpp0x/regress/call1.C: New. + * g++.dg/cpp0x/variadic107.C: New. * g++.dg/cpp0x/sfinae11.C: New. diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/call1.C b/gcc/testsuite/g++.dg/cpp0x/regress/call1.C new file mode 100644 index 00000000000..833318b0560 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/regress/call1.C @@ -0,0 +1,13 @@ +// PR c++/48500 +// { dg-options -std=c++0x } + +struct linked_ptr { +}; +template linked_ptr make_linked_ptr(T* ptr); +struct Concrete; +struct NewedClass { + NewedClass(const Concrete& req){} +}; +template void AddObjToChange(const ArgT& req) { + linked_ptr p = make_linked_ptr(new NewedClass(req)); +} -- 2.30.2