Upstream-Status: Inappropriate [Backport] From c9ec81bbd73666b97ab9049b759b5ab8d0e06681 Mon Sep 17 00:00:00 2001 From: jason Date: Fri, 8 Apr 2011 15:02:28 +0000 Subject: [PATCH 090/200] PR c++/48500 * semantics.c (potential_constant_expression_1) [CALL_EXPR]: Check arguments even if we don't know the function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@172195 138bc75d-0d04-0410-961f-82ee72b054a4 index 3a85ddb..e6bb1dc 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7374,6 +7374,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) @@ -7389,51 +7391,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 " new file mode 100644 index 0000000..833318b --- /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)); +} -- 1.7.0.4