aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDouglas Gregor <doug.gregor@gmail.com>2008-08-07 15:38:59 +0000
committerDoug Gregor <dgregor@gcc.gnu.org>2008-08-07 15:38:59 +0000
commited85a1f60b8a827af17129d2e76c332ecf13d7bd (patch)
treed0b0600d972dd2e78c8abdb979bb1a5f24f8b99e /gcc
parente297d9fe0df8e5b1fb5dee3700be0bf3c2894680 (diff)
downloadgcc-ed85a1f60b8a827af17129d2e76c332ecf13d7bd.zip
gcc-ed85a1f60b8a827af17129d2e76c332ecf13d7bd.tar.gz
gcc-ed85a1f60b8a827af17129d2e76c332ecf13d7bd.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/semantics.c26
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype12.C38
4 files changed, 66 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7bf5f01..c4c4680 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 5ada422..9a8af7c 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 417b6b7..bd034f0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype12.C b/gcc/testsuite/g++.dg/cpp0x/decltype12.C
new file mode 100644
index 0000000..77c794b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype12.C
@@ -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 ->*");
+}