OSDN Git Service

2008-08-07 Douglas Gregor <doug.gregor@gmail.com>
authordgregor <dgregor@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Aug 2008 15:38:59 +0000 (15:38 +0000)
committerdgregor <dgregor@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Aug 2008 15:38:59 +0000 (15:38 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@138843 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/decltype12.C [new file with mode: 0644]

index 7bf5f01..c4c4680 100644 (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
index 5ada422..9a8af7c 100644 (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);
index 417b6b7..bd034f0 100644 (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
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype12.C b/gcc/testsuite/g++.dg/cpp0x/decltype12.C
new file mode 100644 (file)
index 0000000..77c794b
--- /dev/null
@@ -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 ->*");
+}