semantics.c (finish_decltype_type): Handle calls to function pointers and references to functions properly.

2008-08-07  Douglas Gregor  <doug.gregor@gmail.com>
	
	* semantics.c (finish_decltype_type): Handle calls to function
	pointers and references to functions properly.
	
2008-08-07  Douglas Gregor  <doug.gregor@gmail.com>

	* g++.dg/cpp0x/decltype12.C: New.

From-SVN: r138843
This commit is contained in:
Douglas Gregor 2008-08-07 15:38:59 +00:00 committed by Doug Gregor
parent e297d9fe0d
commit ed85a1f60b
4 changed files with 66 additions and 7 deletions

View file

@ -1,3 +1,8 @@
2008-08-07 Douglas Gregor <doug.gregor@gmail.com>
* semantics.c (finish_decltype_type): Handle calls to function
pointers and references to functions properly.
2008-08-06 Douglas Gregor <doug.gregor@gmail.com>
PR c++/36460

View file

@ -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);

View file

@ -1,3 +1,7 @@
2008-08-07 Douglas Gregor <doug.gregor@gmail.com>
* g++.dg/cpp0x/decltype12.C: New.
2008-08-07 H.J. Lu <hongjiu.lu@intel.com>
PR target/36992

View file

@ -0,0 +1,38 @@
// { dg-do compile }
// { dg-options "-std=c++0x" }
template<typename T, typename U>
struct is_same
{
static const bool value = false;
};
template<typename T>
struct is_same<T, T>
{
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<decltype(f(i)), int&&>::value, "direct call");
static_assert(is_same<decltype(fp(i)), int&&>::value, "pointer");
static_assert(is_same<decltype((*fp)(i)), int&&>::value,
"dereferenced pointer");
static_assert(is_same<decltype(fr(i)), int&&>::value,
"reference");
static_assert(is_same<decltype(xr.f(i)), int&&>::value,
"member function call");
static_assert(is_same<decltype((xr.*mfp)(i)), int&&>::value,
"member function pointer with .*");
static_assert(is_same<decltype((xp->*mfp)(i)), int&&>::value,
"member function pointer with ->*");
}