diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7bf5f014e2a..c4c4680c8ae 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2008-08-07 Douglas Gregor + + * semantics.c (finish_decltype_type): Handle calls to function + pointers and references to functions properly. + 2008-08-06 Douglas Gregor PR c++/36460 diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 5ada42241fb..9a8af7c0774 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4586,8 +4586,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) } else { - tree fndecl; - /* Expressions of reference type are sometimes wrapped in INDIRECT_REFs. INDIRECT_REFs are just internal compiler representation, not part of the language, so we have to look @@ -4597,14 +4595,28 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) == REFERENCE_TYPE) expr = TREE_OPERAND (expr, 0); - if (TREE_CODE (expr) == CALL_EXPR - && (fndecl = get_callee_fndecl (expr)) - && (fndecl != error_mark_node)) - /* If e is a function call (5.2.2 [expr.call]) or an + if (TREE_CODE (expr) == CALL_EXPR) + { + /* If e is a function call (5.2.2 [expr.call]) or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is defined as the return type of that function. */ - type = TREE_TYPE (TREE_TYPE (fndecl)); + tree fndecl = get_callee_fndecl (expr); + if (fndecl && fndecl != error_mark_node) + type = TREE_TYPE (TREE_TYPE (fndecl)); + else + { + tree target_type = TREE_TYPE (CALL_EXPR_FN (expr)); + if ((TREE_CODE (target_type) == REFERENCE_TYPE + || TREE_CODE (target_type) == POINTER_TYPE) + && (TREE_CODE (TREE_TYPE (target_type)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (target_type)) == METHOD_TYPE)) + type = TREE_TYPE (TREE_TYPE (target_type)); + else + sorry ("unable to determine the declared type of expression %<%E%>", + expr); + } + } else { type = is_bitfield_expr_with_lowered_type (expr); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 417b6b79822..bd034f014fd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-08-07 Douglas Gregor + + * g++.dg/cpp0x/decltype12.C: New. + 2008-08-07 H.J. Lu PR target/36992 diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype12.C b/gcc/testsuite/g++.dg/cpp0x/decltype12.C new file mode 100644 index 00000000000..77c794bcf09 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype12.C @@ -0,0 +1,38 @@ +// { dg-do compile } +// { dg-options "-std=c++0x" } +template +struct is_same +{ + static const bool value = false; +}; + +template +struct is_same +{ + static const bool value = true; +}; + +int&& f(const int&) {} +int&& (*fp)(const int&) = f; +int&& (&fr)(const int&) = f; + +struct X { int&& f(const int&); }; + +int&& (X::*mfp)(const int&) = &X::f; + +void g(X& xr, X* xp) +{ + int i; + static_assert(is_same::value, "direct call"); + static_assert(is_same::value, "pointer"); + static_assert(is_same::value, + "dereferenced pointer"); + static_assert(is_same::value, + "reference"); + static_assert(is_same::value, + "member function call"); + static_assert(is_same::value, + "member function pointer with .*"); + static_assert(is_same*mfp)(i)), int&&>::value, + "member function pointer with ->*"); +}