Core 1212
authorJason Merrill <jason@redhat.com>
Thu, 17 Mar 2011 16:20:16 +0000 (12:20 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 17 Mar 2011 16:20:16 +0000 (12:20 -0400)
Core 1212
* semantics.c (finish_decltype_type): Return T&& for xvalue.
* typeck.c (unlowered_expr_type): Preserve cv-quals.

From-SVN: r171104

gcc/cp/ChangeLog
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/decltype-1212.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/rv-return.C

index 38ac06ce7df42c5396ee96fc110a136e50bd8400..f710f7a7c6d30ad1df1dff93a109d1d9145b9200 100644 (file)
@@ -1,5 +1,9 @@
 2011-03-17  Jason Merrill  <jason@redhat.com>
 
+       Core 1212
+       * semantics.c (finish_decltype_type): Return T&& for xvalue.
+       * typeck.c (unlowered_expr_type): Preserve cv-quals.
+
        PR c++/48166
        * decl.c (revert_static_member_fn): Strip function-cv-quals.
 
index 7519d263f47fd3d2a74eb81f3c5241cb87ea5d3f..cafca56fbba50e581df672023bb7818e47e28f04 100644 (file)
@@ -4787,7 +4787,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
          && processing_template_decl
          && TREE_CODE (expr) == COMPONENT_REF))
     {
-    treat_as_dependent:
       type = cxx_make_type (DECLTYPE_TYPE);
       DECLTYPE_TYPE_EXPR (type) = expr;
       DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type)
@@ -4899,91 +4898,34 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
     }
   else
     {
-      /* 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
-         through them.  */
-      if (TREE_CODE (expr) == INDIRECT_REF
-          && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
-         == REFERENCE_TYPE)
-        expr = TREE_OPERAND (expr, 0);
-
-      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.  */
-          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 if (processing_template_decl)
-               /* Within a template finish_call_expr doesn't resolve
-                  CALL_EXPR_FN, so even though this decltype isn't really
-                  dependent let's defer resolving it.  */
-               goto treat_as_dependent;
-              else
-                sorry ("unable to determine the declared type of expression %<%E%>",
-                       expr);
-            }
-        }
-      else 
-        {
-          type = is_bitfield_expr_with_lowered_type (expr);
-          if (type)
-            {
-              /* Bitfields are special, because their type encodes the
-                 number of bits they store.  If the expression referenced a
-                 bitfield, TYPE now has the declared type of that
-                 bitfield.  */
-              type = cp_build_qualified_type (type, 
-                                              cp_type_quals (TREE_TYPE (expr)));
-              
-              if (real_lvalue_p (expr))
-                type = build_reference_type (type);
-            }
-         /* Within a lambda-expression:
-
-            Every occurrence of decltype((x)) where x is a possibly
-            parenthesized id-expression that names an entity of
-            automatic storage duration is treated as if x were
-            transformed into an access to a corresponding data member
-            of the closure type that would have been declared if x
-            were a use of the denoted entity.  */
-         else if (outer_automatic_var_p (expr)
-                  && current_function_decl
-                  && LAMBDA_FUNCTION_P (current_function_decl))
-           type = capture_decltype (expr);
-          else
-            {
-              /* Otherwise, where T is the type of e, if e is an lvalue,
-                 decltype(e) is defined as T&, otherwise decltype(e) is
-                 defined as T.  */
-              type = TREE_TYPE (expr);
-              if (type == error_mark_node)
-                return error_mark_node;
-              else if (expr == current_class_ptr)
-                /* If the expression is just "this", we want the
-                   cv-unqualified pointer for the "this" type.  */
-                type = TYPE_MAIN_VARIANT (type);
-              else if (real_lvalue_p (expr))
-                {
-                  if (TREE_CODE (type) != REFERENCE_TYPE
-                     || TYPE_REF_IS_RVALUE (type))
-                    type = build_reference_type (non_reference (type));
-                }
-              else
-                type = non_reference (type);
-            }
-        }
+      /* Within a lambda-expression:
+
+        Every occurrence of decltype((x)) where x is a possibly
+        parenthesized id-expression that names an entity of
+        automatic storage duration is treated as if x were
+        transformed into an access to a corresponding data member
+        of the closure type that would have been declared if x
+        were a use of the denoted entity.  */
+      if (outer_automatic_var_p (expr)
+         && current_function_decl
+         && LAMBDA_FUNCTION_P (current_function_decl))
+       type = capture_decltype (expr);
+      else if (error_operand_p (expr))
+       type = error_mark_node;
+      else if (expr == current_class_ptr)
+       /* If the expression is just "this", we want the
+          cv-unqualified pointer for the "this" type.  */
+       type = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
+      else
+       {
+         /* Otherwise, where T is the type of e, if e is an lvalue,
+            decltype(e) is defined as T&; if an xvalue, T&&; otherwise, T. */
+         cp_lvalue_kind clk = lvalue_kind (expr);
+         type = unlowered_expr_type (expr);
+         gcc_assert (TREE_CODE (type) != REFERENCE_TYPE);
+         if (clk != clk_none && !(clk & clk_class))
+           type = cp_build_reference_type (type, (clk & clk_rvalueref));
+       }
     }
 
   if (!type || type == unknown_type_node)
index 03aa49ee178f65eedb60f8189db9866d9358a647..955ff578f11fd17335eb9ef45a34efa3b05293fe 100644 (file)
@@ -1768,10 +1768,13 @@ tree
 unlowered_expr_type (const_tree exp)
 {
   tree type;
+  tree etype = TREE_TYPE (exp);
 
   type = is_bitfield_expr_with_lowered_type (exp);
-  if (!type)
-    type = TREE_TYPE (exp);
+  if (type)
+    type = cp_build_qualified_type (type, cp_type_quals (etype));
+  else
+    type = etype;
 
   return type;
 }
index 47cdbc920e11d2a01dd1d057abd1d75709fd66e3..29d38239df3197db212206802ed45fe85dfd5b43 100644 (file)
@@ -1,3 +1,8 @@
+2011-03-17  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/decltype-1212.C: New.
+       * g++.dg/cpp0x/rv-return.C: Adjust expected type.
+
 2011-03-17  Jason Merrill  <jason@redhat.com>
 
        * g++.dg/parse/memfnquals1.C: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C b/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C
new file mode 100644 (file)
index 0000000..38393d3
--- /dev/null
@@ -0,0 +1,11 @@
+// Core 1212
+// { dg-options -std=c++0x }
+
+template <class T, class U> struct assert_same_type;
+template <class T> struct assert_same_type<T,T> {};
+
+int main()
+{
+  int i;
+  assert_same_type<int&&,decltype(static_cast<int&&>(i))>();
+}
index e52101feae1c627cfd96e40f660e540343631fd4..3ab659833eab4d9b0df1eb075d72488648cd7845 100644 (file)
@@ -7,12 +7,12 @@ template<typename T> struct same_type<T, T> {};
 int const f() { return 0; }
 
 int &&r = f(); // binding "int&&" to "int" should succeed
-same_type<decltype(f()), int const> s1;
+same_type<decltype(f()), int> s1;
 same_type<decltype(0,f()), int> s2;
 
 template <class T>
 T const g() { return 0; }
 
 int &&r2 = g<int>();
-same_type<decltype(g<int>()), int const> s3;
+same_type<decltype(g<int>()), int> s3;
 same_type<decltype(0,g<int>()), int> s4;