diff options
author | Jason Merrill <jason@redhat.com> | 2018-05-23 13:21:22 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2018-05-23 13:21:22 -0400 |
commit | 955da5e5443724cb59f8fbd854c13e78c68bf000 (patch) | |
tree | 5376594ef4febecacfb8c0a3a1831fbdda417c0c /gcc | |
parent | a6b29221604547ab14143081b45d955dd7a61a26 (diff) | |
download | gcc-955da5e5443724cb59f8fbd854c13e78c68bf000.zip gcc-955da5e5443724cb59f8fbd854c13e78c68bf000.tar.gz gcc-955da5e5443724cb59f8fbd854c13e78c68bf000.tar.bz2 |
CWG 616, 1213 - value category of subobject references.
* tree.c (lvalue_kind): A reference to a subobject of a prvalue is
an xvalue.
* typeck2.c (build_m_component_ref): Likewise.
* typeck.c (cp_build_addr_expr_1, lvalue_or_else): Remove diagnostic
distinction between temporary and xvalue.
From-SVN: r260621
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/tree.c | 35 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 14 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/addressof2.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/decltype49.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/c99struct1.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/complit11.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.law/temps1.C | 2 |
10 files changed, 47 insertions, 37 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1e0854f..3adb570 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2018-05-23 Jason Merrill <jason@redhat.com> + + CWG 616, 1213 - value category of subobject references. + * tree.c (lvalue_kind): A reference to a subobject of a prvalue is + an xvalue. + * typeck2.c (build_m_component_ref): Likewise. + * typeck.c (cp_build_addr_expr_1, lvalue_or_else): Remove diagnostic + distinction between temporary and xvalue. + 2018-05-23 Marek Polacek <polacek@redhat.com> Implement P0614R1, Range-based for statements with initializer. diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 15b9697..efb8c2b 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -87,6 +87,7 @@ lvalue_kind (const_tree ref) { case SAVE_EXPR: return clk_none; + /* preincrements and predecrements are valid lvals, provided what they refer to are valid lvals. */ case PREINCREMENT_EXPR: @@ -94,7 +95,14 @@ lvalue_kind (const_tree ref) case TRY_CATCH_EXPR: case REALPART_EXPR: case IMAGPART_EXPR: - return lvalue_kind (TREE_OPERAND (ref, 0)); + case ARRAY_REF: + case VIEW_CONVERT_EXPR: + op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0)); + if (op1_lvalue_kind == clk_class) + /* in the case of an array operand, the result is an lvalue if that + operand is an lvalue and an xvalue otherwise */ + op1_lvalue_kind = clk_rvalueref; + return op1_lvalue_kind; case MEMBER_REF: case DOTSTAR_EXPR: @@ -104,6 +112,11 @@ lvalue_kind (const_tree ref) op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0)); if (TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (ref, 1)))) op1_lvalue_kind = clk_none; + else if (op1_lvalue_kind == clk_class) + /* The result of a .* expression whose second operand is a pointer to a + data member is an lvalue if the first operand is an lvalue and an + xvalue otherwise. */ + op1_lvalue_kind = clk_rvalueref; return op1_lvalue_kind; case COMPONENT_REF: @@ -119,6 +132,11 @@ lvalue_kind (const_tree ref) return lvalue_kind (TREE_OPERAND (ref, 1)); } op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0)); + if (op1_lvalue_kind == clk_class) + /* If E1 is an lvalue, then E1.E2 is an lvalue; + otherwise E1.E2 is an xvalue. */ + op1_lvalue_kind = clk_rvalueref; + /* Look at the member designator. */ if (!op1_lvalue_kind) ; @@ -165,7 +183,6 @@ lvalue_kind (const_tree ref) /* FALLTHRU */ case INDIRECT_REF: case ARROW_EXPR: - case ARRAY_REF: case PARM_DECL: case RESULT_DECL: case PLACEHOLDER_EXPR: @@ -203,11 +220,7 @@ lvalue_kind (const_tree ref) type-dependent expr, that is, but we shouldn't be testing lvalueness if we can't even tell the types yet! */ gcc_assert (!type_dependent_expression_p (CONST_CAST_TREE (ref))); - if (CLASS_TYPE_P (TREE_TYPE (ref)) - || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE) - return clk_class; - else - return clk_none; + goto default_; } op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1) ? TREE_OPERAND (ref, 1) @@ -257,18 +270,14 @@ lvalue_kind (const_tree ref) case PAREN_EXPR: return lvalue_kind (TREE_OPERAND (ref, 0)); - case VIEW_CONVERT_EXPR: - if (location_wrapper_p (ref)) - return lvalue_kind (TREE_OPERAND (ref, 0)); - /* Fallthrough. */ - default: + default_: if (!TREE_TYPE (ref)) return clk_none; if (CLASS_TYPE_P (TREE_TYPE (ref)) || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE) return clk_class; - break; + return clk_none; } /* If one operand is not an lvalue at all, then this expression is diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index ecb334d..82089c4 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5860,11 +5860,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) { if (!(complain & tf_error)) return error_mark_node; - if (kind & clk_class) - /* Make this a permerror because we used to accept it. */ - permerror (input_location, "taking address of temporary"); - else - error ("taking address of xvalue (rvalue reference)"); + /* Make this a permerror because we used to accept it. */ + permerror (input_location, "taking address of rvalue"); } } @@ -9866,11 +9863,8 @@ lvalue_or_else (tree ref, enum lvalue_use use, tsubst_flags_t complain) { if (!(complain & tf_error)) return 0; - if (kind & clk_class) - /* Make this a permerror because we used to accept it. */ - permerror (input_location, "using temporary as lvalue"); - else - error ("using xvalue (rvalue reference) as lvalue"); + /* Make this a permerror because we used to accept it. */ + permerror (input_location, "using rvalue as lvalue"); } return 1; } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index ad0774c..40233e6 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1965,7 +1965,7 @@ build_m_component_ref (tree datum, tree component, tsubst_flags_t complain) if (TYPE_PTRDATAMEM_P (ptrmem_type)) { - cp_lvalue_kind kind = lvalue_kind (datum); + bool is_lval = real_lvalue_p (datum); tree ptype; /* Compute the type of the field, as described in [expr.ref]. @@ -1995,9 +1995,7 @@ build_m_component_ref (tree datum, tree component, tsubst_flags_t complain) return error_mark_node; /* If the object expression was an rvalue, return an rvalue. */ - if (kind & clk_class) - datum = rvalue (datum); - else if (kind & clk_rvalueref) + if (!is_lval) datum = move (datum); return datum; } diff --git a/gcc/testsuite/g++.dg/cpp0x/addressof2.C b/gcc/testsuite/g++.dg/cpp0x/addressof2.C index bf218cc..a38dce0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/addressof2.C +++ b/gcc/testsuite/g++.dg/cpp0x/addressof2.C @@ -17,7 +17,7 @@ auto c = __builtin_addressof (s); auto d = addressof (s); auto e = __builtin_addressof (s.s); // { dg-error "attempt to take address of bit-field" } auto f = addressof (s.s); // { dg-error "cannot bind bitfield" } -auto g = __builtin_addressof (S{}); // { dg-error "taking address of temporary" } +auto g = __builtin_addressof (S{}); // { dg-error "taking address of rvalue" } auto h = addressof (S{}); // { dg-error "cannot bind non-const lvalue reference of type" } auto i = __builtin_addressof (S::t); // { dg-error "invalid use of non-static data member" } auto j = __builtin_addressof (S::foo); // { dg-error "invalid use of non-static member function" } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype49.C b/gcc/testsuite/g++.dg/cpp0x/decltype49.C index c317498..d0a3782 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype49.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype49.C @@ -7,4 +7,4 @@ int A::*ipm = &A::i; template <class T, class U> class assert_same_type; template <class T> class assert_same_type<T,T> { }; -assert_same_type<decltype(A().*ipm),int> x2; +assert_same_type<decltype(A().*ipm),int&&> x2; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C b/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C index 1ca3c41..10a655d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C @@ -4,9 +4,9 @@ template <class T> T&& declval(); int main() { - &declval<int>(); // { dg-error "xvalue" } - declval<int>() = declval<int>(); // { dg-error "xvalue" } - declval<int>()++; // { dg-error "xvalue" } - --declval<int>(); // { dg-error "xvalue" } - declval<int>() += 1; // { dg-error "xvalue" } + &declval<int>(); // { dg-error "rvalue" } + declval<int>() = declval<int>(); // { dg-error "rvalue" } + declval<int>()++; // { dg-error "rvalue" } + --declval<int>(); // { dg-error "rvalue" } + declval<int>() += 1; // { dg-error "rvalue" } } diff --git a/gcc/testsuite/g++.dg/ext/c99struct1.C b/gcc/testsuite/g++.dg/ext/c99struct1.C index 93e84b4..bd5be2d 100644 --- a/gcc/testsuite/g++.dg/ext/c99struct1.C +++ b/gcc/testsuite/g++.dg/ext/c99struct1.C @@ -6,7 +6,7 @@ struct s { int a[1]; }; void foo5 (void) { - ((struct s) { { 0 } }).a[0] = 1; + int i = ((struct s) { { 0 } }).a[0]; } diff --git a/gcc/testsuite/g++.dg/ext/complit11.C b/gcc/testsuite/g++.dg/ext/complit11.C index 0662543..07418ab 100644 --- a/gcc/testsuite/g++.dg/ext/complit11.C +++ b/gcc/testsuite/g++.dg/ext/complit11.C @@ -6,7 +6,7 @@ struct A { int i; }; template<int t> void foo() { - ((struct A) { 0 }).i += 1; // { dg-error "temporary" } + ((struct A) { 0 }).i += 1; // { dg-error "lvalue" } } void g(void) diff --git a/gcc/testsuite/g++.old-deja/g++.law/temps1.C b/gcc/testsuite/g++.old-deja/g++.law/temps1.C index ad42f42..d1ac15d 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/temps1.C +++ b/gcc/testsuite/g++.old-deja/g++.law/temps1.C @@ -17,4 +17,4 @@ struct cookie }; cookie cat(&foo("apabepa"));// { dg-warning "deprecated conversion|forbids converting a string constant" "dep" } -// { dg-warning "taking address of temporary" "add" { target *-*-* } .-1 } +// { dg-warning "taking address of rvalue" "add" { target *-*-* } .-1 } |